@noy-db/hub 0.4.0 → 0.5.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/dist/api-M7REIE7H.js +20 -0
- package/dist/attestation/index.js +16 -16
- package/dist/{backup-X7F3TCFV.js → backup-ENTZYW37.js} +9 -9
- package/dist/blobs/index.js +11 -11
- package/dist/broker/index.js +10 -10
- package/dist/cargo/index.js +26 -26
- package/dist/{chunk-6ZNSB3H6.js → chunk-3LYMOSY7.js} +2 -2
- package/dist/{chunk-LXRTP3AQ.js → chunk-4DGBZEV6.js} +2 -2
- package/dist/{chunk-LRRX57UA.js → chunk-4MSNAB64.js} +4 -4
- package/dist/{chunk-MXUT7FTE.js → chunk-4SG5TOXK.js} +2 -2
- package/dist/{chunk-W66AM5IB.js → chunk-4TXO442D.js} +2 -2
- package/dist/{chunk-UADPR6F4.js → chunk-5EKL6BXI.js} +3 -3
- package/dist/{chunk-ZBYFMI6D.js → chunk-5UKUOMO6.js} +247 -136
- package/dist/chunk-5UKUOMO6.js.map +1 -0
- package/dist/{chunk-SU6SGWXM.js → chunk-623QEHDB.js} +6 -6
- package/dist/{chunk-IVYQAVWO.js → chunk-653KOQ7A.js} +7 -7
- package/dist/{chunk-2BET5QTS.js → chunk-6PFST3FC.js} +4 -4
- package/dist/{chunk-PWPYO73B.js → chunk-6RDTG6E5.js} +5 -5
- package/dist/{chunk-DAFBJS4Y.js → chunk-7P4LL3JH.js} +3 -3
- package/dist/{chunk-S7GIXBXV.js → chunk-AJAOXFCF.js} +8 -8
- package/dist/chunk-AJAOXFCF.js.map +1 -0
- package/dist/{chunk-L3YYLT4E.js → chunk-ALUVACKT.js} +2 -2
- package/dist/{chunk-QZWTRENR.js → chunk-AR5D76T2.js} +5 -1
- package/dist/chunk-AR5D76T2.js.map +1 -0
- package/dist/{chunk-5DRROK5W.js → chunk-BFG7LD6Z.js} +2 -2
- package/dist/{chunk-6UBZ6I5Z.js → chunk-DDB626I7.js} +2 -2
- package/dist/{chunk-W3G5REIU.js → chunk-EAN4TAPC.js} +2 -2
- package/dist/{chunk-4JQK3L4V.js → chunk-EBETHILL.js} +2 -2
- package/dist/{chunk-467SWYT5.js → chunk-ECGDJU5R.js} +3 -3
- package/dist/{chunk-WYUAEZSC.js → chunk-ELJOLQIG.js} +14 -13
- package/dist/chunk-ELJOLQIG.js.map +1 -0
- package/dist/{chunk-ZFG5EBI3.js → chunk-F2WWHKO7.js} +5 -5
- package/dist/{chunk-NJ4DYYO5.js → chunk-F5UWVF6Z.js} +2 -2
- package/dist/{chunk-Q36YXK77.js → chunk-FHK6WWUE.js} +2 -2
- package/dist/{chunk-SHEEBRZ4.js → chunk-FT5Y4VSP.js} +2 -2
- package/dist/{chunk-JQ2AX4T5.js → chunk-FUECZSRM.js} +2 -2
- package/dist/{chunk-Q5YJCVJY.js → chunk-FZAP4JNC.js} +4 -4
- package/dist/{chunk-SFBYQMZM.js → chunk-G3ORJ3IQ.js} +4 -4
- package/dist/{chunk-HLKXPJ4V.js → chunk-G7ZIMGPQ.js} +5 -5
- package/dist/{chunk-QJNCB5SK.js → chunk-GIGLOQL7.js} +2 -2
- package/dist/{chunk-ERGECZEI.js → chunk-GTQF32TP.js} +5 -5
- package/dist/{chunk-JYJFGD2H.js → chunk-GYJRDALN.js} +2 -2
- package/dist/{chunk-HZZP2ZIG.js → chunk-HGDXJVK2.js} +4 -4
- package/dist/{chunk-ZNWSG7XC.js → chunk-IHYSIPEK.js} +6 -6
- package/dist/{chunk-5GQEU4DN.js → chunk-IJV56FWY.js} +2 -2
- package/dist/{chunk-5UQ7Y6SQ.js → chunk-IM2KST7E.js} +3 -3
- package/dist/{chunk-7H3WWH6J.js → chunk-IQ423YMK.js} +3 -3
- package/dist/{chunk-P4JO3H6R.js → chunk-J7YVY7TW.js} +2 -2
- package/dist/{chunk-YGK2HMLR.js → chunk-JLBCK7XM.js} +8 -8
- package/dist/chunk-JLBCK7XM.js.map +1 -0
- package/dist/{chunk-2J6UEN2V.js → chunk-K5OFKXUG.js} +2 -2
- package/dist/{chunk-JEI6JJNI.js → chunk-KDWBVCIX.js} +5 -5
- package/dist/{chunk-T2MOJF76.js → chunk-KJNMTE2W.js} +6 -6
- package/dist/{chunk-NFZGZ4AK.js → chunk-L67H6FAQ.js} +2 -2
- package/dist/{chunk-RBTVFPHF.js → chunk-LQVRK2XJ.js} +4 -4
- package/dist/{chunk-MHMLXJ3I.js → chunk-LXRVTJ5D.js} +2 -2
- package/dist/{chunk-LLYIMSQQ.js → chunk-MDRCEA56.js} +10 -10
- package/dist/{chunk-KRCBZYTZ.js → chunk-MFW466PX.js} +4 -4
- package/dist/{chunk-RO5NM6UI.js → chunk-MGXUAID4.js} +2 -2
- package/dist/{chunk-OWHP3H5C.js → chunk-MPW6AHTC.js} +3 -3
- package/dist/{chunk-35NMVJ7I.js → chunk-MYSNNMJ3.js} +3 -3
- package/dist/{chunk-QGIBI6GL.js → chunk-NG4AQIYJ.js} +4 -4
- package/dist/{chunk-BLBAQRBM.js → chunk-NIKQQXI2.js} +2 -2
- package/dist/{chunk-55LX6FSX.js → chunk-NJHQE4LT.js} +2 -2
- package/dist/{chunk-TS5XLBZR.js → chunk-NMYH55MW.js} +4 -4
- package/dist/{chunk-GTYFIVIZ.js → chunk-NWK6SVBM.js} +5 -5
- package/dist/chunk-NWK6SVBM.js.map +1 -0
- package/dist/{chunk-IFOH7RBI.js → chunk-NZEGQWQ5.js} +4 -4
- package/dist/{chunk-DTFA5DO4.js → chunk-ODCEOSJF.js} +2 -2
- package/dist/{chunk-NYEFP7DY.js → chunk-OKBNFUUX.js} +2 -2
- package/dist/{chunk-SGDPRCC4.js → chunk-OKRXXFZZ.js} +3 -3
- package/dist/{chunk-IG6KUWBX.js → chunk-P6UIVLZK.js} +2 -2
- package/dist/{chunk-V6UQZA2H.js → chunk-PKBONLCP.js} +2 -2
- package/dist/{chunk-MSMJJB4J.js → chunk-PTSVGKSR.js} +2 -2
- package/dist/{chunk-IXNCZTWA.js → chunk-PWEMRXPO.js} +2 -2
- package/dist/{chunk-PTHKZWEH.js → chunk-PZRYKOKP.js} +2 -2
- package/dist/{chunk-KD4HGBJV.js → chunk-Q6MXHDSE.js} +3 -3
- package/dist/{chunk-RQ4ZI4ZI.js → chunk-QITP2JGX.js} +5 -5
- package/dist/{chunk-WBKZUO5V.js → chunk-QMCWYN6O.js} +3 -3
- package/dist/{chunk-4ZKNC6A6.js → chunk-QQL6XPPG.js} +2 -2
- package/dist/{chunk-TG634KCO.js → chunk-QTMZDMJ6.js} +2 -2
- package/dist/{chunk-AT2JJEKJ.js → chunk-RM4FIXY2.js} +4 -4
- package/dist/{chunk-AKKRXT23.js → chunk-RPWMDIGK.js} +2 -2
- package/dist/{chunk-NBXFCQX4.js → chunk-RQILGK3N.js} +8 -8
- package/dist/chunk-RQILGK3N.js.map +1 -0
- package/dist/{chunk-NM5UYF6Q.js → chunk-SBGXQK5I.js} +2 -2
- package/dist/{chunk-SF2ZIRD6.js → chunk-SL3PLML2.js} +3 -3
- package/dist/{chunk-3ECU57YH.js → chunk-TJOUKMWF.js} +8 -8
- package/dist/{chunk-QD46HPZG.js → chunk-U2ID5A2I.js} +2 -2
- package/dist/{chunk-X4MVWPHV.js → chunk-UC5Y7OEJ.js} +3 -3
- package/dist/{chunk-SBHN6QUT.js → chunk-US2AR4BI.js} +2 -2
- package/dist/{chunk-DQZXPGGZ.js → chunk-V3EGXDFN.js} +3 -3
- package/dist/{chunk-ZHDSUZQU.js → chunk-V4O6YZSP.js} +3 -3
- package/dist/{chunk-3HUYRN24.js → chunk-W7C7MMIS.js} +3 -3
- package/dist/{chunk-NLYALJMY.js → chunk-WFYKIDCS.js} +30 -11
- package/dist/chunk-WFYKIDCS.js.map +1 -0
- package/dist/{chunk-TWPK7KUJ.js → chunk-XID22NOA.js} +5 -5
- package/dist/{chunk-E23UGFVC.js → chunk-XVK7TULT.js} +2 -2
- package/dist/{chunk-WUHEP3HH.js → chunk-XX7YB5BI.js} +4 -4
- package/dist/{chunk-ZTLOXFPB.js → chunk-Y2PTKKIN.js} +2 -2
- package/dist/{chunk-KYRDJI5O.js → chunk-YA7Y3EZP.js} +10 -10
- package/dist/classified/index.js +4 -4
- package/dist/{classified-marker-LE54HWSX.js → classified-marker-ZALWKOBC.js} +3 -3
- package/dist/{collection-facade-DO2AABZT.js → collection-facade-KI53O6QB.js} +15 -15
- package/dist/{computed-AB45PS4V.js → computed-YOQCGUCS.js} +3 -3
- package/dist/consent/index.js +7 -7
- package/dist/cover/index.js +2 -2
- package/dist/custody/index.js +9 -9
- package/dist/{dead-filter-V3LVWYEJ.js → dead-filter-6DVWST6U.js} +2 -2
- package/dist/debug/index.js +1 -1
- package/dist/{delegation-JDUMAF6L.js → delegation-WMO3Q3O5.js} +8 -8
- package/dist/derivations/index.js +10 -10
- package/dist/{derive-ZPGVLE2Q.js → derive-P2NXWUNB.js} +8 -8
- package/dist/directory/index.js +8 -8
- package/dist/{dispatch-W7NWQ637.js → dispatch-TKV4UCKB.js} +16 -16
- package/dist/{dispatch-6TV3DGO6.js → dispatch-VNR3TLBX.js} +5 -5
- package/dist/{enclave-YFCLPIDR.js → enclave-YWP3QAIQ.js} +7 -7
- package/dist/executor-M4ZZNX6S.js +28 -0
- package/dist/executor-TI64S4LE.js +9 -0
- package/dist/executor-YBK3I2OT.js +9 -0
- package/dist/export-accessible-GBLYLGW4.js +23 -0
- package/dist/extract-partition-SFV35U2R.js +38 -0
- package/dist/{fanout-sidecar-273RDMYS.js → fanout-sidecar-WYXO6QQT.js} +7 -7
- package/dist/find-HUSSZRBR.js +11 -0
- package/dist/forget/index.js +7 -7
- package/dist/guards/index.js +5 -5
- package/dist/history/index.js +10 -10
- package/dist/i18n/index.js +12 -12
- package/dist/index.d.ts +1 -1
- package/dist/index.js +86 -84
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +2 -2
- package/dist/introspection/index.js +9 -9
- package/dist/issue-6TIJYWKS.js +19 -0
- package/dist/kernel/collection-config.d.ts +4 -0
- package/dist/kernel/collection.d.ts +24 -6
- package/dist/kernel/errors.d.ts +15 -0
- package/dist/kernel/put-many-atomic.d.ts +45 -0
- package/dist/kernel/vault.d.ts +14 -0
- package/dist/{ledger-XE7JF2I2.js → ledger-BLYDYRTQ.js} +9 -9
- package/dist/liberate-TSOW7IG5.js +24 -0
- package/dist/{link-set-CGYC3OH5.js → link-set-7F5ZPDEB.js} +9 -9
- package/dist/materialized-views/index.js +22 -22
- package/dist/money/index.js +3 -3
- package/dist/noydb-KFN6M6UJ.js +81 -0
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +11 -11
- package/dist/pod/index.js +9 -9
- package/dist/policy/index.js +2 -2
- package/dist/port/with/write-hooks.d.ts +6 -0
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-LY35EDTJ.js → post-register-PQSY544J.js} +6 -6
- package/dist/query/index.js +3 -3
- package/dist/reduce/index.js +4 -4
- package/dist/{register-6RIBIT3I.js → register-S3ECUZPV.js} +10 -10
- package/dist/registry-FZOHKUME.js +18 -0
- package/dist/registry-RISV7IDZ.js +19 -0
- package/dist/registry-ZE35A7WC.js +9 -0
- package/dist/{request-withdrawal-FT3ORAWN.js → request-withdrawal-KXVTQKR5.js} +12 -12
- package/dist/{reveal-T34ADTPY.js → reveal-HY7DZST4.js} +4 -4
- package/dist/{revoke-HC7WG3HE.js → revoke-J473JJ22.js} +9 -9
- package/dist/satellites/index.js +1 -1
- package/dist/schema-update/index.js +2 -2
- package/dist/sealed-record/index.js +10 -10
- package/dist/search/index.js +4 -4
- package/dist/{seed-JOV54PB3.js → seed-ALU3BHFS.js} +13 -13
- package/dist/seed-ALU3BHFS.js.map +1 -0
- package/dist/sequence/index.js +7 -7
- package/dist/session/index.js +7 -7
- package/dist/shadow/index.js +2 -2
- package/dist/{signer-CTWOH6KT.js → signer-XLUKCCH3.js} +8 -8
- package/dist/snapshots/index.js +8 -8
- package/dist/{stale-T3V7XEOB.js → stale-U3WO5MYN.js} +8 -8
- package/dist/{storage-LLNLPWWB.js → storage-IQONEOYY.js} +8 -8
- package/dist/sync/index.js +8 -8
- package/dist/team/index.js +11 -11
- package/dist/tiers/index.js +8 -8
- package/dist/to/index.js +1 -1
- package/dist/transactions/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/{verify-7XWHJWUN.js → verify-JEIXSK5U.js} +5 -5
- package/dist/walk-BF36V4SR.js +21 -0
- package/dist/with-commit/tx/atomic-eligibility.d.ts +13 -11
- package/dist/with-sync/engine.d.ts +13 -0
- package/dist/{withdraw-accessible-ANSVG6XG.js → withdraw-accessible-TYTA23XH.js} +11 -11
- package/package.json +3 -3
- package/dist/api-SI2IVBQO.js +0 -20
- package/dist/chunk-GTYFIVIZ.js.map +0 -1
- package/dist/chunk-NBXFCQX4.js.map +0 -1
- package/dist/chunk-NLYALJMY.js.map +0 -1
- package/dist/chunk-QZWTRENR.js.map +0 -1
- package/dist/chunk-S7GIXBXV.js.map +0 -1
- package/dist/chunk-WYUAEZSC.js.map +0 -1
- package/dist/chunk-YGK2HMLR.js.map +0 -1
- package/dist/chunk-ZBYFMI6D.js.map +0 -1
- package/dist/executor-FPHKWDWT.js +0 -28
- package/dist/executor-IEBLTBCW.js +0 -9
- package/dist/executor-RM7XWQDU.js +0 -9
- package/dist/export-accessible-EKM3HGB2.js +0 -23
- package/dist/extract-partition-LS4ET5A6.js +0 -38
- package/dist/find-OZMTRIK3.js +0 -11
- package/dist/issue-LIA7FXBJ.js +0 -19
- package/dist/liberate-WZ3RHVKW.js +0 -24
- package/dist/noydb-ZLPVCDES.js +0 -81
- package/dist/registry-7Y5WF7GS.js +0 -9
- package/dist/registry-MUSL4AW6.js +0 -19
- package/dist/registry-RON4WHAP.js +0 -18
- package/dist/seed-JOV54PB3.js.map +0 -1
- package/dist/walk-G3NFEP5L.js +0 -21
- /package/dist/{api-SI2IVBQO.js.map → api-M7REIE7H.js.map} +0 -0
- /package/dist/{backup-X7F3TCFV.js.map → backup-ENTZYW37.js.map} +0 -0
- /package/dist/{chunk-6ZNSB3H6.js.map → chunk-3LYMOSY7.js.map} +0 -0
- /package/dist/{chunk-LXRTP3AQ.js.map → chunk-4DGBZEV6.js.map} +0 -0
- /package/dist/{chunk-LRRX57UA.js.map → chunk-4MSNAB64.js.map} +0 -0
- /package/dist/{chunk-MXUT7FTE.js.map → chunk-4SG5TOXK.js.map} +0 -0
- /package/dist/{chunk-W66AM5IB.js.map → chunk-4TXO442D.js.map} +0 -0
- /package/dist/{chunk-UADPR6F4.js.map → chunk-5EKL6BXI.js.map} +0 -0
- /package/dist/{chunk-SU6SGWXM.js.map → chunk-623QEHDB.js.map} +0 -0
- /package/dist/{chunk-IVYQAVWO.js.map → chunk-653KOQ7A.js.map} +0 -0
- /package/dist/{chunk-2BET5QTS.js.map → chunk-6PFST3FC.js.map} +0 -0
- /package/dist/{chunk-PWPYO73B.js.map → chunk-6RDTG6E5.js.map} +0 -0
- /package/dist/{chunk-DAFBJS4Y.js.map → chunk-7P4LL3JH.js.map} +0 -0
- /package/dist/{chunk-L3YYLT4E.js.map → chunk-ALUVACKT.js.map} +0 -0
- /package/dist/{chunk-5DRROK5W.js.map → chunk-BFG7LD6Z.js.map} +0 -0
- /package/dist/{chunk-6UBZ6I5Z.js.map → chunk-DDB626I7.js.map} +0 -0
- /package/dist/{chunk-W3G5REIU.js.map → chunk-EAN4TAPC.js.map} +0 -0
- /package/dist/{chunk-4JQK3L4V.js.map → chunk-EBETHILL.js.map} +0 -0
- /package/dist/{chunk-467SWYT5.js.map → chunk-ECGDJU5R.js.map} +0 -0
- /package/dist/{chunk-ZFG5EBI3.js.map → chunk-F2WWHKO7.js.map} +0 -0
- /package/dist/{chunk-NJ4DYYO5.js.map → chunk-F5UWVF6Z.js.map} +0 -0
- /package/dist/{chunk-Q36YXK77.js.map → chunk-FHK6WWUE.js.map} +0 -0
- /package/dist/{chunk-SHEEBRZ4.js.map → chunk-FT5Y4VSP.js.map} +0 -0
- /package/dist/{chunk-JQ2AX4T5.js.map → chunk-FUECZSRM.js.map} +0 -0
- /package/dist/{chunk-Q5YJCVJY.js.map → chunk-FZAP4JNC.js.map} +0 -0
- /package/dist/{chunk-SFBYQMZM.js.map → chunk-G3ORJ3IQ.js.map} +0 -0
- /package/dist/{chunk-HLKXPJ4V.js.map → chunk-G7ZIMGPQ.js.map} +0 -0
- /package/dist/{chunk-QJNCB5SK.js.map → chunk-GIGLOQL7.js.map} +0 -0
- /package/dist/{chunk-ERGECZEI.js.map → chunk-GTQF32TP.js.map} +0 -0
- /package/dist/{chunk-JYJFGD2H.js.map → chunk-GYJRDALN.js.map} +0 -0
- /package/dist/{chunk-HZZP2ZIG.js.map → chunk-HGDXJVK2.js.map} +0 -0
- /package/dist/{chunk-ZNWSG7XC.js.map → chunk-IHYSIPEK.js.map} +0 -0
- /package/dist/{chunk-5GQEU4DN.js.map → chunk-IJV56FWY.js.map} +0 -0
- /package/dist/{chunk-5UQ7Y6SQ.js.map → chunk-IM2KST7E.js.map} +0 -0
- /package/dist/{chunk-7H3WWH6J.js.map → chunk-IQ423YMK.js.map} +0 -0
- /package/dist/{chunk-P4JO3H6R.js.map → chunk-J7YVY7TW.js.map} +0 -0
- /package/dist/{chunk-2J6UEN2V.js.map → chunk-K5OFKXUG.js.map} +0 -0
- /package/dist/{chunk-JEI6JJNI.js.map → chunk-KDWBVCIX.js.map} +0 -0
- /package/dist/{chunk-T2MOJF76.js.map → chunk-KJNMTE2W.js.map} +0 -0
- /package/dist/{chunk-NFZGZ4AK.js.map → chunk-L67H6FAQ.js.map} +0 -0
- /package/dist/{chunk-RBTVFPHF.js.map → chunk-LQVRK2XJ.js.map} +0 -0
- /package/dist/{chunk-MHMLXJ3I.js.map → chunk-LXRVTJ5D.js.map} +0 -0
- /package/dist/{chunk-LLYIMSQQ.js.map → chunk-MDRCEA56.js.map} +0 -0
- /package/dist/{chunk-KRCBZYTZ.js.map → chunk-MFW466PX.js.map} +0 -0
- /package/dist/{chunk-RO5NM6UI.js.map → chunk-MGXUAID4.js.map} +0 -0
- /package/dist/{chunk-OWHP3H5C.js.map → chunk-MPW6AHTC.js.map} +0 -0
- /package/dist/{chunk-35NMVJ7I.js.map → chunk-MYSNNMJ3.js.map} +0 -0
- /package/dist/{chunk-QGIBI6GL.js.map → chunk-NG4AQIYJ.js.map} +0 -0
- /package/dist/{chunk-BLBAQRBM.js.map → chunk-NIKQQXI2.js.map} +0 -0
- /package/dist/{chunk-55LX6FSX.js.map → chunk-NJHQE4LT.js.map} +0 -0
- /package/dist/{chunk-TS5XLBZR.js.map → chunk-NMYH55MW.js.map} +0 -0
- /package/dist/{chunk-IFOH7RBI.js.map → chunk-NZEGQWQ5.js.map} +0 -0
- /package/dist/{chunk-DTFA5DO4.js.map → chunk-ODCEOSJF.js.map} +0 -0
- /package/dist/{chunk-NYEFP7DY.js.map → chunk-OKBNFUUX.js.map} +0 -0
- /package/dist/{chunk-SGDPRCC4.js.map → chunk-OKRXXFZZ.js.map} +0 -0
- /package/dist/{chunk-IG6KUWBX.js.map → chunk-P6UIVLZK.js.map} +0 -0
- /package/dist/{chunk-V6UQZA2H.js.map → chunk-PKBONLCP.js.map} +0 -0
- /package/dist/{chunk-MSMJJB4J.js.map → chunk-PTSVGKSR.js.map} +0 -0
- /package/dist/{chunk-IXNCZTWA.js.map → chunk-PWEMRXPO.js.map} +0 -0
- /package/dist/{chunk-PTHKZWEH.js.map → chunk-PZRYKOKP.js.map} +0 -0
- /package/dist/{chunk-KD4HGBJV.js.map → chunk-Q6MXHDSE.js.map} +0 -0
- /package/dist/{chunk-RQ4ZI4ZI.js.map → chunk-QITP2JGX.js.map} +0 -0
- /package/dist/{chunk-WBKZUO5V.js.map → chunk-QMCWYN6O.js.map} +0 -0
- /package/dist/{chunk-4ZKNC6A6.js.map → chunk-QQL6XPPG.js.map} +0 -0
- /package/dist/{chunk-TG634KCO.js.map → chunk-QTMZDMJ6.js.map} +0 -0
- /package/dist/{chunk-AT2JJEKJ.js.map → chunk-RM4FIXY2.js.map} +0 -0
- /package/dist/{chunk-AKKRXT23.js.map → chunk-RPWMDIGK.js.map} +0 -0
- /package/dist/{chunk-NM5UYF6Q.js.map → chunk-SBGXQK5I.js.map} +0 -0
- /package/dist/{chunk-SF2ZIRD6.js.map → chunk-SL3PLML2.js.map} +0 -0
- /package/dist/{chunk-3ECU57YH.js.map → chunk-TJOUKMWF.js.map} +0 -0
- /package/dist/{chunk-QD46HPZG.js.map → chunk-U2ID5A2I.js.map} +0 -0
- /package/dist/{chunk-X4MVWPHV.js.map → chunk-UC5Y7OEJ.js.map} +0 -0
- /package/dist/{chunk-SBHN6QUT.js.map → chunk-US2AR4BI.js.map} +0 -0
- /package/dist/{chunk-DQZXPGGZ.js.map → chunk-V3EGXDFN.js.map} +0 -0
- /package/dist/{chunk-ZHDSUZQU.js.map → chunk-V4O6YZSP.js.map} +0 -0
- /package/dist/{chunk-3HUYRN24.js.map → chunk-W7C7MMIS.js.map} +0 -0
- /package/dist/{chunk-TWPK7KUJ.js.map → chunk-XID22NOA.js.map} +0 -0
- /package/dist/{chunk-E23UGFVC.js.map → chunk-XVK7TULT.js.map} +0 -0
- /package/dist/{chunk-WUHEP3HH.js.map → chunk-XX7YB5BI.js.map} +0 -0
- /package/dist/{chunk-ZTLOXFPB.js.map → chunk-Y2PTKKIN.js.map} +0 -0
- /package/dist/{chunk-KYRDJI5O.js.map → chunk-YA7Y3EZP.js.map} +0 -0
- /package/dist/{classified-marker-LE54HWSX.js.map → classified-marker-ZALWKOBC.js.map} +0 -0
- /package/dist/{collection-facade-DO2AABZT.js.map → collection-facade-KI53O6QB.js.map} +0 -0
- /package/dist/{computed-AB45PS4V.js.map → computed-YOQCGUCS.js.map} +0 -0
- /package/dist/{dead-filter-V3LVWYEJ.js.map → dead-filter-6DVWST6U.js.map} +0 -0
- /package/dist/{delegation-JDUMAF6L.js.map → delegation-WMO3Q3O5.js.map} +0 -0
- /package/dist/{derive-ZPGVLE2Q.js.map → derive-P2NXWUNB.js.map} +0 -0
- /package/dist/{dispatch-W7NWQ637.js.map → dispatch-TKV4UCKB.js.map} +0 -0
- /package/dist/{dispatch-6TV3DGO6.js.map → dispatch-VNR3TLBX.js.map} +0 -0
- /package/dist/{enclave-YFCLPIDR.js.map → enclave-YWP3QAIQ.js.map} +0 -0
- /package/dist/{executor-FPHKWDWT.js.map → executor-M4ZZNX6S.js.map} +0 -0
- /package/dist/{executor-IEBLTBCW.js.map → executor-TI64S4LE.js.map} +0 -0
- /package/dist/{executor-RM7XWQDU.js.map → executor-YBK3I2OT.js.map} +0 -0
- /package/dist/{export-accessible-EKM3HGB2.js.map → export-accessible-GBLYLGW4.js.map} +0 -0
- /package/dist/{extract-partition-LS4ET5A6.js.map → extract-partition-SFV35U2R.js.map} +0 -0
- /package/dist/{fanout-sidecar-273RDMYS.js.map → fanout-sidecar-WYXO6QQT.js.map} +0 -0
- /package/dist/{find-OZMTRIK3.js.map → find-HUSSZRBR.js.map} +0 -0
- /package/dist/{issue-LIA7FXBJ.js.map → issue-6TIJYWKS.js.map} +0 -0
- /package/dist/{ledger-XE7JF2I2.js.map → ledger-BLYDYRTQ.js.map} +0 -0
- /package/dist/{liberate-WZ3RHVKW.js.map → liberate-TSOW7IG5.js.map} +0 -0
- /package/dist/{link-set-CGYC3OH5.js.map → link-set-7F5ZPDEB.js.map} +0 -0
- /package/dist/{noydb-ZLPVCDES.js.map → noydb-KFN6M6UJ.js.map} +0 -0
- /package/dist/{post-register-LY35EDTJ.js.map → post-register-PQSY544J.js.map} +0 -0
- /package/dist/{register-6RIBIT3I.js.map → register-S3ECUZPV.js.map} +0 -0
- /package/dist/{registry-7Y5WF7GS.js.map → registry-FZOHKUME.js.map} +0 -0
- /package/dist/{registry-MUSL4AW6.js.map → registry-RISV7IDZ.js.map} +0 -0
- /package/dist/{registry-RON4WHAP.js.map → registry-ZE35A7WC.js.map} +0 -0
- /package/dist/{request-withdrawal-FT3ORAWN.js.map → request-withdrawal-KXVTQKR5.js.map} +0 -0
- /package/dist/{reveal-T34ADTPY.js.map → reveal-HY7DZST4.js.map} +0 -0
- /package/dist/{revoke-HC7WG3HE.js.map → revoke-J473JJ22.js.map} +0 -0
- /package/dist/{signer-CTWOH6KT.js.map → signer-XLUKCCH3.js.map} +0 -0
- /package/dist/{stale-T3V7XEOB.js.map → stale-U3WO5MYN.js.map} +0 -0
- /package/dist/{storage-LLNLPWWB.js.map → storage-IQONEOYY.js.map} +0 -0
- /package/dist/{verify-7XWHJWUN.js.map → verify-JEIXSK5U.js.map} +0 -0
- /package/dist/{walk-G3NFEP5L.js.map → walk-BF36V4SR.js.map} +0 -0
- /package/dist/{withdraw-accessible-ANSVG6XG.js.map → withdraw-accessible-TYTA23XH.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-commit/tx/strategy.ts","../src/port/with/archive-strategy.ts","../src/port/with/strategies.ts","../src/port/by/default-provider.ts","../src/port/with/collection-registries.ts","../src/kernel/via/pipeline.ts","../src/kernel/lazy-count.ts","../src/with-lookup/indexing/collection-facade.ts","../src/with-lookup/search/serialize.ts","../src/with-lookup/search/persisted-index-store.ts","../src/with-lookup/indexing/unique-constraints.ts","../src/with-shape/introspection/field-meta.ts","../src/with-shape/introspection/describe.ts","../src/kernel/put-many-atomic.ts","../src/kernel/via/compose.ts","../src/kernel/collection-config.ts","../src/with-formula/computed/lazy.ts","../src/kernel/collection.ts","../src/port/with/capabilities.ts","../src/with-commit/tx/elevated-handle.ts","../src/with-fork/archive/engine.ts","../src/with-fork/archive/index.ts","../src/with-commit/numbering/index.ts","../src/with-audit/periods/vault-facade.ts","../src/kernel/refs.ts","../src/with-shape/links/vault-facade.ts","../src/with-shape/links/lazy-handle.ts","../src/kernel/via/taint-binding.ts","../src/kernel/via/graph-wiring.ts","../src/kernel/via/reconcile.ts","../src/with-shape/satellites/registry.ts","../src/with-shape/satellites/declare.ts","../src/with-shape/satellites/raw-target.ts","../src/with-shape/satellites/fanout.ts","../src/with-shape/satellites/proxy.ts","../src/with-shape/satellites/joined.ts","../src/with-shape/satellites/forget.ts","../src/with-shape/satellites/migrate-cek.ts","../src/with-shape/schema-update/fence-controller.ts","../src/with-audit/attestation/vault-facade.ts","../src/kernel/vault.ts","../src/kernel/events.ts","../src/kernel/write-queue.ts","../src/port/with/write-hooks.ts","../src/port/with/service-bus.ts","../src/with-sync/tab-coordination.ts","../src/with-sync/tab-write-relay.ts","../src/with-party/session/unlock-state.ts","../src/with-fork/snapshots/scheduler.ts","../src/with-fork/snapshots/noydb-facade.ts","../src/kernel/memory-store.ts","../src/with-party/team/noydb-facade.ts","../src/kernel/noydb.ts"],"sourcesContent":["/**\n * Strategy seam for the optional multi-record transaction service.\n * `runTransaction` is only reachable through `withTransactions()`\n * exported from `@noy-db/hub/transactions`. Consumers who don't use\n * `db.transaction(fn)` ship none of the ~288 LOC.\n *\n * @internal\n */\n\nimport type { Noydb } from '../../kernel/noydb.js'\nimport type { TxContext, AmendmentTxOptions } from './transaction.js'\nimport type { DryRunResult } from './dry-run.js'\nimport type { TransactionInvariant } from './invariants.js'\n\n/**\n * @internal\n */\nexport interface TransactionsStrategy {\n runTransaction<T>(\n db: Noydb,\n fn: (tx: TxContext) => Promise<T> | T,\n options?: AmendmentTxOptions,\n txInvariants?: ReadonlyArray<TransactionInvariant>,\n ): Promise<T>\n runDryRun(db: Noydb, fn: (tx: TxContext) => unknown): Promise<DryRunResult>\n}\n\nconst NOT_ENABLED = new Error(\n 'Multi-record transactions require the tx strategy. Import ' +\n '`{ withTransactions }` from \"@noy-db/hub/transactions\" and pass it to ' +\n '`createNoydb({ transactionsStrategy: withTransactions() })`.',\n)\n\n/**\n * @internal\n */\nexport const NO_TRANSACTIONS: TransactionsStrategy = {\n async runTransaction(\n _db: Noydb,\n _fn: unknown,\n _options?: AmendmentTxOptions,\n _txInvariants?: ReadonlyArray<TransactionInvariant>,\n ): Promise<never> { throw NOT_ENABLED },\n async runDryRun() { throw NOT_ENABLED },\n}\n","/**\n * Strategy seam between the kernel spine and the optional archive service\n * (#838 — precedent: `port/with/blob-strategy.ts`). Lives on the `/with`\n * port so `Vault` can hold the `NO_ARCHIVE` default without a\n * spine→service static import.\n *\n * `archiveStrategy` was the one service with no NO-op stub: the spine held\n * it as `ArchiveStrategy | undefined` and hand-rolled a null gate before\n * every use. That made it the sole exception to the strategy-bag's \"every\n * key always resolves\" rule (#838), so the stub exists to remove the\n * exception rather than to add a capability.\n *\n * `ArchiveStrategy`'s only member is a live cold `NoydbStore`, and there is\n * no meaningful no-op store — so the stub throws on access instead of\n * standing in. That reproduces the previous gate exactly: `_archiveContext()`\n * read `strategy.store` immediately after its null check, so the throw lands\n * in the same call with the same message.\n *\n * The `ArchiveStrategy` import is TYPE-ONLY and therefore erased — importing\n * it does not pull `with-fork/archive/index.js`'s runtime re-exports of the\n * relocation engine.\n *\n * @internal\n */\n\nimport type { ArchiveStrategy } from '../../with-fork/archive/index.js'\n\nconst ARCHIVE_NOT_ENABLED =\n 'vault.archive/restore/listArchived require `archiveStrategy: withArchive({ store })` in createNoydb'\n\n/**\n * The un-opted-in archive strategy. Reading `.store` throws with a pointer\n * at the `withArchive()` factory — the archive service has no degraded mode\n * to fall back to.\n */\nexport const NO_ARCHIVE: ArchiveStrategy = {\n get store(): never {\n throw new Error(ARCHIVE_NOT_ENABLED)\n },\n}\n","/**\n * The strategy bag (#838) — one resolved, immutable record of every opt-in\n * service, built once in `createNoydb` and carried by reference down the\n * spine: `Noydb` → `Vault` → `Collection`.\n *\n * ## Why this exists\n *\n * Threading one service through the spine used to cost ~10 mechanical edits\n * with no logic in any of them: a field on `NoydbOptions`, a conditional\n * spread at the `new Vault(` site, a field declaration + constructor\n * parameter + constructor assignment on `Vault`, a forwarding spread into\n * the collection options, a field + `?? NO_*` default in\n * `collection-config.ts`, and a field + assignment on `Collection`. Nothing\n * checked that a new service reached every layer, which is exactly how #834\n * happened — one of three copies of the Vault option block had silently\n * dropped six strategies, and a vault reached that way threw\n * `*NotEnabledError` for services the caller had actually configured.\n *\n * Here the layers hold ONE field. Adding a service is a row in\n * {@link StrategyBag} plus a row in {@link STRATEGY_DEFAULTS} — both in this\n * file, and omitting either is a compile error rather than a bug that only\n * shows up through one construction path.\n *\n * ## Every key always resolves\n *\n * There is no `undefined` in the bag. An un-opted-in service resolves to its\n * `NO_*` stub, which is the tree-shake seam: the stubs are deliberately tiny\n * modules on the `/with` port that the spine may import statically, while the\n * real implementation arrives only when the consumer imports the service's\n * subpath. Holding a stub costs a few hundred bytes; it does not pull the\n * machinery in.\n *\n * Two services needed adjusting to fit that rule, both recorded here because\n * the reasons are not obvious:\n *\n * - `archive` had no stub at all and was held as `ArchiveStrategy |\n * undefined` behind a hand-rolled null gate. {@link NO_ARCHIVE} now stands\n * in and throws on `.store` access — see `port/with/archive-strategy.ts`.\n * - `lazy`'s floor is {@link IMPLICIT_LAZY}, not a no-op: an un-opted-in\n * collection still gets a working LRU, it just warns. So its default row\n * is a real strategy, which is why this table maps keys to defaults rather\n * than assuming a `NO_*` naming convention.\n *\n * `coordinationStrategy` is deliberately NOT in the bag. It is a\n * `CoordinationProvider`, not a service strategy — it has no `with*()`\n * factory, no `NO_*` stub, and is resolved asynchronously from the store\n * (`createDefaultCoordinationProvider`) rather than passed through. The\n * completeness assertion at the bottom of this file excludes it by name so\n * that the exclusion is explicit and survives future edits.\n *\n * @internal\n */\n\nimport type { NoydbOptions } from '../../kernel/types.js'\n\nimport { NO_REDUCE, type ReduceStrategy } from '../../with-lookup/reduce/strategy.js'\nimport { NO_ATTESTATION, type AttestationStrategy } from '../../with-audit/attestation/strategy.js'\nimport { NO_BLOBS, type BlobsStrategy } from './blob-strategy.js'\nimport { NO_BROKER, type BrokerStrategy } from './broker-strategy.js'\nimport { NO_CARGO, type CargoStrategy } from '../../with-cargo/strategy.js'\nimport { NO_CLASSIFIED, type ClassifiedStrategy } from './classified-strategy.js'\nimport { NO_CONSENT, type ConsentStrategy } from '../../with-audit/consent/strategy.js'\nimport { NO_CRDT, type CrdtStrategy } from '../../with-commit/crdt/strategy.js'\nimport { NO_CUSTODY, type CustodyStrategy } from '../../with-party/custody/strategy.js'\nimport { NO_FORGET, type ForgetStrategy } from '../../with-audit/forget/strategy.js'\nimport { NO_HISTORY, type HistoryStrategy } from '../../with-commit/history/strategy.js'\nimport { NO_I18N, type I18nStrategy } from './i18n-strategy.js'\nimport { NO_INDEXING, type IndexingStrategy } from '../../with-lookup/indexing/strategy.js'\nimport { NO_PERIODS, type PeriodsStrategy } from '../../with-audit/periods/strategy.js'\nimport { NO_PORTABILITY, type PortabilityStrategy } from '../../with-audit/portability/strategy.js'\nimport { NO_SEALED_RECORD, type SealedRecordStrategy } from '../../with-audit/sealed-record/strategy.js'\nimport { NO_SEARCH, type SearchStrategy } from '../../with-lookup/search/strategy.js'\nimport { NO_SEQUENCE, type SequenceStrategy } from '../../with-commit/sequence/strategy.js'\nimport { NO_SESSION, type SessionStrategy } from '../../with-party/session/strategy.js'\nimport { NO_SHADOW, type ShadowStrategy } from '../../with-fork/shadow/strategy.js'\nimport { NO_SNAPSHOTS, type SnapshotsStrategy } from '../../with-fork/snapshots/strategy.js'\nimport { NO_SYNC, type SyncStrategy } from '../../with-sync/strategy.js'\nimport { NO_TEAM, type TeamStrategy } from './team-strategy.js'\nimport { NO_TIERS, type TiersStrategy } from '../../with-audit/tiers/strategy.js'\nimport { NO_TRANSACTIONS, type TransactionsStrategy } from '../../with-commit/tx/strategy.js'\nimport { IMPLICIT_LAZY, type LazyStrategy } from './lazy-strategy.js'\nimport { NO_ARCHIVE } from './archive-strategy.js'\nimport type { ArchiveStrategy } from '../../with-fork/archive/index.js'\n\n/**\n * Every opt-in service, resolved. One field per service, never `undefined`.\n *\n * Keys drop the `Strategy` suffix the `createNoydb` option carries, so\n * `searchStrategy: withSearch()` reads back as `strategies.search`. The\n * completeness assertion below pins that correspondence.\n */\nexport interface StrategyBag {\n readonly reduce: ReduceStrategy\n readonly archive: ArchiveStrategy\n readonly attestation: AttestationStrategy\n readonly blobs: BlobsStrategy\n readonly broker: BrokerStrategy\n readonly cargo: CargoStrategy\n readonly classified: ClassifiedStrategy\n readonly consent: ConsentStrategy\n readonly crdt: CrdtStrategy\n readonly custody: CustodyStrategy\n readonly forget: ForgetStrategy\n readonly history: HistoryStrategy\n readonly i18n: I18nStrategy\n readonly indexing: IndexingStrategy\n readonly lazy: LazyStrategy\n readonly periods: PeriodsStrategy\n readonly portability: PortabilityStrategy\n readonly sealedRecord: SealedRecordStrategy\n readonly search: SearchStrategy\n readonly sequence: SequenceStrategy\n readonly session: SessionStrategy\n readonly shadow: ShadowStrategy\n readonly snapshots: SnapshotsStrategy\n readonly sync: SyncStrategy\n readonly team: TeamStrategy\n readonly tiers: TiersStrategy\n readonly transactions: TransactionsStrategy\n}\n\n/** The name of every service in the bag. */\nexport type StrategyKey = keyof StrategyBag\n\n/**\n * The un-opted-in floor: what each service resolves to when the caller passed\n * no `with*()` factory. Annotating this `StrategyBag` is what makes a missing\n * row a compile error.\n */\nexport const STRATEGY_DEFAULTS: StrategyBag = {\n reduce: NO_REDUCE,\n archive: NO_ARCHIVE,\n attestation: NO_ATTESTATION,\n blobs: NO_BLOBS,\n broker: NO_BROKER,\n cargo: NO_CARGO,\n classified: NO_CLASSIFIED,\n consent: NO_CONSENT,\n crdt: NO_CRDT,\n custody: NO_CUSTODY,\n forget: NO_FORGET,\n history: NO_HISTORY,\n i18n: NO_I18N,\n indexing: NO_INDEXING,\n lazy: IMPLICIT_LAZY,\n periods: NO_PERIODS,\n portability: NO_PORTABILITY,\n sealedRecord: NO_SEALED_RECORD,\n search: NO_SEARCH,\n sequence: NO_SEQUENCE,\n session: NO_SESSION,\n shadow: NO_SHADOW,\n snapshots: NO_SNAPSHOTS,\n sync: NO_SYNC,\n team: NO_TEAM,\n tiers: NO_TIERS,\n transactions: NO_TRANSACTIONS,\n}\n\n/** Every key of the bag, as a runtime array. Derived, so it cannot drift. */\nconst STRATEGY_KEYS = Object.keys(STRATEGY_DEFAULTS) as StrategyKey[]\n\n/**\n * Build the bag from user options. Called ONCE, in `createNoydb` — every\n * layer below shares the resulting reference.\n *\n * The two casts are the price of mapping `blob` ↔ `blobsStrategy` in a loop\n * instead of writing 27 hand-copied lines; the correspondence they assume is\n * proven at compile time by the assertion below, so a typo cannot survive a\n * build.\n */\nexport function resolveStrategies(options: NoydbOptions): StrategyBag {\n const provided = options as unknown as Record<string, unknown>\n const resolved = { ...STRATEGY_DEFAULTS } as unknown as Record<string, unknown>\n\n for (const key of STRATEGY_KEYS) {\n const value = provided[`${key}Strategy`]\n if (value !== undefined) resolved[key] = value\n }\n\n return resolved as unknown as StrategyBag\n}\n\n// ─── Completeness: the bag and the public options must name the same set ──\n//\n// If a service is added to `NoydbOptions` without a bag row (or a bag row is\n// added without the option), one of these aliases resolves to the offending\n// key instead of `never` and fails to compile, naming it in the error.\n\n/** A type that only accepts `never` — see the two assertions below. */\ntype AssertNever<T extends never> = T\n\n/** Every `*Strategy` key the public `createNoydb` options declare. */\ntype OptionStrategyKeys = Extract<keyof NoydbOptions, `${string}Strategy`>\n\n/** What those keys would be if derived from the bag. */\ntype BagOptionKeys = `${StrategyKey}Strategy`\n\n/**\n * Options that are `*Strategy`-shaped but deliberately not services. See the\n * file header for why `coordinationStrategy` is excluded.\n */\ntype NonServiceStrategyOptions = 'coordinationStrategy'\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ntype _EveryOptionHasABagRow = AssertNever<\n Exclude<OptionStrategyKeys, BagOptionKeys | NonServiceStrategyOptions>\n>\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ntype _EveryBagRowHasAnOption = AssertNever<Exclude<BagOptionKeys, OptionStrategyKeys>>\n","/**\n * Lazy factory for the store-backed default {@link CoordinationProvider}.\n * `with-shape/schema-update` is service-layer code the kernel spine may not\n * statically import — the dynamic `import()` below is the port-layering\n * law's sanctioned escape hatch for this exact case.\n */\nimport type { NoydbStore } from '../../kernel/types.js'\nexport type { CoordinationProvider } from './types.js'\n\nexport async function createDefaultCoordinationProvider(store: NoydbStore) {\n const { StoreCoordinationProvider } = await import('../../with-shape/schema-update/store-coordination-provider.js')\n return new StoreCoordinationProvider(store)\n}\n","/**\n * Vault-level registries a collection declaration populates (#841).\n *\n * `Vault.collection()` carried ~70 lines that did nothing but fan a\n * declaration out into ten registries — refs, i18n fields, blob retention,\n * archive policy, attestation schema, the dict/lookup family, and the\n * schema-update names. None of it is orchestration, and all of it obscured\n * the method's actual job.\n *\n * ## Why this is on the port and not in `kernel/`\n *\n * The registry types reach into services — `BlobFieldsConfig`\n * (`with-shape/blobs`) and `ArchivePolicy` (`with-fork/archive`) — and\n * `port-layering` forbids the spine from statically importing a `with-*`\n * module, **including type-only** (the guard scans import statements, not\n * their erasure). Port files may reach services freely, which is why\n * `strategies.ts` and `collection-options.ts` already live here.\n *\n * @internal\n */\n\nimport type { AttestationFieldSchema } from '@noy-db/attestation'\n\nimport type { BlobFieldsConfig } from '../../with-shape/blobs/blob-compaction.js'\nimport type { ArchivePolicy } from '../../with-fork/archive/index.js'\nimport type { OpenCollectionOptions } from './collection-options.js'\nimport { isStaticDictDescriptor, type StaticDictDescriptor } from './i18n-strategy.js'\nimport { collectLookupDictCompat, dictCollectionName, type LookupDescriptor } from './lookup-strategy.js'\n\n/** The via-derived field maps a declaration resolves to before registration. */\nexport interface EffectiveViaFields {\n readonly i18nFields?: Record<string, unknown> | undefined\n readonly dictKeyFields?: Record<string, StaticDictDescriptor | { name: string }> | undefined\n readonly lookupFields?: Record<string, LookupDescriptor<string>> | undefined\n}\n\n/**\n * The ten registries a collection declaration writes into. Passed by\n * reference — these are the Vault's own maps, mutated in place.\n */\nexport interface CollectionRegistries {\n readonly refRegistry: { register(collection: string, refs: Record<string, unknown>): void }\n readonly i18nFieldRegistry: Map<string, unknown>\n readonly blobFieldsRegistry: Map<string, BlobFieldsConfig<unknown>>\n readonly archiveRegistry: Map<string, ArchivePolicy>\n readonly attestation: { register(collection: string, schema: AttestationFieldSchema): void }\n readonly dictKeyFieldRegistry: Map<string, Record<string, string>>\n readonly staticDictNames: Set<string>\n readonly staticByName: Map<string, StaticDictDescriptor>\n readonly staticDescriptorByField: Map<string, Record<string, StaticDictDescriptor>>\n readonly reservedLookupCollections: Map<string, string>\n readonly schemaUpdateNames: Map<string, string[]>\n}\n\n/**\n * Fan a collection declaration out into the vault's registries.\n *\n * Called once, before the `Collection` is constructed, so the first `put()`\n * already sees its refs through `vault.enforceRefsOnPut`.\n */\nexport function populateCollectionRegistries<T>(\n r: CollectionRegistries,\n collectionName: string,\n options: OpenCollectionOptions<T> | undefined,\n effectiveViaFields: EffectiveViaFields,\n): void {\n // Register ref declarations (if any) with the vault-level\n // registry BEFORE constructing the Collection. This way the\n // first put() on the new collection already sees its refs via\n // vault.enforceRefsOnPut.\n if (options?.refs) {\n r.refRegistry.register(collectionName, options.refs)\n }\n\n // Register i18nText fields\n if (effectiveViaFields.i18nFields) {\n r.i18nFieldRegistry.set(collectionName, effectiveViaFields.i18nFields)\n }\n\n // register blobFields retention/TTL policy\n if (options?.blobFields) {\n r.blobFieldsRegistry.set(collectionName, options.blobFields as BlobFieldsConfig<unknown>)\n }\n\n // register record archival policy\n if (options?.archive) {\n r.archiveRegistry.set(collectionName, options.archive as ArchivePolicy)\n }\n\n // register the per-collection attestation field-schema\n if (options?.attestation !== undefined) {\n r.attestation.register(collectionName, options.attestation)\n }\n\n // Register dictKey / staticDict fields. Plain dictKey fields go into\n // the rename-tracking registry; staticDict fields skip it (no\n // per-vault pointer rewrite) and instead populate the static\n // registries that back the read-path resolver, the readonly guard, and\n // put-time code validation. Native lookup()/dict() reserved/static\n // fields fold into the SAME registries (#650 Task 2 — collectLookupDictCompat).\n if (effectiveViaFields.dictKeyFields || effectiveViaFields.lookupFields) {\n const dictFieldMap: Record<string, string> = {}\n const staticFieldMap: Record<string, StaticDictDescriptor> = {}\n for (const [field, desc] of Object.entries(effectiveViaFields.dictKeyFields ?? {})) {\n if (isStaticDictDescriptor(desc)) {\n staticFieldMap[field] = desc\n r.staticDictNames.add(desc.name)\n r.staticByName.set(desc.name, desc)\n } else {\n dictFieldMap[field] = desc.name\n }\n }\n const lookupCompat = collectLookupDictCompat(effectiveViaFields.lookupFields)\n Object.assign(dictFieldMap, lookupCompat.dictFieldMap)\n for (const [field, desc] of lookupCompat.staticEntries) {\n staticFieldMap[field] = desc\n r.staticDictNames.add(desc.name)\n r.staticByName.set(desc.name, desc)\n }\n if (Object.keys(dictFieldMap).length > 0) {\n r.dictKeyFieldRegistry.set(collectionName, dictFieldMap)\n // #650 Task 4 (#647) — declare these dimensions' _dict_* collections into the\n // reserved-lookup sync registry NOW, at schema-declare time — before any local\n // dictionary() call/write/read touches them this session.\n for (const dictName of new Set(Object.values(dictFieldMap))) {\n r.reservedLookupCollections.set(dictCollectionName(dictName), dictName)\n }\n }\n if (Object.keys(staticFieldMap).length > 0) {\n r.staticDescriptorByField.set(collectionName, staticFieldMap)\n }\n }\n\n // Capture registered schema-update strategy names for introspection.\n if ((options?.schemaUpdate?.length ?? 0) > 0) {\n r.schemaUpdateNames.set(collectionName, (options!.schemaUpdate ?? []).map((s) => s.name))\n }\n}\n","import type { ViaBinding, ViaPosture, ViaWriteCtx, ViaReadCtx, ViaCryptoCtx, SealedSlotRef, ViaEraseCtx, ViaEraseReport } from './index.js'\nimport { ValidationError, FieldNotQueryableError } from '../errors.js'\n\n/** Opaque per-clause query payload carried on FieldClause (replaces the money-only slot). */\nexport interface ViaClause {\n readonly brand: string\n readonly payload: unknown\n}\n\n/**\n * The graph-computed taint overlay (#638 Task 3) — `postureFor`'s\n * assignment→enforcement bridge. `postures`/`sealFields` are the\n * enforcement-facing shapes `via/taint-binding.ts#buildTaintOverlay`\n * produces from `ViaGraph.taintedPostures`/`taintSealedFields`;\n * `provenance` (optional — introspection only, never consulted by\n * `postureFor`) is `ViaGraph.taintProvenance`'s output, surfaced by\n * `describe()`.\n */\nexport interface ViaTaintOverlay {\n readonly postures: ReadonlyMap<string, ViaPosture>\n readonly sealFields: ReadonlySet<string>\n readonly provenance?: ReadonlyMap<string, readonly string[]>\n /** #642 — the whole-record floor for a derivation/MV/overlay OUTPUT collection (the '*' target's\n * folded, clamped effective posture). postureFor falls back to it for ANY field; redactForExport\n * picks it up per-field; a sealed default drives taintBinding's sealAllFields mode. O(1) read. */\n readonly defaultPosture?: ViaPosture\n}\n\nexport class ViaPipeline {\n /**\n * Present-phase-ONLY order (#665, corrected under #665 review) — a stable\n * THREE-WAY partition of `bindings` computed once here at construction:\n * every `'money'`-brand binding first (existing relative order), then\n * every `'computed'`-brand binding (existing relative order), then\n * everything else (existing relative order). `present()` folds over this\n * instead of `bindings` so a `mode: 'virtual'` computed field's value\n * exists before i18n/lookup's dressing `present()` hooks run on it\n * (today's `compileViaBindings` order is money→i18n→lookup→classified→\n * blob→computed, `collection-config.ts:554`, so dressing unconditionally\n * ran BEFORE the value it dresses existed). This reorder is binding-level,\n * not conditioned on any particular field composition — it applies to\n * EVERY collection that compiles a `'computed'` binding at all, not only\n * ones stacking a dresser on the SAME field as a computed one. EVERY other\n * phase (`ingest`/`encodeWrite`/`encodeAtRest`/`enforceWrite`/etc.) keeps\n * folding over `bindings` unchanged — those write/query phases need\n * money-first (`_applyMoneyFields` PREPENDS money, `_applyClassifiedFields`\n * APPENDS classified to preserve it, `kernel/collection.ts:1275-1284,1364-\n * 1368`).\n *\n * Money is deliberately carved OUT of the generic \"everything else\" slice\n * and kept FIRST — the original two-way `[computed..., rest...]` partition\n * regressed money's composed-field behavior from a benign missing-dressing\n * gap into VALUE CORRUPTION: money's `present()` DECODES its input as a\n * STORED SCALED-INT (and derives `<field>Formatted` from it) — it is not a\n * pure dressing CONSUMER like i18n/lookup, which only ADD a `<field>Label`\n * key and never rewrite the field's own value. Running money AFTER\n * computed on a field composing `computed(virtual)` + `money(...)` on\n * ITSELF means money's decode sees the virtual field's raw MAJOR-unit\n * output (e.g. `21`) and misreads it as a scaled-int, producing a\n * corrupted value (`'0.21'`) instead of the pre-#665 result (the raw `21`\n * surviving untouched, with no `Formatted` key added — a benign\n * missing-dressing gap, not a wrong value). Money-first restores money's\n * exact pre-#665 present position — byte-identical money behavior; the\n * materialized composition pins from the #631 work and the money suites\n * all ran under money-first. i18n/lookup are genuine dressing consumers\n * (they only ADD, never rewrite), so they stay after computed, which is\n * the fix #665 intended. A `'taint'` binding (appended LAST by\n * `via/graph-wiring.ts#applyTaintOverlay`) stays last here too (it's\n * neither money nor computed, so it lands at the tail of the \"everything\n * else\" slice), preserving its \"runs after computed, redacts tainted\n * virtual output\" contract (`via/taint-binding.ts`'s `taintBinding` doc\n * comment).\n *\n * Money-dressing a virtual computed field's OWN output (the composed\n * `computed(virtual) + money` case) is NOT resolved by this partition\n * alone — #669 resolves it with a separate mid-fold hook instead:\n * `ViaBinding.presentLate` runs after every binding's `present()` in this\n * money+computed segment, before the \"everything else\" segment below, so\n * money can quantize/reinterpret a virtual field's fresh MAJOR-UNITS\n * output as if it were a stored value, without perturbing this ordering\n * or the #665 invariant above it (`_presentLateBoundary` below marks\n * exactly where that mid-fold point sits within `_presentOrder`).\n */\n private readonly _presentOrder: readonly ViaBinding[]\n /** #669 — index into `_presentOrder` where the money+computed segment ends and the\n * \"everything else\" segment begins (`moneyBindings.length + computedBindings.length`);\n * `present()` runs every binding's `presentLate` at exactly this boundary. */\n private readonly _presentLateBoundary: number\n\n private constructor(readonly bindings: readonly ViaBinding[], readonly taint?: ViaTaintOverlay) {\n const moneyBindings = bindings.filter((b) => b.brand === 'money')\n const computedBindings = bindings.filter((b) => b.brand === 'computed')\n const restBindings = bindings.filter((b) => b.brand !== 'money' && b.brand !== 'computed')\n this._presentOrder = [...moneyBindings, ...computedBindings, ...restBindings]\n this._presentLateBoundary = moneyBindings.length + computedBindings.length\n }\n\n /** undefined when there is nothing to enforce — the zero-via fast path is\n * `this.via === undefined` (#553: keeps an all-plain collection sync). A\n * `'*'`-defaulted output collection (#642) counts as \"something to enforce\"\n * even with zero field-specific postures and zero bindings. */\n static build(bindings: readonly ViaBinding[], taint?: ViaTaintOverlay): ViaPipeline | undefined {\n if (bindings.length === 0 && (!taint || (taint.postures.size === 0 && taint.defaultPosture === undefined))) return undefined\n return new ViaPipeline(bindings, taint)\n }\n\n /** Refuse a write before crypto runs: awaits each binding's `enforceWrite` in order — first throw wins. */\n async enforceWrite(record: Record<string, unknown>, ctx: ViaWriteCtx): Promise<void> {\n for (const b of this.bindings) if (b.enforceWrite) await b.enforceWrite(record, ctx)\n }\n\n ingest(record: Record<string, unknown>): Record<string, unknown> {\n let r = record\n for (const b of this.bindings) if (b.ingest) r = b.ingest(r)\n return r\n }\n\n canonicalizeStored(record: Record<string, unknown>): Record<string, unknown> {\n let r = record\n for (const b of this.bindings) if (b.canonicalizeStored) r = b.canonicalizeStored(r)\n return r\n }\n\n async encodeWrite(record: Record<string, unknown>, ctx: ViaWriteCtx): Promise<Record<string, unknown>> {\n let r = record\n for (const b of this.bindings) if (b.encodeWrite) r = await b.encodeWrite(r, ctx)\n return r\n }\n\n /**\n * Final write-pipeline stage: folds each binding's `encodeAtRest` in\n * order, threading the record and accumulating the sealed-slot map. A\n * field belongs to exactly one via feature — two bindings sealing the\n * same field is a brand-keyed collision and throws.\n */\n async encodeAtRest(\n record: Record<string, unknown>,\n crypto: ViaCryptoCtx,\n ): Promise<{ record: Record<string, unknown>; sealed?: Record<string, SealedSlotRef> }> {\n let r = record\n let sealed: Record<string, SealedSlotRef> | undefined\n const sealedBy = new Map<string, string>()\n for (const b of this.bindings) {\n if (!b.encodeAtRest) continue\n const result = await b.encodeAtRest(r, crypto)\n r = result.record\n if (!result.sealed) continue\n for (const [field, ref] of Object.entries(result.sealed)) {\n const priorBrand = sealedBy.get(field)\n if (priorBrand !== undefined) {\n throw new ValidationError(\n `via encodeAtRest: field \"${field}\" sealed by binding \"${priorBrand}\" is also sealed by binding \"${b.brand}\"`,\n )\n }\n sealedBy.set(field, b.brand)\n sealed ??= {}\n sealed[field] = ref\n }\n }\n return sealed ? { record: r, sealed } : { record: r }\n }\n\n /** First read-pipeline stage: folds each binding's `decodeAtRest` in order. */\n async decodeAtRest(\n record: Record<string, unknown>,\n sealed: Record<string, SealedSlotRef>,\n crypto: ViaCryptoCtx,\n opts: { asHandles: boolean },\n ): Promise<Record<string, unknown>> {\n let r = record\n for (const b of this.bindings) if (b.decodeAtRest) r = await b.decodeAtRest(r, sealed, crypto, opts)\n return r\n }\n\n async present(record: Record<string, unknown>, ctx: ViaReadCtx): Promise<Record<string, unknown>> {\n let r = record\n for (let i = 0; i < this._presentLateBoundary; i++) {\n const b = this._presentOrder[i]!\n if (b.present) r = await b.present(r, ctx)\n }\n for (const b of this.bindings) if (b.presentLate) r = await b.presentLate(r, ctx)\n for (let i = this._presentLateBoundary; i < this._presentOrder.length; i++) {\n const b = this._presentOrder[i]!\n if (b.present) r = await b.present(r, ctx)\n }\n return r\n }\n\n buildClause(field: string, op: string, value: unknown): ViaClause | undefined {\n for (const b of this.bindings) {\n const payload = b.buildClause?.(field, op, value)\n if (payload !== undefined) return { brand: b.brand, payload }\n }\n return undefined\n }\n\n evaluateClause(clause: ViaClause, actual: unknown, op: string): boolean {\n const b = this.bindings.find((x) => x.brand === clause.brand)\n // buildClause and evaluateClause are produced/consumed by the same binding by construction.\n return b?.evaluateClause ? b.evaluateClause(actual, op, clause.payload) : false\n }\n\n /**\n * Resolve a `buildClause` payload to an index-probe operand (#625) —\n * mirrors `evaluateClause`'s brand dispatch. `undefined` (a binding\n * with no `indexProbe`, or one that declines to probe this op/payload)\n * means the caller (`candidateRecords()`) must fall back to a scan.\n */\n // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents\n indexProbe(clause: ViaClause, op: string): unknown | undefined {\n const b = this.bindings.find((x) => x.brand === clause.brand)\n return b?.indexProbe ? b.indexProbe(op, clause.payload) : undefined\n }\n\n /**\n * Resolve a raw STORED field value to its canonical eager-index bucket\n * key (#672) — folds every binding's `canonicalizeIndexKey`, first\n * non-undefined wins (same fold discipline as `buildClause`). `undefined`\n * means no binding claims `field` (or the value can't be canonicalized)\n * — the caller buckets the raw stringified value, unchanged from before\n * this hook existed.\n */\n canonicalizeIndexKey(field: string, rawValue: unknown): string | undefined {\n for (const b of this.bindings) {\n const key = b.canonicalizeIndexKey?.(field, rawValue)\n if (key !== undefined) return key\n }\n return undefined\n }\n\n decodeResults(record: unknown): unknown {\n let r = record\n for (const b of this.bindings) if (b.decodeResults) r = b.decodeResults(r)\n return r\n }\n\n /** undefined = no binding covers the field → caller falls back to generic compare. */\n compareForOrder(field: string, a: unknown, b: unknown): number | undefined {\n for (const bind of this.bindings) {\n const c = bind.compareForOrder?.(field, a, b)\n if (c !== undefined) return c\n }\n return undefined\n }\n\n /** undefined = no binding resolves an order-sort label for `key` at `field`/`locale` (#650 Task 7 —\n * the `orderBy(..., {by:'label'})` per-call-locale channel `compareForOrder` above can't serve). */\n resolveOrderLabel(field: string, key: string, locale: string | undefined): string | undefined {\n for (const bind of this.bindings) {\n const label = bind.resolveOrderLabel?.(field, key, locale)\n if (label !== undefined) return label\n }\n return undefined\n }\n\n /**\n * Which posture governs `field`, if any binding covers it — `undefined`\n * means no binding declares `field` (the generic, non-via query path\n * applies). #629 Task 8's posture consumer: `.where()`/`.orderBy()`\n * consult this before building/evaluating a clause, refusing fields whose\n * posture is `queryable: 'none'` (e.g. blob); every other posture\n * ('det-exact'/'ordered'/'full') is left to the existing per-binding\n * buildClause/evaluateClause/compareForOrder machinery, unchanged.\n *\n * #638 Task 3: the graph-computed taint overlay is consulted FIRST — a\n * derived field's assigned (most-restrictive-of-sources) posture wins over\n * whatever a binding would otherwise report for that field name (no\n * binding covers a computed/derived field today, so this never actually\n * shadows one — see `via/taint-binding.ts`'s `taintBinding.covers`, which\n * only claims the sealed subset for `encodeAtRest`/`decodeAtRest`, not for\n * this lookup).\n */\n postureFor(field: string): ViaPosture | undefined {\n const t = this.taint?.postures.get(field)\n if (t) return t\n for (const b of this.bindings) {\n if (b.covers?.(field)) return b.posture\n }\n // #642 — a '*'-defaulted output collection's whole-record floor: O(1) read,\n // no fold (the fold ran once at applyTaintOverlay/reapply time).\n return this.taint?.defaultPosture\n }\n\n /**\n * Refuse any field-based reducer over a `queryable: 'none'` field (blob) —\n * metadata-only: walks each reducer's `.field` and checks posture, no\n * rewriting. Reducers with no `.field` (e.g. `count()`) are skipped.\n *\n * Shared by `wrapReducers` below (which ALSO applies each binding's\n * rewrite, e.g. money's exact-BigInt reducer swap) and by\n * `ScanBuilder.aggregate()` (#629 Task 8 review fix wave 1), which must\n * call THIS, not `wrapReducers` — wiring full `wrapReducers` into\n * `ScanBuilder.aggregate()` would newly activate money/i18n reducer\n * wrapping on a path that has never run it, a parity-breaking behavior\n * change for existing brands.\n */\n refuseUnqueryableReducers<S>(spec: S): void {\n for (const reducer of Object.values(spec as unknown as Record<string, { readonly field?: string }>)) {\n const field = reducer?.field\n if (field !== undefined && this.postureFor(field)?.queryable === 'none') {\n throw new FieldNotQueryableError(field)\n }\n }\n }\n\n /**\n * Rewrite an aggregate spec (money exact reducers), then refuse any\n * field-based reducer over a `queryable: 'none'` field (blob) — the same\n * posture gate `.where()`/`.orderBy()` apply, extended to `.aggregate()`\n * (both the bare-spec and builder forms funnel through here).\n */\n wrapReducers<S>(spec: S): S {\n this.refuseUnqueryableReducers(spec)\n let s: unknown = spec\n for (const b of this.bindings) if (b.wrapReducers) s = b.wrapReducers(s)\n return s as S\n }\n\n /**\n * Deliberate export-layer redaction (#629 Task 9's posture consumer):\n * for every OWN field the decoded record carries, if the covering\n * binding's posture declares `exportable: false` (classified today;\n * money/i18n/blob are all `true`), replace the value with\n * {@link EXPORT_REDACTION_MARKER} — the same `'[sealed]'` string\n * `SealedHandle.toJSON()` (`kernel/types.ts`) already emits, so this is\n * byte-parity with today's accidental redaction, now independent of the\n * field's runtime shape. `SealedHandle.toJSON()` stays untouched as\n * defense-in-depth: a record read via `collection.get()` and\n * JSON.stringify'd outside `exportStream()` still gets the accident's\n * redaction on its own. Never mutates the input; returns a new object\n * only when a field was actually redacted.\n */\n redactForExport(record: Record<string, unknown>): Record<string, unknown> {\n let out: Record<string, unknown> | undefined\n for (const field of Object.keys(record)) {\n if (this.postureFor(field)?.exportable === false) {\n out ??= { ...record }\n out[field] = EXPORT_REDACTION_MARKER\n }\n }\n return out ?? record\n }\n\n /**\n * Shared fold over a subset of `this.bindings`: runs each binding's\n * `erase`, concatenating shredded/retainedShared counts and residue.\n * Consults `posture.forgettable` (#629 Task 10) — a binding declaring\n * `forgettable: false` is skipped even if it defines `erase` (none does\n * today; a future non-forgettable binding is supported without a brand check).\n */\n private async foldErase(ctx: ViaEraseCtx, bindings: readonly ViaBinding[]): Promise<ViaEraseReport> {\n let shredded = 0\n let retainedShared = 0\n const residue: unknown[] = []\n for (const b of bindings) {\n if (!b.erase || b.posture.forgettable === false) continue\n const report = await b.erase(ctx)\n shredded += report.shredded\n retainedShared += report.retainedShared ?? 0\n residue.push(...report.residue)\n }\n return retainedShared > 0 ? { shredded, residue, retainedShared } : { shredded, residue }\n }\n\n /** `forget()`'s per-ref erasure door: folds every binding's `erase`. */\n async erase(ctx: ViaEraseCtx): Promise<ViaEraseReport> {\n return this.foldErase(ctx, this.bindings)\n }\n\n /**\n * `forget()`'s SEALED-posture-only erase fold (#629 Task 10, `Collection._onViaErase`'s\n * one caller) — classified today; metadata-filtered on\n * `posture.encryptedAtRest`, not brand-checked. `undefined` when no\n * sealed-posture binding is compiled in — `vault.ts` then falls back to\n * its own bare-`sensitive` classification, which no via binding covers.\n */\n async eraseSealed(ctx: ViaEraseCtx): Promise<ViaEraseReport | undefined> {\n const sealed = this.bindings.filter((b) => b.posture.encryptedAtRest === 'sealed')\n return sealed.length === 0 ? undefined : this.foldErase(ctx, sealed)\n }\n\n /** True iff any binding implements decodeResults (query fast-path gating). */\n get hasResultDecode(): boolean {\n return this.bindings.some((b) => b.decodeResults !== undefined)\n }\n\n /**\n * True iff any binding declares an at-rest hook (`encodeAtRest`/\n * `decodeAtRest`) — the codec boundary's async-stack gate (#629 Task 3\n * consults this to choose between the hook path and today's inline\n * sealed-slot path; a stack with only sync hooks, e.g. money-only, stays\n * `false`).\n */\n get hasAtRestHooks(): boolean {\n return this.bindings.some((b) => b.encodeAtRest !== undefined || b.decodeAtRest !== undefined)\n }\n\n /**\n * Fold every binding's `describeFragment()` into one `brand -> fragment`\n * map (#650 Task 7 — the first-ever consumer; `describeFragment` was\n * declared at `via/index.ts:136` since #623 with zero callers until this task).\n * `undefined` when no compiled binding implements it. Consumed by\n * `Collection.describe()`/`describeAsync()`, threaded to `buildDescription`\n * as `BuildDescriptionInput.viaFragments`.\n */\n describeFragments(): Record<string, Record<string, unknown>> | undefined {\n let out: Record<string, Record<string, unknown>> | undefined\n for (const b of this.bindings) {\n const f = b.describeFragment?.()\n if (f !== undefined) { out ??= {}; out[b.brand] = f }\n }\n return out\n }\n}\n\n/**\n * The marker `redactForExport` writes for a non-exportable field —\n * intentionally the same literal `SealedHandle.toJSON()` (`kernel/types.ts`)\n * returns, so the two independent redaction layers (deliberate + accident)\n * produce byte-identical export output. Duplicated, not imported, because\n * `SealedHandle.toJSON()` is untouched by #629 Task 9 (belt-and-braces —\n * `via/export-posture-b.test.ts` asserts both layers agree on this string).\n */\nexport const EXPORT_REDACTION_MARKER = '[sealed]'\n\n/**\n * Structural shape `exportRedact` needs from a collection: just the typed\n * `_via` accessor `Collection` exposes (`kernel/collection.ts`, #634). A\n * named interface rather than the real `Collection` type, because\n * `collection.ts` imports `ViaPipeline` from this module — importing\n * `Collection` back here would be circular.\n */\ninterface HasViaPipeline {\n readonly _via: ViaPipeline | undefined\n}\n\n/**\n * Widened sibling of {@link HasViaPipeline}: `via/graph-wiring.ts`'s\n * `applyTaintOverlay` (#666) needs to REASSIGN the live pipeline, not just\n * read it — `_setVia` is `Collection`'s typed writer seam (`kernel/\n * collection.ts`, beside `_via`), replacing the earlier untyped `coll as {\n * via; codec: { setVia } }` cast. Exported (unlike `HasViaPipeline`) because\n * its one consumer lives in a different module.\n */\nexport interface HasWritableViaPipeline extends HasViaPipeline {\n _setVia(pipeline: ViaPipeline | undefined): void\n}\n\n/**\n * `vault.ts`'s `exportStream()` reach-in (#629 Task 9): apply the owning\n * collection's export redaction to one decoded record. Typed via {@link\n * HasViaPipeline} against `Collection`'s `_via` accessor (#634) — replaces\n * the earlier untyped any-cast reach-in.\n */\nexport function exportRedact(coll: HasViaPipeline, record: unknown): unknown {\n if (record === null || typeof record !== 'object') return record\n const via = coll._via\n return via ? via.redactForExport(record as Record<string, unknown>) : record\n}\n","/**\n * Lazy-mode `count()` support (#706): count ids whose envelope is LIVE at\n * tier 0 — parity with eager count (the hydrated cache excludes tombstones,\n * delete markers, and elevated records, #701). Envelope inspection only —\n * no record body is ever decrypted here.\n *\n * #713: when the adapter implements the optional `listPage`, page through\n * it and apply the same predicate to each page's envelopes — one\n * round-trip per page instead of one `list()` + one `get()` per id. Stores\n * without `listPage` keep the original N+1 loop.\n */\nimport type { EncryptedEnvelope, NoydbStore } from './types.js'\nimport { isTombstone, isDeleteMarker } from './enclave/index.js'\n\n/** Page size for the listPage batching path (#713). */\nconst COUNT_PAGE_SIZE = 1000\n\nfunction isLive(env: EncryptedEnvelope | null, storeCiphertext: boolean): boolean {\n return !!env && !isTombstone(env, storeCiphertext) && !isDeleteMarker(env) && (env._tier ?? 0) === 0\n}\n\nexport async function countLiveEnvelopes(\n adapter: NoydbStore, vault: string, name: string, storeCiphertext: boolean,\n): Promise<number> {\n let n = 0\n if (adapter.listPage) {\n let cursor: string | undefined\n let page = await adapter.listPage(vault, name, cursor, COUNT_PAGE_SIZE)\n while (true) {\n for (const { envelope } of page.items) {\n if (isLive(envelope, storeCiphertext)) n++\n }\n if (page.nextCursor === null) break\n cursor = page.nextCursor\n page = await adapter.listPage(vault, name, cursor, COUNT_PAGE_SIZE)\n }\n return n\n }\n const ids = await adapter.list(vault, name)\n for (const id of ids) {\n const env = await adapter.get(vault, name, id)\n if (isLive(env, storeCiphertext)) n++\n }\n return n\n}\n","/**\n * Collection-level index maintenance — the eager/unique rebuild-from-cache\n * helpers, the full `rebuildIndexes` / `reconcileIndex` repair surface, and the\n * persisted `_idx/<field>/<recordId>` side-car maintenance fired from the write\n * path.\n *\n * Eager mode keeps an in-memory `CollectionIndexes` + `UniqueConstraintSet`;\n * lazy mode keeps durable encrypted side-cars whose in-memory mirror is a\n * `PersistedCollectionIndex`. These functions write/repair both. The unique-\n * constraint correctness and the side-car drift reconciliation are the parts to\n * watch: behaviour here is byte-identical to the inline code it replaced.\n *\n * Every function takes a small {@link IndexingContext} (the exact `this.*` the\n * moving methods touched) instead of `this`, mirroring the `record-keys/`\n * siblings. The eager `cache` Map and the three index/constraint mirror objects\n * are passed by reference (the SAME instances `Collection` owns, never copied)\n * so maintenance always mutates the live mirrors the query path reads. The\n * `persistedIndexesLoaded` flag and `ensure*` hydration stay collection-resident\n * and are reached via callbacks.\n *\n * Internal service — not exported as a `@noy-db/hub/*` subpath.\n */\nimport type { NoydbStore, EncryptedEnvelope } from '../../kernel/types.js'\nimport type { RecordCodec } from '../../kernel/enclave/index.js'\nimport type { NoydbEventEmitter } from '../../kernel/events.js'\nimport { IndexWriteFailureError } from '../../kernel/errors.js'\nimport type { CollectionIndexes } from './eager-indexes.js'\nimport type { UniqueConstraintSet } from './unique-constraints.js'\nimport { encodeIdxId, decodeIdxId, type PersistedCollectionIndex, type PersistedIndexDef } from './persisted-indexes.js'\n\n/** Everything the moving index-maintenance methods touched on `this.*`. */\nexport interface IndexingContext<T> {\n /** Collection name — the canonical record namespace + error context. */\n readonly name: string\n /** Vault namespace the records + side-cars live under. */\n readonly vault: string\n /** The ciphertext store. */\n readonly adapter: NoydbStore\n /** The record codec — decrypts records + side-car bodies, encrypts side-cars. */\n readonly codec: RecordCodec<T>\n /** The eager working-set cache (SHARED `Map` reference, never copied). */\n readonly cache: Map<string, { record: T; version: number }>\n /** True in lazy mode — eager rebuild short-circuits, reconcile requires it. */\n readonly lazy: boolean\n /** Event emitter — surfaces `index:write-partial` on side-car write failure. */\n readonly emitter: NoydbEventEmitter\n /** The in-memory eager index mirror, or null (SHARED reference). */\n readonly indexes: CollectionIndexes | null\n /** The in-memory unique-constraint mirror, or null (SHARED reference). */\n readonly uniqueConstraints: UniqueConstraintSet | null\n /** The lazy-mode persisted-index mirror, or null (SHARED reference). */\n readonly persistedIndexes: PersistedCollectionIndex | null\n /** Hydrate the eager cache before rebuilding from it. */\n ensureHydrated(): Promise<void>\n /** Bulk-load the persisted-index mirror from side-cars (lazy mode). */\n ensurePersistedIndexesLoaded(): Promise<void>\n /** Set the collection-resident `persistedIndexesLoaded` flag. */\n setPersistedIndexesLoaded(value: boolean): void\n}\n\n/**\n * Read a field value from a plain record for persisted-index maintenance.\n * Supports dotted paths so declarations like `indexes: ['billing.clientId']`\n * work the same way `readPath` handles them for the eager-mode builder.\n */\nfunction readPersistedValue(record: Record<string, unknown>, field: string): unknown {\n if (!field.includes('.')) return record[field]\n const segments = field.split('.')\n let cursor: unknown = record\n for (const segment of segments) {\n if (cursor === null || cursor === undefined) return undefined\n cursor = (cursor as Record<string, unknown>)[segment]\n }\n return cursor\n}\n\n/**\n * Canonicalize a typed value for storage inside the side-car body so it\n * round-trips through `JSON.parse` without losing fidelity. Dates are\n * serialised as ISO strings; everything else passes through.\n *\n * The in-memory mirror compares on the stringified bucket key, so the\n * exact storage form is not query-critical — this just protects the\n * reconciler, which compares the stored body against the\n * live record value and would otherwise mismatch on Date objects.\n */\nfunction serializeIndexValue(value: unknown): unknown {\n if (value instanceof Date) return value.toISOString()\n return value\n}\n\n/**\n * Extract the indexable value for a declaration — a scalar for\n * single-field, or a tuple array for composite. Returns `null` when\n * the value is not indexable (single-field null/undefined, composite\n * with any null/undefined component — the whole composite is skipped\n * if any part is missing).\n */\nfunction extractIndexValue(\n record: Record<string, unknown>,\n def: PersistedIndexDef,\n): unknown {\n if (def.kind === 'single') {\n const v = readPersistedValue(record, def.field)\n return v === undefined || v === null ? null : v\n }\n const tuple: unknown[] = []\n for (const f of def.fields) {\n const v = readPersistedValue(record, f)\n if (v === undefined || v === null) return null\n tuple.push(v)\n }\n return tuple\n}\n\n/**\n * Compare the decrypted side-car body's `value` against the live record\n * field value, in the same canonical form used for storage. Handles the\n * Date-is-ISO-string round trip so reconcile doesn't flag a false drift.\n */\nfunction valuesMatch(stored: unknown, live: unknown): boolean {\n const serialized = serializeIndexValue(live)\n if (stored === serialized) return true\n if (stored === undefined || serialized === undefined) return stored === serialized\n // JSON-stringify both sides for structural equality on arrays/objects.\n try {\n return JSON.stringify(stored) === JSON.stringify(serialized)\n } catch {\n return false\n }\n}\n\n/**\n * Rebuild the eager in-memory `CollectionIndexes` from the current cache.\n * Called after any bulk hydration; incremental put/delete updates go through\n * `indexes.upsert()`/`.remove()` directly, so this only fires for full reloads.\n */\nexport function rebuildEagerIndexesFromCache<T>(ctx: IndexingContext<T>): void {\n const eager = ctx.indexes\n if (!eager || eager.fields().length === 0) return\n const snapshot: Array<{ id: string; record: T }> = []\n for (const [id, entry] of ctx.cache) {\n snapshot.push({ id, record: entry.record })\n }\n eager.build(snapshot)\n}\n\n/**\n * Rebuild unique-constraint maps from the current in-memory cache.\n * Called after any bulk hydration alongside `rebuildEagerIndexesFromCache`.\n */\nexport function rebuildUniqueConstraintsFromCache<T>(ctx: IndexingContext<T>): void {\n if (!ctx.uniqueConstraints) return\n ctx.uniqueConstraints.build(\n (function* (cache: Map<string, { record: T }>) {\n for (const [id, entry] of cache) yield [id, entry.record] as const\n })(ctx.cache),\n )\n}\n\n/**\n * Rebuild every declared index from scratch — eager refresh from cache, or a\n * full lazy-mode side-car teardown + rewrite. NOT incremental; for per-field\n * drift repair use {@link reconcileIndex}.\n */\nexport async function rebuildIndexes<T>(ctx: IndexingContext<T>): Promise<void> {\n if (!ctx.lazy) {\n await ctx.ensureHydrated()\n rebuildEagerIndexesFromCache(ctx)\n return\n }\n\n const persisted = ctx.persistedIndexes\n if (!persisted) return\n const fields = persisted.fields()\n if (fields.length === 0) return\n\n // 1. Collect canonical ids (skip every reserved-namespace id —\n // `_idx/`, `_keyring`, `_history/`, `_ledger_deltas/`, `_meta/`,\n // `_ledger`, `_blob_`, etc. User records may not start with `_`\n // per the monorepo convention used across the hub).\n const allIds = await ctx.adapter.list(ctx.vault, ctx.name)\n const canonicalIds: string[] = []\n const staleIdxIds: string[] = []\n for (const id of allIds) {\n if (decodeIdxId(id)) {\n staleIdxIds.push(id)\n } else if (!id.startsWith('_')) {\n canonicalIds.push(id)\n }\n }\n\n // 2. Drop every existing side-car. Errors here are tolerated — the\n // next step overwrites any remnants. If a side-car is for a\n // field that is no longer declared, the delete still removes\n // the stale row from storage.\n for (const id of staleIdxIds) {\n try { await ctx.adapter.delete(ctx.vault, ctx.name, id) } catch { /* ignore */ }\n }\n persisted.clear()\n\n // 3. Walk records and write fresh side-cars for every declared field.\n for (const recordId of canonicalIds) {\n const envelope = await ctx.adapter.get(ctx.vault, ctx.name, recordId)\n if (!envelope) continue\n // #709: an elevated record must not be (re)indexed — the sidecar stores the\n // PLAINTEXT field value under the tier-0 DEK, so minting one here would\n // publish what elevation is meant to hide. Gate BEFORE the decrypt: a warm\n // cekCache would otherwise let it succeed (and a cold session throw).\n if ((envelope._tier ?? 0) > 0) continue\n const record = await ctx.codec.decryptRecord(envelope, { skipValidation: true, id: recordId })\n if (record === null) continue // shredded (tombstone) — no side-car to build\n await maintainPersistedIndexesOnPut(ctx, recordId, record, null, envelope._v)\n }\n\n ctx.setPersistedIndexesLoaded(true)\n}\n\n/**\n * Compare the persisted `_idx/<field>/*` side-cars against the canonical\n * records for a single field, reporting the drift (and optionally repairing\n * it). Lazy mode only — eager mode throws (the in-memory index cannot drift).\n */\nexport async function reconcileIndex<T>(\n ctx: IndexingContext<T>,\n field: string,\n opts: { dryRun?: boolean } = {},\n): Promise<{ field: string; missing: string[]; stale: string[]; applied: number }> {\n if (!ctx.lazy) {\n throw new Error(\n `Collection \"${ctx.name}\": reconcileIndex is only meaningful in lazy mode ` +\n `(prefetch: false). Eager mode maintains indexes in memory with no drift.`,\n )\n }\n const persisted = ctx.persistedIndexes\n if (!persisted) {\n throw new Error(\n `Collection \"${ctx.name}\": indexing is disabled on this Noydb instance. ` +\n `Pass \\`withIndexing()\\` from \"@noy-db/hub/indexing\" to \\`createNoydb({ indexingStrategy })\\`.`,\n )\n }\n if (!persisted.has(field)) {\n throw new Error(\n `Collection \"${ctx.name}\": field \"${field}\" is not declared in indexes. ` +\n `Declare it in the collection options before reconciling.`,\n )\n }\n\n const dryRun = opts.dryRun === true\n const allIds = await ctx.adapter.list(ctx.vault, ctx.name)\n\n // Map side-car recordId → stored value (if readable). Also capture\n // \"stale\" side-cars whose field matches but whose record is gone.\n const sidecar = new Map<string, unknown>()\n const sidecarIds = new Map<string, string>() // recordId -> sidecar id\n for (const id of allIds) {\n const decoded = decodeIdxId(id)\n if (!decoded || decoded.field !== field) continue\n sidecarIds.set(decoded.recordId, id)\n const env = await ctx.adapter.get(ctx.vault, ctx.name, id)\n if (!env) continue\n try {\n const sidecarJson = await ctx.codec.decryptJsonString(env)\n if (sidecarJson === null) {\n // Tombstone side-car (shredded) — treat as stale so it's rewritten.\n sidecar.set(decoded.recordId, undefined)\n } else {\n const body = JSON.parse(sidecarJson) as { value: unknown }\n sidecar.set(decoded.recordId, body.value)\n }\n } catch {\n // Unreadable — treat as stale so it gets rewritten.\n sidecar.set(decoded.recordId, undefined)\n }\n }\n\n // Walk canonical records and compare against side-car state.\n const missing: string[] = []\n const stale: string[] = []\n const fixesPut: Array<{ recordId: string; record: T; version: number }> = []\n for (const id of allIds) {\n if (decodeIdxId(id)) continue\n if (id.startsWith('_')) continue\n const env = await ctx.adapter.get(ctx.vault, ctx.name, id)\n if (!env) continue\n if ((env._tier ?? 0) > 0) continue // #709: skip elevated records — see rebuildIndexes' gate above\n const record = await ctx.codec.decryptRecord(env, { skipValidation: true, id })\n // Shredded (tombstone) canonical record: treat like a vanished record —\n // leave its `id` in `sidecarIds` so any lingering side-car is marked\n // stale (and deleted) by the leftover loop below.\n if (record === null) continue\n const live = readPersistedValue(record as unknown as Record<string, unknown>, field)\n const stored = sidecar.get(id)\n const hasSidecar = sidecarIds.has(id)\n const indexable = live !== null && live !== undefined\n\n if (indexable && !hasSidecar) {\n missing.push(id)\n fixesPut.push({ recordId: id, record, version: env._v })\n } else if (indexable && hasSidecar && !valuesMatch(stored, live)) {\n // Side-car body drifted from live value (e.g. partial write\n // after an update). Rewrite so lookups agree with reality.\n missing.push(id)\n fixesPut.push({ recordId: id, record, version: env._v })\n } else if (!indexable && hasSidecar) {\n // Record exists but its value is no longer indexable (null/\n // undefined). The side-car is stale.\n stale.push(sidecarIds.get(id)!)\n }\n sidecarIds.delete(id)\n }\n // Any side-car whose canonical record vanished is stale.\n for (const [, idxId] of sidecarIds) stale.push(idxId)\n\n let applied = 0\n if (!dryRun) {\n for (const idxId of stale) {\n try {\n await ctx.adapter.delete(ctx.vault, ctx.name, idxId)\n applied++\n } catch { /* ignore — next reconcile picks it up */ }\n }\n for (const fix of fixesPut) {\n await maintainPersistedIndexesOnPut(ctx, fix.recordId, fix.record, null, fix.version)\n applied++\n }\n // In-memory mirror is authoritative for query dispatch — make\n // sure it matches what's on disk now.\n persisted.clear()\n ctx.setPersistedIndexesLoaded(false)\n await ctx.ensurePersistedIndexesLoaded()\n }\n\n return { field, missing, stale, applied }\n}\n\n/**\n * Write / update / delete the `_idx/<field>/<recordId>` side-cars for every\n * declared persistence-index field after a successful main-record `put()`.\n * Called AFTER `adapter.put()` of the main record succeeds; side-car write\n * failures surface as `index:write-partial` and do NOT fail the put.\n */\nexport async function maintainPersistedIndexesOnPut<T>(\n ctx: IndexingContext<T>,\n id: string,\n newRecord: T,\n previousRecord: T | null,\n version: number,\n): Promise<void> {\n const persisted = ctx.persistedIndexes\n if (!persisted) return\n const defs = persisted.definitions()\n if (defs.length === 0) return\n\n const newRec = newRecord as unknown as Record<string, unknown>\n const prevRec = previousRecord as unknown as Record<string, unknown> | null\n\n for (const def of defs) {\n const newValue = extractIndexValue(newRec, def)\n const previousValue = prevRec ? extractIndexValue(prevRec, def) : null\n\n // Update the in-memory mirror first — it's the authoritative source\n // for query dispatch. If the adapter write below fails, the mirror\n // still reflects intended state; the reconciler compares mirror\n // against side-cars on next run.\n persisted.upsert(id, def.key, newValue, previousValue)\n\n const idxId = encodeIdxId(def.key, id)\n try {\n if (newValue === null || newValue === undefined) {\n // Clear any pre-existing side-car for this (field, record).\n if (previousValue !== null && previousValue !== undefined) {\n await ctx.adapter.delete(ctx.vault, ctx.name, idxId)\n }\n } else {\n const body = JSON.stringify({\n field: def.key,\n value: serializeIndexValue(newValue),\n recordId: id,\n writtenAt: new Date().toISOString(),\n })\n const envelope = await ctx.codec.encryptJsonString(body, version)\n await ctx.adapter.put(ctx.vault, ctx.name, idxId, envelope)\n }\n } catch (cause) {\n ctx.emitter.emit('index:write-partial', {\n vault: ctx.vault,\n collection: ctx.name,\n id,\n action: 'put',\n error: new IndexWriteFailureError({ recordId: id, field: def.key, op: 'put', cause }),\n })\n }\n }\n}\n\n/**\n * Tear down `_idx/<field>/<recordId>` side-cars for a deleted record.\n * Mirror state updates regardless of adapter outcome; adapter failures\n * surface on `index:write-partial` the same way put does.\n */\nexport async function maintainPersistedIndexesOnDelete<T>(ctx: IndexingContext<T>, id: string, previousRecord: T): Promise<void> {\n const persisted = ctx.persistedIndexes\n if (!persisted) return\n const defs = persisted.definitions()\n if (defs.length === 0) return\n\n const prevRec = previousRecord as unknown as Record<string, unknown>\n for (const def of defs) {\n const previousValue = extractIndexValue(prevRec, def)\n if (previousValue !== null && previousValue !== undefined) {\n persisted.remove(id, def.key, previousValue)\n }\n\n const idxId = encodeIdxId(def.key, id)\n try {\n await ctx.adapter.delete(ctx.vault, ctx.name, idxId)\n } catch (cause) {\n ctx.emitter.emit('index:write-partial', {\n vault: ctx.vault,\n collection: ctx.name,\n id,\n action: 'delete',\n error: new IndexWriteFailureError({ recordId: id, field: def.key, op: 'delete', cause }),\n })\n }\n }\n}\n\n/**\n * @internal — hard-delete this record's persisted `_idx/<field>/<recordId>`\n * side-cars for the erasure path. `forget()` crypto-shreds the body but\n * keeps the collection DEK, under which these side-cars are encrypted — so\n * without this they leave the indexed field VALUES readable after a \"forget\".\n *\n * Content-free: the side-car id is `encodeIdxId(def.key, id)`, so it needs no\n * body decode (the body is being shredded). Eager mode has no durable side-car\n * → no-op. The in-memory mirror is left as-is: it is ephemeral (rebuilt from\n * the now-deleted side-cars on reopen) and live reads skip the tombstone, so a\n * stale mirror hit cannot surface the erased record. Returns the count deleted\n * + the `def.key`s whose delete FAILED (residue that still leaks the value).\n */\nexport async function purgePersistedIndexes<T>(ctx: IndexingContext<T>, id: string): Promise<{ purged: number; residue: string[] }> {\n const persisted = ctx.persistedIndexes\n if (!persisted) return { purged: 0, residue: [] }\n let purged = 0\n const residue: string[] = []\n for (const def of persisted.definitions()) {\n try {\n await ctx.adapter.delete(ctx.vault, ctx.name, encodeIdxId(def.key, id))\n purged++\n } catch {\n residue.push(def.key)\n }\n }\n return { purged, residue }\n}\n\n/**\n * Sync this collection's indexes after a tier move (#709). Persisted\n * `_idx/<field>/<recordId>` side-cars are always encrypted under the\n * tier-0 DEK regardless of the record's own tier, and the eager in-memory\n * `CollectionIndexes` mirror holds plaintext bucket values too — so both\n * leak an elevated record's indexed field values unless swept the same way\n * `purgePersistedIndexes` already sweeps them for `forget()` (\"forget()\n * crypto-shreds the body but keeps the collection DEK, under which these\n * side-cars are encrypted — so without this they leave the indexed field\n * VALUES readable\", `purgePersistedIndexes` above).\n *\n * `record === null` — the record just left tier 0: purge its persisted\n * side-cars (content-free, no decrypt needed) and drop its eager-mirror\n * entry, read from `ctx.cache` (the caller's pre-write value — the caller\n * MUST invoke this before evicting/overwriting that cache entry, so it\n * still reflects the value being replaced).\n *\n * `record` given — the record is tier-0 again: (re)build its entries from\n * that record, using the SAME pre-write `ctx.cache` read as the previous\n * value so a stale bucket (e.g. a same-tier `putAtTier` value change) is\n * cleaned up rather than left as a false-positive hit. `version` stamps\n * the rebuilt side-car's own envelope version.\n *\n * `priorEnvelope` (#720) — the RAW envelope the caller read BEFORE its own\n * overwrite landed (`putAtTier`'s `existing` / `demote`'s pre-move\n * `envelope`), for the `ctx.cache`-miss lazy case: by this call's time the\n * adapter already holds the NEW envelope, so a `ctx.adapter.get()` here\n * would only ever re-observe the write just made — useless for recovering\n * what a same-tier `putAtTier` may have dropped. Optional: the null-record\n * branches (elevate / demote-to-intermediate / putAtTier(tier>0)) never\n * need it — their only prior-dependent step, the eager `indexes.remove`\n * below, already has what it needs from `ctx.cache` (eager mode is\n * unaffected by the raw-envelope overwrite; lazy mode has no eager mirror).\n *\n * No-ops fast when the collection has neither index kind declared.\n */\nexport async function syncTierIndexes<T>(\n ctx: IndexingContext<T>,\n id: string,\n record: T | null,\n version: number,\n priorEnvelope?: EncryptedEnvelope,\n): Promise<void> {\n if (!ctx.indexes && !ctx.persistedIndexes) return\n const prior: T | null = await resolveTierSyncPrior(ctx, id, priorEnvelope)\n if (record === null) {\n await purgePersistedIndexes(ctx, id)\n if (prior) ctx.indexes?.remove(id, prior)\n } else {\n await maintainPersistedIndexesOnPut(ctx, id, record, prior, version)\n ctx.indexes?.upsert(id, record, prior)\n }\n}\n\n/**\n * Resolve the pre-write record `syncTierIndexes` needs as \"previous\" for\n * index maintenance. `ctx.cache` (eager mode, or a lazy record a prior tier\n * op already synced into it via `syncCache`) is checked first — cheap, no\n * I/O. Lazy mode falls back to a TIER-GATED decode of the caller-supplied\n * `priorEnvelope` (read before the caller's own overwrite, see the doc\n * comment above): gating on `(env._tier ?? 0) > 0` before decoding — the\n * campaign's standard \"elevated ≡ missing\" skip, never an ungated decode —\n * means a prior that was itself elevated (a `demote(0)` off an\n * `elevate()`-purged record) resolves to null cleanly instead of risking the\n * warm-cekCache-succeeds/cold-session-throws asymmetry #709 eliminated\n * elsewhere. No `priorEnvelope` (the null-record branches never pass one) or\n * eager mode both resolve to null here — by design, per the doc comment\n * above.\n */\nasync function resolveTierSyncPrior<T>(ctx: IndexingContext<T>, id: string, priorEnvelope: EncryptedEnvelope | undefined): Promise<T | null> {\n const cached = ctx.cache.get(id)?.record\n if (cached !== undefined) return cached\n if (!ctx.lazy || !priorEnvelope || (priorEnvelope._tier ?? 0) > 0) return null\n return await ctx.codec.decryptRecord(priorEnvelope, { skipValidation: true, id })\n}\n","/** (De)serialize an InvertedIndex to/from a JSON string for persistence (L1.5). */\nimport { InvertedIndex } from './inverted-index.js'\n\nexport function serializeIndex(idx: InvertedIndex): string {\n return JSON.stringify(idx.toSnapshot())\n}\n\nexport function deserializeIndex(json: string): InvertedIndex {\n return InvertedIndex.fromSnapshot(JSON.parse(json))\n}\n","/**\n * Persisted backend for the L1 lexical index (L1.5). Crypto-free: the\n * collection injects load/save/remove + a fingerprint provider. In-memory while\n * live (L1 behavior); persists an opaque snapshot via a debounced flush, and\n * validates a loaded blob against a {count,maxVersion} fingerprint so a stale\n * blob is never used — only rebuilt.\n *\n * #725: a debounced save (encrypt + adapter.put) racing a purge (removePersisted,\n * called by elevate's tier purge and forget's erasure) is guarded by an epoch counter\n * — see the `epoch` field doc for the mechanism and why it also closes the issue's\n * variant (b) for free. Residual gap, structurally unavoidable without a durable\n * write-ahead log: a process CRASH strictly between a stale save's `adapter.put`\n * landing and its compensating `remove()` running (or between the compensating\n * remove landing and `pendingCompensation` being persisted somewhere durable — it is\n * in-memory only) leaves the resurrected blob at rest until the next natural\n * rebuild-persist. This is on par with the gate-before-put optimization's own crash\n * residual (a crash between `isStale()` returning false and the put landing) — both\n * are eliminated only by making the purge and the save's commit point transactional\n * with the store, which is out of scope for an in-memory debounce layer over an\n * arbitrary opaque-blob backend.\n */\nimport { InvertedIndex, type IndexDoc } from './inverted-index.js'\nimport { serializeIndex, deserializeIndex } from './serialize.js'\nimport type { IndexStore } from './index-store.js'\nimport { PersistedIndexCompensationError } from '../../kernel/errors.js'\n\nexport interface Fingerprint { readonly count: number; readonly maxVersion: number }\n\nexport interface PersistedIndexCallbacks {\n load(): Promise<{ json: string; fingerprint: Fingerprint } | null>\n /** `isStale()` reflects whether a purge (removePersisted) has landed since this\n * save's epoch was captured — check it AFTER any async encrypt step and BEFORE\n * the actual adapter.put, skipping the write when true (#725 review: shrinks the\n * at-rest window for purge-beats-encrypt orderings to zero). Belt-and-suspenders:\n * PersistedIndexStore's own post-save epoch check (persist(), below) is the\n * backstop that catches every other ordering, including a purge landing during\n * the put itself. */\n save(json: string, fp: Fingerprint, isStale: () => boolean): Promise<void>\n remove(): Promise<void>\n currentFingerprint(): Fingerprint\n debounceMs?: number\n}\n\nfunction fpEqual(a: Fingerprint, b: Fingerprint): boolean {\n return a.count === b.count && a.maxVersion === b.maxVersion\n}\n\nexport class PersistedIndexStore implements IndexStore {\n private index: InvertedIndex | undefined\n private timer: ReturnType<typeof setTimeout> | null = null\n private lastBuild: (() => ReadonlyArray<IndexDoc>) | undefined\n private readonly debounceMs: number\n /**\n * Bumped by every purge (removePersisted). A save() captured under a since-stale\n * epoch undoes its own effect once it settles, however it interleaves with the\n * purge's own delete — a delete can never be overtaken by a save that was\n * scheduled before it (#725).\n *\n * Subsumes the issue's variant (b) (a stale, pre-purge in-memory index getting\n * paired with a live, post-purge fingerprint and TRUSTED by a cold load, defeating\n * the fingerprint backstop) for free — no separate handling needed: removePersisted()\n * always resets `index` to undefined in the SAME synchronous step that bumps the\n * epoch (below), and the only two paths that can repopulate `index` (ensureBuilt's\n * cold rebuild, rebuildAndPersist's rebuild) do so strictly from `lastBuild()`, which\n * the collection wires to read its LIVE cache at call time — not a frozen snapshot.\n * Cache eviction (the collection dropping the purged/forgotten record) always\n * precedes removePersisted() in both the elevate and forget call paths (#721's\n * syncCache eviction / forget's tombstone write both land before syncSearch /\n * _purgeSearchIndex runs). So any rebuild that executes strictly after\n * removePersisted() — the only way `index` becomes defined again post-purge —\n * necessarily observes the post-purge cache, and any rebuild that predates\n * removePersisted() has its `index` wiped by it. There is no ordering in which a\n * stale (pre-purge) index survives to be skip-rebuilt and persisted under a\n * matching live fingerprint. Regression-pinned in\n * `search-persisted-index-store.test.ts` (\"variant (b) is subsumed...\").\n */\n private epoch = 0\n /**\n * Set when a compensating/purging remove() (`compensate()` undoing a stale\n * save, or `removePersisted()`'s own purge, #764) fails. Unlike the routine\n * best-effort swallow on the debounced flush path (markDirty's timer\n * .catch(), below — safe there because the fingerprint backstop forces a\n * rebuild on the next cold load), a failed removal leaves a resurrected or\n * un-purged blob at rest whose fingerprint can still match the live cache —\n * a cold load would TRUST it, not rebuild past it. So this is never silently\n * dropped: every subsequent store entrypoint (ensureBuilt, rebuildAndPersist,\n * removePersisted) retries the remove first and refuses to proceed past it\n * until it succeeds (#725 review), and the raw adapter error is wrapped in\n * {@link PersistedIndexCompensationError} (#764) so a caller can catch a\n * stuck removal deliberately instead of an indistinguishable adapter error.\n * A crash between a landed put and its compensating remove (before this\n * flag or a retry can run) is a residual gap — see the class doc.\n */\n private pendingCompensation = false\n\n constructor(private readonly cb: PersistedIndexCallbacks) {\n this.debounceMs = cb.debounceMs ?? 1000\n }\n\n get built(): boolean { return this.index !== undefined }\n\n async ensureBuilt(build: () => ReadonlyArray<IndexDoc>): Promise<InvertedIndex> {\n await this.retryPendingCompensation()\n this.lastBuild = build\n if (this.index !== undefined) return this.index\n const loaded = await this.cb.load()\n if (loaded !== null && fpEqual(loaded.fingerprint, this.cb.currentFingerprint())) {\n this.index = deserializeIndex(loaded.json)\n return this.index\n }\n this.index = InvertedIndex.build(build())\n await this.persist()\n return this.index\n }\n\n markDirty(): void {\n this.index = undefined\n if (this.timer) clearTimeout(this.timer)\n this.timer = setTimeout(() => {\n this.timer = null\n // Best-effort: an ordinary save failure here is fine (the fingerprint backstop\n // forces a rebuild on the next cold load). A failed COMPENSATION is different —\n // it sets pendingCompensation (see field doc) instead of relying on this\n // swallow, and is retried — not dropped — by whichever store operation runs next.\n void this.rebuildAndPersist().catch(() => { /* best-effort flush; fingerprint backstop forces rebuild next load */ })\n }, this.debounceMs)\n }\n\n /** Force an immediate persist (cancels any pending debounce). */\n async flush(): Promise<void> {\n if (this.timer) { clearTimeout(this.timer); this.timer = null }\n await this.rebuildAndPersist()\n }\n\n /** Delete the persisted blob and drop the in-memory index (forget/erasure/tier\n * move). A failed purge is wrapped in {@link PersistedIndexCompensationError}\n * (#764) and left sticky (`pendingCompensation`) so the next store entrypoint\n * retries it — never silently dropped, same posture #725 established for a\n * stale save's own compensating remove. */\n async removePersisted(): Promise<void> {\n if (this.timer) { clearTimeout(this.timer); this.timer = null }\n await this.retryPendingCompensation()\n this.epoch++ // any save() already in flight is now stale — it will self-undo\n this.index = undefined\n try {\n await this.cb.remove()\n this.pendingCompensation = false\n } catch (e) {\n this.pendingCompensation = true\n throw new PersistedIndexCompensationError(e)\n }\n }\n\n /** Rebuild using the last known build thunk, then persist. */\n private async rebuildAndPersist(): Promise<void> {\n await this.retryPendingCompensation()\n if (this.lastBuild === undefined) return\n if (this.index === undefined) {\n this.index = InvertedIndex.build(this.lastBuild())\n }\n await this.persist()\n }\n\n /** Persist the current index, then undo it if a purge (removePersisted) landed\n * while the save was in flight — a delete can never be overtaken by a save\n * that was scheduled before it (#725). A failed undo does not silently vanish:\n * see `pendingCompensation`. */\n private async persist(): Promise<void> {\n if (this.index === undefined) return\n const epoch = this.epoch\n await this.cb.save(serializeIndex(this.index), this.cb.currentFingerprint(), () => this.epoch !== epoch)\n if (this.epoch !== epoch) await this.compensate()\n }\n\n /** Undo a stale save. Failure is sticky, not swallowed: see `pendingCompensation`.\n * Wraps the raw adapter error in {@link PersistedIndexCompensationError} (#764) so\n * a caller (e.g. the tier ops' `syncTierSearch`) can catch a stuck compensation\n * deliberately instead of treating it as an indistinguishable adapter failure. */\n private async compensate(): Promise<void> {\n try {\n await this.cb.remove()\n this.pendingCompensation = false\n } catch (e) {\n this.pendingCompensation = true\n throw new PersistedIndexCompensationError(e)\n }\n }\n\n /** Retries a sticky compensation before any store entrypoint proceeds. Failure\n * re-wraps the raw adapter error the same way `compensate()` does (#764) — the\n * flag stays set (untouched here) so the NEXT entrypoint retries again. */\n private async retryPendingCompensation(): Promise<void> {\n if (!this.pendingCompensation) return\n try {\n await this.cb.remove()\n this.pendingCompensation = false\n } catch (e) {\n throw new PersistedIndexCompensationError(e)\n }\n }\n}\n","/**\n * In-memory unique-constraint enforcement for eager-mode collections.\n *\n * Each `UniqueConstraintSet` holds one or more constraints, each covering\n * an ordered tuple of field names. On every `put()` the caller invokes\n * `check()` BEFORE the store write; on success it calls `upsert()` to\n * update the maps. `remove()` is called on `delete()`.\n *\n * Null-distinct semantics: if ANY constrained field is `null` or\n * `undefined` in the record, that record is exempt from the constraint —\n * `keyFor` returns `null` and the record is silently skipped.\n * This matches standard SQL NULL-distinct behavior.\n *\n * Only used in eager mode (`prefetch !== false`). Lazy-mode collections\n * throw at registration instead (see Collection constructor).\n */\n\nimport { readPath } from '../../kernel/query/predicate.js'\nimport { canonicalGroupKey } from '../reduce/canonical-key.js'\nimport { UniqueConstraintError, UnsupportedIndexOptionError } from '../../kernel/errors.js'\nimport type { IndexDef } from './eager-indexes.js'\n\ninterface Constraint {\n readonly fields: readonly string[]\n /** canonicalKey → id of the record holding that key */\n readonly map: Map<string, string>\n}\n\nexport class UniqueConstraintSet {\n private readonly constraints: Constraint[]\n\n constructor(\n private readonly collectionName: string,\n uniqueDefs: readonly (readonly string[])[],\n ) {\n this.constraints = uniqueDefs.map(fields => ({ fields, map: new Map() }))\n }\n\n get size(): number {\n return this.constraints.length\n }\n\n /**\n * Compute the canonical key for a record under a given constraint.\n * Returns `null` if any constrained field is `null` or `undefined`\n * (the record is exempt — no constraint is checked).\n */\n private keyFor(fields: readonly string[], record: unknown): string | null {\n const row: Record<string, unknown> = {}\n for (const f of fields) {\n const v = readPath(record, f)\n if (v === null || v === undefined) return null\n row[f] = v\n }\n return canonicalGroupKey(fields, row)\n }\n\n /**\n * Throw `UniqueConstraintError` if writing `id` with `record` would\n * collide with a DIFFERENT existing record. Call BEFORE the store write.\n */\n check(id: string, record: unknown): void {\n for (const c of this.constraints) {\n const key = this.keyFor(c.fields, record)\n if (key === null) continue\n const holder = c.map.get(key)\n if (holder !== undefined && holder !== id) {\n throw new UniqueConstraintError(this.collectionName, id, c.fields, holder)\n }\n }\n }\n\n /**\n * Update the constraint maps after a successful write.\n * Pass `previous` when updating an existing record (so the old key\n * is removed first). Pass `null` or `undefined` for a fresh insert.\n */\n upsert(id: string, record: unknown, previous?: unknown): void {\n if (previous != null) this.remove(id, previous)\n for (const c of this.constraints) {\n const key = this.keyFor(c.fields, record)\n if (key !== null) c.map.set(key, id)\n }\n }\n\n /**\n * Remove a record from all constraint maps.\n * Called by `Collection.delete()`.\n */\n remove(id: string, record: unknown): void {\n for (const c of this.constraints) {\n const key = this.keyFor(c.fields, record)\n if (key !== null && c.map.get(key) === id) c.map.delete(key)\n }\n }\n\n /**\n * Rebuild all constraint maps from a full snapshot.\n * Called after hydration (ensureHydrated / hydrateFromSnapshot).\n *\n * **Last-writer-wins**: this method does NOT validate pre-existing data\n * for duplicates. If the store already contains two records sharing a\n * constrained value (written before the unique index was declared), the\n * last one processed wins the map slot and the duplicate is silently\n * displaced — no error is thrown, and the earlier holder is evicted from\n * the map. Callers retrofitting a unique index onto populated data should\n * run a one-time uniqueness scan before relying on enforcement.\n */\n build(entries: Iterable<readonly [string, unknown]>): void {\n for (const c of this.constraints) c.map.clear()\n for (const [id, record] of entries) {\n this.upsert(id, record)\n }\n }\n}\n\n/**\n * Build the `UniqueConstraintSet` for a collection from its `IndexDef[]`,\n * or return `null` when no `unique: true` index is declared.\n *\n * Unique enforcement is **eager-mode only**. If any `unique` index is\n * declared on a lazy (`prefetch:false`), CRDT, or tiered collection, this\n * throws `UnsupportedIndexOptionError` at registration rather than letting\n * those write paths (which bypass `check()`/`upsert()`) silently skip\n * enforcement. Kept out of the Collection constructor to keep that\n * always-on kernel file lean (kernel-surface invariant).\n */\nexport function buildUniqueConstraintSet(\n collectionName: string,\n indexes: readonly IndexDef[] | undefined,\n mode: { readonly lazy: boolean; readonly crdt: boolean; readonly tiered: boolean },\n): UniqueConstraintSet | null {\n const uniqueDefs: (readonly string[])[] = []\n for (const def of indexes ?? []) {\n if (\n def !== null &&\n typeof def === 'object' &&\n !Array.isArray(def) &&\n (def as { unique?: boolean }).unique === true\n ) {\n uniqueDefs.push((def as { fields: readonly string[] }).fields)\n }\n }\n if (uniqueDefs.length === 0) return null\n\n if (mode.lazy) {\n throw new UnsupportedIndexOptionError(\n 'unique',\n `unique indexes are not yet supported in lazy mode (prefetch:false) — use the default eager mode. Collection \"${collectionName}\".`,\n )\n }\n if (mode.crdt) {\n throw new UnsupportedIndexOptionError(\n 'unique',\n `unique indexes are not supported on CRDT collections (crdt mode is incompatible with eager unique enforcement). Collection \"${collectionName}\".`,\n )\n }\n if (mode.tiered) {\n throw new UnsupportedIndexOptionError(\n 'unique',\n `unique indexes are not supported on tiered collections (tier writes use a separate path that bypasses unique enforcement). Collection \"${collectionName}\".`,\n )\n }\n return new UniqueConstraintSet(collectionName, uniqueDefs)\n}\n","/**\n * Consumer-neutral, data-relatable field descriptors — the canonical,\n * validator-agnostic authoring channel. Merged by `collection.describe()`.\n *\n * Descriptive, never prescriptive: label/semanticType/unit/sensitivity/\n * aggregate/aliases/displayFor only. Layout, styling, and active-locale\n * selection stay app-side.\n *\n * @module\n */\n\n/** Known semantic types; the union is open — unknown strings pass through. */\nexport type SemanticType =\n | 'date' | 'datetime' | 'email' | 'url' | 'currency' | 'percent'\n | 'country' | 'vat' | 'iban' | 'entity'\n | (string & {})\n\nexport interface FieldMeta {\n /** Human label for any displayable field. Required. */\n label: string\n description?: string\n semanticType?: SemanticType\n /** Display unit, e.g. '€', '%', 'kg'. */\n unit?: string\n /** Data classification driving redaction/inspector masking. */\n sensitivity?: 'public' | 'pii' | 'secret'\n /** Default aggregation for this field. */\n aggregate?: 'sum' | 'count' | 'distinct' | 'none'\n /** Canonical search synonyms (data vocabulary, not UI). */\n aliases?: readonly string[]\n /** Entity pairing: the field holding the human label for this id (buyerId → buyerName). */\n displayFor?: string\n /**\n * Override the widget hint derived from semanticType/type.\n * e.g. 'textarea', 'date', 'money', 'select', 'checkbox', 'number', 'text'.\n * When absent, the widget is derived automatically by buildDescription.\n */\n widget?: string\n /**\n * Card/section grouping hint for detail & form layouts (e.g. 'Identity',\n * 'Amounts'). Purely descriptive metadata — consumers group; describe()\n * keeps emitting fields alphabetically.\n */\n group?: string\n /** Relative ordering hint within (and across) groups. Lower renders first. */\n order?: number\n}\n\nexport class FieldMetaUnknownFieldError extends Error {\n constructor(public readonly collection: string, public readonly key: string) {\n super(`fieldMeta for collection \"${collection}\" references unknown field \"${key}\". `\n + `Declare it in the schema/config or remove the fieldMeta entry.`)\n this.name = 'FieldMetaUnknownFieldError'\n }\n}\n\n/** Reject fieldMeta keys that are not known fields (typo guard), fail-loud. */\nexport function validateFieldMetaKeys(\n collection: string,\n fieldMeta: Record<string, FieldMeta>,\n knownFields: ReadonlySet<string>,\n): void {\n for (const key of Object.keys(fieldMeta)) {\n if (!knownFields.has(key)) throw new FieldMetaUnknownFieldError(collection, key)\n }\n}\n\nexport interface MergeInputs {\n channel?: FieldMeta\n zodMeta?: Partial<FieldMeta>\n inferred?: Partial<FieldMeta>\n}\nexport interface ResolvedMeta extends Partial<FieldMeta> { label: string }\n\n/** camelCase / snake_case → Title Case words. */\nexport function humanizeFieldKey(key: string): string {\n return key\n .replace(/[_-]+/g, ' ')\n .replace(/([a-z0-9])([A-Z])/g, '$1 $2')\n .trim()\n .split(/\\s+/)\n .map((w) => w.charAt(0).toUpperCase() + w.slice(1))\n .join(' ')\n}\n\n/** Merge one field's metadata: channel > zodMeta > inferred; label always present. */\nexport function resolveFieldMeta(key: string, inputs: MergeInputs): ResolvedMeta {\n const { channel, zodMeta, inferred } = inputs\n const pick = <K extends keyof FieldMeta>(k: K): FieldMeta[K] | undefined =>\n channel?.[k] ?? zodMeta?.[k] ?? inferred?.[k]\n const description = pick('description')\n const semanticType = pick('semanticType')\n const unit = pick('unit')\n const sensitivity = pick('sensitivity')\n const aggregate = pick('aggregate')\n const aliases = pick('aliases')\n const displayFor = pick('displayFor')\n const widget = pick('widget')\n const group = pick('group')\n const order = pick('order')\n return {\n label: pick('label') ?? humanizeFieldKey(key),\n ...(description !== undefined ? { description } : {}),\n ...(semanticType !== undefined ? { semanticType } : {}),\n ...(unit !== undefined ? { unit } : {}),\n ...(sensitivity !== undefined ? { sensitivity } : {}),\n ...(aggregate !== undefined ? { aggregate } : {}),\n ...(aliases !== undefined ? { aliases } : {}),\n ...(displayFor !== undefined ? { displayFor } : {}),\n ...(widget !== undefined ? { widget } : {}),\n ...(group !== undefined ? { group } : {}),\n ...(order !== undefined ? { order } : {}),\n }\n}\n","/**\n * `buildDescription` — pure assembler that merges collection config\n * (moneyFields / dictKeyFields / refs / computed / fieldMeta) with an\n * optional validator-derived `zodFields` map into a normalised\n * {@link CollectionDescription}.\n *\n * The sync path (`collection.describe()`) passes `zodFields: undefined`.\n * The async path supplies a populated map and validator-derived type\n * strings.\n *\n * @module\n */\n\nimport type { FieldMeta } from './field-meta.js'\nimport { resolveFieldMeta, validateFieldMetaKeys, FieldMetaUnknownFieldError, humanizeFieldKey } from './field-meta.js'\nimport type { CollectionMeta } from './meta.js'\nimport type { MoneyDescriptor } from '../../via/money/descriptor.js'\nimport type { ViaDescriptor, ViaPosture } from '../../kernel/via/index.js'\nimport type { DictKeyDescriptor, StaticDictDescriptor } from '../../via/i18n/dictionary.js'\nimport { isStaticDictDescriptor } from '../../via/i18n/dictionary.js'\n// #650 Task 2 — native lookup()/enumOf()/dict() fields (separate from\n// dictKeyFields above, which stays the dictKey()/staticDict() alias's own\n// input). Emits the SAME `dict` block shape for byte-parity (the tiers this\n// covers — 'static' with a table, 'reserved' — are the alias-equivalent\n// ones; a first-class 'collection' backing degrades to the \"no resolved\n// labels\" fallback, same as an unresolved dynamic dictKey).\nimport type { LookupDescriptor } from '../../via/lookup/descriptor.js'\n// #650 Task 7 — the 'lookup' binding's describeFragment payload shape (the\n// first-ever ViaBinding.describeFragment consumer, via/index.ts:136). describe.ts\n// is NOT under kernel/**, so importing this via/ type directly is fine\n// (Check 14 via-layering only restricts the kernel spine).\nimport type { LookupDescribeFragment, LookupDescribeFragmentEntry } from '../../via/lookup/binding.js'\n// #657 — the 'blob' binding's describeFragment payload shape (the second-ever\n// ViaBinding.describeFragment consumer, after lookup above). Same rationale:\n// describe.ts is not under kernel/**, so importing this via/ type is fine.\nimport type { BlobDescribeFragment, BlobDescribeFragmentEntry } from '../../via/blob/binding.js'\nimport type { I18nTextDescriptor } from '../../via/i18n/core.js'\nimport type { ComputedFields } from '../../with-formula/computed/index.js'\nimport type { RefDescriptor } from '../../kernel/refs.js'\nimport type { ClassifiedFieldSpec } from '../../via/classified/descriptor.js'\nimport { derivePersistedSchema, isZod4Schema } from '../persisted-schemas/derive.js'\nimport { jsonSchemaToFields } from './fields.js'\n\n// ─── Public types ──────────────────────────────────────────────────────────\n\nexport interface DescribedField {\n readonly key: string\n /** Sync: inferred from config ('number'|'enum'|'string'|'array'|'unknown'). Async (Task 4): validator-derived. */\n readonly type: string\n readonly optional: boolean\n readonly constraints?: Record<string, unknown>\n readonly label: string\n readonly description?: string\n /** Card/section grouping hint for detail & form layouts. From fieldMeta/zod .meta(). */\n readonly group?: string\n /** Relative ordering hint within and across groups. Lower renders first. */\n readonly order?: number\n readonly semanticType?: string\n readonly unit?: string\n readonly sensitivity?: 'public' | 'pii' | 'secret'\n readonly aggregate?: 'sum' | 'count' | 'distinct' | 'none'\n readonly aliases?: readonly string[]\n readonly ref?: { target: string; mode: string; isArray?: true }\n readonly displayFor?: string\n readonly money?: { mode: 'fixed' | 'multi'; currency?: string; scale?: number; rounding?: string }\n readonly dict?: { name: string; static: boolean; values?: readonly { value: string; label?: string }[] }\n /**\n * Normalized lookup metadata (#650 Task 7 — the first-ever\n * `ViaBinding.describeFragment` consumer; sourced from the `'lookup'`\n * binding's fragment, NOT from config directly — see `buildDescription`).\n * Present for every `lookup()`/`enumOf()`/`dict()` field, ALONGSIDE the\n * pre-existing `dict` block above (kept byte-stable for the\n * `dictKey()`/`staticDict()` alias — this is additive, not a replacement).\n * `dimension` is omitted for a bare `enumOf()` (no backing store, no\n * dimension name — the #650 Task 2 `dimension:''` sentinel resolved).\n * `keys` is the statically-known closed-vocabulary key set (declared\n * `keys`, or a static table's own keys) — omitted when membership lives\n * only in the backing collection/dictionary.\n */\n readonly lookup?: {\n readonly dimension?: string\n readonly backing: 'static' | 'reserved' | 'collection'\n readonly vocabulary: 'open' | 'closed'\n readonly key: string\n readonly altKeys?: readonly string[]\n readonly present?: { readonly label: string; readonly by?: string }\n readonly sortBy?: string\n readonly onDelete: 'restrict' | 'cascade' | 'nullify'\n readonly keys?: readonly string[]\n }\n readonly computed?: true\n /** i18n metadata for fields declared with i18nText(). Present only when the field is i18n-enabled. */\n readonly i18n?: { readonly locales?: readonly string[]; readonly densify?: boolean }\n /** Widget hint derived from semanticType+type, overridable via fieldMeta.widget. */\n readonly widget: string\n /** Whether the field is user-editable. False for computed, id, and provenance-stamped fields. */\n readonly editable: boolean\n /** Present when the field is classified. Serialized read-projection contract. */\n readonly classified?: {\n readonly preset: string\n readonly storage: 'recoverable' | 'never' | 'digest-only'\n readonly list: 'omit' | { readonly mask: string } | { readonly rider: string }\n /**\n * Present (and `true`) only when the field opted into the equatable blind\n * index. Additive metadata — emitted UNGATED (no `withClassified()` needed;\n * `toJSONSchema()` carries it too), so it advertises *that* the field is\n * equatable beyond the DEK-consent boundary. Intended: it's a structural\n * property a schema consumer legitimately needs and discloses no value. A\n * deployment wanting it gated can gate this behind its value-bearing door.\n */\n readonly equatable?: true\n }\n /**\n * Present only for a field declared via `blobFields` (#657) — out-of-band\n * attachment storage (`collection.blob(id)`), never a sealed or plaintext\n * record field. `queryable` mirrors the binding's fixed `ViaPosture`\n * (blob content is never indexed — always `'none'`); the rest mirrors the\n * declared `blobFields[field]` policy verbatim (scalars) or as a presence\n * flag (predicate knobs — a predicate has no serializable form). Sourced\n * from the `'blob'` binding's `describeFragment()`, the same\n * `viaFragments` door the `lookup` block above is sourced from.\n */\n readonly blob?: {\n readonly retainDays?: number\n readonly evictWhen?: true\n readonly legalHold?: true\n readonly retainUntil?: true\n readonly external?: true\n readonly public?: true\n readonly backlink?: string\n readonly queryable: 'none'\n }\n /**\n * Present only for a graph-tainted derived field (#638 Task 3 — computed/\n * derivation output whose effective posture was forced away from the\n * plain baseline by a source's posture, e.g. a computed field reading a\n * classified field). `forcedBy` names the immediate declared source\n * field(s) responsible.\n */\n readonly taint?: {\n readonly posture: ViaPosture\n readonly forcedBy: readonly string[]\n }\n}\n\nexport interface CollectionDescription {\n readonly collection: string\n readonly fields: readonly DescribedField[]\n /** Collection-level descriptive metadata; label falls back to the humanized collection name. */\n readonly meta: CollectionMeta\n}\n\n/** Options for the async describe(opts) overload. */\nexport interface DescribeOptions {\n /**\n * When true, resolve dynamic-dict labels from vault.dictionary(name).list()\n * and populate dict.values[].label for dynamic dictKey fields.\n */\n readonly resolveDictLabels?: boolean\n}\n\n// ─── ZodField slot (async path wires this; sync path passes undefined) ───\n\nexport interface ZodFieldSlot {\n readonly type?: string\n readonly optional?: boolean\n readonly constraints?: Record<string, unknown>\n readonly meta?: Partial<FieldMeta>\n}\n\n// ─── RECOGNIZED zod-4 .meta() keys ────────────────────────────────────────\n//\n// Empirically verified 2026-06-25 via:\n// node -e \"const {z,toJSONSchema}=require('zod'); console.log(JSON.stringify(toJSONSchema(z.object({n:z.number().meta({label:'L',unit:'kg',sensitivity:'public',semanticType:'percent',description:'d',aggregate:'sum',aliases:['a'],displayFor:'x'})}))), null, 2)\"\n// Result: .meta() keys are emitted INLINE on each JSON Schema property object\n// at the same level as `type`/`format` — NOT nested under a `metadata` key.\n// Example: z.number().meta({ unit: 'kg' }) → { \"type\": \"number\", \"unit\": \"kg\" }\n// Unknown .meta() keys (not in this set) are ignored.\nconst ZOD_META_KEYS = new Set<string>([\n 'label', 'description', 'unit', 'semanticType', 'sensitivity', 'aggregate', 'aliases', 'displayFor',\n 'group', 'order',\n])\n\n// ─── deriveZodFields ──────────────────────────────────────────────────────\n\n/**\n * Derive per-field slots from a Standard Schema validator.\n * - Calls `derivePersistedSchema` to get the JSON Schema.\n * - Falls back to `{}` for non-Zod or unknown validators.\n * - For zod-4 schemas: reads recognized `.meta()` keys from inline property annotations.\n * - Returns: `Record<fieldKey, { type, optional, constraints?, meta? }>`.\n *\n * No static zod import — all zod access is lazy via derivePersistedSchema.\n */\nexport async function deriveZodFields(\n schema: unknown,\n): Promise<Record<string, ZodFieldSlot>> {\n const envelope = await derivePersistedSchema(schema)\n if (!envelope.jsonSchema) return {}\n\n const isZod4 = isZod4Schema(schema)\n const jsonSchema = envelope.jsonSchema as Record<string, unknown>\n\n // Use the existing JSON-Schema→field mapper for type/optional/constraints.\n const fieldDescriptors = jsonSchemaToFields(jsonSchema, 'live-validator')\n\n // For zod-4: the JSON Schema properties contain inline .meta() annotations.\n // We need to walk the raw properties to extract recognized meta keys.\n const propertiesRaw = jsonSchema['properties'] as Record<string, Record<string, unknown>> | undefined\n\n const result: Record<string, ZodFieldSlot> = {}\n\n for (const [key, descriptor] of Object.entries(fieldDescriptors)) {\n let meta: Partial<FieldMeta> | undefined\n\n if (isZod4 && propertiesRaw) {\n const prop = propertiesRaw[key]\n if (prop) {\n const extracted: Partial<FieldMeta> = {}\n let hasAny = false\n for (const mk of ZOD_META_KEYS) {\n if (mk in prop) {\n (extracted as Record<string, unknown>)[mk] = prop[mk]\n hasAny = true\n }\n }\n if (hasAny) meta = extracted\n }\n }\n\n result[key] = {\n type: descriptor.type,\n optional: descriptor.optional === true,\n ...(descriptor.constraints !== undefined ? { constraints: descriptor.constraints } : {}),\n ...(meta !== undefined ? { meta } : {}),\n }\n }\n\n return result\n}\n\n// ─── buildDescription ─────────────────────────────────────────────────────\n\nexport interface BuildDescriptionInput {\n readonly collection: string\n readonly fieldMeta: Record<string, FieldMeta> | undefined\n /**\n * Kernel-visible collections only carry the opaque {@link ViaDescriptor}\n * marker (the kernel never inspects a Via feature's concrete descriptor\n * shape). Every entry here is actually a {@link MoneyDescriptor} — only\n * `money()` constructs them — narrowed locally below where its\n * mode/currency/scale are read for the describe() output.\n */\n readonly moneyFields: Record<string, ViaDescriptor> | undefined\n readonly dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined\n /** Native lookup()/enumOf()/dict() fields (#650 Task 2) — declared only via `viaFields`/`via()`, no sugar key. */\n readonly lookupFields?: Record<string, LookupDescriptor> | undefined\n readonly computed: ComputedFields | undefined\n readonly refs: Record<string, RefDescriptor>\n /** Async path fills this; sync path passes `undefined`. */\n readonly zodFields: Record<string, ZodFieldSlot> | undefined\n /**\n * Async path: when `resolveDictLabels` was true, this map holds\n * `{ dictName -> { value -> label } }` for dynamic dictKey fields.\n * Used to populate `dict.values[].label`.\n */\n readonly dictLabels?: Record<string, Record<string, string>> | undefined\n /** Collection-level descriptive metadata. Label falls back to humanized collection name. */\n readonly meta?: CollectionMeta | undefined\n /**\n * Map of field name → I18nTextDescriptor for fields declared with i18nText().\n * When present, describe() surfaces an `i18n` block on matching DescribedField entries.\n */\n readonly i18nFields?: Record<string, I18nTextDescriptor> | undefined\n /** Per-field classified specs (already resolved/flattened). */\n readonly classified?: Record<string, ClassifiedFieldSpec> | undefined\n /** Graph-computed taint overlay (#638 Task 3) — `Collection.via?.taint`. */\n readonly taint?: { readonly postures: ReadonlyMap<string, ViaPosture>; readonly provenance?: ReadonlyMap<string, readonly string[]> } | undefined\n /**\n * Per-binding `describeFragment()` output, keyed by binding brand (#650\n * Task 7 — first-ever consumer of `ViaBinding.describeFragment`,\n * `via/index.ts:136`). `Collection.describe()`/`describeAsync()` build this\n * from `this.via?.describeFragments()`. The `'lookup'` brand's fragment\n * feeds the `lookup` block below; `'blob'`'s feeds the `blob` block\n * (#657, the second consumer). Other brands' fragments ride along unread\n * until they gain a consumer too.\n */\n readonly viaFragments?: Record<string, Record<string, unknown>> | undefined\n}\n\n// Re-export so that callers that want to catch the error don't need another import path.\nexport { FieldMetaUnknownFieldError }\n\n// ─── Widget derivation ────────────────────────────────────────────────────────\n\n/**\n * Derive a widget hint from resolved field metadata.\n * Priority: explicit override (resolvedWidget) > semanticType > dict > type > 'text'.\n */\nfunction deriveWidget(opts: {\n semanticType?: string\n type: string\n dict?: unknown\n /** #650 Task 7 — same 'select' outcome as `dict` (today always co-present for a lookup field via the existing `dict` block; kept as its own check so a future lookup-only field, with no `dict` block, still derives 'select'). */\n lookup?: unknown\n /** #657 — a blobFields-declared field derives the 'file' widget, never the 'text' default (binary content, not a text input). */\n blob?: unknown\n resolvedWidget?: string\n}): string {\n if (opts.resolvedWidget !== undefined) return opts.resolvedWidget\n switch (opts.semanticType) {\n case 'date':\n case 'datetime':\n return 'date'\n case 'currency':\n return 'money'\n case 'entity':\n return 'ref-select'\n case 'url':\n return 'url'\n case 'email':\n return 'email'\n case 'percent':\n return 'number'\n }\n if (opts.dict !== undefined || opts.lookup !== undefined) return 'select'\n if (opts.blob !== undefined) return 'file'\n if (opts.type === 'boolean') return 'checkbox'\n if (opts.type === 'number') return 'number'\n return 'text'\n}\n\n/**\n * Pure assembler: no I/O, no side effects.\n * Builds a {@link CollectionDescription} from the collection's in-memory config.\n *\n * When `zodFields` is supplied (async path), validates that every `fieldMeta` key\n * refers to a known field (config ∪ zodFields). Throws `FieldMetaUnknownFieldError`\n * on the first unknown key — this is the real validation that the vault.ts no-op\n * couldn't do (schema fields weren't knowable synchronously).\n */\nexport function buildDescription(input: BuildDescriptionInput): CollectionDescription {\n const { collection, fieldMeta, moneyFields, dictKeyFields, lookupFields, computed, refs, zodFields, dictLabels, meta, i18nFields, classified, taint } = input\n\n // #650 Task 7 — the 'lookup' binding's describeFragment, keyed per field.\n // Deliberately routed through `viaFragments` rather than reused directly\n // from `lookupFields` above (which only feeds the pre-existing `dict`\n // block, byte-stable for the alias) — this IS the first-ever\n // `describeFragment` consumption the task wires up.\n const lookupFragments = (input.viaFragments?.['lookup'] as LookupDescribeFragment | undefined)?.lookupFields\n\n // #657 — the 'blob' binding's describeFragment, keyed per field (same\n // routing pattern as lookupFragments above). A blobFields-declared field\n // has no other config-map source (unlike money/dict/lookup/i18n/classified,\n // each of which is fed a dedicated map below) — `blobFragments` is BOTH\n // this field's block source AND (via its keys) how it joins `allKeys` at\n // all, since otherwise a blobFields-only field with no fieldMeta entry is\n // invisible in describe() (#657 finding 1).\n const blobFragments = (input.viaFragments?.['blob'] as BlobDescribeFragment | undefined)?.blobFields\n\n // When zodFields is present AND non-empty (async path, validator successfully derived\n // a schema): validate fieldMeta keys against the real known-field set = config keys ∪\n // zodFields keys. This is the carry from Task 1: vault.ts couldn't do this synchronously\n // (schema fields weren't knowable at config time without running async derivation).\n //\n // When zodFields is empty (non-zod / unknown validator returned no schema info),\n // we cannot validate — skip to remain validator-agnostic.\n if (zodFields !== undefined && Object.keys(zodFields).length > 0 && fieldMeta !== undefined) {\n const knownFields = new Set<string>([\n ...Object.keys(moneyFields ?? {}),\n ...Object.keys(dictKeyFields ?? {}),\n ...Object.keys(refs),\n ...Object.keys(computed ?? {}),\n ...Object.keys(zodFields),\n ...Object.keys(i18nFields ?? {}),\n ...Object.keys(lookupFields ?? {}),\n ...Object.keys(blobFragments ?? {}),\n ])\n validateFieldMetaKeys(collection, fieldMeta, knownFields)\n }\n\n // Union of all config key sources — stable alphabetical order.\n const allKeys = new Set<string>([\n ...Object.keys(moneyFields ?? {}),\n ...Object.keys(dictKeyFields ?? {}),\n ...Object.keys(lookupFields ?? {}),\n ...Object.keys(refs),\n ...Object.keys(computed ?? {}),\n ...Object.keys(fieldMeta ?? {}),\n ...Object.keys(zodFields ?? {}),\n ...Object.keys(i18nFields ?? {}),\n ...Object.keys(classified ?? {}),\n ...Object.keys(blobFragments ?? {}),\n ])\n\n const fields: DescribedField[] = []\n\n for (const key of [...allKeys].sort()) {\n const zod = zodFields?.[key]\n // Narrow the opaque marker back to the concrete descriptor — see the\n // {@link BuildDescriptionInput.moneyFields} doc comment.\n const money = moneyFields?.[key] as MoneyDescriptor | undefined\n const dict = dictKeyFields?.[key]\n const lookupDesc = lookupFields?.[key]\n const refDesc = refs[key]\n const isComputed = computed !== undefined && key in computed\n const i18nDesc = i18nFields?.[key]\n const cls = classified?.[key]\n const blobFragmentEntry: BlobDescribeFragmentEntry | undefined = blobFragments?.[key]\n const taintPosture = taint?.postures.get(key)\n\n // ── Infer type + structural extras ────────────────────────────────────\n let type = zod?.type ?? 'unknown'\n const inferred: Partial<FieldMeta> = {}\n\n let moneyBlock: DescribedField['money'] | undefined\n let dictBlock: DescribedField['dict'] | undefined\n let refBlock: DescribedField['ref'] | undefined\n let lookupBlock: DescribedField['lookup'] | undefined\n let blobBlock: DescribedField['blob'] | undefined\n\n if (money) {\n type = 'number'\n inferred.semanticType = 'currency'\n inferred.aggregate = 'sum'\n const currency = money.soleCurrency()\n const scale = currency !== undefined ? money.scaleFor(currency) : undefined\n moneyBlock = {\n mode: money.mode,\n ...(currency !== undefined ? { currency } : {}),\n ...(scale !== undefined ? { scale } : {}),\n ...(money.rounding !== undefined ? { rounding: money.rounding } : {}),\n }\n } else if (refDesc) {\n type = refDesc.isArray ? 'array' : 'string'\n inferred.semanticType = 'entity'\n refBlock = {\n target: refDesc.target,\n mode: refDesc.mode,\n ...(refDesc.isArray ? { isArray: true as const } : {}),\n }\n } else if (dict) {\n type = 'enum'\n if (isStaticDictDescriptor(dict)) {\n // Static dict: labels available synchronously from the in-code table.\n const displayLocale = dict.displayLocale\n const values = dict.keys.map((k) => {\n const localeMap = dict.table[k]\n const label = displayLocale !== undefined\n ? (localeMap?.[displayLocale] ?? undefined)\n : undefined\n return label !== undefined\n ? { value: k, label }\n : { value: k }\n })\n dictBlock = { name: dict.name, static: true, values }\n } else {\n // Dynamic dictKey: keys declared in config; labels optionally resolved\n // from vault.dictionary(name).list() when resolveDictLabels was requested.\n const labelMap = dictLabels?.[dict.name]\n const labelMapHasEntries = labelMap !== undefined && Object.keys(labelMap).length > 0\n if (labelMapHasEntries) {\n // We have resolved labels — build values from the label map.\n const values = Object.entries(labelMap).map(([value, label]) => ({ value, label }))\n dictBlock = { name: dict.name, static: false, values }\n } else if (dict.keys !== undefined) {\n const values = dict.keys.map((k) => {\n const label = dict.labels?.[k]\n return label !== undefined ? { value: k, label } : { value: k }\n })\n dictBlock = { name: dict.name, static: false, values }\n } else {\n dictBlock = { name: dict.name, static: false }\n }\n }\n } else if (lookupDesc) {\n // Native lookup()/enumOf()/dict() field (#650 Task 2) — the SAME `dict`\n // block shape as above, for byte-parity with the dictKey()/staticDict()\n // alias. A table-bearing descriptor ('static' backing, the lookup(static)\n // form staticDict() compiles onto) resolves synchronously like a static\n // dict; a reserved-tier dict() resolves via `dictLabels` exactly like a\n // dynamic dictKey (review fix — was previously falling to the\n // declared-keys-only fallback below, breaking async describe parity);\n // everything else (collection/bare enum) falls to that fallback.\n type = 'enum'\n const lookupLabelMap = dictLabels?.[lookupDesc.dimension]\n const lookupLabelMapHasEntries = lookupLabelMap !== undefined && Object.keys(lookupLabelMap).length > 0\n if (lookupDesc.table !== undefined) {\n const displayLocale = lookupDesc.displayLocale\n const table = lookupDesc.table\n const values = (lookupDesc.keys ?? Object.keys(table)).map((k) => {\n const localeMap = table[k]\n const label = displayLocale !== undefined\n ? (localeMap?.[displayLocale] ?? undefined)\n : undefined\n return label !== undefined ? { value: k, label } : { value: k }\n })\n dictBlock = { name: lookupDesc.dimension, static: true, values }\n } else if (lookupLabelMapHasEntries) {\n const values = Object.entries(lookupLabelMap).map(([value, label]) => ({ value, label }))\n dictBlock = { name: lookupDesc.dimension, static: false, values }\n } else if (lookupDesc.keys !== undefined) {\n const values = lookupDesc.keys.map((k) => {\n const label = lookupDesc.labels?.[k]\n return label !== undefined ? { value: k, label } : { value: k }\n })\n dictBlock = { name: lookupDesc.dimension, static: false, values }\n } else {\n dictBlock = { name: lookupDesc.dimension, static: false }\n }\n } else if (i18nDesc) {\n // i18nText field: the stored value is a locale-map object, but the resolved\n // type exposed to consumers is 'string' (locale resolution collapses to a string).\n type = 'string'\n } else if (isComputed) {\n // type already initialized to zod?.type ?? 'unknown' above; no re-set needed\n } else if (blobFragmentEntry !== undefined) {\n // #657 finding 1 — a blobFields-only field (no schema/money/dict/\n // lookup/i18n config) was previously invisible; with a fieldMeta\n // entry it fell through to the 'unknown'/'text'/editable:true default,\n // actively wrong for binary content. `type` is a plain `string` on\n // DescribedField (not a closed union), so 'blob' is not a breaking\n // union extension.\n type = 'blob'\n blobBlock = { ...blobFragmentEntry, queryable: 'none' }\n }\n\n // ── lookup block (#650 Task 7 — first-ever ViaBinding.describeFragment\n // consumer) ── Sourced from `lookupFragments` (the binding's fragment),\n // NOT from `lookupDesc` above (which only feeds the pre-existing `dict`\n // block, byte-stable for the alias) — routing through the fragment is\n // the point: `backing`/`vocabulary`/`key`/`onDelete` have no other\n // source in this function, so their presence here is itself proof the\n // describeFragment seam (declared via/index.ts:136, zero consumers before\n // this task) carries data end to end from binding to describe() output.\n const lookupFragmentEntry: LookupDescribeFragmentEntry | undefined = lookupFragments?.[key]\n if (lookupFragmentEntry !== undefined) {\n lookupBlock = {\n ...(lookupFragmentEntry.dimension !== undefined ? { dimension: lookupFragmentEntry.dimension } : {}),\n backing: lookupFragmentEntry.backing,\n vocabulary: lookupFragmentEntry.vocabulary,\n key: lookupFragmentEntry.key,\n onDelete: lookupFragmentEntry.onDelete,\n ...(lookupFragmentEntry.altKeys !== undefined ? { altKeys: lookupFragmentEntry.altKeys } : {}),\n ...(lookupFragmentEntry.present !== undefined ? { present: lookupFragmentEntry.present } : {}),\n ...(lookupFragmentEntry.sortBy !== undefined ? { sortBy: lookupFragmentEntry.sortBy } : {}),\n ...(lookupFragmentEntry.keys !== undefined ? { keys: lookupFragmentEntry.keys } : {}),\n }\n }\n\n // Classified sensitivity feeds inferred meta at lowest precedence — channel\n // fieldMeta and zod .meta() still win via resolveFieldMeta's merge order.\n if (cls !== undefined) inferred.sensitivity = cls.sensitivity\n\n // ── Merge fieldMeta channel ────────────────────────────────────────────\n const channelEntry = fieldMeta?.[key]\n const zodMeta = zod?.meta\n const resolved = resolveFieldMeta(key, {\n ...(channelEntry !== undefined ? { channel: channelEntry } : {}),\n ...(zodMeta !== undefined ? { zodMeta } : {}),\n inferred,\n })\n\n // ── i18n block (only for i18nText fields) ─────────────────────────────\n let i18nBlock: DescribedField['i18n'] | undefined\n if (i18nDesc !== undefined) {\n const locales = i18nDesc.options.languages\n const densify = i18nDesc.options.densifyOnWrite\n i18nBlock = {\n ...(locales !== undefined ? { locales } : {}),\n ...(densify !== undefined ? { densify } : {}),\n }\n }\n\n // ── Widget (derived, overridable via resolvedWidget from fieldMeta/zodMeta) ──\n const widget = deriveWidget({\n type,\n ...(resolved.semanticType !== undefined ? { semanticType: resolved.semanticType } : {}),\n ...(dictBlock !== undefined ? { dict: dictBlock } : {}),\n ...(lookupBlock !== undefined ? { lookup: lookupBlock } : {}),\n ...(blobBlock !== undefined ? { blob: blobBlock } : {}),\n ...(resolved.widget !== undefined ? { resolvedWidget: resolved.widget } : {}),\n })\n\n // ── Editable: false for computed, id, provenance-stamped, blob fields ──\n // Provenance fields (_source, _sourceTs) are envelope-level metadata, not\n // user schema fields — they won't appear as keys in fieldMeta so this check\n // is implicitly handled (they'd never appear in allKeys). Explicitly guard\n // computed + 'id' as the two structural non-editable cases. A blobFields\n // field (#657) is never written through the record codec — it's mutated\n // exclusively via `collection.blob(id)` — so it is never editable either.\n const editable = !isComputed && key !== 'id' && blobBlock === undefined\n\n // ── Assemble the field (exactOptionalPropertyTypes-safe spreads) ───────\n const field: DescribedField = {\n key,\n type,\n optional: zod?.optional ?? false,\n ...(zod?.constraints !== undefined ? { constraints: zod.constraints } : {}),\n label: resolved.label,\n ...(resolved.description !== undefined ? { description: resolved.description } : {}),\n ...(resolved.group !== undefined ? { group: resolved.group } : {}),\n ...(resolved.order !== undefined ? { order: resolved.order } : {}),\n ...(resolved.semanticType !== undefined ? { semanticType: resolved.semanticType } : {}),\n ...(resolved.unit !== undefined ? { unit: resolved.unit } : {}),\n ...(resolved.sensitivity !== undefined ? { sensitivity: resolved.sensitivity } : {}),\n ...(resolved.aggregate !== undefined ? { aggregate: resolved.aggregate } : {}),\n ...(resolved.aliases !== undefined ? { aliases: resolved.aliases } : {}),\n ...(resolved.displayFor !== undefined ? { displayFor: resolved.displayFor } : {}),\n ...(refBlock !== undefined ? { ref: refBlock } : {}),\n ...(moneyBlock !== undefined ? { money: moneyBlock } : {}),\n ...(dictBlock !== undefined ? { dict: dictBlock } : {}),\n ...(lookupBlock !== undefined ? { lookup: lookupBlock } : {}),\n ...(blobBlock !== undefined ? { blob: blobBlock } : {}),\n ...(isComputed ? { computed: true as const } : {}),\n ...(i18nBlock !== undefined ? { i18n: i18nBlock } : {}),\n widget,\n editable,\n ...(cls !== undefined ? {\n classified: {\n preset: cls.preset,\n storage: cls.storage,\n list: cls.list.kind === 'omit' ? 'omit' as const\n : cls.list.kind === 'mask' ? { mask: cls.list.pattern }\n : { rider: cls.list.rider },\n ...(cls.equatable === true ? { equatable: true as const } : {}),\n },\n } : {}),\n ...(taintPosture !== undefined ? { taint: { posture: taintPosture, forcedBy: taint?.provenance?.get(key) ?? [] } } : {}),\n }\n\n fields.push(field)\n }\n\n // Build collection-level meta with label fallback to humanized collection name.\n const collectionMeta: CollectionMeta = {\n ...meta,\n label: meta?.label ?? humanizeFieldKey(collection),\n }\n\n return {\n collection,\n fields,\n meta: collectionMeta,\n }\n}\n","/**\n * `Collection.putMany({ atomic: true })` — both commit strategies (#921).\n *\n * Extracted from `collection.ts` (kernel-surface budget) when the atomic\n * mode became the second consumer of the #904/#905 prepare/commit seam:\n *\n * - **Delegating branch** (#921): on a store that declares `txAtomic` AND\n * implements `tx()`, with no duplicate id in the batch and\n * `_txAtomicSafe('put')` on the collection, the batch is prepared via\n * `_preparePut` (zero observable side effects), submitted as ONE\n * `store.tx(ops)` call with per-leg CAS, then finalized via\n * `_finalizePut` — same shape and failure semantics as #906's\n * `commitAtomicBatch`: a `tx()` throw means the store applied NOTHING,\n * so it rethrows without a revert pass; a finalize throw walks the\n * existing revert path. History/ledger/cache/change events fire\n * post-commit, in entry order.\n * - **Sequential branch** (pre-#921 behavior, unchanged): Phase-1\n * pre-flight CAS, then per-entry `Collection.put()` with best-effort\n * revert of executed ops (including nested derivation outputs, via the\n * transient-TxContext mechanism) on mid-batch failure.\n *\n * The caller passes its private store/vault/name plus a structural view of\n * the collection ({@link PutManyAtomicHost}). Kernel spine file: it may\n * not import `with-commit` even type-only, so the transaction context it\n * shares with `dispatchDerivations` is typed STRUCTURALLY\n * ({@link BulkTxContext} — satisfied by the real `TxContext`), and reverts\n * go straight through the kernel-native `bestEffortRevert` (exactly what\n * `with-commit`'s `revertExecuted` does when handed no `db`).\n *\n * @internal\n */\nimport { ConflictError } from './errors.js'\nimport { bestEffortRevert } from './best-effort-revert.js'\nimport type { BestEffortRevertLeg } from './best-effort-revert.js'\nimport type { PreparedPut } from './prepared-write.js'\nimport type {\n EncryptedEnvelope,\n NoydbStore,\n PutManyItemOptions,\n PutManyResult,\n TxOp,\n} from './types.js'\n\n/** @internal Structural view of one executed op on a transaction context. */\ninterface BulkExecutedOp {\n readonly op: {\n readonly type: 'put' | 'delete'\n readonly vaultName: string\n readonly collectionName: string\n readonly id: string\n }\n readonly priorEnvelope: EncryptedEnvelope | null\n}\n\n/** @internal Structural slice of `with-commit`'s `TxContext` this module drives. */\ninterface BulkTxContext {\n readonly _executed: BulkExecutedOp[]\n}\n\n/** @internal The slice of `Collection` both branches drive. */\nexport interface PutManyAtomicHost<T> {\n put(id: string, record: T): Promise<void>\n _preparePut(id: string, record: T): Promise<PreparedPut<T>>\n _finalizePut(prepared: PreparedPut<T>): Promise<void>\n _fireAtomicAfterWrite(opType: 'put', prepared: PreparedPut<T>): Promise<void>\n _assertWriteGates(): Promise<void>\n _txAtomicSafe(opType: 'put' | 'delete'): boolean\n _invalidateCacheEntry(id: string): Promise<void>\n}\n\n/** @internal The owning collection's private coordinates + wiring. */\nexport interface PutManyAtomicContext<T> {\n readonly host: PutManyAtomicHost<T>\n readonly store: NoydbStore\n readonly vault: string\n readonly name: string\n readonly derivationSource?: {\n createTxContext(): BulkTxContext\n setActiveTxContext(ctx: BulkTxContext): void\n clearActiveTxContext(ctx: BulkTxContext): void\n getCollection(name: string): { _invalidateCacheEntry(id: string): Promise<void> }\n } | undefined\n}\n\ntype PutManyEntries<T> = ReadonlyArray<readonly [id: string, record: T, opts?: PutManyItemOptions]>\n\nconst toRevertLeg = ({ op, priorEnvelope }: BulkExecutedOp): BestEffortRevertLeg => ({\n vaultName: op.vaultName,\n collectionName: op.collectionName,\n id: op.id,\n prior: priorEnvelope,\n})\n\n/** @internal Atomic-mode implementation of `Collection.putMany`. */\nexport async function runPutManyAtomic<T>(\n ctx: PutManyAtomicContext<T>,\n entries: PutManyEntries<T>,\n): Promise<PutManyResult> {\n const { store, vault, name } = ctx\n // Phase 1 — pre-flight CAS + prior-envelope snapshot for revert. Shared by\n // both branches; the duplicate-id scan rides along because a single\n // `store.tx()` write set can't express \"this key changes twice in sequence\"\n // (same rule as `canCommitAtomically` condition 3).\n const priors = new Map<string, EncryptedEnvelope | null>()\n let duplicateId = false\n for (const [id, , opts] of entries) {\n if (priors.has(id)) duplicateId = true\n else priors.set(id, await store.get(vault, name, id))\n if (opts?.expectedVersion !== undefined) {\n const actual = priors.get(id)?._v ?? 0\n if (actual !== opts.expectedVersion) {\n throw new ConflictError(\n actual,\n `putMany atomic: ${vault}/${name}/${id} ` +\n `expected v${opts.expectedVersion}, found v${actual}`,\n )\n }\n }\n }\n // #921 — the single-collection puts-only reduction of the #906 gate:\n // store bits + no duplicate ids + `_txAtomicSafe('put')`.\n if (\n !duplicateId &&\n store.capabilities?.txAtomic === true &&\n typeof store.tx === 'function' &&\n ctx.host._txAtomicSafe('put')\n ) {\n return commitViaStoreTx(ctx, entries, priors)\n }\n return commitSequentially(ctx, entries, priors)\n}\n\n/**\n * The delegating branch — mirrors `commitAtomicBatch`\n * (`with-commit/tx/transaction.ts`); see that function's comments for the\n * reasoning each step leans on.\n *\n * @internal\n */\nasync function commitViaStoreTx<T>(\n ctx: PutManyAtomicContext<T>,\n entries: PutManyEntries<T>,\n priors: ReadonlyMap<string, EncryptedEnvelope | null>,\n): Promise<PutManyResult> {\n const { host, store, vault, name } = ctx\n // The two refusals `put()` asserts before anything else (schema-update\n // gate + schema fence). One collection and prepare writes nothing, so a\n // single up-front assertion is equivalent to the wrapper's per-op one.\n await host._assertWriteGates()\n\n // ─── Prepare ─── zero observable side effects; a throw here needs no\n // unwind. The revert plan is recorded all the same for the finalize path.\n const executed: BulkExecutedOp[] = []\n const legs: Array<{ prepared: PreparedPut<T>; txOp: TxOp }> = []\n for (const [id, record] of entries) {\n const prior = priors.get(id) ?? null\n executed.push({ op: { type: 'put', vaultName: vault, collectionName: name, id }, priorEnvelope: prior })\n const prepared = await host._preparePut(id, record)\n legs.push({\n prepared,\n // Every leg carries CAS against the Phase-1 snapshot, so a writer\n // landing between prepare and the batch reaching the store loses.\n txOp: { type: 'put', vault, collection: name, id, expectedVersion: prior?._v ?? 0, envelope: prepared.envelope },\n })\n }\n\n // ─── The batch ─── deliberately NOT revert-guarded: a rejection means the\n // all-or-nothing store applied nothing, and no ledger/history/event has\n // fired yet. The error (`ConflictError` when a leg lost its CAS) surfaces\n // unwrapped.\n await store.tx!(legs.map(l => l.txOp))\n\n // ─── Finalize ─── history snapshot, ledger entry, cache/index update,\n // change event — per record, in entry order, all AFTER the bytes are\n // durable (where the sequential branch interleaves them per op). #931:\n // then the after-write observers, which no longer gate eligibility.\n try {\n for (const leg of legs) {\n await host._finalizePut(leg.prepared)\n await host._fireAtomicAfterWrite('put', leg.prepared)\n }\n } catch (err) {\n // Bytes ARE durable now — best-effort unwind over the recorded plan,\n // plus the same cache-desync guard the sequential branch runs.\n await bestEffortRevert(executed.map(toRevertLeg), store)\n for (const { op } of [...executed].reverse()) {\n try { await host._invalidateCacheEntry(op.id) } catch { /* best-effort */ }\n }\n throw err\n }\n return { ok: true, success: entries.map(([id]) => id), failures: [] }\n}\n\n/**\n * The sequential branch — pre-#921 `putManyAtomic` Phase 2, moved verbatim.\n *\n * When a derivation registry is wired, publish a transient TxContext for the\n * duration of the loop so `dispatchDerivations` can register recursive\n * derived-output writes onto `ctx._executed`; the revert then unwinds the\n * combined list (source ops + side-effect ops) in reverse, matching the\n * `runTransaction` rollback semantics. When no derivation registry is\n * configured, a local `executed` list keeps a single code path.\n *\n * @internal\n */\nasync function commitSequentially<T>(\n ctx: PutManyAtomicContext<T>,\n entries: PutManyEntries<T>,\n priors: ReadonlyMap<string, EncryptedEnvelope | null>,\n): Promise<PutManyResult> {\n const { host, store, vault, name, derivationSource } = ctx\n const txCtx = derivationSource?.createTxContext() ?? null\n if (txCtx !== null && derivationSource) {\n derivationSource.setActiveTxContext(txCtx)\n }\n const localExecuted: BulkExecutedOp[] = []\n try {\n for (const [id, record] of entries) {\n // Record the revert plan BEFORE the call so a mid-`put` throw\n // (e.g. strict derivation failure firing after `store.put`\n // already committed the source envelope) still has the source\n // write reverted. Mirrors `runTransaction`'s Phase 2 pattern.\n const entry: BulkExecutedOp = {\n op: { type: 'put', vaultName: vault, collectionName: name, id },\n priorEnvelope: priors.get(id) ?? null,\n }\n if (txCtx !== null) txCtx._executed.push(entry)\n else localExecuted.push(entry)\n await host.put(id, record)\n }\n return { ok: true, success: entries.map(([id]) => id), failures: [] }\n } catch (err) {\n const executedForRevert = txCtx !== null ? txCtx._executed : localExecuted\n // Restore prior envelopes via the raw store — walks in reverse,\n // best-effort on each restore, one atomic batch when the store can\n // (#886). Same semantics as `revertExecuted` handed no `db`.\n await bestEffortRevert(executedForRevert.map(toRevertLeg), store)\n // Cache desync guard. The revert above bypasses the Collection layer,\n // so walk the executed ops and invalidate caches via the source\n // collection for entries that target it, and via\n // `derivationSource.getCollection(name)` for nested derived outputs\n // that live in sibling collections — otherwise an eager cache on a\n // derived-output collection still serves the rolled-back record.\n for (const { op } of [...executedForRevert].reverse()) {\n if (op.vaultName !== vault) continue\n try {\n if (op.collectionName === name) {\n await host._invalidateCacheEntry(op.id)\n } else if (derivationSource) {\n await derivationSource.getCollection(op.collectionName)._invalidateCacheEntry(op.id)\n }\n } catch { /* best-effort */ }\n }\n throw err\n } finally {\n if (txCtx !== null && derivationSource) {\n derivationSource.clearActiveTxContext(txCtx)\n }\n }\n}\n","/**\n * via() — the public composer for declaring a field's Via-bound feature(s)\n * directly, as an alternative to a feature's dedicated sugar key\n * (`moneyFields`/`i18nFields`/`dictKeyFields`). Wraps one or more\n * `ViaDescriptor`s (`money()`, `i18nText()`, `dictKey()`, `staticDict()`, …)\n * into a single tagged container a collection's `viaFields` option can hold.\n *\n * Declaring a field via `via()` is equivalent to declaring the same\n * descriptor under its feature's sugar key — `compileViaBindings`\n * (kernel/collection-config.ts) groups a `viaFields` map by each\n * descriptor's `_viaBrand` and merges it with the sugar keys, throwing when\n * the same field is declared in both places (#623 Task 9).\n */\nimport { ValidationError } from '../errors.js'\nimport type { ViaBinding, ViaDescriptor } from './index.js'\nimport type { ViaPipeline } from './pipeline.js'\n// Types + shape-classification predicates reach through the kernel's own\n// `port/with/` hook seam (never `src/via/` directly) — #623 Task 11.\n// `isI18nTextDescriptor`/`isDictKeyDescriptor` are pure tag checks moved\n// onto the port alongside `isStaticDictDescriptor` (see i18n-strategy.ts);\n// the descriptor types were already port-owned re-exports (#623 Task 8).\nimport type { DictKeyDescriptor, I18nTextDescriptor, StaticDictDescriptor } from '../../port/with/i18n-strategy.js'\nimport { isDictKeyDescriptor, isI18nTextDescriptor, isStaticDictDescriptor } from '../../port/with/i18n-strategy.js'\n// `ComputedDescriptor` is a type-only need — the eager link that makes\n// `viaBinder('computed')` resolvable lives in `collection-config.ts`'s value\n// import of this same port module (#638 Task 7).\nimport type { ComputedDescriptor } from '../../port/with/computed-strategy.js'\n// #650 Task 2 — `LookupDescriptor`/`isLookupDescriptor` reach through the\n// SAME kernel port seam (no new `src/via/**` specifier here; `linkLookupVia()`\n// already ran when the caller constructed the descriptor via `lookup()`/\n// `enumOf()`/`dict()`, so `viaBinder('lookup')` is resolvable with no eager\n// import needed here, mirroring i18n/money — see `descriptor.ts`).\nimport type { LookupDescriptor } from '../../port/with/lookup-strategy.js'\nimport { isLookupDescriptor } from '../../port/with/lookup-strategy.js'\n\n/** Tagged container returned by {@link via}. Readonly — never mutated after construction. */\nexport interface ViaFieldSpec {\n readonly _noydbVia: true\n readonly descriptors: readonly ViaDescriptor[]\n}\n\n/**\n * Compose one or more Via feature descriptors for a single field.\n *\n * @example\n * ```ts\n * vault.collection('invoices', {\n * viaFields: { total: via(money({ currency: 'EUR' })) },\n * })\n * ```\n */\nexport function via(...descriptors: ViaDescriptor[]): ViaFieldSpec {\n if (descriptors.length === 0) {\n throw new ValidationError('via(): at least one descriptor is required, e.g. via(money({ currency: \\'EUR\\' }))')\n }\n return { _noydbVia: true, descriptors }\n}\n\n/** Runtime predicate for detecting a {@link ViaFieldSpec}. */\nexport function isViaFieldSpec(x: unknown): x is ViaFieldSpec {\n return typeof x === 'object' && x !== null && (x as { _noydbVia?: unknown })._noydbVia === true\n}\n\n/** The money/i18n/lookup sugar keys + a `viaFields` map — the inputs {@link mergeViaFields} reconciles. */\nexport interface ViaFieldSources {\n readonly moneyFields?: Record<string, ViaDescriptor> | undefined\n readonly i18nFields?: Record<string, I18nTextDescriptor> | undefined\n readonly dictKeyFields?: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined\n /** — lookup()/enumOf()/dict() sugar key (#650 Task 2). */\n readonly lookupFields?: Record<string, LookupDescriptor> | undefined\n readonly viaFields?: Record<string, ViaFieldSpec> | undefined\n}\n\n/** The effective per-feature field maps after merging sugar keys with `viaFields`. */\nexport interface MergedViaFields {\n readonly moneyFields: Record<string, ViaDescriptor> | undefined\n readonly i18nFields: Record<string, I18nTextDescriptor> | undefined\n readonly dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined\n /** `via(computed(fn, { deps, mode }))` entries (#638 Task 7) — there is no `computed`\n * sugar KEY to merge against here (unlike money/i18n/dictKey); `collection-config.ts`\n * unions this with the `computed:` option's own entries before splitting by mode. */\n readonly computedFields: Record<string, ComputedDescriptor> | undefined\n /** `lookupFields` sugar key merged with `via(lookup(...))`/`via(enumOf(...))`/`via(dict(...))`\n * entries (#650 Task 2) — a SEPARATE binding from i18n; `dictKey()`/`staticDict()` stay\n * routed onto `dictKeyFields`/the i18n binding (the alias, unchanged). */\n readonly lookupFields: Record<string, LookupDescriptor> | undefined\n}\n\n/**\n * Merge `viaFields` (the {@link via} composer) with the money/i18n sugar\n * keys into the effective maps every consumer reads — the kernel's\n * `compileViaBindings` (the `ViaPipeline` bindings) and `vault.ts`'s own\n * i18n/dict registries (put-time validation, dict-join/search resolution)\n * both call this so a field declared via `viaFields` behaves identically to\n * one declared under its feature's sugar key.\n *\n * Each `viaFields` entry's descriptors are grouped by `_viaBrand`; an\n * `'i18n'`-branded descriptor further splits by shape (i18nText vs\n * dictKey/staticDict) via the existing descriptor-shape predicates. A field\n * name declared in BOTH a sugar key and `viaFields` throws `ValidationError`\n * — one declaration site per field (#623 Task 9).\n */\nexport function mergeViaFields(sources: ViaFieldSources): MergedViaFields {\n // Sugar-vs-sugar collision (review fix): dictKeyFields and lookupFields\n // naming the same field is otherwise silently ambiguous — mirrors the\n // viaFields-vs-sugar check below (#623 Task 9), one declaration site per field.\n for (const field of Object.keys(sources.dictKeyFields ?? {})) {\n if (sources.lookupFields && field in sources.lookupFields) {\n throw new ValidationError(\n `mergeViaFields(): field \"${field}\" is declared in both \\`dictKeyFields\\` and \\`lookupFields\\` — declare it in one place only.`,\n )\n }\n }\n if (!sources.viaFields || Object.keys(sources.viaFields).length === 0) {\n return {\n moneyFields: sources.moneyFields, i18nFields: sources.i18nFields, dictKeyFields: sources.dictKeyFields,\n computedFields: undefined, lookupFields: sources.lookupFields,\n }\n }\n const sugarFieldNames = new Set([\n ...Object.keys(sources.moneyFields ?? {}),\n ...Object.keys(sources.i18nFields ?? {}),\n ...Object.keys(sources.dictKeyFields ?? {}),\n ...Object.keys(sources.lookupFields ?? {}),\n ])\n const viaMoney: Record<string, ViaDescriptor> = {}\n const viaI18nText: Record<string, I18nTextDescriptor> = {}\n const viaDictKey: Record<string, DictKeyDescriptor | StaticDictDescriptor> = {}\n const viaComputed: Record<string, ComputedDescriptor> = {}\n const viaLookup: Record<string, LookupDescriptor> = {}\n for (const [field, spec] of Object.entries(sources.viaFields)) {\n if (sugarFieldNames.has(field)) {\n throw new ValidationError(\n `via(): field \"${field}\" is declared via both a sugar key and \\`viaFields\\` — declare it in one place only.`,\n )\n }\n for (const descriptor of spec.descriptors) {\n if (descriptor._viaBrand === 'money') {\n viaMoney[field] = descriptor\n } else if (descriptor._viaBrand === 'i18n') {\n if (isI18nTextDescriptor(descriptor)) viaI18nText[field] = descriptor\n else if (isDictKeyDescriptor(descriptor) || isStaticDictDescriptor(descriptor)) viaDictKey[field] = descriptor\n } else if (descriptor._viaBrand === 'computed') {\n viaComputed[field] = descriptor as ComputedDescriptor\n } else if (descriptor._viaBrand === 'lookup' && isLookupDescriptor(descriptor)) {\n viaLookup[field] = descriptor\n } else {\n throw new ValidationError(`via(): field \"${field}\" has a descriptor with unrecognized _viaBrand \"${descriptor._viaBrand}\" — via() only supports money/i18n/computed/lookup descriptors today.`)\n }\n }\n }\n return {\n moneyFields: Object.keys(viaMoney).length > 0 ? { ...(sources.moneyFields ?? {}), ...viaMoney } : sources.moneyFields,\n i18nFields: Object.keys(viaI18nText).length > 0 ? { ...(sources.i18nFields ?? {}), ...viaI18nText } : sources.i18nFields,\n dictKeyFields: Object.keys(viaDictKey).length > 0 ? { ...(sources.dictKeyFields ?? {}), ...viaDictKey } : sources.dictKeyFields,\n computedFields: Object.keys(viaComputed).length > 0 ? viaComputed : undefined,\n lookupFields: Object.keys(viaLookup).length > 0 ? { ...(sources.lookupFields ?? {}), ...viaLookup } : sources.lookupFields,\n }\n}\n\n/** Maps each per-family field-map's option key to its binding family name — used by\n * {@link guardCrossBindingFieldCollisions}/{@link guardReconcileCollisions} to tell a genuine\n * cross-family collision apart from the SAME family surfaced through two sugar keys\n * (`i18nFields` + `dictKeyFields` both feed the ONE 'i18n' binder — not this guard's job; a\n * family's own duplicate handling stays wherever it already lives). Moved here from\n * `collection-config.ts` (#664 Part 1) — that module now imports `guardCrossBindingFieldCollisions`\n * back from here instead (a circular import the other way: `collection-config.ts` already\n * imports FROM this module for `mergeViaFields`). Module-private — only the two guards above,\n * both in this file, read it. */\nconst VIA_FIELD_MAP_FAMILY: Readonly<Record<string, string>> = {\n moneyFields: 'money', i18nFields: 'i18n', dictKeyFields: 'i18n', lookupFields: 'lookup',\n classifiedFields: 'classified', blobFields: 'blob', computed: 'computed',\n}\n\n/**\n * #631 — declare-time cross-binding same-field collision guard. Today the same field named\n * in two DIFFERENT via-binding families (e.g. the same field in both `moneyFields` and\n * `blobFields`) resolves silently by compile-order first-wins in `ViaPipeline`'s per-field\n * posture/clause lookup — undefined pipeline behavior for a config that is almost certainly a\n * mistake. `mergeViaFields` already guards sugar-vs-`viaFields` and `dictKeyFields`-vs-\n * `lookupFields` collisions (#623 Task 9); this runs one step later, in `compileViaBindings`\n * (fresh construction) or {@link guardReconcileCollisions} (late-attach reconcile), because\n * those are the only seams that also see `classifiedFields`/`blobFields` — neither is part of\n * `ViaFieldSources`, so `mergeViaFields` never sees them.\n *\n * WHY FAMILY-BASED, NOT PROVENANCE-BASED (#631 review, round 2 — Controller ruling): a field\n * declared via `via(computed(fn), money(...))` and a field declared via two independent sugar\n * maps (`computed: { total: fn }` + `moneyFields: { total: money(...) }`) are NOT\n * distinguishable here — `mergeViaFields` folds both declaration STYLES into the IDENTICAL\n * merged per-family field maps this function receives; provenance (which style produced a given\n * map entry) is erased before this guard ever runs. Narrowing the exemption to \"only\n * via()-composed fields\" would therefore require threading a second, parallel\n * provenance-tracking data structure through `mergeViaFields` for the sole purpose of refusing a\n * config that is BEHAVIORALLY IDENTICAL to the sanctioned one — refusing it would be a\n * behavior-lock violation (breaking a legal, meaningful config), not a bug fix. The exemption is\n * therefore keyed on the FAMILY SET alone, and instead earned empirically per family (below).\n *\n * EXEMPT (test-earned, not merely asserted): `computed` colliding with EXACTLY ONE of\n * `money`/`i18n`/`lookup` on the same field. `via()`'s descriptor loop only accepts\n * money/i18n/computed/lookup `_viaBrand`s (`mergeViaFields` throws on any other brand), so a\n * computed+classified or computed+blob same-field pairing can never arise from composition — it\n * can only come from mistakenly naming the same field in `computed`/`viaFields` AND\n * `classifiedFields`/`blobFields`, which this guard still refuses. For the three families that\n * CAN legitimately arise, each is pinned by an end-to-end runtime test proving the composition\n * does something real (not just \"doesn't throw\") — see `computed/virtual.test.ts`:\n * - money: the \"composed grammar\" tests (materialized-mode money formatting the computed\n * output; the ORIGINAL evidence this exemption started from — see the money DOES/does NOT\n * format the computed output pair).\n * - i18n (dictKey) / lookup (dict()): the \"composed grammar — computed + i18n/lookup\n * families (#631 collision-guard exemption pins)\" block, BOTH declaration styles\n * (`via(computed(...), dictKey(...)/dict(...))` and the two-independent-sugar-maps form),\n * materialized mode — proven to dress `<field>Label` off the computed output identically\n * either way (the provenance-erasure claim above, empirically confirmed). Virtual mode for\n * both families hits the SAME present-ORDER limitation money's own virtual composed-grammar\n * test already documents (i18n/lookup's `present()` runs BEFORE computed's — a virtual field\n * is never stored, so there is nothing to dress yet); pinned as a known limitation, not\n * grounds to drop the family from the exemption (materialized mode is what proves the family\n * genuinely composes).\n *\n * 3-CLAIMANT TIGHTENING (#631 review, round 2): the exemption requires EXACTLY TWO claimant\n * source-keys, not just two families. A field named in `computed` + BOTH `i18nFields` AND\n * `dictKeyFields` collapses to the same two families (`{computed, i18n}` — `dictKeyFields`\n * shares the `i18n` family) but is a genuine THREE-claimant collision: two independent i18n\n * sugar keys both claiming the field is itself a mistake this guard exists to catch, and must\n * not slip through because the family SET happens to match the earned exemption's shape.\n */\nexport function guardCrossBindingFieldCollisions(\n fieldMaps: Readonly<Record<string, Record<string, unknown> | undefined>>,\n // Minor fix (opus task review on #664a) — caller-accurate error prefix: fresh construction\n // (`collection-config.ts`) keeps the old default; {@link guardReconcileCollisions} (the\n // late-attach reconcile path) passes its OWN name instead of this function silently claiming\n // to be `compileViaBindings()` on a call it never made.\n callerPrefix = 'compileViaBindings()',\n): void {\n const claimantsByField = new Map<string, Set<string>>()\n for (const [sourceKey, map] of Object.entries(fieldMaps)) {\n for (const field of Object.keys(map ?? {})) {\n const claimants = claimantsByField.get(field) ?? new Set<string>()\n claimants.add(sourceKey)\n claimantsByField.set(field, claimants)\n }\n }\n for (const [field, sourceKeys] of claimantsByField) {\n const families = new Set([...sourceKeys].map((key) => VIA_FIELD_MAP_FAMILY[key]))\n if (families.size < 2) continue // same family via two sugar keys (e.g. i18n/dictKey) — not this guard's job\n // Exactly two CLAIMANTS (not just two families) — see \"3-CLAIMANT TIGHTENING\" above.\n if (sourceKeys.size === 2 && families.has('computed')) {\n const other = [...families].find((f) => f !== 'computed')\n if (other === 'money' || other === 'i18n' || other === 'lookup') continue // composed grammar, test-earned (#638/#631)\n }\n const keys = [...sourceKeys].sort().map((k) => `\\`${k}\\``)\n const joined = keys.length === 2 ? keys.join(' and ') : `${keys.slice(0, -1).join(', ')}, and ${keys[keys.length - 1]}`\n throw new ValidationError(\n `${callerPrefix}: field \"${field}\" is declared in both ${joined} — a field cannot be claimed by two ` +\n 'different via-binding families. Declare it in one place only.',\n )\n }\n}\n\n/**\n * #664 Part 1 — the late-attach reconcile-path sibling of {@link guardCrossBindingFieldCollisions}.\n * `vault.ts`'s reconcile ladder (a second-or-later `vault.collection(name, {...})` call on an\n * ALREADY-open collection) never ran the fresh-construction guard above, so two probe recipes\n * slipped through (round-2 fable review, 2026-07-13):\n *\n * - **(a) incoming×incoming** — the SAME reconcile call names a field in two different\n * families (e.g. `moneyFields`+`blobFields` both claiming `\"amount\"`). Fix: re-run\n * {@link guardCrossBindingFieldCollisions} verbatim over THIS call's own merged field maps —\n * identical semantics to fresh construction, just invoked one call later.\n * - **(b) existing×incoming** — an EARLIER call already compiled a binding covering a field\n * (money reconciled onto it, or it shipped with the collection's first declaration), and\n * THIS call's incoming family map claims the SAME field for a DIFFERENT family (e.g. call-1\n * `classifiedFields:['ssn']`, call-2 `moneyFields:{ssn}`) — undetectable by (a) alone since\n * the collision spans two calls. Read via the LIVE collection's compiled bindings\n * (`coll._via.bindings`): each `ViaBinding.covers(field)` (`via/index.ts`) plus its `brand` tells us\n * which family already owns the field, mapped through the SAME {@link VIA_FIELD_MAP_FAMILY}\n * the incoming side uses — no new collection.ts surface needed.\n *\n * Both sub-checks honor the SAME #631 exemption (`{computed,money}`/`{computed,i18n}`/\n * `{computed,lookup}`, exactly-two-claimants) as the fresh guard — a composition that would be\n * legal in one `vault.collection()` call (`via(computed(fn), money(...))`) must stay legal when\n * split across two calls (computed declared fresh, money late-attached), since the two paths are\n * behaviorally equivalent by the same provenance-erasure argument {@link guardCrossBindingFieldCollisions}\n * documents. `existingFamilies` is collected as a SET (every binding covering the field, not just\n * the first match) so an already-legally-composed pair (e.g. existing `{computed, money}`) is\n * checked against the incoming family individually — a THIRD family colliding with either half\n * is still refused.\n */\nexport function guardReconcileCollisions(\n existingVia: ViaPipeline | undefined,\n incomingFieldMaps: Readonly<Record<string, Record<string, unknown> | undefined>>,\n): void {\n guardCrossBindingFieldCollisions(incomingFieldMaps, 'guardReconcileCollisions()') // (a) incoming×incoming\n if (!existingVia) return\n // `taint` is a posture OVERLAY, not a field-owning family — under `sealAll` its `covers()` is\n // true for every non-`_` field, so it must never be mapped through VIA_FIELD_MAP_FAMILY here\n // (same exclusion precedent as via/graph-wiring.ts's `.filter(b => b.brand !== 'taint')`).\n const existingBindings: readonly ViaBinding[] = existingVia.bindings.filter((b) => b.brand !== 'taint')\n for (const [sourceKey, map] of Object.entries(incomingFieldMaps)) {\n const incomingFamily = VIA_FIELD_MAP_FAMILY[sourceKey]\n if (incomingFamily === undefined) continue\n for (const field of Object.keys(map ?? {})) {\n const existingFamilies = new Set(\n existingBindings.filter((b) => b.covers?.(field)).map((b) => b.brand),\n )\n for (const existingFamily of existingFamilies) {\n if (existingFamily === incomingFamily) continue // same family — first-wins on the _apply* side handles it\n const isExempt = (existingFamily === 'computed' && (incomingFamily === 'money' || incomingFamily === 'i18n' || incomingFamily === 'lookup'))\n || (incomingFamily === 'computed' && (existingFamily === 'money' || existingFamily === 'i18n' || existingFamily === 'lookup'))\n if (isExempt) continue // composed grammar, test-earned (#638/#631) — legal fresh, stays legal late\n throw new ValidationError(\n `vault.collection(): field \"${field}\" is already bound by the \"${existingFamily}\" via family on this ` +\n `collection — an incoming \\`${sourceKey}\\` declaration cannot claim it for a different family ` +\n `(\"${incomingFamily}\"). Declare it in one place only.`,\n )\n }\n }\n }\n}\n","/**\n * Collection construction config — the PURE half of the `Collection`\n * constructor.\n *\n * `resolveCollectionConfig` takes the raw `CollectionOpts` the Vault threads in\n * and resolves every `?? default`, every normalized/derived field, and runs the\n * pure construction-time validations (embeddings-on-CRDT, money-field paths,\n * deterministic-risk acknowledgement). It holds **no `this`** and performs no\n * external side effect — the only objects it allocates (`Set`s, `VectorSet`,\n * the CEK `Lru`) are the same instances the collection then owns by reference.\n *\n * The `this`-dependent construction (the search-index store whose persisted\n * callback closes over `this.searchContext()`, the `RecordCodec`, and the\n * SyncEngine conflict-resolver registration) stays in the constructor — those\n * genuinely capture the live instance (and the conflict-resolver closures close\n * over `conflictPolicy: ConflictPolicy<T>`, whose invariant-in-T custom-merge\n * signature can't be exposed via a method without breaking `Collection<T>`\n * assignability to `Collection<unknown>`).\n */\nimport type { StrategyBag } from '../port/with/strategies.js'\nimport type { NoydbStore, ConflictPolicy, CollectionConflictResolver, HistoryConfig, TierMode, CrossTierAccessEvent, VdigFieldPolicy } from './types.js'\nimport type { EnclaveKey } from './enclave/index.js'\nimport type { UnlockedKeyring } from '../with-party/team/keyring.js'\nimport type { NoydbEventEmitter } from './events.js'\nimport type { WriteQueueTracker } from './write-queue.js'\nimport type { WriteHookRegistry } from '../port/with/write-hooks.js'\nimport type { ServiceBus } from '../port/with/service-bus.js'\nimport type { SchemaUpdateGate } from '../with-shape/schema-update/gate.js'\nimport type { SchemaFenceController } from '../with-shape/schema-update/fence-controller.js'\nimport type { StandardSchemaV1 } from './schema.js'\nimport type { LedgerStore } from '../with-commit/history/ledger/index.js'\nimport type { CrdtMode } from '../with-commit/crdt/crdt.js'\n// CrdtStrategy imported directly from ./types.js (not with-commit/crdt/strategy.js)\n// — #667: collection-config.ts sits in the shared dts chunk with types.ts, so\n// routing this through strategy.ts's re-export closed a cycle in the dts rollup\n// graph. NO_CRDT (a runtime value, only defined in strategy.ts) still comes from there.\nimport type { ObjectProjection } from '../with-shape/blobs/object-projection.js'\nimport type { BlobFieldsConfig } from '../with-shape/blobs/blob-compaction.js'\nimport type { IndexDef } from '../with-lookup/indexing/eager-indexes.js'\nimport type { I18nTextDescriptor, DictKeyDescriptor, StaticDictDescriptor, DictionaryHandle } from '../port/with/i18n-strategy.js'\n// #650 Task 2 — `LookupDescriptor` type-only, mirroring the i18n descriptor\n// imports above; no eager value import needed (lookup()/enumOf()/dict()\n// each call `linkLookupVia()` themselves, so `viaBinder('lookup')` is\n// already resolvable by the time a `lookupFields` entry exists).\nimport type { LookupDescriptor, MaterializedBacking } from '../port/with/lookup-strategy.js'\nimport { buildPresentForJoin } from '../port/with/lookup-strategy.js'\nimport type { ComputedFields, ComputedFn, ComputedFieldEntry } from '../with-formula/computed/index.js'\nimport type { RollupDeleteIntent } from './via/dispatch.js'\n// #638 Task 7 — the value import (not just `import type`) forces the port module's eager\n// `linkComputedVia()` to run whenever this file loads (collection-config.ts is always in the\n// dependency graph), so `viaBinder('computed')` is resolvable before `compileViaBindings` needs it.\nimport '../port/with/computed-strategy.js'\nimport type { ComputedDescriptor } from '../port/with/computed-strategy.js'\nimport {\n resolveClassifiedFields, guardClassifiedCompat,\n type ClassifiedEntry, type ResolvedClassified, type ClassifiedGuardCtx, type ClassifiedViaConfig,\n} from '../port/with/classified-strategy.js'\nimport { ClassifiedConfigError, ValidationError, UnsupportedTierCompositionError } from './errors.js'\nimport type { FieldRef, Grain } from './via/graph.js'\nimport type { FieldMeta } from '../with-shape/introspection/field-meta.js'\nimport type { CollectionMeta } from '../with-shape/introspection/meta.js'\nimport type { RefDescriptor } from './refs.js'\nimport type { JoinableSource } from './query/index.js'\nimport { VectorSet, type EmbeddingDescriptor } from '../with-lookup/embeddings/index.js'\nimport { Lru } from './cache/index.js'\nimport type { ReadOnlyVaultFacade } from '../with-audit/guards/types.js'\nimport type { DerivationRegistry } from '../with-formula/derivations/registry.js'\nimport type { TxContext } from '../with-commit/tx/transaction.js'\nimport type { MaterializedViewRegistry } from '../with-formula/materialized-views/registry.js'\nimport type { MVQueryContext } from '../with-formula/materialized-views/types.js'\nimport type { Collection, OnDirtyCallback, CacheOptions } from './collection.js'\nimport { ViaPipeline } from './via/pipeline.js'\nimport { viaBinder, type ViaBinding, type ViaDescriptor } from './via/index.js'\nimport { mergeViaFields, guardCrossBindingFieldCollisions, type ViaFieldSpec } from './via/compose.js'\n\n/**\n * Raw options handed to the {@link Collection} constructor by the Vault.\n * One named type shared by the constructor and the pure resolver.\n */\nexport interface CollectionOpts<T> {\n adapter: NoydbStore\n vault: string\n name: string\n keyring: UnlockedKeyring\n encrypted: boolean\n /**\n * Every opt-in service, resolved once by `createNoydb` (#838). Replaces the\n * eleven optional `*Strategy` fields this interface used to declare, each of\n * which re-applied a `?? NO_*` default that had already been applied\n * upstream. Each entry is a tree-shake seam: an un-opted-in service holds\n * its `NO_*` stub, so the real machinery never reaches the bundle.\n */\n strategies: StrategyBag\n /**\n * Opt-in: keep the working set encrypted in RAM, decrypting on read (future phase).\n * Default false — the working set is plaintext.\n */\n ramCiphertext?: boolean\n emitter: NoydbEventEmitter\n /**\n * Vault-level in-flight write tracker. When present,\n * `put`/`delete` run inside `writeQueue.track()` so `hub.writeQueue`\n * reflects outstanding writes. Optional so direct Collection\n * construction in tests still works untracked.\n */\n writeQueue?: WriteQueueTracker | undefined\n /** Per-collection schema-update gate; `put`/`delete` await it. */\n schemaUpdateGate?: SchemaUpdateGate | undefined\n /** Vault-level fence controller; `put`/`delete` consult it. */\n schemaFence?: SchemaFenceController | undefined\n /** Hub-level write-hook registry; fired around put/delete. */\n writeHooks?: WriteHookRegistry | undefined\n /** The observe bus, threaded from Noydb. */\n subsystemBus?: ServiceBus | undefined\n /** Active transaction id supplier (null outside a transaction). */\n activeTxId?: (() => string | null) | undefined\n getDEK: (collectionName: string) => Promise<EnclaveKey>\n historyConfig?: HistoryConfig | undefined\n /**\n * When `true`, the caller explicitly provided `historyConfig` rather than\n * inheriting the vault-wide default. Used by `getConfig()` to decide\n * whether to surface `history: true` in the schema dump.\n */\n historyConfigExplicit?: boolean | undefined\n onDirty?: OnDirtyCallback | undefined\n /**\n * #693: live check for whether multi-tab coordination is active at all\n * (`Noydb._tabCoordinationActive`). When true, the shared local store may be\n * written out-of-band by another tab, so the #606 marker-id-set gate falls\n * back to an unconditional store read on re-create.\n */\n tabCoordinated?: (() => boolean) | undefined\n objectStore?: ObjectProjection | undefined\n blobFields?: BlobFieldsConfig | undefined\n /**\n * #724 Arc 10 Task 3: how `elevate()`/`demote()`/`putAtTier()` rehome a\n * SHARED blob (`refCount > 1`) it can't rewrap in place. `'isolate'`\n * (default) forks a private tier-scoped copy for the moving record and\n * releases its hold on the shared object — co-owners stay byte-for-byte\n * untouched. `'dedup'` (#741, opt-in) leaves the shared object in place;\n * the Task-1 runtime read gate still hides it, but the chunks stay\n * decryptable at rest under the flat `_blob` DEK (documented residue).\n */\n blobTierPolicy?: 'isolate' | 'dedup' | undefined\n indexes?: IndexDef[] | undefined\n /**\n * Auto-reconcile behavior for persisted-index drift on lazy-mode\n * collections. Defaults to `'off'` — operators call\n * `collection.reconcileIndex(field)` explicitly.\n *\n * - `'off'` (default): no implicit work. Same semantics as.\n * - `'dry-run'`: on first lazy-mode query, run\n * `reconcileIndex(field, { dryRun: true })` per declared field\n * and emit `index:reconciled` with the diff. Nothing is written.\n * - `'auto'`: same walk as `'dry-run'` but with `dryRun: false`.\n * Drift is repaired in-place and the fix count surfaces on the\n * event.\n *\n * Unattended long-lived processes (Workers, Node services with no\n * human operator) should set `'auto'`. Attended desktop apps should\n * leave it `'off'` and surface a manual \"rebuild indexes\" button.\n */\n reconcileOnOpen?: 'off' | 'dry-run' | 'auto'\n /**\n * Hydration mode. `'eager'` (default) loads everything into memory on\n * first access — matches behavior exactly. `'lazy'` defers loads\n * to per-id `get()` calls and bounds memory via the `cache` option.\n */\n prefetch?: boolean\n /**\n * LRU cache options. Only meaningful when `prefetch: false`. At least\n * one of `maxRecords` or `maxBytes` must be set in lazy mode — an\n * unbounded lazy cache defeats the purpose.\n */\n cache?: CacheOptions | undefined\n /**\n * Optional Standard Schema v1 validator (Zod, Valibot, ArkType,\n * Effect Schema, etc.). When set, every `put()` is validated before\n * encryption and every read is validated after decryption. See the\n * `schema` field docstring for the error semantics.\n */\n schema?: StandardSchemaV1<unknown, T> | undefined\n /** Declares this collection a satellite of `satelliteOf` (spec #591). */\n satelliteOf?: string | undefined\n /** Satellite routing table — the fields owned by this satellite (required with satelliteOf). */\n fields?: readonly string[] | undefined\n /** Registers the full-record joined handle under this name (optional; see vault.joined()). */\n joined?: string | undefined\n /**\n * Optional reference to the compartment's hash-chained ledger.\n * When present, successful mutations append a ledger entry via\n * `LedgerStore.append()`. Constructed at the Vault level and\n * threaded through — see the Vault.collection() source for\n * the wiring.\n */\n ledger?: LedgerStore | undefined\n /**\n * Optional back-reference to the owning compartment's ref\n * enforcer`).\n * Collection.put calls `enforceRefsOnPut` before the adapter\n * write; Collection.delete calls `enforceRefsOnDelete` before\n * its own adapter delete. See the `refEnforcer` field docstring\n * for the full protocol.\n */\n refEnforcer?:\n | {\n enforceRefsOnPut(collectionName: string, record: unknown): Promise<void>\n enforceRefsOnDelete(collectionName: string, id: string): Promise<void>\n /** #922 — see `Vault._deleteCascadesPossible`; consulted by `_txAtomicSafe('delete')`. */\n _deleteCascadesPossible(collectionName: string): boolean\n }\n | undefined\n /**\n * Optional back-reference to the owning compartment's join\n * resolver. When present, `query()` builds a\n * `JoinContext` so `.join(field)` can resolve through the\n * existing `ref()` declaration into the target collection.\n * Absent in tests that construct a Collection directly without\n * a vault; production usage always has one because\n * Vault.collection() passes `this` through.\n */\n joinResolver?:\n | {\n resolveSource(collectionName: string): JoinableSource | null\n resolveRef(leftCollection: string, field: string): RefDescriptor | null\n resolveDictSource?: (leftCollection: string, field: string) => JoinableSource | null\n }\n | undefined\n /** — i18nText field descriptors for locale-aware reads. */\n i18nFields?: Record<string, I18nTextDescriptor> | undefined\n /** — embedding config for write-time vector derivation + semantic retrieval. */\n embeddings?: EmbeddingDescriptor | undefined\n /** — string fields exposed to client-side `retrieve()`. */\n textIndexes?: readonly string[] | undefined\n /** — pre-build the lexical index on open (eager-only). */\n warmIndexOnOpen?: boolean | undefined\n /** — persist the lexical index as an opaque encrypted blob at `_ftindex/<name>`. */\n textIndexPersist?: boolean | undefined\n /** — dictKey field descriptors for label resolution on reads. */\n dictKeyFields?: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined\n /** — consumer-neutral per-field descriptors. Read via getFieldMeta(). */\n fieldMeta?: Record<string, FieldMeta> | undefined\n /** — collection-level descriptive metadata. Read via getMeta(). */\n meta?: CollectionMeta | undefined\n moneyFields?: Record<string, ViaDescriptor> | undefined\n /** — declare via() composed fields; grouped by `_viaBrand` and merged with the money/i18n sugar keys above (a field in both throws). */\n viaFields?: Record<string, ViaFieldSpec> | undefined\n /** — outbound ref declarations (snapshot from vault refRegistry). Used by describe(). */\n declaredRefs?: Record<string, RefDescriptor> | undefined\n computed?: ComputedFields | undefined\n /** — declare classified() sensitive-field descriptors (sealed + riders + projections). */\n classifiedFields?: Record<string, ClassifiedEntry> | undefined\n /**\n * The forget-cascade subject key for this collection (from\n * `withForget({ subjects })`), plumbed by the Vault. Consumed by the\n * classified refusal matrix (R4: a digest-only field cannot be the subject key).\n */\n subjectKeyField?: string | undefined\n /**\n * Register a record's forget-subject ref directly (bypassing the write-hook\n * pipeline), wired by the Vault when this collection declares a forget-\n * subject field. Consumed by `putAtTier` (#766, via `TiersContext.addSubjectRef`)\n * so a record whose first write is a tier write still enters `_subject_index`.\n * `undefined` when no forget strategy declares this collection (no-op).\n */\n addSubjectRef?: ((id: string, record: unknown) => Promise<void>) | undefined\n /**\n * async callback that resolves a dict key to its label\n * for a given locale. Provided by the Vault.\n */\n dictLabelResolver?:\n | ((\n dictName: string,\n key: string,\n locale: string,\n fallback?: string | readonly string[],\n ) => Promise<string | undefined>)\n | undefined\n /**\n * Async callback to open a dynamic dictionary handle.\n * Provided by the Vault for dynamic-dict label-map resolution in\n * the search index. Static dicts bypass this.\n */\n getDictionary?: ((name: string) => Promise<DictionaryHandle>) | undefined\n /**\n * synchronous callback that validates i18nText fields\n * on put. Provided by the Vault. Throws MissingTranslationError.\n */\n i18nPutValidator?: ((record: unknown) => void) | undefined\n /** — declare lookup()/enumOf()/dict() fields (#650 Task 2 sugar key, mirrors dictKeyFields), merged with `via(lookup(...))` entries. */\n lookupFields?: Record<string, LookupDescriptor> | undefined\n /**\n * async label resolver for the `'lookup'` binding's `'static'`/`'reserved'`\n * tiers. Provided by the Vault — the SAME closure as `dictLabelResolver`\n * (static table first, else the `vault.dictionary()` handle), so a\n * native `dict()`/`lookup(static)` field resolves through identical\n * label data as its `dictKey()`/`staticDict()` alias.\n */\n lookupLabelResolver?:\n | ((dimension: string, key: string, locale: string, fallback?: string | readonly string[]) => Promise<string | undefined>)\n | undefined\n /** — the matrix (`backing:'collection'`) tier's present-time row accessor, keyed by the full\n * descriptor so it can resolve by `descriptor.key`, not the backing row's PUT-id (#651 Task 3).\n * Provided by the Vault. */\n getLookupBacking?: ((descriptor: LookupDescriptor) => (key: string) => Promise<Record<string, unknown> | undefined>) | undefined\n /** — closed-vocabulary write-time membership test (#650 Task 3). Provided by the Vault. */\n membership?: ((field: string, key: string) => boolean | Promise<boolean>) | undefined\n /** — altKeys `ingest` normalization source (#650 Task 3). Provided by the Vault. */\n getAltIndex?: ((desc: LookupDescriptor) => MaterializedBacking | undefined) | undefined\n /**\n * — sync materialized `key -> row` rows for a lookup descriptor (#650\n * Task 6, spec §5's snapshot+locale seam; matrix-tier routing added Task\n * 7). Provided by the Vault; feeds the `'lookup'` binding's\n * `compareForOrder`/`resolveOrderLabel` and this collection's\n * `presentForJoin` hook (`resolveCollectionConfig` builds the latter via\n * `buildPresentForJoin`, below).\n */\n snapshotFor?: ((descriptor: LookupDescriptor) => ReadonlyMap<string, Record<string, unknown>> | undefined) | undefined\n /**\n * translator callback from Noydb. When present, missing\n * translations for `autoTranslate: true` i18nText fields are generated\n * before the i18n validator runs.\n */\n autoTranslateHook?:\n | ((text: string, from: string, to: string, field: string, collection: string) => Promise<string>)\n | undefined\n /**\n * vault-default locale, inherited from\n * `openVault(name, { locale })` or `vault.setLocale()`.\n */\n defaultLocale?: string | undefined\n /**\n * collection-level conflict resolution policy.\n * Overrides the db-level `conflict` option for this collection only.\n */\n conflictPolicy?: ConflictPolicy<T> | undefined\n /**\n * callback to register an envelope-level resolver with the\n * SyncEngine. Provided by the Vault (wired from the SyncEngine).\n */\n onRegisterConflictResolver?: ((name: string, resolver: CollectionConflictResolver) => void) | undefined\n /**\n * CRDT mode for this collection. When set, `put()` stores\n * CRDT state in the envelope and `get()` returns the resolved snapshot.\n * `getRaw(id)` returns the full CRDT state for merge operations.\n */\n crdt?: CrdtMode | undefined\n /**\n * optional remote/sync adapter. When present, `presence()`\n * writes heartbeats to this adapter so other devices can read them.\n * If the adapter implements pub/sub, presence updates are real-time.\n */\n syncAdapter?: NoydbStore | undefined\n /**\n * called by the collection after every successful\n * `get` / `put` / `delete`. The Vault installs a callback that\n * appends a consent-audit entry when `withConsent` is active;\n * outside a consent scope the callback is a no-op. Awaited so a\n * thrown audit write surfaces to the caller.\n */\n onAccess?: (op: 'get' | 'put' | 'delete' | 'reveal' | 'verify' | 'find', id: string) => Promise<void>\n /**\n * invoked by `put`/`delete` before any adapter\n * write. Receives the prior envelope timestamp + decrypted\n * record (or `null` if no prior) and the incoming record (or\n * `null` for delete). Throws `PeriodClosedError` to abort.\n */\n /**\n * opt-in deterministic-encryption index.\n *\n * Field names listed here get a deterministic AES-GCM ciphertext\n * attached to every envelope's `_det` map, which enables blind\n * equality search via `collection.findByDet(field, value)`.\n *\n * **Leaks equality.** Two records with the same value in a\n * deterministic field produce identical ciphertexts, so anyone\n * with store access can tell which records share a value without\n * learning the value itself. This is the textbook trade-off of\n * deterministic encryption — strictly opt-in for that reason.\n *\n * Declaring any field here without also passing\n * `acknowledgeDeterministicRisk: true` throws at construction,\n * so the risk must be explicitly acknowledged.\n */\n deterministicFields?: readonly string[] | undefined\n /**\n * gate for `deterministicFields`. Must be `true` when\n * any deterministic field is declared. Any other value throws.\n */\n acknowledgeDeterministicRisk?: boolean | undefined\n /**\n * gate for the classified `equatable` knob (R8 double door). Must be `true`\n * when any classified field declares `equatable: true`; otherwise construction\n * throws. One-directional — setting it with zero equatable members is a\n * silent no-op (mirrors `acknowledgeDeterministicRisk`).\n */\n acknowledgeEquatableRisk?: boolean | undefined\n /**\n * Structural group-encryption. Fields listed here are\n * encrypted into their own `_sealed[field]` envelope slot — each under\n * an HKDF-derived per-field key — instead of sitting inside the open\n * `_data` blob. Default-off: with no `sensitive` fields the envelope is\n * byte-identical to today. Read merges them back inline (the\n * `Sealed<V>`/`reveal()` access restriction is a separate follow-up).\n *\n * **Incompatible with `perRecordKeys`/forget-cascade:** sealed\n * field keys derive off the *collection* DEK, not the per-record CEK, so\n * crypto-shredding a record does not erase its sealed fields.\n */\n sensitive?: readonly string[] | undefined\n /**\n * Per-record content-encryption keys. When `true`, every record body\n * (and every history version of it) is encrypted under a fresh\n * per-record CEK, AES-KW-wrapped under the collection DEK and stored\n * on the envelope's `_cek`. Off by default. Foundation for per-record\n * erasure and record-scoped sealing. `_det` slots stay\n * keyed to the collection DEK regardless.\n */\n perRecordKeys?: boolean | undefined\n /**\n * Per-record provenance tracking. When `true`, `put()` calls that\n * supply a `source` option stamp `_source` (opaque source id) and\n * `_sourceTs` (ISO-8601 timestamp) onto the unencrypted envelope\n * metadata. Off by default — zero cost for collections that don't\n * need lineage tracking.\n */\n provenance?: boolean | undefined\n /**\n * declared tiers this collection supports. An\n * undefined or empty list disables the hierarchical-tier surface\n * on this collection (`putAtTier`, `getAtTier`, `elevate`, `demote`\n * throw). Tier 0 is implicit and always available.\n */\n tiers?: readonly number[] | undefined\n /**\n * what a lower-tier caller sees for above-tier\n * records. Default `'invisibility'`.\n */\n tierMode?: TierMode | undefined\n /**\n * optional callback fired on every cross-tier access.\n * Provided by the Vault; collects notification events and writes\n * to the ledger.\n */\n onCrossTierAccess?: ((event: CrossTierAccessEvent) => void) | undefined\n /**\n /**\n * Optional back-reference to the owning vault's derivation\n * registry + collection accessor. When present, successful\n * `put()` dispatches registered derivation strategies for the\n * source collection.\n */\n derivationSource?: {\n registry(): DerivationRegistry\n getCollection(name: string): Collection<Record<string, unknown>>\n /**\n * Read-only vault facade handed to `derive(source, ctx)` so a\n * derivation can fetch sibling records. Same shape and\n * instance the guards service uses for `check(incoming, ctx)`.\n */\n getReadOnlyFacade(): ReadOnlyVaultFacade\n /**\n * Read access to the owning Noydb's currently-active multi-record\n * transaction context, or `null` when no transaction is running.\n * `dispatchDerivations` consults this so a recursive derived-output\n * write can register its pre-write envelope onto `ctx._executed`\n * and roll back alongside the source op on mid-batch failure.\n */\n getActiveTxContext(): TxContext | null\n /**\n * Construct a transient TxContext bound to the owning Noydb. Used\n * by `Collection.putManyAtomic` to publish an active context for\n * its Phase 2 loop.\n */\n createTxContext(): TxContext\n /** Publish a TxContext for the duration of a bulk-atomic loop. */\n setActiveTxContext(ctx: TxContext): void\n /** Drop a previously-published TxContext. */\n clearActiveTxContext(ctx: TxContext): void\n } | undefined\n /**\n * Vault-internal hook for materialized-view dispatch.\n * Parallel to `derivationSource`. When set, `Collection.put` fires\n * registered MV `onSourceWrite` after the standard derivation\n * dispatch.\n */\n materializedViewSource?: {\n\n registry(): MaterializedViewRegistry\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getCollection(name: string): Collection<any>\n getActiveTxContext(): TxContext | null\n getQueryContext(): MVQueryContext\n } | undefined\n /**\n * #638 Task 4 — thin collector hook wired by the Vault (`Vault._collectGraphTouch`). Every\n * `sync-apply`/`cutover`/`restore` mutation origin calls `collect(this.name, id)`; a no-op\n * when no batch is open (`_beginGraphBatch()` wasn't called) or the vault has no graph.\n * `collectDelete` (#640) is the sync-apply delete socket — the resolved rollup-parent intents\n * for a deleted record, captured pre-invalidation.\n */\n graphDispatch?:\n | { collect(collection: string, id: string): void; collectDelete(collection: string, id: string, intents: readonly RollupDeleteIntent[]): void }\n | undefined\n}\n\n/** One normalized `ComputedFields` entry — a plain `ComputedFn` or a `ComputedFieldEntry`\n * reduced to its parts, `mode` always defaulted (#638 Task 7). Exported so\n * `via/graph-wiring.ts`'s reconcile-path guard can check `mode` without duplicating\n * the plain-fn-vs-object-form normalization. */\nexport interface ComputedEntryParts { readonly fn: ComputedFn; readonly deps?: readonly string[]; readonly mode: 'materialized' | 'virtual' }\n\nexport function computedEntryParts(entry: ComputedFn | ComputedFieldEntry): ComputedEntryParts {\n if (typeof entry === 'function') return { fn: entry, mode: 'materialized' }\n return { fn: entry.fn, ...(entry.deps !== undefined ? { deps: entry.deps } : {}), mode: entry.mode ?? 'materialized' }\n}\n\n/**\n * #638 Task 7 — union the `computed:` sugar option with `via(computed(...))`-declared\n * entries (`kernel/via/compose.ts#mergeViaFields`'s `computedFields` output) into ONE\n * per-field map. NEVER includes `resolvedClassified.riderComputed` — that sanctioned\n * classified→computed channel (seam map Part 4) stays outside every guard this map feeds\n * (`resolveComputedEdges`'s depsless-on-classified refusal, the rider-name collision check).\n * Both `compileViaBindings` (to find `mode: 'virtual'` fields) and `resolveCollectionConfig`\n * (to split materialized entries into `mergedComputed` + extract graph edges) read this.\n */\nfunction unifyComputedFields<T>(opts: CollectionOpts<T>, viaComputedFields: Record<string, ComputedDescriptor> | undefined): ComputedFields {\n return { ...(opts.computed ?? {}), ...(viaComputedFields ?? {}) }\n}\n\n/**\n * Compile a collection's declared config into the ordered list of `ViaBinding`s\n * for its `ViaPipeline`.\n *\n * money then i18n then lookup then classified then blob then computed — order\n * pinned for pipeline parity with the hand-wired baseline this replaces: money\n * encode ran before the i18n write stages, and money decode ran before i18n\n * locale/dict-label resolution on read. Lookup compiles right after i18n\n * (#650 Task 2) — a separate binding for native lookup()/enumOf()/dict()\n * fields (`dictKeyFields`/`dictKey()`/`staticDict()` stay on the i18n\n * binding above, unchanged); its `present` hook only adds `<field>Label`,\n * same shape of read-time addition as i18n's own dict-label dressing, and\n * declares no write-pipeline hooks yet (Task 3 adds `ingest`/`enforceWrite`).\n * Classified compiles after those (#629 Task 6): its\n * `encodeAtRest`/`decodeAtRest` hooks make the pipeline's `hasAtRestHooks`\n * true, retiring the codec's inline `sensitiveFields` seal path\n * (record-codec.ts) for any collection that declares `classifiedFields` —\n * `classifiedGuardCtx` is the SAME `ClassifiedGuardCtx`\n * `resolveCollectionConfig` already built for door 1's\n * `guardClassifiedCompat` call, threaded in by its one caller below. Blob\n * compiles next (#629 Task 7) but its position is inert: the blob binding\n * declares NO write/read pipeline hooks (blob content is out-of-band\n * `BlobSet` side-collections — it must never flip `hasAtRestHooks`), only\n * `erase`/`describeFragment`. Computed compiles LAST (#638 Task 7) — its\n * `present` hook must run AFTER money's own `present` so a virtual field's\n * `deps` read the decoded (quantized) amount, not the raw stored form; at\n * present-time i18n/lookup's DRESSING now runs AFTER computed instead (#665\n * `_presentOrder`, `via/pipeline.ts` — compile order here is unchanged).\n * `via/graph-wiring.ts#applyTaintOverlay` appends the `taint`\n * binding after WHATEVER this function returns, so taint's present-time\n * redaction always runs after computed's regardless of this ordering.\n * {@link Collection._applyMoneyFields} PREPENDS money for the same reason\n * on its own (MV-precreation reconcile) path — see its docstring;\n * {@link Collection._applyClassifiedFields} APPENDS classified on that same\n * reconcile path (blobFields/computed have no late-attach reconcile door —\n * `viaFields`, like i18nFields/dictKeyFields, is construction-only).\n *\n * `eraseCfgOut` (#629 Task 10, optional out-param) — this function runs\n * before the owning `Collection` exists (`this.codec` isn't built yet), so\n * the classified binding's `classifySealedShred` closure can't be wired\n * here. When supplied, `eraseCfgOut.classified` is set to the SAME cfg\n * object instance handed to `viaBinder('classified')`, so a caller\n * (`resolveCollectionConfig`) can thread it out to the `Collection`\n * constructor, which mutates `classifySealedShred` in place once\n * `this.codec` exists. Additive — every existing caller omits it and keeps\n * getting a plain `ViaBinding[]`.\n */\nexport function compileViaBindings<T>(\n opts: CollectionOpts<T>,\n classifiedGuardCtx: ClassifiedGuardCtx,\n eraseCfgOut?: { classified?: ClassifiedViaConfig },\n): ViaBinding[] {\n const { moneyFields, i18nFields, dictKeyFields, computedFields, lookupFields } = mergeViaFields(opts)\n const allComputedFields = unifyComputedFields(opts, computedFields)\n guardCrossBindingFieldCollisions({\n moneyFields, i18nFields, dictKeyFields, lookupFields,\n classifiedFields: opts.classifiedFields !== undefined\n ? resolveClassifiedFields(opts.name, opts.classifiedFields).byField\n : undefined,\n blobFields: opts.blobFields,\n computed: allComputedFields,\n })\n const bindings: ViaBinding[] = []\n // #669 — hoisted above the money push (was built at the tail of this function, alongside\n // the `computed` binding push below) so money's own binding config can be told which of\n // ITS fields are ALSO virtual-mode computed (the money+virtual-on-the-same-field\n // MAJOR-UNITS case) — money needs this at construction time; nothing else in this\n // function depends on the hoist.\n const virtualFields = new Map<string, ComputedDescriptor>()\n for (const [field, entry] of Object.entries(allComputedFields)) {\n const parts = computedEntryParts(entry)\n if (parts.mode === 'virtual') {\n virtualFields.set(field, { _viaBrand: 'computed', fn: parts.fn, mode: 'virtual', ...(parts.deps !== undefined ? { deps: parts.deps } : {}) })\n }\n }\n if (moneyFields) {\n const virtualMoney = resolveVirtualMoneyFields(Object.keys(moneyFields), (f) => virtualFields.has(f))\n bindings.push(viaBinder('money')({ moneyFields, ...(virtualMoney.size > 0 ? { virtualMoneyFields: virtualMoney } : {}) }))\n }\n if (i18nFields || dictKeyFields) {\n // Densify-enabled subset (fields opting into `densifyOnWrite: true`) —\n // undefined when none opt in, so the write path skips densify work\n // entirely for ordinary collections.\n const densify = i18nFields\n ? Object.fromEntries(\n Object.entries(i18nFields).filter(([, d]) => d.options.densifyOnWrite === true),\n )\n : {}\n const i18nDensifyFields = Object.keys(densify).length > 0 ? densify : undefined\n bindings.push(viaBinder('i18n')({\n ...(i18nFields !== undefined ? { i18nFields } : {}),\n ...(dictKeyFields !== undefined ? { dictKeyFields } : {}),\n ...(i18nDensifyFields !== undefined ? { i18nDensifyFields } : {}),\n strategy: opts.strategies.i18n,\n ...(opts.defaultLocale !== undefined ? { defaultLocale: opts.defaultLocale } : {}),\n ...(opts.autoTranslateHook !== undefined ? { autoTranslateHook: opts.autoTranslateHook } : {}),\n ...(opts.dictLabelResolver !== undefined ? { dictLabelResolver: opts.dictLabelResolver } : {}),\n ...(opts.i18nPutValidator !== undefined ? { i18nPutValidator: opts.i18nPutValidator } : {}),\n collectionName: opts.name,\n }))\n }\n // #650 Task 2 — native lookup()/enumOf()/dict() fields (the `lookupFields`\n // sugar key, merged with `via(lookup(...))` entries by mergeViaFields). A\n // SEPARATE binding from i18n above — dictKey()/staticDict() stay on the\n // i18n binding (the alias, unchanged); a collection declaring BOTH\n // dictKeyFields and lookupFields compiles both bindings.\n // must move together with via/reconcile.ts's lookup binder-config block (reconcileLookupFields,\n // the `viaBinder('lookup')({...})` call) (#664) — same option-shape contract.\n if (lookupFields !== undefined) {\n bindings.push(viaBinder('lookup')({\n lookupFields,\n ...(opts.lookupLabelResolver !== undefined ? { lookupLabelResolver: opts.lookupLabelResolver } : {}),\n ...(opts.getLookupBacking !== undefined ? { getLookupBacking: opts.getLookupBacking } : {}),\n ...(opts.membership !== undefined ? { membership: opts.membership } : {}),\n ...(opts.getAltIndex !== undefined ? { getAltIndex: opts.getAltIndex } : {}),\n ...(opts.snapshotFor !== undefined ? { snapshotFor: opts.snapshotFor } : {}),\n collectionName: opts.name,\n }))\n }\n if (opts.classifiedFields !== undefined) {\n const classifiedCfg: ClassifiedViaConfig = {\n entries: opts.classifiedFields,\n collectionName: opts.name,\n guardCtx: classifiedGuardCtx,\n }\n if (eraseCfgOut) eraseCfgOut.classified = classifiedCfg\n bindings.push(viaBinder('classified')(classifiedCfg))\n }\n if (opts.blobFields !== undefined) {\n bindings.push(viaBinder('blob')({\n fields: opts.blobFields,\n collectionName: opts.name,\n }))\n }\n if (virtualFields.size > 0) {\n bindings.push(viaBinder('computed')({ virtualFields }))\n }\n return bindings\n}\n\n/**\n * The money∩virtual-mode-computed field-name intersection (#669) — shared by\n * `compileViaBindings` above (fresh construction, `isVirtual` closes over the just-built\n * `virtualFields` Map) and {@link Collection._applyMoneyFields} (late-attach, `isVirtual`\n * closes over the already-compiled pipeline's `computed` binding instead — virtual-mode\n * computed fields have no late-attach door of their own (declaring one on a reconcile call\n * throws), so by the time money reconciles onto an existing collection, any virtual field\n * is already sitting in `bindings`, never in `this.computed`: `resolveCollectionConfig`\n * deliberately excludes virtual-mode entries from the map it assigns to `this.computed`,\n * since that field feeds ONLY the write-time `evalComputedFields` path — see\n * `materializedComputed` above). Both callers get the identical intersection semantics from\n * one function, so money's `presentLate` MAJOR-UNITS dressing (`via/money/binding.ts`) can\n * never silently disagree between the fresh and late-attach paths.\n */\nexport function resolveVirtualMoneyFields(\n moneyFieldNames: Iterable<string>,\n isVirtual: (field: string) => boolean,\n): Set<string> {\n const out = new Set<string>()\n for (const field of moneyFieldNames) if (isVirtual(field)) out.add(field)\n return out\n}\n\n/** One `ViaGraph.registerDerived` call's worth of edge data — target + sources,\n * `kind` chosen by the caller (#638 Task 2 edge extraction). `grain` defaults to\n * `'record'` when absent; `resolveComputedEdges` (#638 Task 7) sets it to `'virtual'`\n * for a `mode: 'virtual'` computed field's edge. */\nexport interface GraphEdge { readonly target: FieldRef; readonly sources: readonly FieldRef[]; readonly grain?: Grain }\n\n/**\n * The known-field-name universe builder (#638 Task 2 fix wave 2) — used by\n * {@link resolveCollectionConfig} to validate `resolveViaBindingDepsEdges`'s `deps`\n * entries, and by {@link resolveComputedEdges}'s classified-collection dep-name check\n * (Finding I2ii's \"shared, so the two paths cannot silently drift apart\" rationale).\n * #638 Task 7 dropped `resolveComputedEdges`'s dep-name check entirely (legalizing a\n * plain-field dep on a non-classified collection); the Task 7 review's CRITICAL finding\n * (a typo'd dep on a CLASSIFIED collection reopens the #636 leak) restored a\n * classified-only slice of it, scoped through this SAME helper rather than a\n * hand-rolled second universe — exported so `via/graph-wiring.ts`'s reconcile path can\n * build its own call-scoped knownFields the identical way the fresh path does.\n */\nexport function collectKnownFieldNames(parts: {\n readonly moneyFields?: Record<string, unknown> | undefined\n readonly i18nFields?: Record<string, unknown> | undefined\n readonly dictKeyFields?: Record<string, unknown> | undefined\n readonly classifiedFields?: Record<string, unknown> | undefined\n readonly computed?: Record<string, unknown> | undefined\n readonly lookupFields?: Record<string, unknown> | undefined\n}): Set<string> {\n return new Set<string>([\n ...Object.keys(parts.moneyFields ?? {}),\n ...Object.keys(parts.i18nFields ?? {}),\n ...Object.keys(parts.dictKeyFields ?? {}),\n ...Object.keys(parts.classifiedFields ?? {}),\n ...Object.keys(parts.computed ?? {}),\n ...Object.keys(parts.lookupFields ?? {}),\n ])\n}\n\n/** Default `knownFields` for a `resolveComputedEdges` call that never checks it\n * (`hasClassifiedFields === false`) — lets existing direct-unit-test call sites\n * omit the 4th argument. */\nconst EMPTY_KNOWN_FIELDS: ReadonlySet<string> = new Set()\n\n/**\n * Validate each `computed` entry's `deps` well-formedness and resolve them into graph\n * edges (#638 Task 2; #638 Task 7 folded the formerly-separate `computedDeps` sibling\n * option into each entry's own `{ fn, deps?, mode? }` shape — see\n * `with-formula/computed/index.ts#ComputedFieldEntry`). `computed` is the RAW\n * user-declared map — `unifyComputedFields`'s union of the `computed:` sugar option and\n * `via(computed(...))` entries, NEVER `mergedComputed`: a classified preset's\n * `riderComputed` companions are a sanctioned, already-vetted classified→computed channel\n * and are deliberately NOT subject to this guard. A depsless entry is fine UNLESS the\n * collection also declares classified fields (`hasClassifiedFields`), in which case an\n * opaque computed function could silently copy a classified field's plaintext into an\n * ordinary, unredacted field (the #636 leak) — refused at declare time, regardless of\n * `mode` (a virtual field's read-time redaction, `via/taint-binding.ts`, only fires for a\n * field the graph actually taints — a depsless one never is).\n *\n * A `deps` entry may name ANY field — including a PLAIN field with no via feature\n * declared on it at all (#638 Task 7; Task 2's original design only ever validated a\n * `deps` entry against `moneyFields`/`i18nFields`/`dictKeyFields`/`classifiedFields`/\n * `computed`'s own declared names — `collection-config.ts` has no schema-introspection\n * API to check a `deps` entry against the record's FULL field set, since\n * `StandardSchemaV1` — Zod/Valibot/ArkType/Effect, deliberately schema-library-agnostic —\n * exposes no \"list of field names\" capability). This is safe on a NON-classified\n * collection: a dep with no registered `ViaGraph` node contributes `DEFAULT_POSTURE`\n * when folded (`ViaGraph._contribution`'s `?? DEFAULT_POSTURE` fallback) — i.e. nothing,\n * exactly like any other untainted source.\n *\n * Task 7 review CRITICAL fix (empirically confirmed leak reopening): on a collection\n * that DOES declare classified fields, an UNKNOWN `deps` entry (a typo — e.g.\n * `deps: ['sssn']` instead of `['ssn']`) used to fold to `DEFAULT_POSTURE` exactly like\n * the \"harmless plain field\" case above, silently reopening the #636 leak — construction\n * didn't throw, and the derived field was written/read UNSEALED even though its `fn`\n * actually read a classified field. `knownFields` (built by {@link collectKnownFieldNames}\n * the SAME way at every call site — never a hand-rolled second universe, the exact drift\n * that caused a Task 2 bug) restores the \"every dep must name a known field\" check, but\n * ONLY when `hasClassifiedFields` — a non-classified collection keeps the Task 7 freedom\n * (any string is a legal dep, per the paragraph above) since an untainted fold there is\n * always safe regardless of typos.\n *\n * KNOWN LIMIT (pre-existing since Task 2, phase-E territory — pinned by\n * `via/taint.test.ts`'s \"KNOWN LIMIT\" test): this only checks that a `deps` entry names\n * SOME known field, not that it names the RIGHT one. A `deps` entry naming a real,\n * declared-but-WRONG field (e.g. `fn` reads classified field `ssn` but `deps: ['amount']`\n * — a genuine, known, non-classified field) still passes this check and still leaks:\n * the graph edge folds from `amount`'s posture, not `ssn`'s, so the derived field is\n * folded/sealed as if it read `amount`, while its actual output is `ssn`'s plaintext.\n * There is no schema-introspection capability (see above) to verify a `deps` entry\n * actually corresponds to what `fn` reads — closing this fully would need runtime\n * read-tracking or a schema-aware capability, out of this fix's scope.\n */\nexport function resolveComputedEdges(\n collectionName: string,\n computed: ComputedFields | undefined,\n hasClassifiedFields: boolean,\n knownFields: ReadonlySet<string> = EMPTY_KNOWN_FIELDS,\n): readonly GraphEdge[] {\n if (!computed) return []\n const edges: GraphEdge[] = []\n for (const [field, entry] of Object.entries(computed)) {\n const parts = computedEntryParts(entry)\n const deps = parts.deps\n if (deps === undefined) {\n if (hasClassifiedFields) {\n throw new ValidationError(\n `Collection \"${collectionName}\": computed field \"${field}\" has no declared \\`deps\\` and the ` +\n `collection declares classified fields — an opaque computed function could silently copy a ` +\n `classified field's plaintext into an ordinary, unredacted field. Declare \\`deps\\` naming the ` +\n `source fields it reads, e.g. computed: { ${field}: { fn, deps: [...] } } or ` +\n `via(computed(fn, { deps: [...] })).`,\n )\n }\n continue\n }\n if (deps.length === 0) {\n throw new ValidationError(`Collection \"${collectionName}\": computed field \"${field}\"'s \\`deps\\` must be non-empty.`)\n }\n for (const dep of deps) {\n if (typeof dep !== 'string' || dep.length === 0) {\n throw new ValidationError(`Collection \"${collectionName}\": computed field \"${field}\"'s \\`deps\\` entries must be non-empty strings.`)\n }\n if (hasClassifiedFields && !knownFields.has(dep)) {\n throw new ValidationError(\n `Collection \"${collectionName}\": computed field \"${field}\"'s \\`deps\\` entry \"${dep}\" does not name a ` +\n `declared field, and the collection declares classified fields — an opaque computed function could ` +\n `silently copy a classified field's plaintext into an ordinary, unredacted field via a mistyped/unknown ` +\n `dep name. Declare \\`deps\\` naming only known fields (money/i18n/dictKey/classified/computed) — check ` +\n `\"${dep}\" for a typo.`,\n )\n }\n }\n edges.push({\n target: { collection: collectionName, field },\n sources: deps.map((d) => ({ collection: collectionName, field: d })),\n grain: parts.mode === 'virtual' ? 'virtual' : 'record',\n })\n }\n return edges\n}\n\n/**\n * Extract graph edges from `ViaBinding.deps` (#638 Task 2 — `deps` goes from\n * inert to validated). For any compiled binding declaring `deps`, every field\n * it `covers()` (tested against `knownFields`) becomes a derived target whose\n * sources are `deps`; an unknown source field throws declare-time\n * `ValidationError`. No shipped binding declares `deps` today (money/i18n/\n * classified/blob don't) — this is the general path a future derive-bearing\n * binding (phase C Task 7's `computed` via-binding) plugs into.\n */\nexport function resolveViaBindingDepsEdges(\n collectionName: string,\n bindings: readonly ViaBinding[],\n knownFields: ReadonlySet<string>,\n): readonly GraphEdge[] {\n const edges: GraphEdge[] = []\n for (const binding of bindings) {\n if (!binding.deps || binding.deps.length === 0) continue\n for (const dep of binding.deps) {\n if (!knownFields.has(dep)) {\n throw new ValidationError(\n `Collection \"${collectionName}\": via binding \"${binding.brand}\" deps references undeclared field \"${dep}\".`,\n )\n }\n }\n const sources = binding.deps.map((d) => ({ collection: collectionName, field: d }))\n for (const field of knownFields) {\n if (binding.covers?.(field)) edges.push({ target: { collection: collectionName, field }, sources })\n }\n }\n return edges\n}\n\n/**\n * Resolve the raw {@link CollectionOpts} into the concrete field values the\n * {@link Collection} constructor assigns — every `?? default`, every derived\n * `Set`/subset, plus the three pure construction-time validations. Pure: no\n * `this`, no external side effect. The allocated `Set`/`VectorSet`/`Lru`\n * instances become the collection's own by reference.\n */\nexport function resolveCollectionConfig<T>(opts: CollectionOpts<T>) {\n // Guard: CRDT collections cannot use embeddings (the embedding-derive\n // block is unreachable after the CRDT early-return in _putInternal; full\n // CRDT-derivation is out of scope).\n if (opts.embeddings && opts.crdt) {\n throw new Error(\n `Collection \"${opts.name}\": embeddings are not supported on CRDT collections (L2). Use a non-CRDT collection for semantic search.`,\n )\n }\n\n // Guard (#850): `sensitive` promises each field its own `_sealed` slot under\n // an HKDF-derived per-field key, but the CRDT branch of `_putInternal`\n // persists through `encryptJsonString` and returns before any sealing runs —\n // so the fields were silently stored in the ordinary body instead, with no\n // error. Refuse, matching what embeddings / unique indexes / classified\n // digest-only (R2) already do for the same underlying reason: the CRDT write\n // path bypasses the pipeline these options are enforced by. Fail loud rather\n // than deliver less encryption than the caller asked for.\n if (opts.sensitive && opts.sensitive.length > 0 && opts.crdt) {\n throw new Error(\n `Collection \"${opts.name}\": sensitive (structural group-encryption) is not supported on ` +\n `CRDT collections — the CRDT write path bypasses per-field sealing, so the fields would ` +\n `be stored in the ordinary encrypted body with no \\`_sealed\\` slot and no per-field key. ` +\n `Use a non-CRDT collection for sealed fields.`,\n )\n }\n\n // #724 I1 — a tiered collection that declares blobFields must opt into\n // perRecordKeys: legacy (non-perRecordKeys) blobs have no per-blob `_cek`,\n // so `rehomeForTier` cannot rewrap/re-put them under a tier DEK on\n // elevate/demote — they would stay tier-0-decryptable at rest. Refuse\n // loudly at construction instead of leaking silently.\n if (opts.tiers && opts.tiers.length > 0 && opts.blobFields !== undefined && Object.keys(opts.blobFields).length > 0 && opts.perRecordKeys !== true) {\n throw new UnsupportedTierCompositionError(\n 'blobs',\n `Collection \"${opts.name}\": tiered collections that declare blobFields require \\`perRecordKeys: true\\` — ` +\n `legacy (non-perRecordKeys) blobs have no per-blob content CEK and cannot be tier-isolated on elevate/demote.`,\n )\n }\n\n // #748 — tiers × a `public: true` external blob field is a structural dead\n // end, not a crypto gap the perRecordKeys mandate above can close. An\n // external-public object's key (`{collection}/{recordId}/{slotName}`) is\n // deterministic and its bytes are world-readable by design (CDN origin) —\n // elevating the owning record re-keys/re-scopes the ENCRYPTED slot catalog\n // entry, but can never retroactively hide an already-public bucket object,\n // nor stop a future `public: true` write from re-publishing it at the same\n // predictable key. Refuse at construction; private/presigned external\n // fields (`public` omitted or `false`) are unaffected — only the catalog\n // entry needs tier-isolation there, which perRecordKeys already provides.\n if (opts.tiers && opts.tiers.length > 0 && opts.blobFields !== undefined) {\n for (const [field, policy] of Object.entries(opts.blobFields)) {\n if (policy?.external && policy.public === true) {\n throw new UnsupportedTierCompositionError(\n 'blobs',\n `Collection \"${opts.name}\": blob field \"${field}\" cannot be both \\`external: true, public: true\\` ` +\n `and declared on a tiered collection — the object key is deterministic and its bytes are ` +\n `world-readable by design, so tier-invisibility can never be enforced for it once elevated. ` +\n `Use a private/presigned external field (\\`public\\` omitted or \\`false\\`) or move this field to ` +\n `a non-tiered collection.`,\n )\n }\n }\n }\n\n // #740 — tiers declare per-tier ENCRYPTION keys (elevate/demote re-key and\n // re-put the record under the target tier's DEK). A plaintext\n // (`encrypted: false`) collection has nothing to re-key: `putAtTier`/\n // `elevate` would encrypt/decrypt incoherently against a collection that\n // never encrypts. Refuse at construction instead of leaking silently.\n if (opts.tiers && opts.tiers.length > 0 && opts.encrypted === false) {\n throw new UnsupportedTierCompositionError(\n 'plaintext',\n `Collection \"${opts.name}\": tiers are per-tier ENCRYPTION keys — a plaintext collection ` +\n `(\\`encrypted: false\\`) has nothing to re-key, so \\`putAtTier\\`/\\`elevate\\` would ` +\n `encrypt/decrypt incoherently. Use an encrypted collection.`,\n )\n }\n\n // #739 — a CRDT-mode collection's decrypted body is the raw `CrdtState`\n // (edit log + bidx pointer), not the resolved record: `RecordCodec\n // .decryptRecordAtDek()` — the tier-aware pre-move decode `syncDerived`\n // uses on `elevate()`/`demote()`/`putAtTier()` (#722) — has no CRDT\n // resolution step (same gap as `getAtTier`'s tier>0 leg), so a registered\n // rollup/derivation reading this collection sees `undefined` for every\n // field (e.g. `_rollupDeleteIntents`'s `deleted[spec.rollup.key]`) and its\n // recompute silently no-ops — the #722 derived-output-follows-tier fix\n // never fires for this combination. Refuse at construction instead of\n // leaking silently.\n //\n // Caught here: rollup/derivation sources, reliably — `DerivationRegistry`\n // is fully populated (every `withDerivation()`/`withRollup()` handle\n // registered) by `Noydb.openVault()` before any `vault.collection()` call\n // reaches user code, so source/derived registration order never matters.\n //\n // NOT caught: a materialized-view SOURCE first constructed inside the\n // MV's own single-query `query(db)` callback (the common `query: (db) =>\n // db.collection(name)...` shape) — `MaterializedViewRegistry.register()`\n // invokes that callback (which constructs THIS collection) before it\n // records the dependency, so `materializedViewSource.registry()\n // .mvsForSource(name)` is still empty at this exact call. A\n // `unionSources`/aggregate-with-explicit-`sources` MV, or a source\n // constructed by an earlier `vault.collection()` call, is still caught.\n if (\n opts.tiers && opts.tiers.length > 0 && opts.crdt !== undefined &&\n ((opts.derivationSource?.registry().strategiesForSource(opts.name).length ?? 0) > 0 ||\n (opts.materializedViewSource?.registry().mvsForSource(opts.name).length ?? 0) > 0)\n ) {\n throw new UnsupportedTierCompositionError(\n 'crdt-derivation',\n `Collection \"${opts.name}\": tiers + crdt cannot be combined with this collection acting as a ` +\n `derivation/rollup source (#739) — the tier-aware pre-move decode \\`syncDerived\\` uses on ` +\n `elevate()/demote() does not resolve CRDT state, so a registered derivation/rollup reads raw ` +\n `CrdtState instead of the record and silently no-ops. Use a non-CRDT collection for a tiered ` +\n `derivation/rollup source, or move the derivation off this collection.`,\n )\n }\n\n // via() / sugar-key merge (#623 Task 9) — throws on a field declared in both.\n const effectiveViaFields = mergeViaFields(opts)\n\n const resolvedClassified: ResolvedClassified | undefined =\n opts.classifiedFields !== undefined\n ? resolveClassifiedFields(opts.name, opts.classifiedFields)\n : undefined\n\n // #638 Task 7 — union the `computed:` sugar option with `via(computed(...))` entries,\n // then split by mode: materialized (default) folds into `mergedComputed` exactly like\n // today's sugar map; virtual NEVER does (it's never stored — `evalComputedFields` must\n // not see it) and instead feeds the computed via-binding's config (`compileViaBindings`,\n // above, does the identical split independently — both are pure/cheap, mirrors\n // `resolveCollectionConfig` already re-deriving `effectiveViaFields`).\n const allComputed = unifyComputedFields(opts, effectiveViaFields.computedFields)\n const materializedComputed: ComputedFields = {}\n for (const [field, entry] of Object.entries(allComputed)) {\n if (computedEntryParts(entry).mode !== 'virtual') materializedComputed[field] = entry\n }\n\n // rider companions run first; user `computed` fns may read them.\n // A user `computed` key colliding with a rider companion is a config error\n // (checked against BOTH modes' field names — a virtual field can collide too).\n let mergedComputed: ComputedFields | undefined =\n Object.keys(materializedComputed).length > 0 ? materializedComputed : undefined\n if (resolvedClassified !== undefined) {\n for (const key of Object.keys(allComputed)) {\n if (resolvedClassified.riderComputed[key] !== undefined) {\n throw new ClassifiedConfigError(opts.name, `computed field \"${key}\" collides with a rider companion`)\n }\n }\n mergedComputed = { ...resolvedClassified.riderComputed, ...materializedComputed }\n }\n\n // deterministic-encryption wiring\n let deterministicFields: ReadonlySet<string> | null\n if (opts.deterministicFields && opts.deterministicFields.length > 0) {\n if (opts.acknowledgeDeterministicRisk !== true) {\n throw new Error(\n `Collection \"${opts.name}\": deterministicFields requires \\`acknowledgeDeterministicRisk: true\\`. ` +\n `Deterministic encryption leaks equality between records — two records with the same field value ` +\n `produce identical ciphertexts visible to anyone with store access. If that trade-off is acceptable ` +\n `for your threat model, set \\`acknowledgeDeterministicRisk: true\\` to enable.`,\n )\n }\n deterministicFields = Object.freeze(new Set(opts.deterministicFields))\n } else {\n deterministicFields = null\n }\n\n // Refusal matrix (R1-R5) — door 1. The SAME guard + ctx runs again at door 2\n // (`_applyClassifiedFields`, the reconcile seam), because crdt/conflictPolicy/\n // perRecordKeys are construction-only while classifiedFields can attach later\n // (C5's lesson). The ctx is always built (and returned) so door 2 has it even\n // when this construction declared no classified fields.\n const guardIndexedFields = new Set<string>()\n for (const ix of opts.indexes ?? []) {\n if (typeof ix === 'string') guardIndexedFields.add(ix)\n else if (Array.isArray(ix)) for (const f of ix) guardIndexedFields.add(f)\n else for (const f of (ix as { readonly fields: readonly string[] }).fields) guardIndexedFields.add(f)\n }\n const embeddingSources = opts.embeddings === undefined ? []\n : typeof opts.embeddings.source === 'string' ? [opts.embeddings.source] : [...opts.embeddings.source]\n const classifiedGuardCtx: ClassifiedGuardCtx = {\n perRecordKeys: opts.perRecordKeys === true,\n crdt: opts.crdt !== undefined,\n hasConflictPolicy: opts.conflictPolicy !== undefined,\n storeCiphertext: opts.encrypted,\n deterministicFields,\n indexedFields: guardIndexedFields,\n textIndexFields: new Set(opts.textIndexes ?? []),\n vectorSourceFields: new Set(embeddingSources),\n subjectKeyField: opts.subjectKeyField,\n bareSensitiveFields: new Set(opts.sensitive ?? []),\n acknowledgeEquatableRisk: opts.acknowledgeEquatableRisk === true,\n }\n if (resolvedClassified !== undefined) {\n guardClassifiedCompat(opts.name, resolvedClassified.byField, classifiedGuardCtx) // door 1\n }\n\n // structural group-encryption wiring: the set of fields sealed\n // into `_sealed` per-field slots. Empty when the option is absent.\n // Recoverable classified fields are unioned in — they seal via the same\n // mechanism with zero new crypto code.\n const classifiedSensitive = resolvedClassified === undefined ? [] :\n Object.entries(resolvedClassified.byField)\n .filter(([, s]) => s.storage === 'recoverable')\n .map(([f]) => f)\n const sensitiveList = [...(opts.sensitive ?? []), ...classifiedSensitive]\n const sensitiveFields: ReadonlySet<string> = sensitiveList.length > 0\n ? Object.freeze(new Set(sensitiveList))\n : Object.freeze(new Set<string>())\n\n // Digest-only classified fields → the enclave-consumable policy map\n // (stage 2). Both the codec write path and the verify engine key off it.\n const vdigEntries: Array<readonly [string, VdigFieldPolicy]> =\n resolvedClassified === undefined ? [] :\n Object.entries(resolvedClassified.byField)\n .filter(([, s]) => s.storage === 'digest-only')\n .map(([f, s]) => [f, {\n normalize: s.verifyNormalize ?? 'password',\n notLastN: s.notLastN ?? 0,\n equatable: s.equatable === true,\n ...(s.rotateDays !== undefined ? { rotateDays: s.rotateDays } : {}),\n }] as const)\n const vdigFields: ReadonlyMap<string, VdigFieldPolicy> | null =\n vdigEntries.length > 0 ? new Map(vdigEntries) : null\n\n // per-record CEK wiring. The cache is bounded by record count; CEKs\n // are tiny CryptoKey handles, so a generous entry budget is cheap.\n const perRecordCek = opts.perRecordKeys === true\n const cekCache = perRecordCek ? new Lru<string, EnclaveKey>({ maxRecords: 4096 }) : null\n\n // #629 Task 10 — captures the classified binding's cfg (see compileViaBindings's doc comment) for the constructor's post-codec wiring.\n const viaEraseCfgOut: { classified?: ClassifiedViaConfig } = {}\n const via = ViaPipeline.build(compileViaBindings(opts, classifiedGuardCtx, viaEraseCfgOut))\n\n // #638 Task 2 — the field-name universe `resolveViaBindingDepsEdges` validates `deps`\n // entries against (\"references undeclared field\" otherwise) — still true for the general\n // `ViaBinding.deps` path. `resolveComputedEdges` (#638 Task 7) only consults this when\n // `hasClassifiedFields` (the Task 7 review's CRITICAL fix — see its own doc comment): a\n // computed `deps` entry may still name a plain field with no via feature at all on a\n // NON-classified collection.\n const knownFields = collectKnownFieldNames({\n moneyFields: effectiveViaFields.moneyFields,\n i18nFields: effectiveViaFields.i18nFields,\n dictKeyFields: effectiveViaFields.dictKeyFields,\n classifiedFields: resolvedClassified?.byField,\n computed: allComputed,\n lookupFields: effectiveViaFields.lookupFields,\n })\n const computedEdges = resolveComputedEdges(opts.name, allComputed, resolvedClassified !== undefined, knownFields)\n const viaDepsEdges = resolveViaBindingDepsEdges(opts.name, via?.bindings ?? [], knownFields)\n\n return {\n adapter: opts.adapter,\n vault: opts.vault,\n name: opts.name,\n keyring: opts.keyring,\n storeCiphertext: opts.encrypted,\n ramCiphertext: opts.ramCiphertext ?? false,\n emitter: opts.emitter,\n writeQueue: opts.writeQueue,\n schemaUpdateGate: opts.schemaUpdateGate,\n schemaFence: opts.schemaFence,\n writeHooks: opts.writeHooks,\n subsystemBus: opts.subsystemBus,\n activeTxId: opts.activeTxId,\n strategies: opts.strategies,\n objectStore: opts.objectStore,\n blobFields: opts.blobFields,\n reconcileOnOpen: opts.reconcileOnOpen ?? 'off',\n getDEK: opts.getDEK,\n onDirty: opts.onDirty,\n tabCoordinated: opts.tabCoordinated,\n historyConfig: opts.historyConfig ?? { enabled: true },\n historyConfigExplicit: opts.historyConfigExplicit ?? false,\n schema: opts.schema,\n ledger: opts.ledger,\n refEnforcer: opts.refEnforcer,\n joinResolver: opts.joinResolver,\n i18nFields: effectiveViaFields.i18nFields,\n textIndexes: opts.textIndexes,\n embeddings: opts.embeddings,\n vectorSet: opts.embeddings ? new VectorSet() : undefined,\n dictKeyFields: effectiveViaFields.dictKeyFields,\n lookupFields: effectiveViaFields.lookupFields,\n // #650 Task 6 — the sync join-dressing hook (#626 retirement, spec §5);\n // `undefined` when this collection declares neither i18nText nor lookup\n // fields, matching today's `i18nFields`-absent JoinableSource shape.\n presentForJoin: buildPresentForJoin(effectiveViaFields.i18nFields, effectiveViaFields.lookupFields, opts.snapshotFor),\n fieldMeta: opts.fieldMeta,\n meta: opts.meta,\n _refs: opts.declaredRefs ?? {},\n via,\n classifiedEraseCfg: viaEraseCfgOut.classified,\n moneyFields: effectiveViaFields.moneyFields,\n classified: resolvedClassified,\n classifiedGuardCtx,\n computed: mergedComputed,\n computedEdges,\n viaDepsEdges,\n // #638 Task 7 — every declared computed field name (both modes, both surfaces); the\n // reconcile path's cross-call depsless-computed leak-guard memory\n // (`via/graph-wiring.ts#registerCollectionGraphSources`) reads this instead of\n // `Object.keys(opts.computed ?? {})` alone, so a via(computed(...))-declared field\n // participates in that guard identically to a sugar-declared one.\n computedFieldNames: Object.keys(allComputed),\n dictLabelResolver: opts.dictLabelResolver,\n getDictionary: opts.getDictionary,\n i18nPutValidator: opts.i18nPutValidator,\n autoTranslateHook: opts.autoTranslateHook,\n defaultLocale: opts.defaultLocale,\n crdtMode: opts.crdt,\n syncAdapter: opts.syncAdapter,\n onAccess: opts.onAccess,\n derivationSource: opts.derivationSource,\n materializedViewSource: opts.materializedViewSource,\n graphDispatch: opts.graphDispatch,\n tiers: opts.tiers && opts.tiers.length > 0 ? new Set(opts.tiers) : null,\n tierMode: opts.tierMode ?? 'invisibility',\n blobTierPolicy: opts.blobTierPolicy ?? 'isolate',\n onCrossTierAccess: opts.onCrossTierAccess,\n addSubjectRef: opts.addSubjectRef,\n deterministicFields,\n sensitiveFields,\n vdigFields,\n perRecordCek,\n cekCache,\n provenance: opts.provenance === true,\n }\n}\n","/**\n * Lazy loader for the computed-fields engine (#553).\n *\n * The `computed` declaration on `collection({ … })` is the opt-in unit;\n * the engine's only kernel consultation is the (async) write pipeline,\n * so it loads on the first computed-declared put and stays out of the\n * floor bundle otherwise. Cached after first load — mirrors the\n * deferred-load pattern used for guards/derivations.\n */\nimport type * as ComputedModule from './index.js'\nimport { lazy } from '../../kernel/lazy.js'\n\ntype EvalComputedFieldsFn = typeof ComputedModule.evalComputedFields\n\nconst loadComputed = lazy(() => import('./index.js'))\n\nexport async function loadEvalComputedFields(): Promise<EvalComputedFieldsFn> {\n return (await loadComputed()).evalComputedFields\n}\n","import type { StrategyBag } from '../port/with/strategies.js'\nimport type { NoydbStore, EncryptedEnvelope, ChangeEvent, HistoryConfig, HistoryOptions, HistoryEntry, PruneOptions, ListPageResult, LocaleReadOptions, CollectionConflictResolver, PutManyItemOptions, PutManyOptions, PutManyResult, DeleteManyResult, SealedView, VdigFieldPolicy, ClassifiedVerdict } from './types.js'\nimport type { PreparedPut, PreparedDelete } from './prepared-write.js'\nimport type { FieldMeta } from '../with-shape/introspection/field-meta.js'\nimport type { CollectionMeta } from '../with-shape/introspection/meta.js'\nimport { resolveClassifiedFields, guardClassifiedCompat, type ClassifiedEntry, type ClassifiedFieldSpec, type ResolvedClassified, type ClassifiedGuardCtx, type ClassifiedVerifyCtx } from '../port/with/classified-strategy.js'\nimport type { CrdtMode, CrdtState, LwwMapState, RgaState } from '../with-commit/crdt/crdt.js'\nimport type { I18nTextDescriptor, DictKeyDescriptor, StaticDictDescriptor, DictionaryHandle } from '../port/with/i18n-strategy.js'\nimport { isStaticDictDescriptor } from '../port/with/i18n-strategy.js'\nimport type { LookupDescriptor } from '../port/with/lookup-strategy.js'\nimport { ViaPipeline } from './via/pipeline.js'\nimport { viaBinder, type ViaDescriptor, type ViaWriteCtx, type ViaEraseReport } from './via/index.js'\nimport type { MutationOrigin } from './mutation.js'\nimport { putDerivedOutput, ledgerAuditHook, selfWriteFieldEqual, resolveRollupDeleteIntents, findRollupSpecForIntent, type WaveContext, type RollupOutcome, type RollupDeleteIntent } from './via/dispatch.js'\nimport type { ComputedFields } from '../with-formula/computed/index.js'\nimport {\n isTombstone, isDeleteMarker, buildTombstone, buildDeleteMarker,\n resolveStableCek, findByDet, queryByDet, RecordCodec,\n type DeterministicContext, type EnclaveKey, type SealedShredSlot,\n} from './enclave/index.js'\nimport { countLiveEnvelopes } from './lazy-count.js'\nimport { liveRecordIsElevated, assertTierWritable, assertCutoverTierSafe } from './tier-visibility.js'\nimport {\n classifySealedShred as classifySealedShredImpl, syncDerivedOutputs,\n type TiersContext, type TierMoveResult,\n} from '../with-audit/tiers/index.js'\nimport {\n buildPersistedIndexCallbacks as buildPersistedIndexCallbacksImpl,\n syncTierSearch as syncTierSearchImpl,\n type SearchContext,\n} from '../with-lookup/search/collection-facade.js'\nimport {\n rebuildEagerIndexesFromCache as rebuildEagerIndexesFromCacheImpl, rebuildUniqueConstraintsFromCache as rebuildUniqueConstraintsFromCacheImpl, rebuildIndexes as rebuildIndexesImpl,\n reconcileIndex as reconcileIndexImpl, maintainPersistedIndexesOnPut as maintainPersistedIndexesOnPutImpl, maintainPersistedIndexesOnDelete as maintainPersistedIndexesOnDeleteImpl,\n purgePersistedIndexes as purgePersistedIndexesImpl, syncTierIndexes as syncTierIndexesImpl, type IndexingContext,\n} from '../with-lookup/indexing/collection-facade.js'\nimport { ReadOnlyError, ClassifiedConfigError, ClassifiedRevealError, ClassifiedVerifyError } from './errors.js'\nimport type { GhostRecord, TierMode, CrossTierAccessEvent } from './types.js'\nimport type { UnlockedKeyring } from '../with-party/team/keyring.js'\nimport { hasWritePermission } from '../with-party/team/keyring.js'\nimport type { NoydbEventEmitter } from './events.js'\nimport type { WriteQueueTracker } from './write-queue.js'\nimport type { WriteHookRegistry, WriteEvent } from '../port/with/write-hooks.js'\nimport type { ServiceBus, GatePutEvent, GatePoint } from '../port/with/service-bus.js'\nimport type { SchemaUpdateGate } from '../with-shape/schema-update/gate.js'\nimport type { SchemaFenceController } from '../with-shape/schema-update/fence-controller.js'\nimport type { StandardSchemaV1 } from './schema.js'\nimport { validateSchemaInput } from './schema.js'\nimport { derivePersistedSchema } from '../with-shape/persisted-schemas/derive.js'\nimport type { LedgerStore } from '../with-commit/history/ledger/index.js'\nimport type { DiffEntry } from '../with-commit/history/diff.js'\nimport { NO_HISTORY } from '../with-commit/history/strategy.js'\nimport { Query, ScanBuilder } from './query/index.js'\nimport type { QuerySource, JoinContext, JoinableSource } from './query/index.js'\nimport type { CollectionIndexes } from '../with-lookup/indexing/eager-indexes.js'\nimport { decodeIdxId } from '../with-lookup/indexing/persisted-indexes.js'\nimport type { PersistedCollectionIndex } from '../with-lookup/indexing/persisted-indexes.js'\nimport { LazyQuery } from '../with-lookup/indexing/lazy-builder.js'\nimport type { LazyQuerySource } from '../with-lookup/indexing/lazy-builder.js'\nimport { type IndexState } from '../with-lookup/indexing/strategy.js'\nimport type { SearchOptions, SearchResult } from '../with-lookup/search/index.js'\nimport { MemoryIndexStore, type IndexStore } from '../with-lookup/search/index-store.js'\nimport { PersistedIndexStore } from '../with-lookup/search/persisted-index-store.js'\nimport type { RetrieveOptions, RetrieveHit } from '../with-lookup/search/retrieve-types.js'\nimport { encodeVecId, type VectorSet, type EmbeddingDescriptor } from '../with-lookup/embeddings/index.js'\nimport { buildUniqueConstraintSet, type UniqueConstraintSet } from '../with-lookup/indexing/unique-constraints.js'\nimport type { RefDescriptor } from './refs.js'\nimport { buildDescription, deriveZodFields, type CollectionDescription, type DescribeOptions } from '../with-shape/introspection/describe.js'\nimport type { CollectionConfig } from '../with-shape/introspection/types.js'\nimport { estimateRecordBytes, type Lru, type LruStats } from './cache/index.js'\nimport { generateULID } from '../with-pod/ulid.js'\nimport type { PresenceHandle, PresenceHandleOpts } from '../with-sync/presence.js'\nimport type { BlobSet } from '../with-shape/blobs/blob-set.js'\nimport { NO_BLOBS } from '../port/with/blob-strategy.js'\nimport type { ObjectProjection } from '../with-shape/blobs/object-projection.js'\nimport type { BlobFieldsConfig } from '../with-shape/blobs/blob-compaction.js'\nimport type { ReadOnlyVaultFacade } from '../with-audit/guards/types.js'\nimport type { DerivationRegistry } from '../with-formula/derivations/registry.js'\nimport type { TxContext } from '../with-commit/tx/transaction.js'\nimport { runPutManyAtomic } from './put-many-atomic.js'\n// Type-only — runtime class loaded via dynamic import in\n// `dispatchDerivations` when an eager-mode strategy fires. Keeps the\n// derivation executor chunk out of the floor bundle.\nimport type {\n} from '../with-formula/derivations/fanout-sidecar.js'\nimport { resolveStaleOnRead } from '../with-formula/derivations/stale.js'\nimport type { MaterializedViewRegistry } from '../with-formula/materialized-views/registry.js'\nimport type { MVQueryContext } from '../with-formula/materialized-views/types.js'\nimport { resolveCollectionConfig, resolveVirtualMoneyFields, type CollectionOpts } from './collection-config.js'\nimport { loadEvalComputedFields } from '../with-formula/computed/lazy.js'\n\n/**\n * Callback for dirty tracking (sync engine integration). `action: 'revert'`\n * (spec #591) means \"un-dirty\" — the fan-out wiring in `noydb.ts` routes it\n * to `SyncEngine.removeDirty` instead of `trackChange`; `version` is unused\n * for that action.\n */\nexport type OnDirtyCallback = (collection: string, id: string, action: 'put' | 'delete' | 'revert', version: number) => Promise<void>\n\n\n/**\n * Event delivered to a `collection.subscribe()` callback. Distinct\n * from the hub-level `ChangeEvent` — this one is bound to a single\n * collection's type `T` and hydrates the record from cache on put.\n *\n * - `type: 'put'` — `record` is the current decrypted value, or\n * `null` in the rare case where another op deleted the record\n * between the emit and the handler firing.\n * - `type: 'delete'` — `record` is always `null`; the deletion is\n * the only information.\n */\nexport interface CollectionChangeEvent<T> {\n readonly type: 'put' | 'delete'\n readonly id: string\n readonly record: T | null\n}\n\n/**\n * Per-collection cache configuration. Only meaningful when paired with\n * `prefetch: false` (lazy mode); eager mode keeps the entire decrypted\n * cache in memory and ignores these bounds.\n */\nexport interface CacheOptions {\n /** Maximum number of records to keep in memory before LRU eviction. */\n maxRecords?: number\n /**\n * Maximum total decrypted byte size before LRU eviction. Accepts a raw\n * number or a human-friendly string: `'50KB'`, `'50MB'`, `'1GB'`.\n * Eviction picks the least-recently-used entry until both budgets\n * (maxRecords AND maxBytes, if both are set) are satisfied.\n */\n maxBytes?: number | string\n}\n\n/** Statistics exposed via `Collection.cacheStats()`. */\nexport interface CacheStats extends LruStats {\n /** True if this collection is in lazy mode. */\n lazy: boolean\n}\n\n/**\n * Track which adapter names have already triggered the listPage fallback\n * warning. We only emit once per adapter per process so consumers see the\n * heads-up without log spam.\n */\nconst fallbackWarned = new Set<string>()\nfunction warnOnceFallback(adapterName: string): void {\n if (fallbackWarned.has(adapterName)) return\n fallbackWarned.add(adapterName)\n // Only warn in non-test environments — vitest runs are noisy enough.\n if (typeof process !== 'undefined' && process.env['NODE_ENV'] === 'test') return\n console.warn(\n `[noy-db] Store \"${adapterName}\" does not implement listPage(); ` +\n `Collection.scan()/listPage() are using a synthetic fallback (slower). ` +\n `Add a listPage method to opt into the streaming fast path.`,\n )\n}\n\n/** A typed collection of records within a vault. */\nexport class Collection<T, S extends keyof T = never, Q extends keyof T & string = never, M extends keyof T & string = never> {\n private readonly adapter: NoydbStore\n private readonly vault: string\n private readonly name: string\n private readonly keyring: UnlockedKeyring\n private readonly storeCiphertext: boolean\n private readonly ramCiphertext: boolean\n private readonly emitter: NoydbEventEmitter\n private readonly writeQueue: WriteQueueTracker | undefined\n private readonly schemaUpdateGate: SchemaUpdateGate | undefined\n private readonly schemaFence: SchemaFenceController | undefined\n private readonly writeHooks: WriteHookRegistry | undefined\n private readonly subsystemBus: ServiceBus | undefined\n private readonly activeTxId: (() => string | null) | undefined\n private readonly getDEK: (collectionName: string) => Promise<EnclaveKey>\n private readonly onDirty: OnDirtyCallback | undefined\n /** #693: live check — true when multi-tab write-propagation is active; gates the #606 marker-id-set fallback read. */\n private readonly tabCoordinated: (() => boolean) | undefined\n private readonly historyConfig: HistoryConfig\n /** True when the caller explicitly provided a `historyConfig` option (vs. inheriting the vault default). */\n private readonly historyConfigExplicit: boolean\n\n /**\n * Every opt-in service, resolved once by `createNoydb` (#838) and shared by\n * reference with the owning `Vault` and `Noydb`.\n *\n * Each entry is a tree-shake seam. An un-opted-in service resolves to its\n * `NO_*` stub — a tiny module that throws with an actionable message —\n * so, for example, none of the BlobSet / chunk / MIME-magic machinery\n * reaches the bundle unless the consumer imports `@noy-db/hub/blobs` and\n * passes `blobsStrategy: blobs()` to `createNoydb`.\n */\n private readonly strategies: StrategyBag\n private readonly objectStore: ObjectProjection | undefined\n private readonly blobFields: BlobFieldsConfig | undefined; private readonly blobTierPolicy: 'isolate' | 'dedup' // #724 T2/T3\n\n // In-memory cache of decrypted records (eager mode only). Lazy mode\n // uses `lru` instead. Both fields exist so a single Collection instance\n // doesn't need a runtime branch on every cache access.\n private readonly cache = new Map<string, { record: T; version: number }>()\n private hydrated = false\n\n /**\n * #606: ids known to carry a delete marker in the store — lets the #589\n * re-create version-continuity gate in `_putInternal` read the store ONLY\n * for a known marker prior, instead of unconditionally on every insert.\n * Populated on hydration (`ensureHydrated`/`hydrateFromSnapshot`), local\n * delete (`_commitDelete`), and the sync/tab/cutover choke point\n * (`_invalidateCacheEntry`). Accepted drift: `vault._purgeDeleteMarkers`/\n * `_purgeMarkersOn` remove markers directly on the raw store, bypassing\n * Collection, so this set can hold stale ids after a purge on an\n * already-loaded collection — perf-only and self-healing (a stale id just\n * costs one `adapter.get` that returns non-marker/null, and version\n * resolution falls back to 1 correctly). Do not try to wire purge into it.\n */\n private readonly markerIds = new Set<string>()\n\n /**\n * Lazy mode flag. `true` when constructed with `prefetch: false`.\n * In lazy mode the cache is bounded by an LRU and `list()`/`query()`\n * throw — callers must use `scan()` or per-id `get()` instead.\n */\n private readonly lazy: boolean\n\n /**\n * LRU cache for lazy mode. Only allocated when `prefetch: false` is set.\n * Stores `{ record, version }` entries the same shape as `this.cache`.\n * Tree-shaking note: importing Collection without setting `prefetch:false`\n * still pulls in the Lru class today; future bundle-size work could\n * lazy-import the cache module.\n */\n private readonly lru: Lru<string, { record: T; version: number }> | null\n\n /**\n * tree-shake seam — per-Collection indexing state. Owned by the\n * `IndexingStrategy` passed through from `createNoydb({ indexingStrategy })`.\n * Defaults to a disabled state (both accessors return null) so the\n * `CollectionIndexes` / `PersistedCollectionIndex` / `LazyQuery`\n * classes never reach the bundle when indexing is unused.\n *\n * Accessor helpers below (`get indexes()`, `get persistedIndexes()`)\n * preserve the field-access ergonomics without changing every\n * caller site.\n */\n private readonly indexState: IndexState\n\n /**\n * In-memory unique-constraint enforcement for eager mode.\n * `null` when no `unique:true` indexes are declared on this collection, or when the collection is in lazy mode (which throws at registration).\n */\n private readonly uniqueConstraints: UniqueConstraintSet | null\n\n /**\n * True once `_idx/*` side-cars have been bulk-loaded into\n * `persistedIndexes`. Flipped by `ensurePersistedIndexesLoaded()` on\n * first lazy-mode query so subsequent queries skip the adapter round\n * trip. Invalidation (remote sync, rotation) resets it alongside\n * `persistedIndexes.clear()`.\n */\n private persistedIndexesLoaded = false\n\n /**\n * Accessor for the in-memory eager-mode index mirror. Returns `null`\n * when indexing is disabled on this Noydb instance (the\n * `NO_INDEXING` default) or when the collection is in lazy mode\n * (which uses the persisted mirror instead).\n */\n private get indexes(): CollectionIndexes | null {\n return this.indexState.getEagerIndexes()\n }\n\n /**\n * Accessor for the persisted-mirror (lazy-mode) index. Returns `null` when indexing is disabled or the collection is in eager mode.\n */\n private get persistedIndexes(): PersistedCollectionIndex | null {\n return this.indexState.getPersistedIndexes()\n }\n\n /**\n * per-collection reconcile-on-open policy. Read once\n * from `CollectionOptions.reconcileOnOpen` and applied by\n * `ensurePersistedIndexesLoaded()` on the first lazy-mode query.\n */\n private readonly reconcileOnOpen: 'off' | 'dry-run' | 'auto'\n\n /**\n * Re-entrancy guard for the auto-reconcile path. `reconcileIndex`\n * reloads the mirror after applying fixes, which re-enters\n * `ensurePersistedIndexesLoaded`; without this flag we'd trigger a\n * second auto-reconcile pass and potentially infinite recursion.\n */\n private autoReconciling = false\n\n /**\n * Optional Standard Schema v1 validator. When set, every `put()` runs\n * the input through `validateSchemaInput` before encryption, and every\n * record coming OUT of `decryptRecord` runs through\n * `validateSchemaOutput`. A rejected input throws\n * `SchemaValidationError` with `direction: 'input'`; drifted stored\n * data throws with `direction: 'output'`. Both carry the rich issue\n * list from the validator so UI code can render field-level messages.\n *\n * The schema is stored as `StandardSchemaV1<unknown, T>` because the\n * collection type parameter `T` is the OUTPUT type — whatever the\n * validator produces after transforms and coercion. Users who pass a\n * schema to `defineNoydbStore` (or `Collection.constructor`) get their\n * `T` inferred automatically via `InferOutput<Schema>`.\n */\n private readonly schema: StandardSchemaV1<unknown, T> | undefined\n\n /**\n * Vault-default locale. Used as the fallback when no per-call\n * locale option is passed to `get()`/`list()`. Provided by Vault\n * at collection construction time via the `collection({ locale })` or\n * `openVault(name, { locale })` path.\n *\n * `undefined` means \"no default locale set\" — i18nText fields will\n * throw `LocaleNotSpecifiedError` unless a per-call locale is passed.\n */\n private readonly defaultLocale: string | undefined\n\n /** Field name → `I18nTextDescriptor` for `i18nText()` fields (`i18nFields` option); write/read runs through the compiled `via` i18n binding — this remains for `describe()` and the search-index build path. Mutable — see {@link _reconcileReadState} (#671 item 2). */\n private i18nFields: Record<string, I18nTextDescriptor> | undefined\n\n /** The configured string fields exposed to `retrieve()`; `undefined` for ordinary collections (zero-cost). */\n private readonly textIndexes: readonly string[] | undefined\n\n /** Session-scoped lexical index store; `undefined` (zero-cost) unless `textIndexes` is non-empty. */\n private readonly searchIndexStore: IndexStore | undefined\n\n /** Embedding config for write-time vector derivation; `undefined` (zero-cost) for ordinary\n * collections. When set, `put()` encodes the source field(s) and stores an encrypted `_vec` sidecar. */\n private readonly embeddings: EmbeddingDescriptor | undefined\n\n /** In-memory vector set, populated lazily from `_vec` sidecars; `undefined` when no embedding config is declared. */\n private vectorSet: VectorSet | undefined\n\n /** Field name → `DictKeyDescriptor` for `dictKey()` fields; used by `get()`/`list()` to add `<field>Label` virtual fields when a locale is requested. Mutable — see {@link _reconcileReadState} (#671 item 2). */\n private dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined\n\n /** Field name → `LookupDescriptor` for native `lookup()`/`enumOf()`/`dict()` fields (#650 Task 2) — describe()-only in this task. Mutable — see {@link _reconcileReadState} (#671 item 2). */\n private lookupFields: Record<string, LookupDescriptor> | undefined\n /** Sync join-dressing hook (#650 Task 6, #626 retirement) — `querySourceForJoin()`'s `presentForJoin`. Mutable — see {@link _reconcileReadState} (#671 item 3). */\n private presentForJoin: ((record: unknown, locale: string) => unknown) | undefined\n\n /** Consumer-neutral per-field descriptors declared via `fieldMeta`; read by `getFieldMeta()`, merged by `describe()`. */\n private fieldMeta: Record<string, FieldMeta> | undefined\n\n /** Collection-level descriptive metadata declared via `meta`; read by `getMeta()`, surfaced in `describe()`. */\n private meta: CollectionMeta | undefined\n\n /** Outbound ref declarations (snapshot from vault refRegistry at construction time); used by `describe()`. */\n private readonly _refs: Record<string, RefDescriptor>\n\n /** Money field descriptors keyed by field path, typed as the opaque {@link ViaDescriptor} marker\n * (the kernel never inspects the concrete shape); `put()` quantizes to a scaled-int string,\n * `get()`/`list()` decode back. Mutable so {@link _applyMoneyFields} can attach. */\n private moneyFields: Record<string, ViaDescriptor> | undefined; private via: ViaPipeline | undefined // compiled Via pipeline (money, i18n); rebuilt by {@link _applyMoneyFields}\n\n /**\n * Computed scalar fields, evaluated first on every `put()`. Mutable for\n * the same MV-pre-creation reconcile as {@link moneyFields}.\n */\n private computed: ComputedFields | undefined\n\n /**\n * Resolved classified() sensitive-field descriptors, declared via the\n * `classifiedFields` collection option. Mutable so {@link _applyClassifiedFields}\n * can attach a declaration to a collection MV-analysis pre-created.\n */\n private classified: ResolvedClassified | undefined\n\n /**\n * Frozen construction-time facts the refusal matrix (R1-R5) checks against.\n * Stored so {@link _applyClassifiedFields} — door 2, the reconcile seam —\n * can re-run the SAME guard the config resolver ran at door 1 (C5's lesson:\n * crdt/conflictPolicy/perRecordKeys are construction-only but\n * classifiedFields can attach later).\n */\n private readonly classifiedGuardCtx: ClassifiedGuardCtx\n\n /**\n * Digest-only classified fields (`storage: 'digest-only'`), keyed by field\n * name — the enclave-consumable policy map the codec's write path carries\n * `_vdig` forward under (C6). `null` when the collection declares none.\n */\n private readonly vdigFields: ReadonlyMap<string, VdigFieldPolicy> | null\n\n /** C-A/R10 memoization: marker declared-set lookup (undefined=unresolved) + classified-handle persist-once flag. */\n private _markerDigestOnlyCache: readonly string[] | undefined = undefined\n private _markerPersisted = false\n\n\n /** Async callback provided by the Vault to open a dynamic dictionary handle (for label-map pre-computation in the search index). Only used in `resolveDictLabelMaps()`; static dicts bypass this entirely. Mutable, assign-once — see {@link _reconcileReadState} (#671 item 1). */\n private getDictionary: ((name: string) => Promise<DictionaryHandle>) | undefined\n\n /**\n * declared deterministic fields. `null` when the feature\n * is inactive for this collection; a frozen `Set` otherwise.\n */\n private readonly deterministicFields: ReadonlySet<string> | null\n\n /**\n * Declared structural-group-encryption fields (`sensitive`). Each is\n * sealed into its own `_sealed[field]` slot under a per-field key and kept\n * out of the open `_data` blob. Empty set ⇒ feature off (byte-identical\n * output). See {@link encryptRecord} / {@link decryptRecord}.\n */\n private readonly sensitiveFields: ReadonlySet<string>\n\n /**\n * Per-record CEK opt-in (`perRecordKeys: true`). When set, writes mint /\n * reuse a per-record content-encryption key and stamp `_cek` on the\n * envelope (see {@link EncryptedEnvelope._cek}). OFF by default — a\n * non-adopting collection takes the byte-identical legacy path. The READ\n * path does not consult this flag: `_cek` presence on the envelope is the\n * format discriminant, so a mixed vault (and a recipient that never set the\n * flag) still decrypts CEK records.\n */\n private readonly perRecordCek: boolean\n\n /**\n * Per-record provenance opt-in (`provenance: true`). When set, `put()` calls\n * that supply a `source` option stamp `_source`/`_sourceTs` onto the\n * unencrypted envelope metadata. Off by default — zero cost for collections\n * that don't need lineage tracking.\n */\n private readonly provenance: boolean\n\n /**\n * Session-scoped `(id) → CEK` cache for this collection. Lets updates\n * reuse a record's stable CEK and lets repeated reads skip the AES-KW\n * unwrap. Bounded by LRU; never persisted. Dropped when the owning\n * collection instance is discarded — `vault.load()` clears the\n * collectionCache, so a keyring refresh drops every CEK alongside the\n * DEK cache. `null` unless `perRecordCek` is set.\n */\n private readonly cekCache: Lru<string, EnclaveKey> | null\n\n /**\n * The per-record envelope build + encrypt/decrypt + per-record-CEK +\n * sealed-field crypto, extracted off this god-object. Holds no mutable\n * state of its own — it shares this collection's `cekCache` reference (so\n * tier methods and `vault.invalidateRecordCaches` evictions stay visible to\n * it) and reads the rest of its dependencies as a frozen context snapshot.\n */\n private readonly codec: RecordCodec<T>\n\n /**\n * declared tiers for this collection. `null` when\n * tier-aware methods are disabled. Tier 0 is implicit and never\n * stored here.\n */\n private readonly tiers: ReadonlySet<number> | null\n private readonly tierMode: TierMode\n private readonly onCrossTierAccess: ((event: CrossTierAccessEvent) => void) | undefined\n private readonly addSubjectRef: ((id: string, record: unknown) => Promise<void>) | undefined // #766: putAtTier's first-write subject-index registration (wired by the Vault; undefined ⇒ no forget-subject field declared)\n\n /**\n * Optional reference to the vault-level hash-chained audit log. When present, every successful `put()` and `delete()` appends an entry to the ledger AFTER the adapter write succeeds (so a failed adapter write never produces an orphan ledger entry).\n *\n * The ledger is always a vault-wide singleton — all\n * collections in the same vault share the same LedgerStore.\n * Vault.ledger() does the lazy init; this field just holds\n * the reference so Collection doesn't need to reach back up to the\n * vault on every mutation.\n *\n * `undefined` means \"no ledger attached\" — supported for tests that\n * construct a Collection directly without a vault, and for\n * future backwards-compat scenarios. Production usage always has a\n * ledger because Vault.collection() passes one through.\n */\n private readonly ledger: LedgerStore | undefined\n\n /** — per-collection CRDT mode, or undefined for normal LWW-at-record-level. */\n private readonly crdtMode: CrdtMode | undefined\n\n /** — optional remote/sync adapter for presence broadcasting. */\n private readonly syncAdapter: NoydbStore | undefined\n\n /** — consent-audit hook, no-op when no scope is active. */\n private readonly onAccess:\n | ((op: 'get' | 'put' | 'delete' | 'reveal' | 'verify' | 'find', id: string) => Promise<void>)\n | undefined\n\n /**\n * Vault-internal hook for derivation dispatch. When set,\n * `Collection.put` consults the registry after the source-write\n * commits and writes derived outputs through `getCollection(name).put`.\n */\n private readonly derivationSource:\n | {\n registry(): DerivationRegistry\n getCollection(name: string): Collection<Record<string, unknown>>\n getReadOnlyFacade(): ReadOnlyVaultFacade\n getActiveTxContext(): TxContext | null\n /**\n * Construct a fresh transient TxContext bound to the owning\n * Noydb. Used by `Collection.putManyAtomic` to publish an\n * `_activeTxContext` for the duration of its Phase 2 loop so\n * recursive derived-output writes register their pre-write\n * envelopes on `ctx._executed` and roll back alongside the\n * bulk-put source ops.\n */\n createTxContext(): TxContext\n /** Publish a TxContext for the duration of a bulk-atomic loop. */\n setActiveTxContext(ctx: TxContext): void\n /** Drop a previously-published TxContext (defensive no-op if mismatched). */\n clearActiveTxContext(ctx: TxContext): void\n }\n | undefined\n\n /**\n * Vault-internal hook for materialized-view dispatch.\n * Parallel to `derivationSource` — when set, `Collection.put` fires\n * `MaterializedViewRegistry.onSourceWrite` after the source-write\n * commits + after `dispatchDerivations` has run.\n */\n private readonly materializedViewSource:\n | {\n \n registry(): MaterializedViewRegistry\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n getCollection(name: string): Collection<any>\n getActiveTxContext(): TxContext | null\n getQueryContext(): MVQueryContext\n }\n | undefined\n\n /** #638 Task 4 — `Vault._collectGraphTouch`; a no-op absent an open batch. `collectDelete` (#640) is the sync-apply delete socket. */\n private readonly graphDispatch: { collect(collection: string, id: string): void; collectDelete(collection: string, id: string, intents: readonly RollupDeleteIntent[]): void } | undefined\n\n /**\n * Optional back-reference to the owning compartment's ref\n * enforcer. When present, `Collection.put` calls\n * `refEnforcer.enforceRefsOnPut(name, record)` before the adapter\n * write, and `Collection.delete` calls\n * `refEnforcer.enforceRefsOnDelete(name, id)` before its own\n * adapter delete. The Vault handles the actual registry\n * lookup and cross-collection enforcement — Collection just\n * notifies it at the right points in the lifecycle.\n *\n * Typed as a structural interface rather than `Vault`\n * directly to avoid a circular import. Vault implements\n * these two methods; any other object with the same shape would\n * work too (used only in unit tests).\n */\n private readonly refEnforcer:\n | {\n enforceRefsOnPut(collectionName: string, record: unknown): Promise<void>\n enforceRefsOnDelete(collectionName: string, id: string): Promise<void>\n _deleteCascadesPossible(collectionName: string): boolean\n }\n | undefined\n\n /**\n * Optional back-reference to the owning compartment's join resolver\n *`). When present,\n * `Collection.query()` builds a `JoinContext` that lets the Query\n * resolve `.join(field)` calls into target collections via this\n * resolver.\n *\n * Two methods:\n * - `resolveSource(name)` — fetch a `JoinableSource` for the\n * right-side collection by name. Returning `null` means \"no\n * such collection in this compartment\" — the executor then\n * throws an actionable error naming the missing target.\n * - `resolveRef(leftCollection, field)` — look up the ref\n * descriptor the left collection declared for this field.\n * `null` when the field has no ref, which makes `.join()`\n * throw at plan time before any records are touched.\n *\n * Typed structurally rather than as `Vault` to avoid a\n * circular import. Vault implements these two methods; any\n * other object with the same shape works too (used only in unit\n * tests against a plain object).\n */\n private readonly joinResolver:\n | {\n resolveSource(collectionName: string): JoinableSource | null\n resolveRef(leftCollection: string, field: string): RefDescriptor | null\n resolveDictSource?: (leftCollection: string, field: string) => JoinableSource | null\n }\n | undefined\n\n constructor(opts: CollectionOpts<T>) {\n const cfg = resolveCollectionConfig(opts)\n this.adapter = cfg.adapter\n this.vault = cfg.vault\n this.name = cfg.name\n this.keyring = cfg.keyring\n this.storeCiphertext = cfg.storeCiphertext\n this.ramCiphertext = cfg.ramCiphertext\n this.emitter = cfg.emitter\n this.writeQueue = cfg.writeQueue\n this.schemaUpdateGate = cfg.schemaUpdateGate\n this.schemaFence = cfg.schemaFence\n this.writeHooks = cfg.writeHooks\n this.subsystemBus = cfg.subsystemBus\n this.activeTxId = cfg.activeTxId\n this.strategies = cfg.strategies\n this.objectStore = cfg.objectStore\n this.blobFields = cfg.blobFields; this.blobTierPolicy = cfg.blobTierPolicy ?? 'isolate'\n this.reconcileOnOpen = cfg.reconcileOnOpen\n this.getDEK = cfg.getDEK\n this.onDirty = cfg.onDirty\n this.tabCoordinated = cfg.tabCoordinated\n this.historyConfig = cfg.historyConfig\n this.historyConfigExplicit = cfg.historyConfigExplicit\n this.schema = cfg.schema\n this.ledger = cfg.ledger\n this.refEnforcer = cfg.refEnforcer\n this.joinResolver = cfg.joinResolver\n this.i18nFields = cfg.i18nFields\n // Only spin up an index store when text fields are declared, so\n // ordinary collections pay nothing (the dirty poke + retrieve see undefined).\n this.textIndexes = cfg.textIndexes\n // `searchIndexStore` is `this`-dependent: the persisted-store callback thunk\n // closes over `this.searchContext()`. Built BEFORE `this.codec` exists — the\n // thunk is lazy (NOT evaluated here), so the A14 codec-after-this ordering holds.\n this.searchIndexStore =\n opts.textIndexes && opts.textIndexes.length > 0\n ? opts.textIndexPersist\n ? new PersistedIndexStore(buildPersistedIndexCallbacksImpl(() => this.searchContext()))\n : new MemoryIndexStore()\n : undefined\n this.embeddings = cfg.embeddings\n this.vectorSet = cfg.vectorSet\n this.dictKeyFields = cfg.dictKeyFields\n this.lookupFields = cfg.lookupFields\n this.presentForJoin = cfg.presentForJoin\n this.fieldMeta = cfg.fieldMeta\n this.meta = cfg.meta\n this._refs = cfg._refs\n this.moneyFields = cfg.moneyFields\n this.via = cfg.via\n this.classified = cfg.classified\n this.classifiedGuardCtx = cfg.classifiedGuardCtx\n this.vdigFields = cfg.vdigFields\n this.computed = cfg.computed\n this.getDictionary = cfg.getDictionary\n this.defaultLocale = cfg.defaultLocale\n this.crdtMode = cfg.crdtMode\n this.syncAdapter = cfg.syncAdapter\n this.onAccess = cfg.onAccess\n this.derivationSource = cfg.derivationSource\n this.materializedViewSource = cfg.materializedViewSource\n this.graphDispatch = cfg.graphDispatch\n this.tiers = cfg.tiers\n this.tierMode = cfg.tierMode\n this.onCrossTierAccess = cfg.onCrossTierAccess\n this.addSubjectRef = cfg.addSubjectRef\n this.deterministicFields = cfg.deterministicFields\n this.sensitiveFields = cfg.sensitiveFields\n this.perRecordCek = cfg.perRecordCek\n this.cekCache = cfg.cekCache\n this.provenance = cfg.provenance\n\n // Fix 3: warn when `sensitive` is a no-op in debug-plaintext mode. When\n // storeCiphertext is false the sealing path is skipped entirely, so\n // sensitive fields are written in plaintext.\n if (this.sensitiveFields.size > 0 && !this.storeCiphertext) {\n console.warn(\n `[noy-db] collection \"${opts.name}\": \\`sensitive\\` fields are NOT sealed in ` +\n `plaintext (debug) mode — they are written unencrypted.`,\n )\n }\n\n // Warn when a sealed `sensitive` field is also declared in `indexes`: a\n // plaintext secondary index defeats non-residency (the index buckets hold\n // the cleartext value the seal was meant to hide). Compile-time refusal is\n // a deferred follow-up.\n if (this.sensitiveFields.size > 0 && opts.indexes) {\n const indexedFields = new Set<string>()\n for (const def of opts.indexes) {\n if (typeof def === 'string') indexedFields.add(def)\n else if (Array.isArray(def)) for (const f of def) indexedFields.add(f)\n else for (const f of (def as { fields: readonly string[] }).fields) indexedFields.add(f)\n }\n const leaked = [...this.sensitiveFields].filter((f) => indexedFields.has(f))\n if (leaked.length > 0) {\n console.warn(\n `[noy-db] collection \"${opts.name}\": sealed \\`sensitive\\` field(s) ` +\n `${leaked.map((f) => `\"${f}\"`).join(', ')} also appear in \\`indexes\\` — a ` +\n `plaintext secondary index stores the cleartext value and defeats non-residency.`,\n )\n }\n }\n\n // Build the record codec once, AFTER every dependency it reads is assigned\n // (name, keyring, storeCiphertext, provenance, sensitiveFields, deterministicFields,\n // crdtMode, crdtStrategy, schema, getDEK, cekCache, via). `cekCache` is the SAME\n // reference (not a copy) — the codec's resolveEnvelopeCek and the tier/forget cache evictions share it.\n this.codec = new RecordCodec<T>({\n name: this.name,\n actor: this.keyring.userId,\n storeCiphertext: this.storeCiphertext,\n debugPlaintext: this.keyring.debugPlaintext === true,\n provenance: this.provenance,\n sensitiveFields: this.sensitiveFields,\n deterministicFields: this.deterministicFields,\n vdigFields: this.vdigFields,\n crdtMode: this.crdtMode,\n crdtStrategy: this.strategies.crdt,\n schema: this.schema,\n getDEK: (collection) => this.getDEK(collection ?? this.name),\n cekCache: this.cekCache,\n classifiedMarkerDigestOnly: () => this._classifiedMarkerDigestOnly(),\n via: this.via,\n }) // #629 T10: classifySealedShred wired onto cfg.classifiedEraseCfg just below, once this.codec exists\n if (cfg.classifiedEraseCfg) cfg.classifiedEraseCfg.classifySealedShred = (live) => this.codec.classifySealedShred(live as EncryptedEnvelope)\n // Build + register this collection's SyncEngine conflict resolvers (the CRDT\n // merge resolver + the per-collection `conflictPolicy` resolver). Kept inline\n // here: the closures capture private `this` state (this.codec,\n // this.strategies.crdt, this.resolveRecordCek) AND close over `conflictPolicy:\n // ConflictPolicy<T>`, whose custom-merge `(T, T) => T` is invariant in T —\n // exposing them through a method parameter would break the `Collection<T>` →\n // `Collection<unknown>` assignment the Vault relies on. MUST run after\n // `this.codec` (both resolvers decrypt through it) and BEFORE the lazy/index\n // cluster below, preserving the original registration→validation order.\n // register CRDT conflict resolver with SyncEngine\n if (opts.crdt && opts.onRegisterConflictResolver) {\n const crdtMode = opts.crdt\n const crdtResolver: CollectionConflictResolver = async (id, local, remote) => {\n if (crdtMode === 'yjs') {\n // Core cannot merge Yjs without the yjs package — take the higher version\n return local._v >= remote._v ? local : remote\n }\n const localJson = await this.codec.decryptJsonString(local, id)\n const remoteJson = await this.codec.decryptJsonString(remote, id)\n // Tombstone (shredded) on either side: the live envelope is the\n // authoritative merge result — a shred must win and stay shredded.\n if (localJson === null) return local\n if (remoteJson === null) return remote\n const merged = this.strategies.crdt.mergeCrdtStates(JSON.parse(localJson) as CrdtState, JSON.parse(remoteJson) as CrdtState)\n const mergedVersion = Math.max(local._v, remote._v) + 1\n const cek = this.perRecordCek ? await this.resolveRecordCek(id) : undefined\n return this.codec.encryptJsonString(JSON.stringify(merged), mergedVersion, cek)\n }\n opts.onRegisterConflictResolver(this.name, crdtResolver)\n }\n\n // build and register per-collection conflict resolver with SyncEngine\n if (opts.conflictPolicy !== undefined && opts.onRegisterConflictResolver) {\n const policy = opts.conflictPolicy\n const compartmentName = this.vault\n const collectionName = this.name\n const emitter = this.emitter\n let resolver: CollectionConflictResolver\n\n if (policy === 'last-writer-wins') {\n resolver = async (_id, local, remote) => (local._ts >= remote._ts ? local : remote)\n } else if (policy === 'first-writer-wins') {\n resolver = async (_id, local, remote) => (local._v <= remote._v ? local : remote)\n } else if (policy === 'manual') {\n resolver = (id, local, remote) =>\n new Promise<EncryptedEnvelope | null>(resolvePromise => {\n let settled = false\n const resolveCallback = (winner: EncryptedEnvelope | null) => {\n if (!settled) {\n settled = true\n resolvePromise(winner)\n }\n }\n emitter.emit('sync:conflict', {\n vault: compartmentName,\n collection: collectionName,\n id,\n local,\n remote,\n localVersion: local._v,\n remoteVersion: remote._v,\n resolve: resolveCallback,\n })\n // Defer if no handler called resolve synchronously\n if (!settled) {\n settled = true\n resolvePromise(null)\n }\n })\n } else {\n // Custom merge fn: decrypt both → merge → re-encrypt\n const mergeFn = policy as (local: T, remote: T) => T\n resolver = async (id, local, remote) => {\n const localRecord = await this.codec.decryptRecord(local, { skipValidation: true, id })\n const remoteRecord = await this.codec.decryptRecord(remote, { skipValidation: true, id })\n // Tombstone on either side wins — a shredded record must not be\n // resurrected by a merge against a still-live peer.\n if (localRecord === null) return local\n if (remoteRecord === null) return remote\n const merged = mergeFn(localRecord, remoteRecord)\n const mergedVersion = Math.max(local._v, remote._v) + 1\n const cek = this.perRecordCek ? await this.resolveRecordCek(id) : undefined\n // R2 refuses digest-only × conflictPolicy; on a vdig collection this path is\n // unreachable and the codec fail-loud guard backstops it.\n return this.codec.encryptRecord(merged, mergedVersion, cek, undefined, undefined, undefined, id)\n }\n }\n\n opts.onRegisterConflictResolver(collectionName, resolver)\n }\n\n // Default `prefetch: true` keeps semantics. Only opt-in to lazy\n // mode when the consumer explicitly sets `prefetch: false`.\n this.lazy = opts.prefetch === false\n\n if (this.lazy) {\n // #267 lazy service — budget validation + LRU construction live on the\n // strategy seam (withLazy(); IMPLICIT_LAZY = deprecated implicit path).\n this.lru = opts.strategies.lazy\n .createCache<{ record: T; version: number }>(this.name, opts.cache)\n this.hydrated = true // lazy mode is always \"hydrated\" — no bulk load\n } else {\n this.lru = null\n }\n\n // delegate mirror construction + declaration to the active\n // indexing strategy. `NO_INDEXING` returns a state whose accessors\n // both return null; the active strategy (from `@noy-db/hub/indexing`)\n // constructs the appropriate mirror based on lazy vs eager mode and\n // declares every IndexDef. With NO_INDEXING the heavy index classes\n // never reach the bundle.\n const strategy = opts.strategies.indexing\n this.indexState = strategy.createState({\n defs: opts.indexes ?? [],\n lazy: this.lazy,\n })\n this.indexes?.setCanonicalizer((f, v) => this.via?.canonicalizeIndexKey(f, v)) // #672 review C1: one-time canonicalizer registration; lazy `this.via` read survives late `_setVia` (#666)\n this.persistedIndexes?.setCanonicalizer((f, v) => this.via?.canonicalizeIndexKey(f, v)) // #677: lazy twin of the line above\n\n // Unique-constraint enforcement (eager mode only; UnsupportedIndexOptionError)\n // — see buildUniqueConstraintSet. The Arc-7 tiers+blobFields refusal (#724)\n // moved to collection.blob(id)'s runtime read gate (Arc 10 Task 1, blob-set.ts).\n this.uniqueConstraints = buildUniqueConstraintSet(this.name, opts.indexes, {\n lazy: this.lazy,\n crdt: this.crdtMode != null,\n tiered: this.tiers != null,\n })\n }\n /**\n * Return the Standard Schema validator attached to this collection,\n * or `undefined` if none was provided at construction time.\n *\n * Exposed (read-only) for the Vault-level export primitive,\n * which surfaces each collection's schema in the per-chunk metadata\n * so downstream serializers (`@noy-db/as-*` packages, custom\n * exporters) can produce schema-aware output without poking at\n * collection internals. The validator object is returned by\n * reference — callers must treat it as immutable.\n */\n getSchema(): StandardSchemaV1<unknown, T> | undefined {\n return this.schema\n }\n\n /** The declared consumer-neutral field metadata channel (canonical). */\n getFieldMeta(): Record<string, FieldMeta> | undefined { return this.fieldMeta }\n\n /** The collection's declared descriptive metadata. */\n getMeta(): CollectionMeta | undefined { return this.meta }\n\n /**\n * Aggregate all collection-level configuration options that are actively set\n * into a {@link CollectionConfig} snapshot. Returns `undefined` when no options\n * are configured (omitting the `config` block from `dumpSchema()` output).\n * Consumed by `walk.ts` to populate `CollectionDescriptor.config`.\n */\n getConfig(): CollectionConfig | undefined {\n const i18nFields = this.i18nFields !== undefined\n ? Object.keys(this.i18nFields)\n : undefined\n const embeddings = this.embeddings !== undefined\n ? {\n source: this.embeddings.source,\n dim: this.embeddings.dim,\n ...(this.embeddings.model !== undefined ? { model: this.embeddings.model } : {}),\n }\n : undefined\n const textIndexes = this.textIndexes !== undefined && this.textIndexes.length > 0\n ? this.textIndexes\n : undefined\n const textIndexPersist = this.searchIndexStore instanceof PersistedIndexStore ? true : undefined\n const perRecordKeys = this.perRecordCek ? true : undefined\n const provenance = this.provenance ? true : undefined\n const tiers = this.tiers !== null ? Array.from(this.tiers) : undefined\n const tierMode = this.tiers !== null ? (this.tierMode as string) : undefined\n const crdt = this.crdtMode !== undefined ? (this.crdtMode as string) : undefined\n /**\n * `true` when history is explicitly enabled for this collection (i.e. the\n * caller supplied a `historyConfig` option and history is not disabled).\n * Omitted when no per-collection config was provided or history is disabled.\n */\n const history = this.historyConfigExplicit && this.historyConfig.enabled !== false\n ? true\n : undefined\n\n const hasAny =\n i18nFields !== undefined ||\n embeddings !== undefined ||\n textIndexes !== undefined ||\n textIndexPersist !== undefined ||\n perRecordKeys !== undefined ||\n provenance !== undefined ||\n tiers !== undefined ||\n crdt !== undefined ||\n history !== undefined\n\n if (!hasAny) return undefined\n\n return {\n ...(i18nFields !== undefined ? { i18nFields } : {}),\n ...(embeddings !== undefined ? { embeddings } : {}),\n ...(textIndexes !== undefined ? { textIndexes } : {}),\n ...(textIndexPersist !== undefined ? { textIndexPersist } : {}),\n ...(perRecordKeys !== undefined ? { perRecordKeys } : {}),\n ...(provenance !== undefined ? { provenance } : {}),\n ...(tiers !== undefined ? { tiers } : {}),\n ...(tierMode !== undefined ? { tierMode } : {}),\n ...(crdt !== undefined ? { crdt } : {}),\n ...(history !== undefined ? { history } : {}),\n }\n }\n\n /**\n * Describe the collection's field schema from in-memory config — zero store I/O.\n * Sync overload (no args): merges moneyFields/dictKeyFields/refs/computed/fieldMeta/\n * taint into a {@link CollectionDescription} (types inferred from config; the async\n * overload also derives validator-exact types and resolves dynamic dict labels).\n */\n describe(): CollectionDescription\n describe(opts: DescribeOptions): Promise<CollectionDescription>\n describe(opts?: DescribeOptions): CollectionDescription | Promise<CollectionDescription> {\n if (opts) return this.describeAsync(opts)\n return buildDescription({\n collection: this.name,\n fieldMeta: this.fieldMeta,\n moneyFields: this.moneyFields,\n dictKeyFields: this.dictKeyFields,\n ...(this.lookupFields !== undefined ? { lookupFields: this.lookupFields } : {}),\n computed: this.computed,\n refs: this._refs,\n zodFields: undefined,\n ...(this.meta !== undefined ? { meta: this.meta } : {}),\n ...(this.i18nFields !== undefined ? { i18nFields: this.i18nFields } : {}),\n ...(this.classified !== undefined ? { classified: this.classified.byField } : {}),\n ...(this.via?.taint !== undefined ? { taint: this.via.taint } : {}),\n ...(this.via ? { viaFragments: this.via.describeFragments() } : {}), // #650 Task 7\n })\n }\n\n /**\n * Async describe implementation. Derives validator-exact types via deriveZodFields\n * (lazy, no static zod import), optionally resolves dynamic-dict labels from vault.dictionary(name).list(),\n * then delegates to buildDescription (which also runs fieldMeta key-validation).\n */\n private async describeAsync(opts: DescribeOptions): Promise<CollectionDescription> {\n // 1. Derive per-field type/optional/constraints/meta from the validator (if any).\n const zodFields = this.schema !== undefined\n ? await deriveZodFields(this.schema)\n : undefined\n\n // 2. Optionally resolve dynamic-dict labels — dictKeyFields AND reserved-tier\n // lookupFields (native dict()) share the SAME `_dict_<name>` backing (review fix).\n let dictLabels: Record<string, Record<string, string>> | undefined\n if (opts.resolveDictLabels === true && this.getDictionary !== undefined) {\n const names = new Set<string>()\n for (const desc of Object.values(this.dictKeyFields ?? {})) if (!isStaticDictDescriptor(desc)) names.add(desc.name)\n for (const desc of Object.values(this.lookupFields ?? {})) if (desc.backing === 'reserved') names.add(desc.dimension)\n if (names.size > 0) {\n dictLabels = {}\n for (const name of names) {\n const handle = await this.getDictionary(name)\n const entries = await handle.list()\n const valueToLabel: Record<string, string> = {}\n for (const entry of entries) {\n // Pick the first available locale label as the display label.\n const label = Object.values(entry.labels)[0]\n if (label !== undefined) valueToLabel[entry.key] = label\n }\n dictLabels[name] = valueToLabel\n }\n }\n }\n\n return buildDescription({\n collection: this.name,\n fieldMeta: this.fieldMeta,\n moneyFields: this.moneyFields,\n dictKeyFields: this.dictKeyFields,\n ...(this.lookupFields !== undefined ? { lookupFields: this.lookupFields } : {}),\n computed: this.computed,\n refs: this._refs,\n zodFields,\n ...(dictLabels !== undefined ? { dictLabels } : {}),\n ...(this.meta !== undefined ? { meta: this.meta } : {}),\n ...(this.i18nFields !== undefined ? { i18nFields: this.i18nFields } : {}),\n ...(this.classified !== undefined ? { classified: this.classified.byField } : {}),\n ...(this.via?.taint !== undefined ? { taint: this.via.taint } : {}),\n ...(this.via ? { viaFragments: this.via.describeFragments() } : {}), // #650 Task 7\n })\n }\n\n /** JSON Schema for this collection with describe() metadata as x- extensions. */\n async toJSONSchema(): Promise<object> {\n // Lazy import (#553) -- only reachable through this async method.\n const { buildJsonSchema } = await import('../with-shape/introspection/json-schema.js')\n const desc = await this.describe({})\n let base: Record<string, unknown> | null = null\n if (this.schema !== undefined) {\n const env = await derivePersistedSchema(this.schema)\n base = (env.jsonSchema as Record<string, unknown> | null) ?? null\n }\n return buildJsonSchema(desc, base)\n }\n\n /** Single-point audited reveal of one classified field. Requires withClassified(). */\n async reveal(id: string, field: string): Promise<unknown> {\n const spec = this.classified?.byField[field]\n if (spec === undefined) throw new ClassifiedRevealError(this.name, field, 'field is not classified')\n if (spec.storage === 'never') {\n throw new ClassifiedRevealError(this.name, field, `storage:'never' — nothing is stored to reveal`)\n }\n if (spec.storage === 'digest-only') {\n throw new ClassifiedRevealError(this.name, field, `storage:'digest-only' — verify-only; nothing recoverable to reveal`)\n }\n return this.strategies.classified.reveal({\n collection: this.name,\n spec,\n encrypted: this.storeCiphertext,\n getEnvelope: (rid) => this.adapter.get(this.vault, this.name, rid),\n resolveCek: (env) => this.codec.resolveEnvelopeCek(env),\n getDEK: () => this.getDEK(this.name),\n ...(this.onAccess !== undefined\n ? { onAccess: async (_op: 'reveal', rid: string) => { await this.onAccess!('reveal', rid) } }\n : {}),\n }, id, field)\n }\n\n /** Verify-without-reveal: verdict-only oracle for one classified field. Requires withClassified(). */\n async verify(id: string, field: string, candidate: string): Promise<ClassifiedVerdict> {\n const spec = this.classified?.byField[field]\n if (spec === undefined) throw new ClassifiedVerifyError(this.name, field, 'field is not classified')\n if (spec.storage === 'never') {\n throw new ClassifiedVerifyError(this.name, field, `storage:'never' — nothing is stored to verify against`)\n }\n const ctx = this._classifiedVerifyCtx(spec)\n return spec.storage === 'digest-only'\n ? this.strategies.classified.verify(ctx, id, field, candidate)\n : this.strategies.classified.verifyText(ctx, id, field, candidate)\n }\n\n /** k-of-n challenge over the collection's secretAnswer members. Requires withClassified(). */\n async verifyGroup(id: string, answers: Record<string, string>, opts: { readonly min: number }): Promise<{ readonly passed: boolean }> {\n const members = Object.entries(this.classified?.byField ?? {})\n .filter(([, s]) => s.storage === 'digest-only' && s.verifyGroupMember === true)\n .map(([field, spec]) => ({ field, spec }))\n if (members.length === 0) {\n throw new ClassifiedVerifyError(this.name, '*', 'no groupable digest-only (secretAnswer) fields declared')\n }\n const ctx = { ...this._classifiedVerifyCtx(members[0]!.spec), groupMembers: members }\n return this.strategies.classified.matchGroup(ctx, id, answers, opts)\n }\n\n private _classifiedVerifyCtx(spec: ClassifiedFieldSpec): ClassifiedVerifyCtx {\n return {\n collection: this.name,\n spec,\n getEnvelope: (rid) => this.adapter.get(this.vault, this.name, rid),\n resolveCek: (env) => this.codec.resolveEnvelopeCek(env),\n getDEK: () => this.getDEK(this.name),\n now: () => Date.now(), // Q7: injected here; engine tests inject their own\n ...(this.onAccess !== undefined\n ? { onAccess: async (_op: 'verify' | 'find', rid: string) => { await this.onAccess!('verify', rid) } }\n : {}),\n }\n }\n\n /**\n * Equatable blind-index lookup: the ids whose classified digest-only\n * `equatable` field carries a `_bidx` tag matching `candidate` AND whose\n * `_vdig` payload confirms it. Requires the field to be declared\n * `classified.password({ equatable: true })` (or `secretAnswer`) and the\n * collection to have opened its `acknowledgeEquatableRisk` door.\n *\n * The algorithm order is load-bearing (spec §3):\n * 1. Caller-bug refusals thrown at ~0 elapsed, BEFORE any PBKDF2 (R9 /\n * Oracle #6): the three field mis-declarations share ONE constant,\n * field-name-free message so the refusal text cannot enumerate which\n * fields are classified / digest-only / equatable.\n * 2. Derive the ONE blind-index target UNCONDITIONALLY (I-1 / F1): an empty\n * collection still pays exactly one 600K PBKDF2, so wall-time can never\n * distinguish \"no records\" from \"no match\". No early return may precede\n * this line.\n * 3. Scan `list + one get` per id, string-comparing the stored `_bidx` tag —\n * decrypting NOTHING — and retain each hit's already-fetched envelope.\n * 4. Emit the single sweep consent op (`onAccess('find', '*')`) now — after\n * the scan, before confirm (Oracle #5) — fixing its store-write timestamp\n * independent of hit count.\n * 5. Confirm-by-verify against the ALREADY-FETCHED envelope (C-B): run the\n * enclave `verifyDigestField` on an in-memory `getEnvelope` closure so the\n * confirm reads ZERO additional envelopes. A tag-hit whose `_vdig` fails\n * to confirm is dropped silently (a splice is indistinguishable from a\n * stale tag). Store-shape law: the only store calls are `list + N get`.\n */\n async findByDigest(field: string, candidate: string): Promise<readonly string[]> {\n // 1. Caller-bug refusals — pad-exempt, before any PBKDF2. R9 single message.\n const spec = this.classified?.byField[field]\n if (spec === undefined || spec.storage !== 'digest-only' || spec.equatable !== true) {\n throw new ClassifiedVerifyError(this.name, '*',\n 'not a declared equatable digest-only classified field')\n }\n if (typeof candidate !== 'string') {\n throw new ClassifiedVerifyError(this.name, '*', 'candidate must be a string')\n }\n\n // 2. ONE full 600K PBKDF2, run UNCONDITIONALLY before the scan (I-1). A\n // NO_CLASSIFIED strategy surfaces ClassifiedNotEnabledError here.\n const target = await this.strategies.classified.computeTarget(this._classifiedVerifyCtx(spec), field, candidate)\n\n // 3. Scan: list + one get per id; string-compare the stored tag; decrypt\n // nothing; retain each hit's already-fetched envelope for the confirm.\n const ids = await this.adapter.list(this.vault, this.name)\n const hits: string[] = []\n const hitMap = new Map<string, EncryptedEnvelope>()\n for (const id of ids) {\n const env = await this.adapter.get(this.vault, this.name, id)\n if (target !== null && env?._bidx?.[field] === target) {\n hits.push(id)\n hitMap.set(id, env)\n }\n }\n\n // 4. Single sweep consent op — after the scan, before confirm (Oracle #5).\n await this.onAccess?.('find', '*')\n\n // 5. Confirm-by-verify on the IN-HAND envelope (C-B) — the enclave verify\n // door via a dynamic import (the kernel spine reaches the enclave only\n // through import(), never a static deep import). NOT strategy.verify —\n // that re-fetches via ctx.getEnvelope AND emits a per-id 'verify' op.\n if (hits.length === 0) return []\n const { verifyDigestField } = await import('./enclave/classify/verify.js')\n const policy: VdigFieldPolicy = {\n normalize: spec.verifyNormalize ?? 'password',\n notLastN: spec.notLastN ?? 0,\n equatable: true,\n ...(spec.rotateDays !== undefined ? { rotateDays: spec.rotateDays } : {}),\n }\n const confirmCtx = {\n collection: this.name,\n getEnvelope: async (rid: string) => hitMap.get(rid) ?? null, // in-memory: zero extra store.get\n resolveCek: (env: EncryptedEnvelope) => this.codec.resolveEnvelopeCek(env),\n getDEK: () => this.getDEK(this.name),\n now: () => Date.now(),\n }\n const confirmed: string[] = []\n for (const id of hits) {\n const verdict = await verifyDigestField(confirmCtx, id, field, candidate, policy)\n if (verdict.ok === true) confirmed.push(id) // discard mustRotate; drop failures silently\n }\n return confirmed\n }\n\n /**\n * Retire a field's equatable blind-index (`_bidx`) coverage across every\n * live record — the SOLE lazy-write-independent drop-path for a still-live\n * record's tag (besides clear / `forget()` / DEK-rotation). For each envelope\n * carrying `_bidx[field]`, rewrite it WITHOUT that slot (dropping the whole\n * `_bidx` map when it becomes empty), leaving `_vdig[field]` and everything\n * else INTACT — the field stays `digest-only`, only the index coverage is\n * retired. NO crypto, NO re-mint, NO re-encrypt: a targeted envelope rewrite.\n * Returns the count of records scrubbed.\n *\n * This is a maintenance write, not a read-egress: it emits NO `'find'` op and\n * no consent. The field is validated to a declared equatable digest-only\n * classified field (only such a field ever carries `_bidx`).\n *\n * **Ledger consistency**: dropping `_bidx[field]` changes the envelope's\n * payload hash (`_bidx` is bound into `envelopeBodyForHash`), so a raw\n * `adapter.put` of the scrubbed envelope WITHOUT a matching ledger entry would\n * desync the chain and make a future integrity cross-check flag false\n * tampering. After each rewrite we therefore append an `op:'migration'` entry\n * recording the NEW payloadHash at the SAME version — this is index retirement,\n * not a new record version, so `_v` is NOT bumped; the migration op is\n * reverse-delta-inert (`ledger.reconstruct` skips non-put/delete ops) yet\n * keeps the hash chain and the record's latest recorded payloadHash correct.\n */\n async scrubEquatableTags(field: string): Promise<number> {\n const spec = this.classified?.byField[field]\n if (spec === undefined || spec.storage !== 'digest-only' || spec.equatable !== true) {\n throw new ClassifiedVerifyError(this.name, '*',\n 'not a declared equatable digest-only classified field')\n }\n const ids = await this.adapter.list(this.vault, this.name)\n let count = 0\n for (const id of ids) {\n const env = await this.adapter.get(this.vault, this.name, id)\n if (env?._bidx?.[field] === undefined) continue\n\n // Rewrite without the field's tag; drop the whole `_bidx` map if it\n // empties (a fresh mutable copy — `EncryptedEnvelope._bidx` is readonly).\n const nextBidx: Record<string, string> = { ...env._bidx }\n delete nextBidx[field]\n const scrubbedRaw: Record<string, unknown> = { ...env }\n delete scrubbedRaw._bidx\n if (Object.keys(nextBidx).length > 0) scrubbedRaw._bidx = nextBidx\n const scrubbed = scrubbedRaw as unknown as EncryptedEnvelope\n await this.adapter.put(this.vault, this.name, id, scrubbed)\n\n // Keep the ledger verifiable: the scrubbed envelope has a new payload\n // hash, so record it (no `_v` bump — index retirement, not a version).\n if (this.ledger) {\n await this.ledger.append({\n op: 'migration', collection: this.name, id, version: scrubbed._v,\n actor: this.keyring.userId,\n payloadHash: await this.strategies.history.envelopePayloadHash(scrubbed),\n reason: 'classified:scrub-equatable-tags',\n })\n }\n count++\n }\n return count\n }\n\n /**\n * @internal — attach money descriptors post-construction. MV dependency\n * analysis auto-creates a source collection (without options) during\n * `openVault`, before the user's `collection(name, { moneyFields })`\n * declaration; this reconciles that ordering. First-wins. Not public.\n *\n * PREPENDS money rather than appending: {@link compileViaBindings} always\n * compiles money before i18n (money-first pipeline order — see its\n * docstring), and by the time this reconcile runs an i18n binding may\n * already be sitting in `this.via.bindings` (declared at construction).\n * Appending here would yield `[i18n, money]` on this path vs `[money,\n * i18n]` from compile — prepending keeps both paths money-first.\n */\n _applyMoneyFields(moneyFields: Record<string, ViaDescriptor>): void {\n if (this.moneyFields !== undefined) return\n const virtualMoney = resolveVirtualMoneyFields(Object.keys(moneyFields), (f) => this.via?.bindings.find((b) => b.brand === 'computed')?.covers?.(f) ?? false) // #669\n this.via = ViaPipeline.build([viaBinder('money')({ moneyFields, ...(virtualMoney.size > 0 ? { virtualMoneyFields: virtualMoney } : {}) }), ...(this.via?.bindings ?? [])], this.via?.taint) // #671 item 4 — thread taint through the rebuild\n this.moneyFields = moneyFields\n if (this.hydrated) this.rebuildEagerIndexesFromCache() // #686: re-canonicalize buckets built before this money late-attach\n }\n\n /** @internal — attach computed fields post-construction. See {@link _applyMoneyFields}. */\n _applyComputed(computed: ComputedFields): void {\n if (this.computed === undefined) this.computed = computed\n }\n\n /** @internal — attach fieldMeta post-construction. See {@link _applyMoneyFields}. First-wins. */\n _applyFieldMeta(fieldMeta: Record<string, FieldMeta>): void {\n if (this.fieldMeta === undefined) this.fieldMeta = fieldMeta\n }\n\n /** @internal — attach collection-level meta post-construction. See {@link _applyMoneyFields}. First-wins. */\n _applyMeta(meta: CollectionMeta): void {\n if (this.meta === undefined) this.meta = meta\n }\n\n /**\n * @internal — attach classified fields post-construction. See {@link _applyMoneyFields}.\n * First-wins. Note: unlike money/computed/meta, this cannot retro-seal a\n * collection that was already auto-created — `sensitiveFields` is frozen at\n * construction time. A reconciled declaration is only accepted when none of\n * its members are `storage: 'recoverable'` (those require sealing at first\n * open); otherwise this throws rather than silently persisting the value as\n * inline plaintext while `describe()` advertises protection.\n */\n _applyClassifiedFields(classifiedFields: Record<string, ClassifiedEntry>): void {\n const resolved = resolveClassifiedFields(this.name, classifiedFields)\n if (this.classified !== undefined) {\n // R6 (session): first-wins, but a re-declaration that CHANGES a field's\n // storage form is refused — never a silent form flip.\n for (const [field, spec] of Object.entries(resolved.byField)) {\n const prior = this.classified.byField[field]\n if (prior !== undefined && prior.storage !== spec.storage) {\n throw new ClassifiedConfigError(this.name,\n `field \"${field}\" was already declared storage:'${prior.storage}' — ` +\n `storage-form transitions are refused (R6); migrate explicitly`)\n }\n }\n return // identical / compatible re-declaration → first-wins no-op\n }\n // Door 2 (C5): re-run the refusal matrix R1-R5 against the frozen\n // construction-time facts before accepting a late-attached declaration.\n guardClassifiedCompat(this.name, resolved.byField, this.classifiedGuardCtx)\n // Check for collisions: each rider-computed key must not already exist in this.computed\n for (const key of Object.keys(resolved.riderComputed)) {\n if (this.computed?.[key] !== undefined) {\n throw new ClassifiedConfigError(this.name, `rider companion \"${key}\" collides with a declared field`)\n }\n }\n // Digest-only can NEVER retro-attach: the codec's `vdigFields` map is\n // construction-frozen (`null` here, since this collection was built\n // without a classified declaration), so accepting a late digest-only\n // member would write the secret into `_data` recoverably while\n // describe() advertises digest-only. Same \"both doors\" lesson as the\n // recoverable check below (C5).\n const retroDigest = Object.entries(resolved.byField)\n .filter(([, spec]) => spec.storage === 'digest-only')\n .map(([field]) => field)\n if (retroDigest.length > 0) {\n throw new ClassifiedConfigError(this.name,\n `digest-only classified field(s) ${retroDigest.map((f) => `\"${f}\"`).join(', ')} were declared after the `\n + `collection was first opened without them — the digest write path is fixed at first open, so these `\n + `values would persist recoverably in _data. Declare classifiedFields at the collection's first `\n + `vault.collection() call.`)\n }\n const unsealable = Object.entries(resolved.byField)\n .filter(([field, spec]) => spec.storage === 'recoverable' && !this.sensitiveFields.has(field))\n .map(([field]) => field)\n if (unsealable.length > 0) {\n throw new ClassifiedConfigError(this.name,\n `recoverable classified field(s) ${unsealable.map((f) => `\"${f}\"`).join(', ')} were declared after the `\n + `collection was first opened without them — sealing is fixed at first open, so these values would `\n + `persist as inline plaintext. Declare classifiedFields at the collection's first vault.collection() call `\n + `(for materialized-view sources this means recoverable classified fields are not supported in stage 1).`)\n }\n this.classified = resolved\n this.computed = { ...resolved.riderComputed, ...(this.computed ?? {}) }\n // APPEND (not prepend, unlike {@link _applyMoneyFields}) — compile order\n // is money→i18n→classified; this keeps classified last regardless of order.\n this.via = ViaPipeline.build([...(this.via?.bindings ?? []), viaBinder('classified')({\n entries: classifiedFields, collectionName: this.name, guardCtx: this.classifiedGuardCtx, classifySealedShred: (live: unknown) => this.codec.classifySealedShred(live as EncryptedEnvelope), // #629 T10\n })], this.via?.taint) // #671 item 4 — thread taint through the rebuild (code-level consistency; masked today by the reconcilePlan applyTaintOverlay re-run)\n }\n\n get _ramCiphertext(): boolean { return this.ramCiphertext } // @internal — used only in tests; do not read in production code.\n\n /**\n * Get a single record by ID.\n *\n * @param id Record identifier.\n * @param locale Optional locale options. When provided,\n * `i18nText` fields are resolved to the requested locale\n * string, and `dictKey` fields get a `<field>Label`\n * virtual field added. Pass `{ locale: 'raw' }` to\n * return the full `{ [locale]: string }` map instead.\n *\n * @returns The decrypted (and optionally locale-resolved) record, or\n * `null` if not found.\n */\n async get(id: string, locale?: LocaleReadOptions): Promise<SealedView<T, S> | null> {\n const record = await this.#getRaw(id)\n if (record === null) return null\n // The cache/decrypt path already substituted Sealed handles for declared\n // sensitive fields (S); the cast reflects that runtime shape. For\n // collections with no sensitive fields S = never and SealedView<T, never>\n // collapses to T, so this is a no-op widening.\n return this.applyLocaleToRecord(record, locale) as unknown as SealedView<T, S>\n }\n\n /**\n * Raw fetch: cache/adapter → decrypt → tombstone-null, WITHOUT `present()`.\n * Split out of `get()` (#684) so `lazyQuery()`'s `LazyQuerySource` can hand\n * `LazyQuery`'s post-filter the RAW (stored-form) record a `clause.via`\n * evaluator (e.g. money) needs — `present()`/locale decode is applied only\n * to survivors, via `applyLocaleToRecord` (see `lazyQuery()` below). `get()`\n * itself is unchanged: raw fetch, then `applyLocaleToRecord`, same order\n * as before this split.\n */\n async #getRaw(id: string): Promise<T | null> {\n // --- Lazy derivation resolution ---\n // If this collection is the output of a lazy-mode derivation\n // strategy, consult the stale map and re-derive on demand before\n // reading. No-op when nothing is pending — keeps the read fast\n // path cheap.\n if (this.derivationSource !== undefined) {\n const registry = this.derivationSource.registry()\n if (registry.strategiesProducingOutput(this.name).length > 0) {\n await resolveStaleOnRead(this.derivationSource, this.name, id)\n }\n }\n\n // Lazy-MV resolve-on-read. When the collection being read\n // is the output of a registered lazy MV that has at least one\n // pending stale flag, run the executor before returning. No-op\n // when nothing is pending.\n if (this.materializedViewSource !== undefined) {\n const { resolveStaleMVOnRead } = await import('../with-formula/materialized-views/stale.js')\n await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: 'resolve-on-read' }))\n }\n\n let record: T | null\n\n if (this.lazy && this.lru) {\n // Cache hit: promote and return.\n const cached = this.lru.get(id)\n if (cached) {\n record = cached.record\n } else {\n // Cache miss: hit the adapter, decrypt, populate the LRU.\n const envelope = await this.adapter.get(this.vault, this.name, id)\n if (!envelope) return null\n // Tombstone tolerance (decision 5): a shredded record carries no\n // body / CEK. Reads return null rather than throwing TamperedError. #701: elevated records are invisible — gate BEFORE decrypt, or the warm cekCache serves tier plaintext.\n if (isTombstone(envelope, this.storeCiphertext) || isDeleteMarker(envelope) || (envelope._tier ?? 0) > 0) return null\n record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true })\n if (record === null) return null\n this.lru.set(id, { record, version: envelope._v }, estimateRecordBytes(record))\n }\n } else {\n // Eager mode: load everything once, then serve from the in-memory map.\n await this.ensureHydrated()\n const entry = this.cache.get(id)\n record = entry ? entry.record : null\n }\n\n if (record === null) return null\n await this.onAccess?.('get', id)\n return record\n }\n\n /**\n * Return the raw CRDT state for a record.\n * Only available on collections configured with `crdt: 'lww-map' | 'rga' | 'yjs'`.\n * Use this for merge operations or to pass to `@noy-db/yjs`.\n * Throws if the collection is not in CRDT mode.\n */\n async getRaw(id: string): Promise<CrdtState | null> {\n if (!this.crdtMode) {\n throw new Error(\n `Collection \"${this.name}\": getRaw() is only available when the collection ` +\n `is created with a 'crdt' option ('lww-map', 'rga', or 'yjs').`,\n )\n }\n const envelope = await this.adapter.get(this.vault, this.name, id)\n if (!envelope || (envelope._tier ?? 0) > 0) return null\n const json = await this.codec.decryptJsonString(envelope)\n if (json === null) return null // shredded (tombstone)\n return JSON.parse(json) as CrdtState\n }\n\n /**\n * Read a record's unencrypted envelope metadata (version, timestamps,\n * provenance) without decrypting the body.\n *\n * Returns `null` when no envelope exists for `id` (record absent or never\n * written). Only `_source`/`_sourceTs` fields are populated when the\n * collection was opened with `provenance: true` AND the record was written\n * with a `source` option — but this method works on any collection because\n * it reads the raw envelope directly.\n *\n * @returns `{ version, timestamp, by?, source?, sourceTs? }` or `null`.\n *\n * @example\n * const meta = await clients.getMetadata('c1')\n * if (meta) console.log(meta.source, meta.timestamp)\n */\n async getMetadata(id: string): Promise<{\n readonly version: number\n readonly timestamp: string\n readonly by?: string\n readonly source?: string\n readonly sourceTs?: string\n } | null> {\n const env = await this.adapter.get(this.vault, this.name, id)\n if (!env) return null\n return {\n version: env._v,\n timestamp: env._ts,\n ...(env._by !== undefined ? { by: env._by } : {}),\n ...(env._source !== undefined ? { source: env._source } : {}),\n ...(env._sourceTs !== undefined ? { sourceTs: env._sourceTs } : {}),\n }\n }\n\n /**\n * Return a presence handle for this collection.\n *\n * The handle manages an encrypted ephemeral presence channel keyed by an\n * HKDF derivation of this collection's DEK. Presence payloads are invisible\n * to the adapter.\n *\n * @param opts.staleMs Milliseconds before a peer is considered inactive.\n * Default: 30 000.\n * @param opts.pollIntervalMs Milliseconds between storage polls (fallback mode).\n * Default: 5 000.\n */\n presence<P = unknown>(opts?: { staleMs?: number; pollIntervalMs?: number }): PresenceHandle<P> {\n const presenceOpts: PresenceHandleOpts = {\n adapter: this.adapter,\n vault: this.vault,\n collectionName: this.name,\n userId: this.keyring.userId,\n encrypted: this.storeCiphertext,\n getDEK: this.getDEK,\n }\n if (this.syncAdapter !== undefined) presenceOpts.syncAdapter = this.syncAdapter\n if (opts?.staleMs !== undefined) presenceOpts.staleMs = opts.staleMs\n if (opts?.pollIntervalMs !== undefined) presenceOpts.pollIntervalMs = opts.pollIntervalMs\n return this.strategies.sync.buildPresence<P>(presenceOpts)\n }\n\n /**\n * Create or update a record. Runs inside the hub's write-queue tracker\n * so `hub.writeQueue.pending` reflects this write.\n *\n * @param id Record identifier.\n * @param record The record body (validated by the collection's schema\n * if one was attached at `vault.collection(...)` time).\n * @param options Optional metadata for audit + import workflows.\n * `reason` is stamped onto the resulting ledger entry\n * so audit consumers can filter via\n * `entries.filter(e => e.reason?.startsWith('import:'))`.\n * `source` is an opaque source id (e.g. `'crm-sync'`, `'firm-A'`)\n * stamped onto the envelope as `_source`/`_sourceTs` when\n * the collection has `provenance: true`. Ignored otherwise\n * (zero cost).\n * `sourceTs` is an optional ISO-8601 origin timestamp override;\n * when supplied together with `source` on a provenance collection,\n * replaces the machine-stamped `now()` so re-merges preserve the\n * ORIGIN refresh time across vaults. (FR-4)\n */\n async put(id: string, record: T, options?: { readonly reason?: string; readonly source?: string; readonly sourceTs?: string }): Promise<void> {\n // Refuse the write if an update strategy rejected the schema\n // change. Awaited OUTSIDE track() so a rejected write never counts\n // toward writeQueue.depth.\n // BYPASS HAZARD: any refusal or side-effect added to this wrapper must ALSO be covered on the atomic tx path — extend _assertWriteGates or _txAtomicSafe (see commitAtomicBatch in with-commit/tx/transaction.ts); two m44 holes (write-hooks, schema gates) came from exactly this bypass.\n await this.schemaUpdateGate?.assertWritable()\n await this.schemaFence?.assertWritable(this.name)\n // TODO: putManyAtomic / CRDT / blob write paths are not yet tracked by writeQueue nor fired through the write hooks (tx-execute now asserts the schema gates directly — see _assertWriteGates).\n // User write-hooks AND the observe bus both need the\n // WriteEvent. Build it if EITHER consumer is active so the bus is not\n // coupled to write-hooks being present.\n const hooksActive = this.#hooksActive()\n const busAfterPut = (this.subsystemBus?.hasHandlers('afterPut') ?? false)\n && !(this.subsystemBus?.dispatching ?? false)\n let event: WriteEvent | undefined\n if (hooksActive || busAfterPut) {\n const prior = await this.#priorForHook(id)\n event = {\n op: prior.record === null ? 'create' : 'update',\n vault: this.vault, collection: this.name, docId: id, before: prior.record, after: record,\n userId: this.keyring.userId, timestamp: Date.now(), txId: this.#txIdForHook(),\n baseVersion: prior.version, version: prior.version + 1,\n }\n if (hooksActive) await this.writeHooks!.runBefore(event) // throw → aborts the write\n }\n if (this.writeQueue) await this.writeQueue.track(() => this._putInternal(id, record, options))\n else await this._putInternal(id, record, options)\n if (event) {\n // Ordering: user afterWrite hooks run BEFORE observe-bus dispatch in\n // slice 1. Revisit when internal observe services (e.g. MV-refresh\n // notification) need to settle before user hooks observe state.\n if (hooksActive) await this.writeHooks!.runAfter(event)\n if (busAfterPut) await this.subsystemBus!.dispatch('afterPut', event)\n }\n }\n\n /**\n * Resolve the prior stored record (with its `_i18nFilled` marker) for\n * densify. Eager: in-memory cache; lazy: LRU then adapter. undefined if absent.\n */\n private async resolveDensifyPrior(id: string): Promise<Record<string, unknown> | undefined> {\n if (this.lazy && this.lru) {\n const cached = this.lru.get(id)\n if (cached) return cached.record as Record<string, unknown>\n const env = await this.adapter.get(this.vault, this.name, id)\n if (!env || (env._tier ?? 0) > 0) return undefined // #707: elevated ≡ missing\n const rec = await this.codec.decryptRecord(env, { id })\n return rec === null ? undefined : (rec as Record<string, unknown>)\n }\n await this.ensureHydrated()\n return this.cache.get(id)?.record as Record<string, unknown> | undefined\n }\n\n /**\n * Densify provenance for a record: which i18n slots were auto-filled,\n * e.g. `{ name: ['en'] }`. undefined when nothing was filled. The marker is\n * stripped from ordinary reads; this is the sanctioned audit accessor.\n */\n async i18nProvenance(id: string): Promise<Record<string, readonly string[]> | undefined> {\n const prior = await this.resolveDensifyPrior(id)\n const marker = prior?.['_i18nFilled'] as Record<string, string[]> | undefined\n return marker && Object.keys(marker).length > 0 ? marker : undefined\n }\n\n /**\n * Validate a record against this collection's schema WITHOUT writing it.\n * Returns the (possibly coerced) record on success; throws\n * {@link SchemaValidationError} (direction: `'input'`) on violation.\n * A no-op pass-through when no schema is declared.\n *\n * Used by FR-8 migrate-then-merge to pre-validate all staged records\n * before `mergeDecryptedRecords` writes anything — so a failed upgrade\n * never half-writes the receiver.\n */\n async validateInput(record: T): Promise<T> {\n if (this.schema === undefined) return record\n return validateSchemaInput(this.schema, record, `validateInput(${this.name})`)\n }\n\n /** @internal — true when hooks should fire for this write (handlers exist, not re-entrant). */\n #hooksActive(): boolean {\n return this.writeHooks !== undefined && this.writeHooks.hasHandlers && !this.writeHooks.suppressed\n }\n\n /**\n * @internal — resolve the prior record for a hook's `before` and\n * its version. Critically, this uses the SAME basis `_putInternal` writes from\n * (the in-memory cache in eager mode; lru-then-adapter in lazy) — NOT a fresh\n * store read — so `baseVersion`/`version` match the version actually written.\n * A separate store read would diverge once another tab has advanced the shared\n * store past this tab's cache, breaking cross-tab conflict detection.\n */\n async #priorForHook(id: string): Promise<{ record: unknown; version: number }> {\n if (this.lazy && this.lru) {\n const cached = this.lru.get(id)\n if (cached) return { record: cached.record, version: cached.version }\n const env = await this.adapter.get(this.vault, this.name, id)\n if (!env || (env._tier ?? 0) > 0) return { record: null, version: 0 } // #707: elevated ≡ missing\n return { record: (await this.codec.decryptRecord(env, { skipValidation: true, id })) as unknown ?? null, version: env._v }\n }\n await this.ensureHydrated()\n const cached = this.cache.get(id)\n return cached ? { record: cached.record, version: cached.version } : { record: null, version: 0 }\n }\n\n #txIdForHook(): string {\n return this.activeTxId?.() ?? generateULID()\n }\n\n /**\n * Resolve the prior record as REAL VALUES for the eager write/delete paths\n * (history snapshot, ledger patch, index upkeep). The eager cache holds\n * {@link Sealed} handles for sensitive fields (non-residency), so when the\n * collection seals anything we re-decrypt the stored envelope to materialise\n * real values — re-encrypting a handle would otherwise persist the marker\n * `'[sealed]'` in place of the value. `via?.hasAtRestHooks` (#642) catches\n * hook-only sealing (taint/classified, no local `sensitiveFields`).\n */\n private async resolvePriorValues(id: string): Promise<{ record: T; version: number } | undefined> {\n if (this.sensitiveFields.size > 0 || this.via?.hasAtRestHooks === true) {\n const env = await this.adapter.get(this.vault, this.name, id)\n if (!env || isTombstone(env, this.storeCiphertext) || (env._tier ?? 0) > 0) return undefined // #707: elevated ≡ missing\n const rec = await this.codec.decryptRecord(env, { skipValidation: true, id })\n return rec === null ? undefined : { record: rec, version: env._v }\n }\n const cached = this.cache.get(id)\n return cached ? { record: cached.record, version: cached.version } : undefined\n }\n\n /** Resolves the prior envelope/record for a gate event; elides the read (#267) when no handler at `point` needs it (`elided: true`, `env`/`record` null). */\n private async resolveGatePrior(point: GatePoint, id: string): Promise<{ env: EncryptedEnvelope | null; record: unknown; elided: boolean }> {\n if (!this.subsystemBus!.gateNeedsPrior(point)) return { env: null, record: null, elided: true }\n const env = await this.adapter.get(this.vault, this.name, id)\n if (!env) return { env: null, record: null, elided: false }\n if ((env._tier ?? 0) > 0) return { env, record: null, elided: false } // #707: elevated invisible to gate handlers — deterministic, not a swallowed InvalidKeyError\n return { env, record: await this.codec.decryptRecord(env, { skipValidation: true, id }), elided: false }\n }\n\n /**\n * Wraps {@link RecordCodec.toCacheRecord} with an additional strip for\n * digest-only classified fields: the codec already omits them from `_data`\n * on write, but the write path caches the pre-encrypt `record` object\n * directly (to skip a redundant decrypt) — without this, a vdig field's\n * plaintext would sit in the working-set cache and `get()` would leak it\n * right back out, defeating C6.\n */\n private async _toCacheableRecord(record: T, envelope: EncryptedEnvelope, id: string): Promise<T> {\n const base = await this.codec.toCacheRecord(record, envelope, id)\n if (this.vdigFields === null) return base\n const clone = { ...(base as unknown as Record<string, unknown>) }\n for (const field of this.vdigFields.keys()) delete clone[field]\n return clone as unknown as T\n }\n\n /** @internal Untracked put body — call {@link put}, not this. */\n /**\n * Decode a prior envelope's CRDT state, or `undefined` when there is no\n * usable prior: no envelope, a shredded body decrypting to `null`, or a\n * payload that is not a CRDT state. The `lww-map` and `rga` branches each\n * carried a copy, byte-identical apart from the cast (#842).\n */\n async #decodePriorCrdtState<S>(envelope: EncryptedEnvelope | null): Promise<S | undefined> {\n if (!envelope) return undefined\n\n const prevJson = await this.codec.decryptJsonString(envelope)\n if (prevJson === null) return undefined\n\n const prevParsed = JSON.parse(prevJson) as unknown\n if (prevParsed === null || typeof prevParsed !== 'object' || !('_crdt' in prevParsed)) {\n return undefined\n }\n return prevParsed as S\n }\n\n /**\n * Record a write on the active transaction so a mid-batch failure rolls it\n * back. Four sites in the derivation/MV dispatch hand-built this literal (#842).\n */\n #trackPut(txCtx: TxContext, collectionName: string, id: string, priorEnvelope: EncryptedEnvelope | null): void {\n txCtx._executed.push({\n op: { type: 'put', vaultName: this.vault, collectionName, id },\n priorEnvelope,\n })\n }\n\n /**\n * Snapshot the PRIOR version into history, emit, and prune.\n *\n * Deliberately does NOT carry `source` from the current write — a history\n * entry describes the version being replaced, not the one replacing it.\n *\n * Kept OUT of {@link #commitWriteTail} because the two paths call it at\n * different points: the normal path snapshots BEFORE `adapter.put` (so a\n * history failure leaves no write behind), while the CRDT path must merge\n * and persist first to resolve the prior record at all. Folding it into the\n * tail would silently reorder one of them (#842).\n */\n async #savePriorHistory(\n id: string,\n prior: { record: T; version: number },\n cek: EnclaveKey | undefined,\n vdigCtx: { id: string; prev: EncryptedEnvelope | null } | undefined,\n ): Promise<void> {\n if (this.historyConfig.enabled === false) return\n\n await this.strategies.history.saveHistory(\n this.adapter, this.vault, this.name, id,\n await this.codec.encryptRecord(prior.record, prior.version, cek, undefined, undefined, vdigCtx, id),\n )\n this.emitter.emit('history:save', { vault: this.vault, collection: this.name, id, version: prior.version })\n\n if (this.historyConfig.maxVersions) {\n await this.strategies.history.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions })\n }\n }\n\n /**\n * Everything both write paths do once the envelope is on the adapter:\n * classified marker, embedding sidecar, ledger append, cache/index\n * maintenance, and the mutation event that drives derivation dispatch.\n *\n * The CRDT branch used to re-implement all of it, and in doing so skipped\n * `_ensureClassifiedMarker`, the unique-constraint upsert and\n * `_toCacheableRecord` (#835). All three were unreachable — each blocked by\n * a config-time refusal on CRDT collections — but only by accident of what\n * that copy happened to omit. One tail makes the divergence unrepresentable\n * rather than merely unreachable; on a CRDT collection the extra steps are\n * provably no-ops (classified/unique + crdt are refused at construction, and\n * a CRDT body never produces a `_sealed` slot, so `_toCacheableRecord` is\n * the identity).\n */\n async #commitWriteTail(args: {\n readonly id: string\n readonly envelope: EncryptedEnvelope\n readonly version: number\n /** The record as it should appear in caches, indexes and the ledger delta. */\n readonly indexed: T\n /** The record reported to `_onRecordMutated` — what derivations observe. */\n readonly event: T\n readonly prior: { record: T; version: number } | undefined\n readonly reason: string | undefined\n }): Promise<void> {\n const { id, envelope, version, indexed, event, prior, reason } = args\n\n // C-A/R10: persist the x-classified marker on the first classified write\n // (cross-session drift signal). Memoized; no-op for non-classified handles.\n await this._ensureClassifiedMarker()\n\n // Derive the embedding vector at write (encode → encrypted _vec sidecar).\n // The _vec envelope _v is not OCC-checked. Gated behind\n // `searchStrategy: withSearch()`: a collection declaring `embeddings`\n // but not opting into search hits NO_SEARCH's throw here.\n if (this.embeddings) {\n await this.strategies.search.embedOnWrite(this.searchContext(), id, indexed, version)\n }\n\n // Ledger append — AFTER the adapter write succeeds so a failed write never\n // orphans an entry. `payloadHash` is taken from the envelope just written,\n // i.e. the exact bytes the adapter holds; the entry records only metadata,\n // never the record, encrypted under the compartment's ledger DEK.\n //\n // `delta` is a REVERSE patch — how to turn the NEW record back into the\n // previous one. That lets `ledger.reconstruct()` walk backward from current\n // state without a forward-walking base snapshot, which would double the\n // scheme's storage cost. Genesis puts carry no `deltaHash`.\n if (this.ledger) {\n const appendInput: Parameters<typeof this.ledger.append>[0] = {\n op: 'put',\n collection: this.name,\n id,\n version,\n actor: this.keyring.userId,\n payloadHash: await this.strategies.history.envelopePayloadHash(envelope),\n }\n if (prior) appendInput.delta = this.strategies.history.computePatch(indexed, prior.record)\n if (reason !== undefined) appendInput.reason = reason\n await this.ledger.append(appendInput)\n }\n\n // Cache the handle-form (sealed fields → Sealed handles) so plaintext for\n // sensitive fields is never resident in the working set.\n const cacheable = await this._toCacheableRecord(indexed, envelope, id)\n\n if (this.lazy && this.lru) {\n this.lru.set(id, { record: cacheable, version }, estimateRecordBytes(indexed))\n // Persisted-index side-cars. Lazy mode is the only place\n // `persistedIndexes` is populated; eager mode uses `CollectionIndexes`.\n await this.maintainPersistedIndexesOnPut(id, indexed, prior ? prior.record : null, version)\n } else {\n this.cache.set(id, { record: cacheable, version })\n // Incremental secondary-index update — no-op when none are declared.\n // The previous record cleans up old buckets before the new value lands.\n this.indexes?.upsert(id, indexed, prior ? prior.record : null)\n this.uniqueConstraints?.upsert(id, indexed, prior?.record)\n }\n\n // Derivation dispatch (inside `_onRecordMutated`) runs AFTER store +\n // ledger + cache commit, so a failed source-write never produces orphan\n // derived outputs. The recursive `put` into output collections re-enters\n // this pipeline intentionally; cycle detection at vault open is the\n // primary defense against infinite recursion.\n await this._onRecordMutated(id, 'put', 'local-write', { record: event, version })\n }\n\n /**\n * The pre-envelope stages both write paths share (#904): permission + tier\n * refusal, Via ingest, the beforePut gate bus, Via enforceWrite, computed\n * fields, schema validation, Via encodeWrite and ref enforcement. Reads and\n * throws; commits nothing. Returns the record in the shape that gets stored.\n */\n async #prepareWriteRecord(id: string, record: T): Promise<T> {\n if (!hasWritePermission(this.keyring, this.name)) {\n throw new ReadOnlyError()\n }\n // #715: elevated record ⇒ tier-0 API refuses (putAtTier/elevate/demote remedy) — see assertTierWritable's doc.\n await assertTierWritable(this.adapter, this.vault, this.name, id, this.tiers !== null)\n\n // One canonical money encoding from the FIRST pipeline stage:\n // gates, computed fields, and schema validation all see the decoded\n // `get()` shape. Best-effort — bad input passes through and the\n // quantize stage below throws the real error.\n if (this.via) record = this.via.ingest(record as Record<string, unknown>) as T\n\n // Gate bus (Track A) — write-gating services (guards: record-lock /\n // field-freeze / amendment-collect; periods: closed-period guard) run here,\n // before any schema/i18n/history work. A throwing gate handler propagates\n // and aborts the write; the amendment branch collects without throwing.\n // Zero-cost when no gate handler is registered; elides its own\n // prior-read (#267) too — see {@link resolveGatePrior}.\n if (this.subsystemBus?.hasGateHandlers('beforePut')) {\n const { env: existingEnv, record: existingRecord } = await this.resolveGatePrior('beforePut', id)\n const gateEvent: GatePutEvent = {\n op: existingEnv ? 'update' : 'create',\n vault: this.vault, collection: this.name, docId: id,\n incoming: record,\n existing: this.via ? this.via.canonicalizeStored(existingRecord as Record<string, unknown>) : existingRecord,\n existingVersion: existingEnv?._v ?? 0,\n existingTs: existingEnv?._ts,\n userId: this.keyring.userId,\n role: this.keyring.role,\n ...(this.computed !== undefined\n ? { computedFieldNames: new Set(Object.keys(this.computed)) }\n : {}),\n }\n await this.subsystemBus.dispatchGate('beforePut', gateEvent)\n }\n\n // Shared Via write ctx for enforceWrite + encodeWrite below (`prior` is\n // lazy — paid only if a binding calls it, e.g. i18n densify).\n const viaWriteCtx: ViaWriteCtx = {\n id,\n vault: this.vault,\n prior: async () => (await this.resolveDensifyPrior(id)) ?? null,\n emit: (e: string, p: unknown) => (this.emitter.emit as (ev: string, pl: unknown) => void)(e, p),\n }\n\n // Via enforceWrite phase — classified storage:'never' rejection +\n // validators, before riders derive/schema sees the record (#629 Task 6:\n // was a direct enforceClassifiedWrite call, now the pipeline's hook).\n if (this.via) await this.via.enforceWrite(record as Record<string, unknown>, viaWriteCtx)\n\n // Computed scalar fields — evaluated FIRST so the user need not supply\n // them and the schema validates the computed result. Throws\n // ComputedFieldError if a function throws.\n if (this.computed !== undefined) {\n record = (await loadEvalComputedFields())(record as Record<string, unknown>, this.computed, id) as T\n }\n\n // Schema validation — runs BEFORE encryption so invalid records are\n // rejected at the store boundary. The validator may transform the\n // input (e.g., coerce strings → numbers, strip unknown fields), in\n // which case we persist the validated value rather than the raw one.\n // Users who pass a bad shape get a SchemaValidationError with a\n // structured issue list, not a stack trace from deep inside the\n // encrypt path.\n if (this.schema !== undefined) {\n record = await validateSchemaInput(this.schema, record, `put(${id})`)\n }\n\n // Single Via encode-write phase: money quantize, then i18nText\n // translate→densify→script→validate→densify (via the i18n binding) —\n // binding order is money-first (see {@link compileViaBindings}).\n if (this.via) {\n record = await this.via.encodeWrite(record as Record<string, unknown>, viaWriteCtx) as T\n }\n\n // Foreign-key ref enforcement. Runs AFTER schema\n // validation (so the record shape is trustworthy) but BEFORE\n // any write (so a failed strict ref leaves no trace on disk,\n // in history, or in the ledger). The Vault handles the\n // actual target lookups — see `enforceRefsOnPut` over there.\n if (this.refEnforcer !== undefined) {\n await this.refEnforcer.enforceRefsOnPut(this.name, record)\n }\n\n return record\n }\n\n private async _putInternal(id: string, record: T, options?: { readonly reason?: string; readonly source?: string; readonly sourceTs?: string }): Promise<void> {\n // ─── CRDT mode ─────────────────────────────────────────\n // In CRDT mode we always read the raw envelope from the adapter to get\n // the existing CRDT state, merge the incoming record into it, then\n // encrypt the merged CRDT state — bypassing the normal version path.\n // Stays inline: merge-then-persist doesn't decompose into prepare/commit,\n // and CRDT collections never take the atomic path (#904).\n if (this.crdtMode) {\n record = await this.#prepareWriteRecord(id, record)\n const existingEnvelope = await this.adapter.get(this.vault, this.name, id)\n const existingVersion = existingEnvelope?._v ?? 0\n const now = new Date().toISOString()\n\n let crdtState: CrdtState\n\n if (this.crdtMode === 'lww-map') {\n const existingState = await this.#decodePriorCrdtState<LwwMapState>(existingEnvelope)\n crdtState = this.strategies.crdt.buildLwwMapState(record as Record<string, unknown>, existingState, now)\n } else if (this.crdtMode === 'rga') {\n const existingState = await this.#decodePriorCrdtState<RgaState>(existingEnvelope)\n crdtState = this.strategies.crdt.buildRgaState(Array.isArray(record) ? record : [record], existingState, generateULID)\n } else {\n // yjs: record is the base64 update string (produced by @noy-db/yjs)\n crdtState = { _crdt: 'yjs', update: record as unknown as string }\n }\n\n const version = existingVersion + 1\n // Stable per-record CEK shared by the new CRDT body and its history\n // snapshot (undefined on non-CEK collections → legacy path).\n const cek = this.perRecordCek ? await this.resolveRecordCek(id) : undefined\n const envelope = await this.codec.encryptJsonString(JSON.stringify(crdtState), version, cek, options?.source, options?.sourceTs)\n await this.adapter.put(this.vault, this.name, id, envelope)\n\n // Resolve snapshot for cache and history\n const resolvedRecord = this.strategies.crdt.resolveCrdtSnapshot(crdtState) as T\n // A tombstone (shredded) prior envelope yields a null record → treat as\n // \"no previous version\" so we don't snapshot/diff an erased value.\n const existingResolvedRecord = existingEnvelope\n ? await this.codec.decryptRecord(existingEnvelope, { skipValidation: true })\n : null\n const existingResolved = existingResolvedRecord !== null\n ? { record: existingResolvedRecord, version: existingVersion }\n : undefined\n\n if (existingResolved) {\n await this.#savePriorHistory(id, existingResolved, cek, this.vdigFields !== null ? { id, prev: existingEnvelope } : undefined)\n }\n\n // Caches and indexes see the resolved snapshot of the merged state;\n // the mutation event reports the record the caller passed.\n await this.#commitWriteTail({\n id, envelope, version,\n indexed: resolvedRecord,\n event: record,\n prior: existingResolved,\n reason: options?.reason,\n })\n return\n }\n // ─── End CRDT mode ──────────────────────────────────────────────────\n\n await this._commitPut(await this._preparePut(id, record, options))\n }\n\n /**\n * Prepare half of the ordinary (non-CRDT) write (#893/#904): run every\n * pre-envelope stage, resolve the prior version, and produce the encrypted\n * envelope — with ZERO observable side effects. No store write, no cache or\n * index mutation, no history entry, no ledger append, no event. It may READ\n * the store (gate prior, lazy prior, vdig prior) and it may THROW; refusing\n * a write before anything commits is precisely its job.\n *\n * Pairs with {@link _commitPut}. Split out so a batch can prepare every op,\n * submit ONE `store.tx()`, then finalize each op.\n *\n * @internal\n */\n async _preparePut(id: string, record: T, options?: { readonly reason?: string; readonly source?: string; readonly sourceTs?: string }): Promise<PreparedPut<T>> {\n record = await this.#prepareWriteRecord(id, record)\n\n // Resolve the previous record. In eager mode this comes from the\n // in-memory map (no I/O); in lazy mode we have to ask the adapter\n // because the record may have been evicted (or never loaded).\n let existing: { record: T; version: number } | undefined\n // Raw envelope read already performed while resolving `existing` (lazy\n // path below) — reused by the #589 continuity check so the re-create\n // path never pays a second `adapter.get`.\n let priorRaw: EncryptedEnvelope | null = null\n if (this.lazy && this.lru) {\n existing = this.lru.get(id)\n if (!existing) {\n priorRaw = await this.adapter.get(this.vault, this.name, id)\n if (priorRaw) {\n const previousRecord = await this.codec.decryptRecord(priorRaw, { id })\n // Tombstone (shredded) prior → treat as no previous version.\n if (previousRecord !== null) {\n existing = { record: previousRecord, version: priorRaw._v }\n }\n }\n }\n } else {\n await this.ensureHydrated()\n // Real values, not cache handles — `_commitPut` re-encrypts the prior\n // record into a history snapshot; a handle would seal `'[sealed]'`.\n existing = await this.resolvePriorValues(id)\n }\n\n let version = existing ? existing.version + 1 : 1\n // #589: a put re-creating a deleted id must continue past the delete\n // marker's version so it wins convergence — resetting to 1 would lose to\n // the marker's higher `_v` on sync. Markers exist only under sync, so this\n // is gated on `onDirty`; the lazy branch above may have already read the\n // raw envelope, so this reuses it instead of reading twice. Forget\n // tombstones (`isTombstone`, no `_del`) are terminal and are NOT\n // continued — they still reset to 1.\n if (!existing && this.onDirty) {\n // #606: only fall back to a store read when this id is a KNOWN marker\n // — markers are filtered out of the eager cache, so `!existing` alone\n // can't distinguish a re-create from a genuinely-new insert, and most\n // inserts are the latter. The lazy branch above may have already read\n // the raw envelope on an LRU miss regardless of `markerIds` (preserved\n // as-is); this only gates the previously-unconditional second read.\n // #693: when the store may be written out-of-band by another tab (write-relay active),\n // markerIds isn't authoritative during the broadcast-latency window — fall back to the\n // pre-#606 unconditional read so a cross-tab marker is never missed.\n if (priorRaw === null && (this.markerIds.has(id) || this.tabCoordinated?.())) {\n priorRaw = await this.adapter.get(this.vault, this.name, id)\n }\n if (priorRaw && isDeleteMarker(priorRaw)) version = priorRaw._v + 1\n }\n\n // Unique-constraint pre-flight — BEFORE history-save so a violation\n // never writes a history snapshot or fires 'history:save'. Runs after\n // ensureHydrated() (eager path above) so the constraint map already\n // reflects records from prior sessions. No-op when no unique indexes\n // are declared.\n this.uniqueConstraints?.check(id, record)\n\n // Per-record CEK: resolve the record's stable CEK ONCE (insert mints,\n // update reuses the live envelope's CEK), then encrypt BOTH the history\n // snapshot of the prior version AND the new body under it — so every\n // version of a record carries the same `_cek` and dies together on a\n // future shred. `undefined` on a legacy / non-CEK collection → the\n // byte-identical legacy write path.\n const cek = this.perRecordCek ? await this.resolveRecordCek(id) : undefined\n\n // Digest-only classified fields need the PREVIOUS live envelope: the codec\n // carries `_vdig` forward when a field is absent from this write (C6).\n // One adapter read, only on vdig collections — zero-cost otherwise.\n const vdigCtx = this.vdigFields !== null\n ? { id, prev: await this.adapter.get(this.vault, this.name, id) }\n : undefined\n\n const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs, vdigCtx, id)\n\n return { id, envelope, version, indexed: record, event: record, prior: existing, cek, vdigCtx, reason: options?.reason }\n }\n\n /**\n * Commit half (#893/#904): the only place an ordinary put becomes\n * observable — history snapshot of the prior version, store write, marker\n * clear, then the shared write tail.\n *\n * History still runs BEFORE the store write, so a history failure leaves no\n * write behind. It now runs AFTER `encryptRecord` rather than before it —\n * the split's one sanctioned reorder, which also stops an encrypt failure\n * from leaving an orphan snapshot behind.\n *\n * @internal `persist: false` skips the `adapter.put` — see {@link _finalizePut}.\n */\n async _commitPut(prepared: PreparedPut<T>, persist = true): Promise<void> {\n const { id, envelope, version, indexed, event, prior, cek, vdigCtx, reason } = prepared\n\n // CRITICAL: the history snapshot is a record of the PRIOR version — it must\n // NOT carry the source from the current write (source belongs to the new write only).\n if (prior) await this.#savePriorHistory(id, prior, cek, vdigCtx)\n\n if (persist) await this.adapter.put(this.vault, this.name, id, envelope)\n this.markerIds.delete(id) // #606: the live body just overwrote any marker prior — no-op if `id` wasn't one\n\n await this.#commitWriteTail({ id, envelope, version, indexed, event, prior, reason })\n }\n\n /**\n * {@link _commitPut} minus the `adapter.put`: the store already holds this\n * envelope because it was written as one leg of a `store.tx()` batch.\n *\n * @internal\n */\n _finalizePut(prepared: PreparedPut<T>): Promise<void> {\n return this._commitPut(prepared, false)\n }\n\n /**\n * Fire registered MV strategies whose dependency set includes this\n * collection. Eager-mode MVs re-materialize inline via\n * `MaterializedViewExecutor.refresh`; lazy / manual modes are\n * no-ops in the foundation; wired in the lazy-mode implementation.\n *\n * Skips entirely when the record being written is itself an\n * MV-emitted row (carries `_materializedFrom`) — defensive guard\n * against missed cycle detection.\n *\n * @internal `wave` (#638 Task 4): when present (the sync/cutover/restore dispatch wave),\n * an eager MV already refreshed this wave is skipped (per-target dedup, keyed on spec name).\n */\n async dispatchMaterializedViews(id: string, record: T, wave?: WaveContext): Promise<void> {\n if (this.materializedViewSource === undefined) return\n // S4 gate: dynamic import only — see #derivationDeleteCtx (#842).\n const { dispatchMaterializedViews } = await import('../with-formula/materialized-views/dispatch.js')\n return dispatchMaterializedViews(this.#mvDispatchCtx(this.materializedViewSource), id, record as unknown as Record<string, unknown>, wave)\n }\n\n /**\n * Fire registered derivation strategies for this source collection.\n * Eager mode runs `derive` inline and writes each output via the\n * sibling `Collection.put`; lazy mode marks dependent outputs stale\n * (D11 stub today). Errors in non-strict mode are logged and\n * skipped; strict mode propagates the first failing output's error.\n *\n * Skips entirely when the record being written is itself a derived\n * output (carries `_derivedFrom`) — defensive guard against missed\n * cycle detection.\n */\n /**\n * @internal The RAW stored record (canonical-money form, i18n maps\n * intact), WITHOUT the locale resolution `get()` applies. Used as the\n * patch base for self-write reverse-denorm so writing back never clobbers\n * an i18n map or re-quantizes money incorrectly. Returns null for\n * missing / tombstoned records.\n */\n async _getStoredRecord(id: string): Promise<T | null> {\n let raw: T | null\n if (this.lazy && this.lru) {\n if (this.sensitiveFields.size > 0 || this.via?.hasAtRestHooks === true) {\n // Sealed collection (lazy mirror of the eager `resolvePriorValues`):\n // the LRU holds {@link Sealed} handles for sensitive fields (non-\n // residency), but `_getStoredRecord` is the reverse-denorm / rollup\n // PATCH BASE — re-encrypting a handle would persist the marker\n // `'[sealed]'` in place of the value. So always re-decrypt the stored\n // envelope to REAL values for the returned base. On a miss, populate\n // the LRU in HANDLE form via `toCacheRecord` — never `record: raw`\n // plaintext, which would leak sealed plaintext into the working set\n // (a later public `get()` would then return it, defeating the gate).\n const cached = this.lru.get(id)\n const env = await this.adapter.get(this.vault, this.name, id)\n if (!env || isTombstone(env, this.storeCiphertext) || isDeleteMarker(env)) return null\n raw = await this.codec.decryptRecord(env, { id })\n if (raw === null) return null\n if (!cached) {\n this.lru.set(id, { record: await this.codec.toCacheRecord(raw, env, id), version: env._v }, estimateRecordBytes(raw))\n }\n } else {\n const cached = this.lru.get(id)\n if (cached) raw = cached.record\n else {\n const env = await this.adapter.get(this.vault, this.name, id)\n if (!env || isTombstone(env, this.storeCiphertext) || isDeleteMarker(env)) return null\n raw = await this.codec.decryptRecord(env, { id })\n if (raw === null) return null\n this.lru.set(id, { record: raw, version: env._v }, estimateRecordBytes(raw))\n }\n }\n } else {\n await this.ensureHydrated()\n // Patch base for self-write reverse-denorm → must be real values, not\n // the cache's Sealed handles, or a write-back would re-seal the marker.\n raw = (await this.resolvePriorValues(id))?.record ?? null\n }\n if (raw === null) return null\n return (this.via ? this.via.canonicalizeStored(raw as Record<string, unknown>) : raw) as T\n }\n\n /** @internal #638 Task 4 — decrypted STORED-form record + envelope version for the sync/cutover/\n * restore dispatch wave (id threaded into decrypt, matching `_invalidateCacheEntry`'s contract). */\n async _getStoredRecordForDispatch(id: string): Promise<{ record: T; version: number } | null> {\n const env = await this.adapter.get(this.vault, this.name, id)\n if (!env || isTombstone(env, this.storeCiphertext) || isDeleteMarker(env)) return null\n const record = await this.codec.decryptRecord(env, { id })\n return record === null ? null : { record, version: env._v }\n }\n\n /**\n * @internal Ids of records whose top-level `field` equals `value`.\n * Uses the FK index when the field is indexed (O(matches)); otherwise a\n * linear scan (O(N) — fine for small child sets; index the FK to scale).\n */\n async _findMatchingIds(field: string, value: unknown): Promise<string[]> {\n const hit = this.getIndexes()?.lookupEqual(field, value)\n if (hit) return [...hit]\n const target = String(value)\n const matches = (rec: Record<string, unknown>): boolean => {\n const fv = rec[field]\n // FK values are scalars; ignore object/array fields (never a valid FK).\n return (typeof fv === 'string' || typeof fv === 'number') && String(fv) === target\n }\n if (!this.lazy) {\n await this.ensureHydrated()\n const out: string[] = []\n for (const [rid, e] of this.cache) {\n if (matches(e.record as Record<string, unknown>)) out.push(rid)\n }\n return out\n }\n const ids = await this.adapter.list(this.vault, this.name)\n const out: string[] = []\n for (const rid of ids) {\n const raw = await this._getStoredRecord(rid)\n if (raw !== null && matches(raw as Record<string, unknown>)) out.push(rid)\n }\n return out\n }\n\n /** @internal — ctx for `putDerivedOutput`'s frozen-period skip+audit (#638 Task 5). */\n /** What `with-formula/materialized-views/dispatch.ts` needs from this collection (#842). */\n #mvDispatchCtx(materializedViewSource: NonNullable<Collection<T, S, Q, M>['materializedViewSource']>) {\n return {\n materializedViewSource,\n collectionName: this.name,\n dispatchCtx: (source: { readonly collection: string; readonly id: string }) => this.#dispatchCtx(source),\n }\n }\n\n /**\n * What `with-formula/derivations/dispatch.ts` needs from this collection (#842).\n *\n * The return type is inferred, not annotated: importing `DerivationDeleteCtx`\n * would be a STATIC spine→service import, which `port-layering` rejects even\n * when it is type-only — the guard scans import statements, not their\n * erasure. The dynamic `import()` at the call site still types the argument.\n */\n #derivationDeleteCtx(derivationSource: NonNullable<Collection<T, S, Q, M>['derivationSource']>) {\n return {\n derivationSource,\n collectionName: this.name,\n adapter: this.adapter,\n vault: this.vault,\n getDEK: this.getDEK,\n storeCiphertext: this.storeCiphertext,\n }\n }\n\n #dispatchCtx(source: { readonly collection: string; readonly id: string }) {\n return { emit: (e: string, p: unknown) => (this.emitter.emit as (ev: string, pl: unknown) => void)(e, p), source, audit: ledgerAuditHook(this.ledger, this.keyring.userId) }\n }\n\n /** @internal Recompute a rollup aggregate onto the parent from `parentId`'s current children (value-equality guarded; no-op absent parent).\n * `wave` (#638 T4, #640): per-target dedup. Returns the `putDerivedOutput` outcome, or `'noop'` (no parent/no-op/deduped) — `dispatchRollupsOnDelete`'s forget-fanout caller + #640's `_recomputeDeletedRollups` need this to fill their reports. */\n private async recomputeRollup(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n spec: { source: string; rollup?: { from: string; key: string; field: string; compute: (children: any[]) => unknown } }, parentId: string, source: { readonly collection: string; readonly id: string }, wave?: WaveContext,\n ): Promise<RollupOutcome> {\n if (this.derivationSource === undefined || spec.rollup === undefined) return 'noop'\n const { from, key, field, compute } = spec.rollup\n const into = spec.source\n if (wave?.seen(`rollup\\0${into}\\0${parentId}\\0${field}`)) return 'noop'\n const intoColl = this.derivationSource.getCollection(into)\n const base = await intoColl._getStoredRecord(parentId)\n if (base === null) return 'noop' // no parent record to patch\n\n const fromColl = this.derivationSource.getCollection(from)\n const childIds = await fromColl._findMatchingIds(key, parentId)\n const children: Array<Record<string, unknown>> = []\n for (const cid of childIds) {\n const c = await fromColl.get(cid)\n if (c !== null && c !== undefined) children.push(c)\n }\n\n const newValue = compute(children)\n if (selfWriteFieldEqual(base[field], newValue)) return 'noop' // no change → no write\n\n const patched = { ...base, [field]: newValue }\n const txCtx = this.derivationSource.getActiveTxContext()\n if (txCtx !== null) {\n this.#trackPut(txCtx, into, parentId, await this.adapter.get(this.vault, into, parentId))\n }\n return putDerivedOutput(intoColl, parentId, patched, this.#dispatchCtx(source))\n }\n\n /** @internal #640 — this deleted child's rollup PARENT intents (see via/dispatch.ts#resolveRollupDeleteIntents). */\n _rollupDeleteIntents(deleted: T): RollupDeleteIntent[] {\n return resolveRollupDeleteIntents(this.derivationSource?.registry(), this.name, deleted as Record<string, unknown>)\n }\n\n /**\n * @internal Fire any rollups for which THIS collection is the child `from`, recomputing the\n * affected parent after a child delete/forget. Called from the delete path (return discarded)\n * and from `forgetDerivedFanout` (#638 Task 6), which needs the per-target outcome to fill\n * `ForgetResult.derivedAggregatesRecomputed`/`derivedResidueFrozen`). `wave` (#640): per-target dedup for the sync-apply path; `undefined` on local-delete (byte-identical).\n */\n async dispatchRollupsOnDelete(id: string, deleted: T, wave?: WaveContext): Promise<ReadonlyArray<{ readonly into: string; readonly parentId: string; readonly outcome: RollupOutcome }>> {\n const results: Array<{ into: string; parentId: string; outcome: RollupOutcome }> = []\n for (const intent of this._rollupDeleteIntents(deleted)) {\n const spec = findRollupSpecForIntent(this.derivationSource?.registry(), this.name, intent)\n if (spec) results.push({ into: intent.into, parentId: intent.parentId, outcome: await this.recomputeRollup(spec, intent.parentId, { collection: this.name, id }, wave) })\n }\n return results\n }\n\n /** @internal #640 — the wave's per-id driver: recompute each sync-apply delete's rollup parent. */\n async _recomputeDeletedRollups(intents: readonly RollupDeleteIntent[], wave: WaveContext): Promise<void> {\n for (const intent of intents) {\n const spec = findRollupSpecForIntent(this.derivationSource?.registry(), this.name, intent)\n if (spec) await this.recomputeRollup(spec, intent.parentId, { collection: this.name, id: '<sync-delete>' }, wave)\n }\n }\n\n /** @internal `wave` (#638 Task 4) — threaded to `recomputeRollup` for the sync/cutover/restore\n * dispatch wave's per-target dedup; `undefined` on the local-write path (byte-identical). */\n async dispatchDerivations(id: string, record: T, version: number, wave?: WaveContext): Promise<void> {\n if (this.derivationSource === undefined) return\n // S4 gate: dynamic import only — see #derivationDeleteCtx (#842).\n const { dispatchDerivations } = await import('../with-formula/derivations/dispatch.js')\n return dispatchDerivations({\n ...this.#derivationDeleteCtx(this.derivationSource),\n via: this.via,\n recomputeRollup: (spec, parentId, source, w) => this.recomputeRollup(spec, parentId, source, w),\n dispatchCtx: (source) => this.#dispatchCtx(source),\n trackPut: (txCtx, collectionName, rid, prior) => this.#trackPut(txCtx, collectionName, rid, prior),\n }, id, record as unknown as Record<string, unknown>, version, wave)\n }\n\n /**\n * Delete a record by ID. Runs inside the hub's write-queue tracker\n * so `hub.writeQueue.pending` reflects this write.\n */\n async delete(id: string): Promise<void> {\n // BYPASS HAZARD: any refusal or side-effect added to this wrapper must ALSO be covered on the atomic tx path — extend _assertWriteGates or _txAtomicSafe (see commitAtomicBatch in with-commit/tx/transaction.ts); two m44 holes (write-hooks, schema gates) came from exactly this bypass.\n await this.schemaUpdateGate?.assertWritable()\n await this.schemaFence?.assertWritable(this.name)\n // User write-hooks AND the Track A observe bus both need the\n // WriteEvent. Build it if EITHER consumer is active so the bus is not\n // coupled to write-hooks being present. Mirrors the put() path.\n const hooksActive = this.#hooksActive()\n const busAfterDelete = (this.subsystemBus?.hasHandlers('afterDelete') ?? false)\n && !(this.subsystemBus?.dispatching ?? false)\n let event: WriteEvent | undefined\n if (hooksActive || busAfterDelete) {\n const prior = await this.#priorForHook(id)\n event = {\n op: 'delete', vault: this.vault, collection: this.name, docId: id, before: prior.record, after: null,\n userId: this.keyring.userId, timestamp: Date.now(), txId: this.#txIdForHook(),\n baseVersion: prior.version, version: prior.version + 1,\n }\n if (hooksActive) await this.writeHooks!.runBefore(event)\n }\n if (this.writeQueue) await this.writeQueue.track(() => this._deleteInternal(id))\n else await this._deleteInternal(id)\n if (event) {\n // Ordering: user afterWrite hooks run before observe-bus dispatch.\n if (hooksActive) await this.writeHooks!.runAfter(event)\n if (busAfterDelete) await this.subsystemBus!.dispatch('afterDelete', event)\n }\n }\n\n /**\n * @internal — bulk-rewrite every record through a cutover transform. Raw adapter path (bypasses the write gate + guards — the transform is trusted and runs only during the `migrating` phase). Bumps each record's `_v` and appends a ledger `op:'migration'` entry. #708: refuses BEFORE any rewrite if a live record is elevated (assertCutoverTierSafe) — demote it first.\n */\n async _applyCutoverTransform(\n transform: (doc: Record<string, unknown>) => Record<string, unknown>,\n ): Promise<number> {\n const ids = await this.adapter.list(this.vault, this.name)\n await assertCutoverTierSafe(this.adapter, this.vault, this.name, this.tiers !== null)\n let count = 0\n for (const id of ids) {\n const env = await this.adapter.get(this.vault, this.name, id)\n if (!env || isTombstone(env, this.storeCiphertext) || isDeleteMarker(env)) continue\n const decoded = await this.codec.decryptRecord(env, { skipValidation: true, id })\n if (decoded === null) continue // defensive: shredded between list and get\n const record = decoded as unknown as Record<string, unknown>\n const next = transform(record)\n const nextVersion = (env._v ?? 0) + 1\n // Migration pass: on a `perRecordKeys` collection, a legacy (no-`_cek`)\n // record gets a freshly minted CEK here (legacy → CEK re-encrypt), while\n // an already-CEK record reuses its stable CEK. This is the\n // erasure-completeness pass — once migrated, the record body is keyed\n // off a per-record CEK and a future shred can erase it. Until then it\n // stays directly under the collection DEK. `forget()`/shred reports\n // un-migrated records explicitly rather than claiming erasure.\n const cek = this.perRecordCek ? await this.resolveRecordCek(id) : undefined\n await this.adapter.put(this.vault, this.name, id, await this.codec.encryptRecord(next as unknown as T, nextVersion, cek, undefined, undefined, this.vdigFields !== null ? { id, prev: env } : undefined, id))\n await this._onRecordMutated(id, 'put', 'cutover') // refresh in-memory cache after the raw write (parity: cache only)\n if (this.ledger) {\n await this.ledger.append({\n op: 'migration', collection: this.name, id, version: nextVersion,\n actor: this.keyring.userId, payloadHash: '', reason: 'schema:coordinated-cutover',\n }).catch(() => { /* ledger is best-effort here */ })\n }\n count++\n }\n return count\n }\n\n /** @internal Untracked delete body — call {@link delete}, not this. */\n private async _deleteInternal(id: string): Promise<void> {\n await this._doDelete(id, false)\n }\n\n /**\n * @internal — system-internal delete that bypasses user-facing\n * delete hooks (`onDelete`, FK ref enforcer). Used by derivation tombstones and MV refresh\n * (Dim 14 v2) — system housekeeping shouldn't trip user invariants\n * registered against the output collection. The ledger entry and\n * history snapshot still fire so backup integrity and time-travel\n * reconstruction stay consistent.\n *\n * Returns `true` when it erased a live record, `false` for delete-of-absent (idempotent\n * contract — both txCtx-aware and txCtx===null callers honour this, short-circuiting before any side-effect).\n *\n * When a `txCtx` is supplied, the prior envelope is captured and\n * pushed onto `txCtx._executed` BEFORE the delete fires — mirrors\n * the rollback hardening for puts. Callers outside a\n * multi-record transaction pass `null` and skip the tracking.\n *\n * Amendment composition: if `_internalDelete` runs while a vault's\n * `GuardRegistry` has an amendment window open, the `{before, after:\n * null}` change pair is pushed onto the amendment change-set the\n * same way a user-initiated delete would. The `onDelete` user-hook\n * is still skipped (housekeeping must not trip user invariants in\n * normal mode), but the amendment's invariant DOES see the change\n * — so a `RCT-CANCEL-001`-style invariant pairing can reject a\n * derivation-driven tombstone fired during an admin amendment.\n *\n * Constraint to surface to consumers: output collections of\n * derivations with `optional: true` outputs should not be the\n * targets of `strict` or `cascade` inbound foreign-key refs —\n * `_internalDelete` bypasses the ref enforcer by design (the\n * `onDelete` bypass primitive). Treat the housekeeping path as\n * \"system can tombstone its own emissions regardless of FK shape.\"\n *\n * Permission handling is unchanged: the caller must still hold\n * write permission on the collection (derivations run under the\n * user's keyring).\n */\n async _internalDelete(id: string, txCtx: TxContext | null = null): Promise<boolean> {\n // Idempotency contract: short-circuit before any ledger/event\n // side-effect when the target is absent. Both txCtx-aware and\n // txCtx-null callers honour this — `deriveAll` recomputes\n // expense-only allocations that never emitted a receipt without\n // writing spurious v0 ledger entries.\n const prior = await this.adapter.get(this.vault, this.name, id)\n if (prior === null) return false\n if (txCtx !== null) {\n txCtx._executed.push({\n op: {\n type: 'delete',\n vaultName: this.vault,\n collectionName: this.name,\n id,\n },\n priorEnvelope: prior,\n })\n }\n return await this._doDelete(id, true)\n }\n\n private async _doDelete(id: string, internal: boolean): Promise<boolean> {\n const prepared = await this._prepareDelete(id, internal)\n return prepared === null ? false : await this._commitDelete(prepared)\n }\n\n /**\n * Prepare half of the delete (#893/#905): every refusal (write permission,\n * tier, the beforeDelete gate bus, foreign-key refs), the prior-version\n * resolution, the pre-delete payload hash, and the #589 marker DECISION —\n * the marker is minted here but NOT written.\n *\n * Commits nothing of its own: no store write, no history entry, no ledger\n * append, no cache/index mutation, no event, no `markerIds` entry. It READS\n * the store and it may THROW — refusing a delete before anything commits is\n * precisely its job. `null` is the \"nothing to delete\" answer that the early\n * `return false` paths gave: no live record, an already-shredded tombstone,\n * an existing marker, or the #718 elevated-internal skip.\n *\n * ONE exception to that guarantee: on a collection with `cascade` inbound\n * refs, prepare itself deletes the referencing children (via\n * `enforceRefsOnDelete`, as it always has) — prepare is NOT abortable there.\n * The transaction atomic path must never call this on such a collection; its\n * eligibility gate excludes refs-bearing collections.\n *\n * Pairs with {@link _commitDelete}. A deliberately separate split from the\n * put pair (#842c) — delete differs in hydration, in the history-read gate\n * and in the marker rules.\n *\n * @internal\n */\n async _prepareDelete(id: string, internal: boolean): Promise<PreparedDelete<T> | null> {\n if (!hasWritePermission(this.keyring, this.name)) {\n throw new ReadOnlyError()\n }\n // #716: public deletes only — see assertTierWritable's doc + Step 5 investigation for `internal`.\n await assertTierWritable(this.adapter, this.vault, this.name, id, !internal && this.tiers !== null)\n if (internal && this.tiers !== null && await liveRecordIsElevated(this.adapter, this.vault, this.name, id)) return null // #718: internal cleanup treats an elevated record as nonexistent, same as tier-0 reads — skip, no marker, not counted as erased (#761 item 8)\n\n // Gate bus (Track A) — fires for ALL deletes (carrying `internal`), so a\n // gate handler can collect amendment changes on system-internal deletes\n // while branching off `onDelete`/period checks for them. Delete-of-absent\n // does not fire — unless the read is elided (#267, {@link resolveGatePrior}).\n if (this.subsystemBus?.hasGateHandlers('beforeDelete')) {\n const { env: existingEnv, record: existingRecord, elided } = await this.resolveGatePrior('beforeDelete', id)\n if (existingEnv || elided) {\n await this.subsystemBus.dispatchGate('beforeDelete', {\n vault: this.vault, collection: this.name, docId: id,\n existing: this.via ? this.via.canonicalizeStored(existingRecord as Record<string, unknown>) : existingRecord,\n existingVersion: existingEnv?._v ?? 0,\n existingTs: existingEnv?._ts,\n internal,\n userId: this.keyring.userId,\n role: this.keyring.role,\n })\n }\n }\n\n // Foreign-key ref enforcement on delete. Runs BEFORE\n // the adapter delete so a `strict` inbound ref with existing\n // references blocks the delete entirely (no partial state, no\n // history churn, no ledger entry for a rejected op). `cascade`\n // recursively deletes the referencing records first, then falls\n // through to the normal delete path below. `warn` is a no-op\n // here — violations surface through `checkIntegrity()`.\n if (!internal && this.refEnforcer !== undefined) {\n await this.refEnforcer.enforceRefsOnDelete(this.name, id)\n }\n\n // In lazy mode the record may not be cached; ask the adapter so we\n // can still write a history snapshot if history is enabled.\n let existing: { record: T; version: number } | undefined\n if (this.lazy && this.lru) {\n existing = this.lru.get(id)\n if (!existing && this.historyConfig.enabled !== false) {\n const previousEnvelope = await this.adapter.get(this.vault, this.name, id)\n if (previousEnvelope) {\n const previousRecord = await this.codec.decryptRecord(previousEnvelope, { id })\n // Tombstone (shredded) prior → no record to snapshot on delete.\n if (previousRecord !== null) {\n existing = { record: previousRecord, version: previousEnvelope._v }\n }\n }\n }\n } else {\n // Real values, not cache handles — re-encrypted into a history snapshot.\n existing = await this.resolvePriorValues(id)\n }\n\n // Capture the previous envelope's payloadHash BEFORE delete so we\n // have a stable reference for the ledger entry. The hash is of\n // whatever was last visible to readers — for a `delete` of a\n // never-existed record, we use the empty string (which the\n // ledger entry's `payloadHash` field tolerates).\n const previousEnvelope = await this.adapter.get(this.vault, this.name, id)\n const previousPayloadHash = await this.strategies.history.envelopePayloadHash(previousEnvelope)\n\n // #589 (review): the marker is minted at `live._v + 1` and carried on the\n // prepared delete, so `onDirty` reports the SAME version, not\n // `existing?.version` (which can be stale/absent in lazy mode with the\n // record uncached and history disabled, desyncing the dirty entry's version\n // from the marker and breaking push's CAS). `live` reuses `previousEnvelope`\n // above — same read, nothing between them writes to the adapter.\n let marker: EncryptedEnvelope | undefined\n if (this.onDirty) {\n // #589: under sync, delete leaves a version-ordered marker so the deletion\n // converges on pull (a bare adapter.delete is invisible to other pullers).\n // No-op if there is no live record to delete (already marked / shredded).\n const live = previousEnvelope\n if (!live || isTombstone(live, this.storeCiphertext) || isDeleteMarker(live)) return null\n marker = buildDeleteMarker(live._v + 1, this.keyring.userId)\n }\n\n // History-snapshot key material, resolved HERE off the live envelope —\n // re-resolving it in the commit half would read the already-written marker\n // (see {@link PreparedDelete.cek}). `previousEnvelope` is that same\n // pre-write read, so the vdig context costs no extra `adapter.get`.\n const snapshots = existing !== undefined && this.historyConfig.enabled !== false\n const cek = snapshots && this.perRecordCek ? await this.resolveRecordCek(id) : undefined\n const vdigCtx = snapshots && this.vdigFields !== null ? { id, prev: previousEnvelope } : undefined\n\n return { id, internal, existing, previousPayloadHash, marker, cek, vdigCtx }\n }\n\n /**\n * Commit half (#893/#905): the only place a delete becomes observable —\n * history snapshot of the deleted version, the store write (the #589 marker\n * put, or the physical removal when sync is off), then the ledger entry,\n * cache/index teardown, the mutation event, and the user-initiated\n * derivation dispatch.\n *\n * History still runs BEFORE the store write, exactly as today, so a history\n * failure leaves no delete behind.\n *\n * @internal `persist: false` skips the store write — see {@link _finalizeDelete}.\n */\n async _commitDelete(prepared: PreparedDelete<T>, persist = true): Promise<boolean> {\n const { id, internal, existing, previousPayloadHash, marker, cek, vdigCtx } = prepared\n\n // Save history snapshot before deleting. On a CEK collection the\n // snapshot reuses the record's stable CEK (resolved in prepare, off the\n // live envelope) so the displaced version stays in the same key chain as\n // the rest of its history.\n if (existing && this.historyConfig.enabled !== false) {\n await this.strategies.history.saveHistory(this.adapter, this.vault, this.name, id, await this.codec.encryptRecord(existing.record, existing.version, cek, undefined, undefined, vdigCtx, id))\n }\n\n if (marker) {\n if (persist) await this.adapter.put(this.vault, this.name, id, marker)\n this.markerIds.add(id) // #606: this id now carries a marker — the #589 continuity gate should consult it on re-create\n } else if (persist) await this.adapter.delete(this.vault, this.name, id)\n\n // Ledger append — same after-write timing as put(). The recorded\n // version is the version that WAS deleted (existing?.version), not\n // a successor. A delete of a missing record still appends an\n // entry with version 0 so the chain captures the intent.\n if (this.ledger) {\n await this.ledger.append({ op: 'delete', collection: this.name, id, version: existing?.version ?? 0, actor: this.keyring.userId, payloadHash: previousPayloadHash })\n }\n\n if (this.lazy && this.lru) {\n this.lru.remove(id)\n // Tear down persisted-index side-cars for any declared fields on\n // this record. No-op when no fields are declared or the record\n // had never been indexed (e.g. a delete of a missing id).\n if (existing) {\n await this.maintainPersistedIndexesOnDelete(id, existing.record)\n }\n } else {\n this.cache.delete(id)\n // Remove from secondary indexes — no-op if no indexes are declared\n // or the record wasn't previously indexed.\n if (existing) {\n this.indexes?.remove(id, existing.record)\n // Remove from unique-constraint maps so the deleted value is freed.\n this.uniqueConstraints?.remove(id, existing.record)\n }\n }\n\n // #589: under sync the marker rides the push channel as an ordinary CAS put at\n // its own version (live._v + 1); the dirty version must match the marker so\n // push's expectedVersion = marker._v - 1 = live._v matches the remote's live copy.\n // #589 (review): use the marker's own `_v` (the version it was actually minted\n // at), not `existing?.version` — the fallback below is unreachable in\n // practice (onDirty undefined ⇒ no marker ⇒ the `?.` short-circuits\n // before this argument matters) but keeps the expression well-typed.\n await this._onRecordMutated(id, 'delete', 'local-delete', { version: marker?._v ?? (existing?.version ?? 0) + 1 })\n\n // Symmetric to put: user-initiated deletes must fire MV\n // refresh so `onEmpty: 'delete'` MVs tombstone their now-orphan\n // output rows. Gated on `!internal` to prevent recursion — the\n // MV executor's own tombstoning round-trips through\n // `_internalDelete → _doDelete(_, true)` and must NOT re-fire\n // dispatch (matches put's `_materializedFrom` skip in spirit).\n //\n // Record-shape derivations intentionally NOT dispatched on delete:\n // their derived-output id equals the source id, so the user can\n // delete the output directly with `outputCollection.delete(id)` if\n // they want. Array-shape derivations DO cascade on delete\n // because their derived ids are opaque (from the `key(out)`\n // extractor) — without cascade the rows become unfindable orphans.\n if (!internal) {\n await this.dispatchMaterializedViewsOnDelete(id)\n await this.dispatchArrayDerivationsOnDelete(id)\n // Rollup-on-delete: recompute the parent aggregate now\n // that this child is gone. `existing.record` carries the deleted child's\n // FK; the recompute gathers the REMAINING children (this one already\n // removed from the store/cache above).\n if (existing) await this.dispatchRollupsOnDelete(id, existing.record)\n }\n return true\n }\n\n /**\n * {@link _commitDelete} minus the store write: the marker (or the removal)\n * already landed as one leg of a `store.tx()` batch.\n *\n * @internal\n */\n _finalizeDelete(prepared: PreparedDelete<T>): Promise<boolean> {\n return this._commitDelete(prepared, false)\n }\n\n /**\n * @internal — GDPR crypto-shred a LIVE record to a tombstone.\n *\n * Rewrites the on-disk envelope to `{ _noydb, _v, _ts, _by, _iv:'', _data:'' }`,\n * dropping `_iv`/`_data`/`_cek`/`_det`. The wrapped per-record CEK is gone, so\n * the body — and (via {@link tombstoneHistory}) every history version under\n * the same CEK — is permanently undecryptable; the collection DEK and every\n * other record are untouched. `_det` is stripped too, so `findByDet` no\n * longer matches the shredded record (avoiding a post-shred TamperedError).\n *\n * Unlike `delete()`/`_internalDelete`, this:\n * - does NOT fire onDelete guards / MV / derivation dispatch (a shred is an\n * erasure, not a domain delete — re-running those would be wrong),\n * - does NOT append a per-record ledger entry (`vault.forget()` appends a\n * single `op:'forget'` summary for the whole subject),\n * - keeps the record KEY present (it's an overwrite, not an adapter delete)\n * so the version counter + \"record existed\" survive for audit.\n *\n * Idempotent: returns `null` when the record is absent or already a tombstone.\n * Otherwise returns `{ previousVersion }`. Invalidates the eager cache, the\n * lazy LRU, and the per-record CEK cache for this id.\n */\n /**\n * @internal — decrypt an envelope to a plain record for subject-index\n * rebuild. Returns `null` for a tombstone or unreadable envelope.\n * Skips schema validation — the rebuild only reads the subject field.\n */\n async _decodeEnvelope(envelope: EncryptedEnvelope, id: string): Promise<Record<string, unknown> | null> {\n try {\n const rec = await this.codec.decryptRecord(envelope, { skipValidation: true, id })\n return rec === null ? null : (rec as unknown as Record<string, unknown>)\n } catch {\n return null\n }\n }\n\n async _writeTombstone(id: string, actor: string): Promise<{ previousVersion: number } | null> {\n const live = await this.adapter.get(this.vault, this.name, id)\n if (!live || isTombstone(live, this.storeCiphertext) || isDeleteMarker(live)) return null\n\n await this.adapter.put(this.vault, this.name, id, buildTombstone(live._v, actor))\n\n // Invalidate every in-memory view of this record so subsequent reads see\n // the tombstone (→ null), not a stale decrypted value.\n this.cache.delete(id)\n this.lru?.remove(id)\n this.cekCache?.remove(id)\n // #590: enter the sync dirty log — the shred must propagate on push (pull re-assert in team/sync.ts is the backstop)\n await this.onDirty?.(this.name, id, 'put', live._v)\n\n return { previousVersion: live._v }\n }\n\n /**\n * Cascade deletes of array-shape derived rows when a source row is deleted. Reads each\n * registered strategy's fanout sidecar for this source id, deletes every listed derived\n * row, then deletes the sidecar itself. Returns the REAL erased count (#622 review Finding 1).\n *\n * Record-shape derivations are skipped on the ordinary delete path (see _doDelete's comment).\n * `eraseRecordShapeToo` (#638 T6, default `false`) opts a same-id record-shape copy into\n * erasure too — forget()'s fanout, GDPR residue. A delete-of-absent contributes 0 either way.\n * @internal\n */\n async dispatchArrayDerivationsOnDelete(id: string, eraseRecordShapeToo = false): Promise<number> {\n if (this.derivationSource === undefined) return 0\n // S4 gate: the spine may not statically import a with-* service, and this\n // keeps the derivation chunk out of the floor bundle (#842).\n const { dispatchArrayDerivationsOnDelete } = await import('../with-formula/derivations/dispatch.js')\n return dispatchArrayDerivationsOnDelete(this.#derivationDeleteCtx(this.derivationSource), id, eraseRecordShapeToo)\n }\n\n /**\n * Mirror of {@link dispatchMaterializedViews} for the delete/forget path — no `_materializedFrom`\n * skip (record's gone); the `internal` gate at `_doDelete` is the recursion guard. Returns the\n * row count TOMBSTONED across EVERY MV sourced here (#638 T6 — `forgetDerivedFanout`'s\n * `derivedRecordsErased`) — eager AND lazy/manual `invalidateMVAtRest` purges both contribute now\n * (#761 item 1, previously eager-only); lazy persists a stale mark for cold-session recompute;\n * manual serves empty until `refreshView()`. `residueUndecodable`/`residueDeclined` (#776/#785) carry `outputCollection:id` entries whose ownership stamp `invalidateMVAtRest` could not decode, resp. decoded+stamp-matched but declined erasure — surfaced, not erased.\n * @internal\n */\n async dispatchMaterializedViewsOnDelete(id: string): Promise<{ deleted: number; residueUndecodable: string[]; residueDeclined: string[] }> {\n if (this.materializedViewSource === undefined) return { deleted: 0, residueUndecodable: [], residueDeclined: [] }\n // S4 gate: dynamic import only — see #derivationDeleteCtx (#842).\n const { dispatchMaterializedViewsOnDelete } = await import('../with-formula/materialized-views/dispatch.js')\n return dispatchMaterializedViewsOnDelete(this.#mvDispatchCtx(this.materializedViewSource), id)\n }\n\n /**\n * List all records in the collection.\n *\n * Throws in lazy mode — bulk listing defeats the purpose of lazy\n * hydration. Use `scan()` to iterate over the full collection\n * page-by-page without holding more than `pageSize` records in memory.\n *\n * @param locale Optional locale options. When provided,\n * each record is locale-resolved before being returned.\n */\n async list(locale?: LocaleReadOptions): Promise<T[]> {\n if (this.lazy) {\n throw new Error(\n `Collection \"${this.name}\": list() is not available in lazy mode (prefetch: false). ` +\n `Use collection.scan({ pageSize }) to iterate over the full collection.`,\n )\n }\n // Lazy-MV resolve-on-read: if this collection is the\n // output of a registered lazy MV with a pending stale flag, run\n // the executor before returning so callers see fresh data. No-op\n // when nothing is pending — keeps the read path negligible.\n if (this.materializedViewSource !== undefined) {\n const { resolveStaleMVOnRead } = await import('../with-formula/materialized-views/stale.js')\n await resolveStaleMVOnRead(this.materializedViewSource, this.name, this.#dispatchCtx({ collection: this.name, id: 'resolve-on-read' }))\n }\n await this.ensureHydrated()\n const records = [...this.cache.values()].map(e => e.record)\n // Money/computed(virtual) decode must run even with no locale, so list()\n // matches get(). applyLocaleToRecord runs the full Via pipeline present()\n // regardless of locale (#638 Task 7: was money/i18n/dictKey-flag-gated —\n // missed any OTHER binding's `present` hook; `this.via` truthiness is the\n // general no-transform fast-path condition every binding's presence implies).\n if (!this.via) return records\n return Promise.all(records.map(r => this.applyLocaleToRecord(r, locale)))\n }\n\n /**\n * Scan-mode full-text search over a plain-text `field`. Decrypts the\n * collection in memory and ranks records by BM25 against the tokenized query.\n * **Zero added store leakage** — pure client-side scan; nothing searchable is\n * written to the store. (A store-usable blind index for at-scale search is a\n * separate, gated opt-in.) Eager mode only.\n *\n * `opts.match` (`'any'` default | `'all'`), `opts.prefix` (last query term as\n * a prefix → typeahead), `opts.limit` (top-N). Returns `{ id, score, record }`\n * ranked by descending score. The default tokenizer is word-boundary based —\n * see `src/search/tokenize.ts` for the Thai/CJK caveat.\n */\n search(field: string, query: string, opts: SearchOptions = {}): Promise<SearchResult<T>[]> {\n return this.strategies.search.search(this.searchContext(), field, query, opts)\n }\n\n /** Force-persist the lexical index now — gated behind `searchStrategy: withSearch()`. */\n flushIndex(): Promise<void> {\n return this.strategies.search.flushIndex(this.searchContext())\n }\n\n /** Pre-build the lexical index — gated behind `searchStrategy: withSearch()`. */\n warmIndex(): Promise<void> {\n return this.strategies.search.warmIndex(this.searchContext())\n }\n\n /** Retrieval (lexical | semantic | hybrid) — gated behind `searchStrategy: withSearch()`. */\n retrieve(query: string, opts: RetrieveOptions<T> = {}): Promise<RetrieveHit<T>[]> {\n return this.strategies.search.retrieve(this.searchContext(), query, opts)\n }\n\n /** Raw-vector kNN — gated behind `searchStrategy: withSearch()`. */\n similarTo(vector: Float32Array, opts: { k?: number; minScore?: number; includeRecord?: boolean } = {}): Promise<RetrieveHit<T>[]> {\n return this.strategies.search.similarTo(this.searchContext(), vector, opts)\n }\n\n /** Opt-in bulk `_vec` re-derive (#788) — a plain collection has nothing to rebuild; gated behind `searchStrategy: withSearch()` otherwise. */\n rebuildEmbeddings(): Promise<{ rebuilt: number; skipped: number }> {\n if (!this.embeddings) return Promise.resolve({ rebuilt: 0, skipped: 0 })\n return this.strategies.search.rebuildEmbeddings(this.searchContext())\n }\n\n /**\n * Bind the {@link SearchContext} the search/retrieval surface needs. The\n * `cache` is the SAME `Map` reference the eager read/write path owns (passed\n * by reference, never copied) so the index always builds over the live set.\n */\n private searchContext(): SearchContext<T> {\n return {\n name: this.name,\n vault: this.vault,\n adapter: this.adapter,\n codec: this.codec,\n cache: this.cache,\n lazy: this.lazy,\n textIndexes: this.textIndexes,\n i18nFields: this.i18nFields,\n dictKeyFields: this.dictKeyFields,\n blobFields: this.blobFields,\n getDictionary: this.getDictionary,\n searchIndexStore: this.searchIndexStore,\n vectorSet: this.vectorSet,\n embeddings: this.embeddings,\n ensureHydrated: () => this.ensureHydrated(),\n blob: (id) => this.blob(id),\n }\n }\n\n // ─── Bulk operations ─────────────────────────────────────\n\n /**\n * Put many records in one call. Each item is processed sequentially\n * through the normal `put()` path — meaning per-item validation,\n * history snapshots, ledger appends, and change events all still\n * fire. The round-trip saving comes from the adapter staying hot\n * across the batch (no connection re-open, no keyring re-unlock).\n *\n * ## Semantics\n *\n * **Best-effort with per-item results.** If item 5 of 10 fails, items\n * 1–4 are already persisted and items 6–10 are still attempted.\n * The returned {@link PutManyResult} lists every success and failure\n * individually so the caller can decide whether to roll forward\n * (retry the failures) or roll back (manually delete the successes).\n *\n * **True tx-atomic putMany** — pass `{ atomic: true }` to switch\n * to the transaction executor: pre-flight CAS against every\n * item's `expectedVersion`, then commit all ops with best-effort\n * revert on mid-batch failure. On a store that declares `txAtomic`\n * the whole batch is instead submitted as ONE `store.tx()` call with\n * per-leg CAS (#921) — genuinely all-or-nothing, with history/ledger/\n * change events firing after the batch is durable. Atomic mode throws\n * on failure rather than returning a mixed-results object.\n *\n * ## Change events\n *\n * One `change` event per successfully-written record, same as N\n * single-record puts. Subscribers don't need to special-case bulk.\n */\n async putMany(\n entries: ReadonlyArray<readonly [id: string, record: T, opts?: PutManyItemOptions]>,\n options?: PutManyOptions,\n ): Promise<PutManyResult> {\n if (options?.atomic) {\n return this.putManyAtomic(entries)\n }\n const success: string[] = []\n const failures: Array<{ id: string; error: Error }> = []\n for (const entry of entries) {\n const [id, record] = entry\n try {\n await this.put(id, record)\n success.push(id)\n } catch (error) {\n failures.push({ id, error: error as Error })\n }\n }\n return { ok: failures.length === 0, success, failures }\n }\n\n /**\n * Atomic-mode implementation of {@link putMany} — both branches live in\n * `kernel/put-many-atomic.ts`: #921 delegates the batch through ONE\n * `store.tx()` on a `txAtomic` store when the single-collection\n * reduction of the #906 gate admits it (store bits + no duplicate ids +\n * `_txAtomicSafe('put')`); anything else keeps the sequential pre-flight\n * → execute → best-effort-revert loop.\n *\n * @internal\n */\n private putManyAtomic(\n entries: ReadonlyArray<readonly [id: string, record: T, opts?: PutManyItemOptions]>,\n ): Promise<PutManyResult> {\n return runPutManyAtomic(\n { host: this, store: this.adapter, vault: this.vault, name: this.name, derivationSource: this.derivationSource },\n entries,\n )\n }\n\n /**\n * Get many records in one call. Returns a `Map<id, T | null>` —\n * missing records surface as `null` entries so the caller can\n * distinguish \"not found\" from \"lookup failed\". Order-stable\n * iteration (Map preserves insertion order = input `ids` order).\n *\n * Reads go through the per-id `get()` path, which means the cache\n * / hydration logic stays consistent with single-record reads.\n */\n async getMany(ids: readonly string[]): Promise<Map<string, T | null>> {\n const result = new Map<string, T | null>()\n for (const id of ids) {\n result.set(id, (await this.get(id)) as unknown as T | null)\n }\n return result\n }\n\n /**\n * Delete many records in one call. Same best-effort contract as\n * {@link putMany}: if item 5 fails, items 1–4 are already deleted\n * and items 6–10 are still attempted.\n *\n * Deleting a non-existent id is not a failure — matches the\n * idempotent semantics of single-record `delete()`.\n */\n async deleteMany(ids: readonly string[]): Promise<DeleteManyResult> {\n const success: string[] = []\n const failures: Array<{ id: string; error: Error }> = []\n for (const id of ids) {\n try {\n await this.delete(id)\n success.push(id)\n } catch (error) {\n failures.push({ id, error: error as Error })\n }\n }\n return { ok: failures.length === 0, success, failures }\n }\n\n /**\n * Build a chainable query against the collection. Returns a `Query<T>`\n * builder when called with no arguments.\n *\n * Backward-compatible overload: passing a predicate function returns\n * the filtered records directly (the API). Prefer the chainable\n * form for new code.\n *\n * **Lazy-MV gap:** `query()` is synchronous and does NOT\n * trigger lazy materialized-view resolve-on-read. If this\n * collection is a lazy MV's output and the MV is currently stale,\n * `query().toArray()` returns the pre-stale snapshot. To force a\n * fresh read on a lazy MV, either call `list()` (which DOES\n * trigger resolve) or `vault.refreshView(mvName)` before querying.\n * The proper fix — extending `QuerySource` with an async prepare\n * hook — is a separate PR.\n *\n * @example\n * ```ts\n * // New chainable API:\n * const overdue = invoices.query()\n * .where('status', '==', 'open')\n * .where('dueDate', '<', new Date())\n * .orderBy('dueDate')\n * .toArray();\n *\n * // Legacy predicate form (still supported):\n * const drafts = invoices.query(i => i.status === 'draft');\n * ```\n */\n query(): Query<T, S, Q, M>\n query(predicate: (record: T) => boolean): T[]\n query(predicate?: (record: T) => boolean): Query<T, S, Q, M> | T[] {\n if (this.lazy) {\n throw new Error(\n `Collection \"${this.name}\": query() is not available in lazy mode (prefetch: false). ` +\n `Use collection.lazyQuery() for indexed reads, or collection.scan({ pageSize }) ` +\n `and filter the streamed records with a regular for-await loop.`,\n )\n }\n if (predicate !== undefined) {\n // Legacy form: synchronous predicate filter against the cache.\n return [...this.cache.values()].map(e => e.record).filter(predicate)\n }\n // New form: return a chainable builder bound to this collection's cache.\n const source: QuerySource<T> = {\n snapshot: () => [...this.cache.values()].map(e => e.record),\n subscribe: (cb: () => void) => {\n const handler = (event: ChangeEvent): void => {\n if (event.vault === this.vault && event.collection === this.name) {\n cb()\n }\n }\n this.emitter.on('change', handler)\n return () => this.emitter.off('change', handler)\n },\n // Index-aware fast path for `==` and `in` operators on indexed\n // fields. The Query builder consults these when present and falls\n // back to a linear scan otherwise.\n getIndexes: () => this.getIndexes(),\n lookupById: (id: string) => this.cache.get(id)?.record,\n snapshotEntries: () => [...this.cache.entries()].map(([id, e]) => ({ id, record: e.record })),\n ...(this.via ? { via: this.via } : {}),\n }\n // Build a JoinContext if the vault passed a join resolver.\n // Without one, .join() on the resulting Query will throw with an\n // actionable error — the case is unreachable in production but\n // matters for unit tests that construct Collection directly.\n const resolver = this.joinResolver\n const leftCollection = this.name\n const joinContext: JoinContext | undefined = resolver\n ? {\n leftCollection,\n resolveRef: (field: string) => resolver.resolveRef(leftCollection, field),\n resolveSource: (collectionName: string) => resolver.resolveSource(collectionName),\n // Flow the vault/collection default locale to joins so a\n // joined i18n field resolves like get()/list() when no per-call\n // locale is given; toArray({ locale }) overrides it.\n ...(this.defaultLocale !== undefined ? { defaultLocale: this.defaultLocale } : {}),\n ...(resolver.resolveDictSource\n ? { resolveDictSource: (field: string) => resolver.resolveDictSource!(leftCollection, field) }\n : {}),\n }\n : undefined\n return new Query<T, S, Q, M>(source, undefined, joinContext, this.strategies.reduce)\n }\n\n /**\n * Subscribe to every put/delete on this collection. Returns an\n * unsubscribe function.\n *\n * Fires **after** the store write has committed — subscribers see\n * only materialised state, never in-flight or rolled-back writes.\n *\n * This is an event stream, not a reactive value. For reactive\n * \"current array state\" semantics use `query().live()`. Typical\n * use cases for `subscribe()`:\n * - audit-trail / activity-feed UI that lists events as they happen\n * - Pinia-per-collection wiring where each store subscribes once\n * - outbox-style workers that process every new record\n *\n * The callback receives a `CollectionChangeEvent<T>`:\n * - `{ type: 'put', id, record }` — record is the current\n * decrypted value. May be `null` if another op deleted the\n * record between the emit and the handler firing (rare race).\n * - `{ type: 'delete', id, record: null }` — deletion event;\n * the record content is gone by the time the handler runs.\n *\n * The callback is invoked synchronously *with respect to the emit\n * moment*, but the record lookup is async (cache hit for eager\n * collections; one `get()` for lazy collections). If your handler\n * does not need the record, cast it away and ignore — the lookup\n * is still performed, but it's cheap on the hydrated path.\n *\n * ergonomic wrapper over `db.on('change', …)` that\n * filters to this collection and hydrates the record.\n */\n subscribe(cb: (event: CollectionChangeEvent<T>) => void): () => void {\n const handler = (event: ChangeEvent): void => {\n if (event.vault !== this.vault || event.collection !== this.name) return\n if (event.action === 'put') {\n // Cache hit in eager mode; get() in lazy mode.\n void this.get(event.id).then(record => {\n cb({ type: 'put', id: event.id, record: (record ?? null) as unknown as T | null })\n }).catch(() => {\n // Record vanished between emit + lookup (race). Emit with null\n // so subscribers still see the event they were promised.\n cb({ type: 'put', id: event.id, record: null })\n })\n } else {\n // delete\n cb({ type: 'delete', id: event.id, record: null })\n }\n }\n this.emitter.on('change', handler)\n return () => {\n this.emitter.off('change', handler)\n }\n }\n\n /**\n * Return a minimal JoinableSource view of this collection's\n * in-memory cache. Used by the Vault's `resolveSource`\n * method when another collection's `.join()` needs to probe this\n * one as the right side.\n *\n * The returned object captures the cache reference through a\n * closure, so subsequent mutations to the cache are visible to\n * the joined query. That's intentional: a join that fires after\n * the right-side collection has been updated should see the\n * fresh data.\n *\n * Throws in lazy mode because the cache is bounded and could\n * silently miss records — consistent with the `query()` /\n * `list()` lazy-mode policy. If this becomes a blocker for a\n * real consumer, the fix is to add an async `scan()`-backed\n * variant of this method, which is exactly what streaming joins will need anyway.\n */\n querySourceForJoin(): JoinableSource {\n if (this.lazy) {\n throw new Error(\n `Collection \"${this.name}\": .join() cannot use a lazy-mode ` +\n `collection as the right side. Opening it in eager mode ` +\n `(prefetch: true, default) makes it joinable. Streaming joins ` +\n `over lazy collections are not yet supported.`,\n )\n }\n // Structural source — the join executor calls snapshot() and\n // lookupById(); the live-join executor additionally calls\n // subscribe() so right-side mutations propagate. We capture\n // `this.cache` and `this.emitter` by closure so later mutations\n // are visible to the snapshot view AND drive live re-fires.\n return {\n snapshot: () => [...this.cache.values()].map(e => e.record),\n lookupById: (id: string) => this.cache.get(id)?.record,\n subscribe: (cb: () => void) => {\n const handler = (event: ChangeEvent): void => {\n if (event.vault === this.vault && event.collection === this.name) {\n cb()\n }\n }\n this.emitter.on('change', handler)\n return () => this.emitter.off('change', handler)\n },\n // Sync join dressing (#650 Task 6, #626 retirement) — i18n-text + lookup-label, from this collection's own bindings.\n ...(this.presentForJoin !== undefined ? { presentForJoin: this.presentForJoin } : {}),\n }\n }\n\n /**\n * Cache statistics — useful for devtools, monitoring, and verifying\n * that LRU eviction is happening as expected in lazy mode.\n *\n * In eager mode, returns size only (no hits/misses are tracked because\n * every read is a cache hit by construction). In lazy mode, returns\n * the full LRU stats: `{ hits, misses, evictions, size, bytes }`.\n */\n cacheStats(): CacheStats {\n if (this.lazy && this.lru) {\n return { ...this.lru.stats(), lazy: true }\n }\n return {\n hits: 0,\n misses: 0,\n evictions: 0,\n size: this.cache.size,\n bytes: 0,\n lazy: false,\n }\n }\n\n // ─── History Methods ────────────────────────────────────────────\n\n /** Get version history for a record, newest first. */\n async history(id: string, options?: HistoryOptions): Promise<HistoryEntry<T>[]> {\n const envelopes = await this.strategies.history.getHistoryEntries(\n this.adapter, this.vault, this.name, id, options,\n )\n if (await liveRecordIsElevated(this.adapter, this.vault, this.name, id)) return [] // #712: elevated ≡ invisible\n\n const entries: HistoryEntry<T>[] = []\n for (const env of envelopes) {\n if ((env._tier ?? 0) > 0) continue // #712: defensive — a per-version tiered snapshot\n // History reads skip schema validation — see getVersion() docs.\n const record = await this.codec.decryptRecord(env, { skipValidation: true, id })\n // Shredded (tombstoned) history version: the body is permanently gone,\n // so there is nothing to return — skip it. The version still counted in\n // the audit ledger; history() just can't surface its erased content.\n if (record === null) continue\n entries.push({\n version: env._v,\n timestamp: env._ts,\n userId: env._by ?? '',\n record,\n })\n }\n return entries\n }\n\n /**\n * Get a specific past version of a record.\n *\n * History reads intentionally **skip schema validation** — historical\n * records predate the current schema by definition, so validating them\n * against today's shape would be a false positive on any schema\n * evolution. If a caller needs validated history, they should filter\n * and re-put the records through the normal `put()` path.\n */\n async getVersion(id: string, version: number): Promise<T | null> {\n const envelope = await this.strategies.history.getVersionEnvelope(\n this.adapter, this.vault, this.name, id, version,\n )\n if (!envelope || (envelope._tier ?? 0) > 0 || await liveRecordIsElevated(this.adapter, this.vault, this.name, id)) return null\n return this.codec.decryptRecord(envelope, { skipValidation: true, id })\n }\n\n /** Revert a record to a past version. Creates a new version with the old content. */\n async revert(id: string, version: number): Promise<void> {\n const oldRecord = await this.getVersion(id, version)\n if (!oldRecord) {\n throw new Error(`Version ${version} not found for record \"${id}\"`)\n }\n await this.put(id, oldRecord)\n }\n\n /**\n * Compare two versions of a record and return the differences.\n * Use version 0 to represent \"before creation\" (empty).\n * Omit versionB to compare against the current version.\n */\n async diff(id: string, versionA: number, versionB?: number): Promise<DiffEntry[]> {\n const recordA = versionA === 0 ? null : await this.resolveVersion(id, versionA)\n return this.strategies.history.diff(recordA, versionB === undefined || versionB === 0\n ? (versionB === 0 ? null : await this.resolveCurrentOrVersion(id))\n : await this.resolveVersion(id, versionB))\n }\n\n /** Resolve a version: try history first, then check if it's the current version. */\n private async resolveVersion(id: string, version: number): Promise<T | null> {\n // Check history\n const fromHistory = await this.getVersion(id, version)\n if (fromHistory) return fromHistory\n // Check if it's the current live version\n await this.ensureHydrated()\n const current = this.cache.get(id)\n if (current && current.version === version) return current.record\n return null\n }\n\n private async resolveCurrentOrVersion(id: string): Promise<T | null> {\n await this.ensureHydrated()\n return this.cache.get(id)?.record ?? null\n }\n\n /** Prune history entries for a record (or all records if id is undefined). */\n async pruneRecordHistory(id: string | undefined, options: PruneOptions): Promise<number> {\n const pruned = await this.strategies.history.pruneHistory(\n this.adapter, this.vault, this.name, id, options,\n )\n if (pruned > 0) {\n this.emitter.emit('history:prune', {\n vault: this.vault,\n collection: this.name,\n id: id ?? '*',\n pruned,\n })\n }\n return pruned\n }\n\n /** Clear all history for this collection (or a specific record). */\n async clearHistory(id?: string): Promise<number> {\n return this.strategies.history.clearHistory(this.adapter, this.vault, this.name, id)\n }\n\n // ─── Core Methods ─────────────────────────────────────────────\n\n /**\n * Count records in the collection.\n *\n * In eager mode this returns the in-memory cache size (instant). In lazy\n * mode it counts only LIVE tier-0 envelopes via envelope inspection — no\n * record bodies loaded — matching eager's tombstone/tier exclusion (#706).\n */\n async count(): Promise<number> {\n if (this.lazy) {\n return countLiveEnvelopes(this.adapter, this.vault, this.name, this.storeCiphertext)\n }\n await this.ensureHydrated()\n return this.cache.size\n }\n\n // ─── Pagination & Streaming ───────────────────────────────────\n\n /**\n * Fetch a single page of records via the adapter's optional `listPage`\n * extension. Returns the decrypted records for this page plus an opaque\n * cursor for the next page.\n *\n * Pass `cursor: undefined` (or omit it) to start from the beginning.\n * The final page returns `nextCursor: null`.\n *\n * If the adapter does NOT implement `listPage`, this falls back to a\n * synthetic implementation: it loads all ids via `list()`, sorts them,\n * and slices a window. The first call emits a one-time console.warn so\n * developers can spot adapters that should opt into the fast path.\n */\n async listPage(opts: { cursor?: string; limit?: number } = {}): Promise<{\n items: T[]\n nextCursor: string | null\n }> {\n const limit = opts.limit ?? 100\n\n if (this.adapter.listPage) {\n const result = await this.adapter.listPage(this.vault, this.name, opts.cursor, limit)\n const decrypted: T[] = []\n for (const { record, version, id } of await this.decryptPage(result.items)) {\n // Update cache opportunistically — if the page-fetched record isn't\n // in cache yet, populate it. This makes a subsequent .get(id) free.\n // In LAZY mode we deliberately do NOT populate the LRU here:\n // streaming a 100K-record collection should not turn the LRU into\n // a giant write-once buffer that immediately evicts everything.\n // Random-access workloads via .get() are what the LRU is for.\n if (!this.lazy && !this.cache.has(id)) {\n this.cache.set(id, { record, version })\n }\n decrypted.push(record)\n }\n return { items: decrypted, nextCursor: result.nextCursor }\n }\n\n // Fallback: synthetic pagination over list() + get(). Slower than the\n // native path because every id requires its own round-trip, but\n // correct for adapters that haven't opted in.\n warnOnceFallback(this.adapter.name ?? 'unknown')\n const ids = (await this.adapter.list(this.vault, this.name)).slice().sort()\n const start = opts.cursor ? parseInt(opts.cursor, 10) : 0\n const end = Math.min(start + limit, ids.length)\n const items: T[] = []\n for (let i = start; i < end; i++) {\n const id = ids[i]!\n const envelope = await this.adapter.get(this.vault, this.name, id)\n if (envelope && (envelope._tier ?? 0) === 0) {\n const record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true })\n if (record === null) continue // shredded (tombstone) — skip\n items.push(record)\n // Same lazy-mode skip as the native path: don't pollute the LRU\n // with sequential scan results.\n if (!this.lazy && !this.cache.has(id)) {\n this.cache.set(id, { record, version: envelope._v })\n }\n }\n }\n return {\n items,\n nextCursor: end < ids.length ? String(end) : null,\n }\n }\n\n /**\n * Stream every record in the collection page-by-page as an async\n * iterable, with chainable `.where()` / `.filter()` clauses and a\n * memory-bounded `.aggregate(spec)` terminal.\n *\n * The whole point: process collections larger than RAM without\n * ever holding more than `pageSize` records decrypted at once.\n *\n * @example\n * ```ts\n * // Backward-compatible iteration — unchanged from the previous\n * // async-generator shape. `ScanBuilder` implements AsyncIterable.\n * for await (const record of invoices.scan({ pageSize: 500 })) {\n * await processOne(record)\n * }\n *\n * // — streaming aggregation with O(reducers) memory.\n * const { total, n } = await invoices.scan()\n * .where('year', '==', 2025)\n * .aggregate({ total: sum('amount'), n: count() })\n * ```\n *\n * **Lazy-MV gap:** `scan()` is synchronous-build and does\n * NOT trigger lazy materialized-view resolve-on-read. For lazy\n * MVs, call `list()` (which DOES resolve) or `vault.refreshView(name)`\n * before scanning. Same shape as the `query()` limitation.\n *\n * Returns a `ScanBuilder<T>` instead of the raw async iterator\n * that previous versions used. The builder implements\n * `AsyncIterable<T>`, so every existing `for await … of` call\n * continues to work unchanged. Direct `.next()` calls on the\n * iterator — not idiomatic, not used in the codebase — are no\n * longer supported; upgrade to `for await` or call the new\n * `.aggregate()` terminal.\n *\n * Uses `adapter.listPage` when available; otherwise falls back\n * to the synthetic pagination path with the same one-time\n * warning (`listPage()` routes through that fallback internally).\n */\n scan(opts: { pageSize?: number } = {}): ScanBuilder<T, S, M> {\n const pageSize = opts.pageSize ?? 100\n // Build a JoinContext if the vault passed a join resolver\n // — same machinery as `query()`. Without one, `.join()`\n // on the resulting ScanBuilder will throw with an actionable\n // error. The resolver is unreachable in production but matters\n // for unit tests that construct Collection directly.\n const resolver = this.joinResolver\n const leftCollection = this.name\n const joinContext: JoinContext | undefined = resolver\n ? {\n leftCollection,\n resolveRef: (field: string) => resolver.resolveRef(leftCollection, field),\n resolveSource: (collectionName: string) => resolver.resolveSource(collectionName),\n // Flow the vault/collection default locale to joins so a\n // joined i18n field resolves like get()/list() when no per-call\n // locale is given; toArray({ locale }) overrides it.\n ...(this.defaultLocale !== undefined ? { defaultLocale: this.defaultLocale } : {}),\n ...(resolver.resolveDictSource\n ? { resolveDictSource: (field: string) => resolver.resolveDictSource!(leftCollection, field) }\n : {}),\n }\n : undefined\n // The page provider closure is bound to this collection's\n // listPage method so the builder is free of any `this`\n // coupling. Rebinding through the arrow keeps the unbound-\n // method lint rule happy — matches the pattern used in\n // builder.ts's candidateRecords helper.\n return new ScanBuilder<T, S, M>(\n {\n listPage: (listOpts) => this.listPage(listOpts),\n },\n pageSize,\n [],\n [],\n joinContext,\n this.via,\n )\n }\n\n /** Decrypt a page of envelopes returned by `adapter.listPage`. */\n private async decryptPage(\n items: ListPageResult['items'],\n ): Promise<Array<{ id: string; record: T; version: number }>> {\n const out: Array<{ id: string; record: T; version: number }> = []\n for (const { id, envelope } of items) {\n // Public scan/listPage output + opportunistic cache fill — sealed fields stay handles; elevated records are invisible (#706: gate BEFORE decrypt or the warm cekCache leaks tier plaintext, audit-free).\n if ((envelope._tier ?? 0) > 0) continue\n const record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true })\n if (record === null) continue // shredded (tombstone) — skip the page row\n out.push({ id, record, version: envelope._v })\n }\n return out\n }\n\n // ─── Internal ──────────────────────────────────────────────────\n\n /** Load all records from adapter into memory cache. */\n /**\n * @internal — refresh the in-memory cache entry for a single id by\n * re-reading from the adapter. Used by the transaction executor's\n * Phase-3 revert path: that path writes the prior envelope directly\n * via the raw store (to avoid re-firing Collection-level side\n * effects), which would otherwise leave this Collection's eager\n * cache holding the rolled-back value. After revert, the executor\n * calls this hook so subsequent `get` / `query` reads see the\n * actual on-disk state.\n *\n * Lazy mode: drops the LRU entry; the next `get` repopulates from\n * the adapter. Eager mode: re-reads the envelope and either sets\n * the cache entry (record still present) or deletes it (record was\n * gone before the tx and the revert deleted it again).\n */\n /**\n * @internal — evict ONLY the per-record CEK cache entry for `id`. Used by\n * `vault.rotateRecordCek()`: after a hard CEK rotation the cached unwrapped\n * CEK is stale (it would decrypt the pre-rotation body and fail GCM auth on\n * the post-rotation body). Eviction must be synchronous with the live-envelope\n * rewrite so no concurrent read observes the old CEK. Paired with\n * {@link _invalidateCacheEntry} (which refreshes the decrypted-record cache).\n * No-op when the collection is not `perRecordKeys`.\n */\n _invalidateCekCacheEntry(id: string): void {\n this.cekCache?.remove(id)\n }\n\n /** @internal Satellite fan-out revert cleanup (spec #591): drop the sync dirty entry ('revert' is\n * onDirty-channel-only) and re-announce the RESTORED state as a plain put/delete — `subscribe()`\n * only understands those two actions, and the restored record may exist again. */\n async _compensateRevertedWrite(id: string): Promise<void> {\n await this._invalidateCacheEntry(id)\n await this.onDirty?.(this.name, id, 'revert', 0)\n this.emitter.emit('change', { vault: this.vault, collection: this.name, id, action: (await this.get(id)) !== null ? 'put' : 'delete' }) // rare revert path — one read buys a semantically-correct event\n }\n\n async _invalidateCacheEntry(id: string): Promise<void> {\n if (this.lazy && this.lru) {\n this.lru.remove(id)\n return\n }\n const envelope = await this.adapter.get(this.vault, this.name, id)\n // #606: this is the single choke point every sync-apply / tab-mirror /\n // cutover write (plus tx/derivation-revert restores) funnels through, so\n // it's also where the marker-id set tracks a remote marker landing or\n // clearing. MUST run before the `!hydrated` gate below — a marker can\n // land while this collection is still mid-hydration, and hydration\n // snapshots its id list at loop start, so it can never recover an id it\n // never listed. Missing this here permanently drops the id from\n // `markerIds` for the session and reintroduces the #589 divergence.\n if (envelope && isDeleteMarker(envelope)) this.markerIds.add(id)\n else this.markerIds.delete(id)\n if (!this.hydrated) return\n const previous = this.cache.get(id)\n if (!envelope) {\n this.cache.delete(id)\n if (previous) {\n this.indexes?.remove(id, previous.record)\n this.uniqueConstraints?.remove(id, previous.record)\n }\n return\n }\n // Handle-form for the cache (non-residency for sensitive fields).\n const record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true })\n if (record === null) {\n // The on-disk envelope is now a tombstone (shredded). Treat exactly\n // like a deleted record: drop the cache entry and its index rows.\n this.cache.delete(id)\n if (previous) {\n this.indexes?.remove(id, previous.record)\n this.uniqueConstraints?.remove(id, previous.record)\n }\n return\n }\n this.cache.set(id, { record, version: envelope._v })\n this.indexes?.upsert(id, record, previous ? previous.record : null)\n this.uniqueConstraints?.upsert(id, record, previous?.record)\n }\n\n /**\n * Apply a peer tab's committed write to THIS tab's in-memory view:\n * re-read the (already-persisted) envelope from the shared store + refresh\n * cache/indexes, then emit a `change` event so reactive consumers re-render.\n * Never writes to the store and never fires write hooks, so it cannot loop.\n */\n async _applyRemoteChange(id: string, action: 'put' | 'delete'): Promise<void> {\n await this._onRecordMutated(id, action, 'tab-mirror')\n }\n\n /**\n * Origin-tagged mutation choke point (#623 task 10) — the single dispatch\n * point every put/delete path funnels through, AFTER its own store write,\n * to fire the side-effects that path performs today. Each case below\n * performs EXACTLY the side-effect set the seam-map Part-3 table\n * (`.superpowers/sdd/seam-map-i18n-pipeline.md`) records for `origin` —\n * this is a pure parity extraction of existing tails, not a behavior\n * change. Phase C (#621, #622) plugs the dependency-graph dispatch into\n * this socket, keyed off `origin`, without every call site having to\n * learn the graph.\n *\n * `restore` is never reached: `Vault.load` / `backup.ts#loadVault` drops\n * the whole `collectionCache` instead of dispatching per record — the\n * origin is reserved for phase C.\n *\n * @internal\n */\n async _onRecordMutated(\n id: string,\n action: 'put' | 'delete',\n origin: MutationOrigin,\n ctx?: { readonly record?: T; readonly version?: number },\n ): Promise<void> {\n // #606: maintain `markerIds` synchronously, in the SAME continuation as\n // the caller's own `local.put` of this envelope (no `await` between\n // them) — closes the window where a concurrent `put(id)` could read the\n // set before `_invalidateCacheEntry`'s (awaited, below) maintenance\n // catches up. A superset for a moment on a sync-applied tombstone is\n // harmless — `_invalidateCacheEntry`'s read refines it, and a re-create\n // racing ahead of that just does one extra (correct) store read. Gated to\n // eager+synced: lazy mode never consults `markerIds`, and unsynced\n // collections never see markers.\n if (this.onDirty && !this.lazy) {\n if (action === 'delete') this.markerIds.add(id)\n else this.markerIds.delete(id)\n }\n switch (origin) {\n case 'local-write': {\n const record = ctx!.record!\n const version = ctx!.version!\n await this.onDirty?.(this.name, id, 'put', version)\n this.emitter.emit('change', { vault: this.vault, collection: this.name, id, action: 'put' } satisfies ChangeEvent)\n this.searchIndexStore?.markDirty() // zero-cost for non-search collections\n await this.onAccess?.('put', id)\n await this.dispatchDerivations(id, record, version)\n await this.dispatchMaterializedViews(id, record)\n return\n }\n case 'local-delete': {\n await this.onDirty?.(this.name, id, 'put', ctx!.version!)\n this.emitter.emit('change', { vault: this.vault, collection: this.name, id, action: 'delete' } satisfies ChangeEvent)\n this.searchIndexStore?.markDirty() // zero-cost for non-search collections\n await this.onAccess?.('delete', id)\n return\n }\n case 'tab-mirror':\n await this._invalidateCacheEntry(id)\n this.emitter.emit('change', { vault: this.vault, collection: this.name, id, action })\n this.searchIndexStore?.markDirty() // peer write changed the cache; rebuild on next retrieve\n return\n case 'sync-apply': {\n this._invalidateCekCacheEntry(id)\n const prior = action === 'delete' ? this._peekCached(id) : undefined\n await this._invalidateCacheEntry(id)\n if (prior) this.graphDispatch?.collectDelete(this.name, id, this._rollupDeleteIntents(prior))\n else if (action === 'put') this.graphDispatch?.collect(this.name, id)\n return\n }\n case 'cutover':\n // Parity: cache invalidation only — the migration ledger entry\n // stays at the `_applyCutoverTransform` call site.\n await this._invalidateCacheEntry(id)\n this.graphDispatch?.collect(this.name, id)\n return\n case 'restore':\n // Unreachable today — see doc comment above. Phase C (#638) wires the dispatch call anyway.\n this.graphDispatch?.collect(this.name, id)\n return\n }\n }\n\n /** @internal — the current in-memory record without a store read (for conflict capture); also the #640 FK-recovery read on a sync-applied delete — misses on a cold or evicted child (lazy LRU eviction OR an un-hydrated eager collection whose first sync op is a delete), not \"lazy-mode\" only. */\n _peekCached(id: string): T | null {\n const entry = this.lazy && this.lru ? this.lru.get(id) : this.cache.get(id)\n return entry ? entry.record : null\n }\n\n private async ensureHydrated(): Promise<void> {\n if (this.hydrated) return\n\n const ids = await this.adapter.list(this.vault, this.name)\n for (const id of ids) {\n const envelope = await this.adapter.get(this.vault, this.name, id)\n if (envelope && !isTombstone(envelope, this.storeCiphertext) && !isDeleteMarker(envelope) && (envelope._tier ?? 0) === 0) {\n const record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true })\n if (record === null) continue\n this.cache.set(id, { record, version: envelope._v })\n } else if (envelope && isDeleteMarker(envelope)) {\n this.markerIds.add(id) // #606: seed the marker-id set from disk on cold hydration\n }\n }\n this.hydrated = true\n this.rebuildEagerIndexesFromCache()\n this.rebuildUniqueConstraintsFromCache()\n }\n\n /** Hydrate from a pre-loaded snapshot (used by Vault). */\n async hydrateFromSnapshot(records: Record<string, EncryptedEnvelope>): Promise<void> {\n for (const [id, envelope] of Object.entries(records)) {\n if (isDeleteMarker(envelope)) { this.markerIds.add(id); continue } // #606: seed from a pre-loaded snapshot too\n if (isTombstone(envelope, this.storeCiphertext) || (envelope._tier ?? 0) > 0) continue\n const record = await this.codec.decryptRecord(envelope, { id, sealedAsHandles: true })\n if (record === null) continue\n this.cache.set(id, { record, version: envelope._v })\n }\n this.hydrated = true\n this.rebuildEagerIndexesFromCache()\n this.rebuildUniqueConstraintsFromCache()\n }\n\n /**\n * Rebuild secondary indexes from the current in-memory cache.\n *\n * Called after any bulk hydration. Incremental put/delete updates\n * are handled by `indexes.upsert()` / `indexes.remove()` directly,\n * so this only fires for full reloads.\n *\n * Synchronous and O(N × indexes.size); for the target scale of\n * 1K–50K records this completes in single-digit milliseconds.\n */\n private rebuildEagerIndexesFromCache(): void {\n rebuildEagerIndexesFromCacheImpl(this.indexingContext())\n }\n\n /**\n * Rebuild unique-constraint maps from the current in-memory cache.\n * Called after any bulk hydration alongside `rebuildEagerIndexesFromCache`.\n */\n private rebuildUniqueConstraintsFromCache(): void {\n rebuildUniqueConstraintsFromCacheImpl(this.indexingContext())\n }\n\n /**\n * Rebuild every declared index from scratch.\n *\n * Eager mode: refreshes the in-memory `CollectionIndexes` from the\n * current cache — O(records × declaredFields).\n *\n * Lazy mode: tears down every `_idx/<field>/<recordId>`\n * side-car, walks the canonical record namespace, and materialises\n * fresh side-cars for every declared field. The in-memory mirror is\n * cleared and re-ingested. Intended for two scenarios:\n * 1. Adding a new indexed field to a collection that already holds\n * records — after the schema change, call `rebuildIndexes()` to\n * backfill the side-cars.\n * 2. Recovery from a catastrophic drift (audit noticed many\n * `index:write-partial` events, operator wants a clean slate).\n *\n * The rebuild is NOT incremental — it's a full bulk-replace. For\n * per-field drift repair, use `reconcileIndex(field)` instead.\n */\n async rebuildIndexes(): Promise<void> {\n return rebuildIndexesImpl(this.indexingContext())\n }\n\n /**\n * Compare the persisted `_idx/<field>/*` side-cars against the\n * canonical records for a single field, reporting the drift (and\n * optionally repairing it).\n *\n * Lazy mode only. Eager mode throws — the in-memory index cannot\n * drift.\n *\n * `missing` — record ids whose value is indexable but no side-car\n * exists. Happens when a `put()` succeeded but the side-car put\n * failed (surfaced as `index:write-partial`).\n * `stale` — side-car ids pointing to a record that no longer exists\n * or whose current value no longer matches the side-car body.\n * `applied` — number of writes that were actually applied (always 0\n * when `dryRun: true`).\n *\n * Design reference: acceptance criteria.\n */\n async reconcileIndex(\n field: string,\n opts: { dryRun?: boolean } = {},\n ): Promise<{ field: string; missing: string[]; stale: string[]; applied: number }> {\n return reconcileIndexImpl(this.indexingContext(), field, opts)\n }\n\n /**\n * Get the in-memory index store. Used by `Query` to short-circuit\n * `==` and `in` lookups when an index covers the where clause.\n *\n * Returns `null` if no indexes are declared on this collection.\n */\n getIndexes(): CollectionIndexes | null {\n const eager = this.indexes\n return eager && eager.fields().length > 0 ? eager : null\n }\n\n /**\n * Return a `BlobSet` for the given record id.\n *\n * No I/O is performed until you call a method on the handle.\n *\n * ```ts\n * const blobs = invoices.blob('inv-001')\n *\n * // Upload a PDF (deduplicates automatically, MIME auto-detected)\n * await blobs.put('receipt.pdf', pdfBytes)\n *\n * // List slots\n * const files = await blobs.list() // SlotInfo[]\n *\n * // Serve as HTTP response (Content-Type, ETag, streaming body)\n * const res = await blobs.response('receipt.pdf', { inline: true })\n *\n * // Publish a named version (amendment versioning)\n * await blobs.publish('receipt.pdf', 'issued-2025-01')\n *\n * // Raw bytes\n * const bytes = await blobs.get('receipt.pdf')\n * ```\n *\n * Blobs are stored in internal collections (`_blob_slots_*`, `_blob_index`,\n * `_blob_chunks`, `_blob_versions_*`) that are excluded from queries and\n * `list()`. Slot metadata uses this collection's DEK; chunk data uses a\n * vault-shared `_blob` DEK (enabling cross-collection deduplication).\n */\n blob(id: string): BlobSet {\n // tree-shake refactor: delegate to `blobsStrategy`. The default\n // is `NO_BLOBS` (throws with a message pointing at the `@noy-db/hub/blobs`\n // subpath). Users who want blob storage pass `blobs()` from that\n // subpath into `createNoydb({ blobsStrategy: blobs() })`, which\n // threads the active strategy through Vault → Collection.\n return this.strategies.blobs.openSlot({\n store: this.adapter,\n vault: this.vault,\n collection: this.name,\n recordId: id,\n getDEK: this.getDEK,\n encrypted: this.storeCiphertext,\n userId: this.keyring.userId,\n erasableBlobs: this.perRecordCek, tiersActive: this.tiers !== null, keyring: this.keyring,\n debugPlaintext: this.keyring.debugPlaintext === true,\n ...(this.objectStore !== undefined ? { objectStore: this.objectStore } : {}),\n ...(this.blobFields !== undefined ? { blobFields: this.blobFields } : {}),\n })\n }\n\n /** Get all records as encrypted envelopes (for dump). */\n async dumpEnvelopes(): Promise<Record<string, EncryptedEnvelope>> {\n await this.ensureHydrated()\n const result: Record<string, EncryptedEnvelope> = {}\n for (const [id, entry] of this.cache) {\n // Reuse the record's stable CEK on a `perRecordKeys` collection so the\n // dumped envelope matches the stored format and stays in the same key\n // chain. `undefined` → legacy path.\n const cek = this.perRecordCek ? await this.resolveRecordCek(id) : undefined\n const prevForVdig = this.vdigFields !== null ? await this.adapter.get(this.vault, this.name, id) : null\n result[id] = await this.codec.encryptRecord(entry.record, entry.version, cek, undefined, undefined, this.vdigFields !== null ? { id, prev: prevForVdig } : undefined, id)\n }\n return result\n }\n\n /**\n * Apply locale resolution to a record.\n *\n * Called from `get()` and `list()` when locale options are present.\n * Uses the effective locale: per-call `locale` takes precedence over\n * `this.defaultLocale`.\n *\n * - i18nText fields: replaced with the resolved string (or the full\n * map when `locale === 'raw'`).\n * - dictKey fields: `<field>Label` virtual fields added.\n *\n * Returns the record unchanged when no Via pipeline is compiled (#638 Task 7:\n * was money/i18n/dictKey-flag-gated — missed any OTHER binding's `present`\n * hook, e.g. the `computed` via-binding's virtual-mode read-time compute;\n * `this.via` truthiness is the general condition every binding's presence\n * already implies).\n */\n private async applyLocaleToRecord(\n record: T,\n localeOpts?: LocaleReadOptions,\n ): Promise<T> {\n if (!this.via) return record\n\n const locale = localeOpts?.locale ?? this.defaultLocale\n const layer = localeOpts?._layer ?? 'read'\n\n let result = record as unknown as Record<string, unknown>\n\n // Money decode + i18nText/dictKey/computed(virtual) resolution all run through\n // the compiled Via pipeline: money decode is unconditional (virtuals gated on\n // `locale !== 'raw'` inside the money binding); the i18n binding's `present`\n // hook (the i18n via-shape's `runI18nPresent`) applies the SAME locale-active /\n // static-display-hinge / dict-label / densify-marker-strip logic this method\n // used to run inline; `this.via` is already known truthy (the guard above).\n result = await this.via.present(result, { locale, ...(localeOpts?.fallback !== undefined ? { fallback: localeOpts.fallback } : {}), layer })\n\n return result as T\n }\n\n /**\n * Low-level: encrypt a pre-serialised JSON string into an EncryptedEnvelope.\n * Used by both the normal record path and the CRDT path (which serialises\n * a CrdtState rather than a T).\n */\n /**\n * Write / update / delete the `_idx/<field>/<recordId>` side-cars for\n * every declared persistence-index field on this collection after a\n * successful main-record `put()`.\n *\n * Timing: called AFTER `adapter.put()` of the main record succeeds, so\n * a failed main write never leaves a stale index entry. Side-car write\n * failures do NOT fail the overall `put()` — the main record is already\n * durably committed. Per-field failures surface as\n * `IndexWriteFailureError` on the emitter's `index:write-partial`\n * channel and the operator runs a reconcile pass later.\n *\n * Null/undefined field values are not indexed — matches the\n * `PersistedCollectionIndex.stringifyKey` contract. If the prior value\n * was non-null and the new value is null, the side-car is deleted.\n */\n private maintainPersistedIndexesOnPut(\n id: string,\n newRecord: T,\n previousRecord: T | null,\n version: number,\n ): Promise<void> {\n return maintainPersistedIndexesOnPutImpl(this.indexingContext(), id, newRecord, previousRecord, version)\n }\n\n /**\n * Tear down `_idx/<field>/<recordId>` side-cars for a deleted record.\n * Mirror state updates regardless of adapter outcome; adapter failures\n * surface on `index:write-partial` the same way put does.\n */\n private maintainPersistedIndexesOnDelete(id: string, previousRecord: T): Promise<void> {\n return maintainPersistedIndexesOnDeleteImpl(this.indexingContext(), id, previousRecord)\n }\n\n /**\n * @internal — hard-delete this record's persisted `_idx/<field>/<recordId>`\n * side-cars for the erasure path. `forget()` crypto-shreds the body but\n * keeps the collection DEK, under which these side-cars are encrypted — so\n * without this they leave the indexed field VALUES readable after a \"forget\".\n *\n * Content-free: the side-car id is `encodeIdxId(def.key, id)`, so it needs no\n * body decode (the body is being shredded). Eager mode has no durable side-car\n * → no-op. The in-memory mirror is left as-is: it is ephemeral (rebuilt from\n * the now-deleted side-cars on reopen) and live reads skip the tombstone, so a\n * stale mirror hit cannot surface the erased record. Returns the count deleted\n * + the `def.key`s whose delete FAILED (residue that still leaks the value).\n */\n _purgePersistedIndexes(id: string): Promise<{ purged: number; residue: string[] }> {\n return purgePersistedIndexesImpl(this.indexingContext(), id)\n }\n\n /** Drop a record's encrypted _vec sidecar on erasure (a vector is text-invertible).\n * Called by vault.ts forget() inside a resilient try/catch; residue is reported in ForgetResult. */\n async _purgeVector(id: string): Promise<void> {\n await this.adapter.delete(this.vault, '_vec', encodeVecId(this.name, id))\n this.vectorSet?.markDirty()\n }\n\n /** Drop the persisted lexical-index blob (forget/erasure): an opaque\n * all-records index must not survive crypto-shred. Idempotent; no-op without persist. */\n async _purgeSearchIndex(): Promise<void> {\n const store = this.searchIndexStore\n if (store && 'removePersisted' in store) await (store as { removePersisted(): Promise<void> }).removePersisted()\n else store?.markDirty()\n }\n\n /**\n * Bulk-load the persisted-index mirror from `_idx/<field>/*` side-cars\n * on first lazy-mode query. Idempotent — subsequent calls short-circuit\n * on the `persistedIndexesLoaded` flag.\n *\n * Listing the whole id namespace is acceptable here because the caller\n * has already decided to pay a first-query cost (this is the indexed\n * equivalent of lazy-mode hydration, not a per-query scan).\n */\n private async ensurePersistedIndexesLoaded(): Promise<void> {\n if (this.persistedIndexesLoaded) return\n const persisted = this.persistedIndexes\n if (!persisted || persisted.fields().length === 0) {\n this.persistedIndexesLoaded = true\n return\n }\n\n const ids = await this.adapter.list(this.vault, this.name)\n const byField = new Map<string, Array<{ recordId: string; value: unknown }>>()\n for (const id of ids) {\n const decoded = decodeIdxId(id)\n if (!decoded) continue\n if (!persisted.has(decoded.field)) continue\n const envelope = await this.adapter.get(this.vault, this.name, id)\n if (!envelope) continue\n try {\n const json = await this.codec.decryptJsonString(envelope)\n if (json === null) continue // tombstone side-car — skip\n const body = JSON.parse(json) as { value: unknown; recordId: string }\n if (typeof body.recordId !== 'string') continue\n const rows = byField.get(decoded.field) ?? []\n rows.push({ recordId: body.recordId, value: body.value })\n byField.set(decoded.field, rows)\n } catch {\n // Skip unreadable side-cars — the reconciler picks them up later.\n }\n }\n for (const [field, rows] of byField) {\n persisted.ingest(field, rows)\n }\n this.persistedIndexesLoaded = true\n\n // auto-reconcile on first query. The mirror is now\n // populated from whatever side-cars existed; reconcileIndex will\n // diff that against the canonical records and repair (or just\n // report) drift per-field. Skip on the inner reload triggered by\n // reconcileIndex itself — see `autoReconciling` guard.\n if (this.reconcileOnOpen !== 'off' && !this.autoReconciling) {\n await this.autoReconcile()\n }\n }\n\n /**\n * Walk every declared persisted-index field, run `reconcileIndex`\n * per the configured policy, and emit `index:reconciled` for each.\n * Called internally by `ensurePersistedIndexesLoaded()` — exposed as\n * a private helper for readability, not as a public API (the public\n * entry points are `reconcileIndex` and `rebuildIndexes`).\n */\n private async autoReconcile(): Promise<void> {\n const persisted = this.persistedIndexes\n if (!persisted) return\n this.autoReconciling = true\n try {\n const dryRun = this.reconcileOnOpen === 'dry-run'\n for (const def of persisted.definitions()) {\n try {\n const report = await this.reconcileIndex(def.key, { dryRun })\n this.emitter.emit('index:reconciled', {\n vault: this.vault,\n collection: this.name,\n field: def.key,\n missing: report.missing,\n stale: report.stale,\n applied: report.applied,\n skipped: false,\n })\n } catch {\n // Tolerate a single field's failure — a broken reconcile\n // shouldn't prevent the rest of the collection from\n // working. The `index:write-partial` channel captures\n // per-field failures during put/delete; this is its\n // sibling for the reconcile path.\n }\n }\n } finally {\n this.autoReconciling = false\n }\n }\n\n /**\n * Construct a `LazyQuery<T>` bound to this collection. Used by the\n * lazy-mode branch of `query()` and kept private because callers should\n * always go through `query()` to pick up the eager/lazy dispatch.\n */\n /**\n * Build a chainable indexed-read query against a lazy-mode collection.\n *\n * Companion to `query()`, which is eager-mode only and materialises a\n * snapshot. `lazyQuery()` dispatches every read through the persisted\n * index side-cars — no bulk decrypt, no snapshot. Every field touched by\n * `.where(...)` or `.orderBy(...)` MUST be declared in `indexes`;\n * otherwise `.toArray()` throws `IndexRequiredError`.\n *\n * The returned builder is always Promise-returning on its terminals\n * (`toArray`, `first`, `count`) because candidate records are decrypted\n * from the adapter on demand.\n *\n * @example\n * ```ts\n * const disbursements = vault.collection<Disbursement>('disbursements', {\n * prefetch: false,\n * cache: { maxRecords: 1000 },\n * indexes: ['clientId', 'period'],\n * })\n * const rows = await disbursements.lazyQuery()\n * .where('clientId', '==', 'c-42')\n * .orderBy('period', 'desc')\n * .limit(50)\n * .toArray()\n * ```\n *\n * Throws at call time when the collection is in eager mode — use\n * `query()` there. Throws if no index is declared, because a lazy\n * query with no index would need to enumerate the whole collection.\n */\n lazyQuery(): LazyQuery<T, S, Q> {\n if (!this.lazy) {\n throw new Error(\n `Collection \"${this.name}\": lazyQuery() is only available in lazy mode ` +\n `(prefetch: false). Use collection.query() for eager-mode chainable reads.`,\n )\n }\n const persisted = this.persistedIndexes\n if (!persisted) {\n throw new Error(\n `Collection \"${this.name}\": lazyQuery() requires indexing to be enabled. ` +\n `Pass \\`withIndexing()\\` from \"@noy-db/hub/indexing\" to ` +\n `\\`createNoydb({ indexingStrategy: withIndexing() })\\`.`,\n )\n }\n if (persisted.fields().length === 0) {\n throw new Error(\n `Collection \"${this.name}\": lazyQuery() requires at least one field declared ` +\n `in \\`indexes\\`. Declare the fields you'll filter or sort by, or use ` +\n `collection.scan({ pageSize }) for non-indexed iteration.`,\n )\n }\n const source: LazyQuerySource<T> = {\n collectionName: this.name,\n persistedIndexes: persisted,\n canonicalizeIndexKey: (f: string, v: unknown) => this.via?.canonicalizeIndexKey(f, v),\n ensurePersistedIndexesLoaded: () => this.ensurePersistedIndexesLoaded(),\n // #684: raw-fetch seam — post-filter runs against the RAW record;\n // only survivors are decoded via `decodeRecord` below.\n getRawRecord: (id: string) => this.#getRaw(id),\n decodeRecord: (record: unknown) => this.applyLocaleToRecord(record as T, undefined),\n via: () => this.via,\n }\n return new LazyQuery<T, S, Q>(source)\n }\n\n /**\n * Resolve the stable CEK for a record on the WRITE path — see\n * {@link resolveStableCek}. Thin delegate that supplies the collection's\n * CEK cache, live-envelope reader, and DEK resolver.\n */\n private resolveRecordCek(id: string): Promise<EnclaveKey> {\n return resolveStableCek(\n {\n cache: this.cekCache,\n getLive: (rid) => this.adapter.get(this.vault, this.name, rid),\n getDEK: () => this.getDEK(this.name),\n },\n id,\n )\n }\n\n /** C-A/R10: persist the classified marker once per classified handle (store I/O in config-drift.ts). */\n private async _ensureClassifiedMarker(): Promise<void> {\n if (this._markerPersisted || this.vdigFields === null) return\n const { persistClassifiedMarkerForFields } = await import('../port/with/classified-marker.js')\n await persistClassifiedMarkerForFields(this.adapter, this.vault, this.name, this.vdigFields, await this.getDEK(this.name))\n this._markerPersisted = true\n }\n\n /** C-A/R10 drift signal — the marker's declared digest-only set, memoized to one store read per handle (see config-drift.ts). */\n private async _classifiedMarkerDigestOnly(): Promise<readonly string[]> {\n if (this._markerDigestOnlyCache !== undefined) return this._markerDigestOnlyCache\n const { readClassifiedMarkerDigestOnly } = await import('../port/with/classified-marker.js')\n this._markerDigestOnlyCache = await readClassifiedMarkerDigestOnly(this.adapter, this.vault, this.name, await this.getDEK(this.name))\n return this._markerDigestOnlyCache\n }\n\n /**\n * find the first record whose deterministic field matches\n * the given plaintext. Returns `null` when no match exists.\n *\n * Reads every envelope via the adapter and compares the stored\n * `_det[field]` to a freshly computed deterministic ciphertext — no\n * record bodies are decrypted during the search, which is the whole\n * point of a deterministic index.\n *\n * Throws when the field is not declared in `deterministicFields`, so a\n * typo fails loudly at the call site rather than silently returning\n * null forever.\n */\n findByDet(field: string, value: unknown): Promise<T | null> {\n return findByDet(this.detContext(), field, value)\n }\n\n /**\n * return every record whose deterministic field matches.\n * Same semantics as {@link findByDet} but without the short-circuit.\n */\n queryByDet(field: string, value: unknown): Promise<T[]> {\n return queryByDet(this.detContext(), field, value)\n }\n\n /** Bind the {@link DeterministicContext} this collection's det lookups need. */\n private detContext(): DeterministicContext<T> {\n return {\n name: this.name,\n vault: this.vault,\n adapter: this.adapter,\n deterministicFields: this.deterministicFields,\n storeCiphertext: this.storeCiphertext,\n getDEK: () => this.getDEK(this.name),\n codec: this.codec,\n }\n }\n\n // ─── Hierarchical Access ──────────────────────────\n\n /** tier-aware put — gated behind `tiersStrategy: withTiers()`. `searchResidue: true` = stuck search compensation (#774, mirroring #764's elevate/demote posture); the write itself always completes. */\n putAtTier(id: string, record: T, tier: number, opts?: { elevation?: { reason: string; fromTier: number }; source?: string; sourceTs?: string }): Promise<TierMoveResult> {\n return this.strategies.tiers.putAtTier(this.tiersContext(), id, record, tier, opts)\n }\n\n /** tier-aware get — gated behind `tiersStrategy: withTiers()`. */\n getAtTier(id: string): Promise<T | GhostRecord | null> {\n return this.strategies.tiers.getAtTier(this.tiersContext(), id)\n }\n\n /** list ids grouped by the caller's readability — gated behind `withTiers()`. */\n listAtTier(): Promise<Array<{ id: string; tier: number; readable: boolean }>> {\n return this.strategies.tiers.listAtTier(this.tiersContext())\n }\n\n /** elevate a record to a higher tier — gated behind `withTiers()`. `searchResidue: true` = stuck search compensation (#764); the move itself always completes. */\n elevate(id: string, toTier: number): Promise<TierMoveResult> {\n return this.strategies.tiers.elevate(this.tiersContext(), id, toTier)\n }\n\n /** demote a record to a lower tier — gated behind `withTiers()`. Same `searchResidue` posture as {@link elevate} (#764). */\n demote(id: string, toTier: number): Promise<TierMoveResult> {\n return this.strategies.tiers.demote(this.tiersContext(), id, toTier)\n }\n\n /**\n * Emit a cross-tier access event. The subscriber sink stays collection-resident (it captures `onCrossTierAccess`); the tiers module reaches it via the {@link TiersContext.emitCrossTierEvent} callback.\n */\n private emitCrossTierEvent(event: CrossTierAccessEvent): void {\n try {\n this.onCrossTierAccess?.(event)\n } catch {\n // notification sink failures must never block a tier operation\n }\n }\n\n /**\n * Classify a live envelope's `_sealed` slots for crypto-shred completeness\n * (#M-1, 2026-06-30 security review). Kept as a `_`-prefixed method on\n * Collection because `vault.ts` forget() reaches in via this name.\n */\n _classifySealedShred(live: EncryptedEnvelope): Promise<{ readonly slots: readonly SealedShredSlot[] }> {\n return classifySealedShredImpl(this.tiersContext(), live)\n }\n\n async _onViaErase(id: string, live: EncryptedEnvelope): Promise<ViaEraseReport | undefined> { return this.via ? this.via.eraseSealed({ id, vault: this.vault, live, crypto: await this.codec.eraseCryptoCtx(id, live) }) : undefined } // @internal forget()'s per-ref via-erase fold (#629 T10)\n get _via(): ViaPipeline | undefined { return this.via } // @internal exportRedact()'s typed reach-in accessor (fixes #634)\n _setVia(pipeline: ViaPipeline | undefined): void { this.via = pipeline; this.codec.setVia(this.via) } // @internal applyTaintOverlay()'s typed writer seam — assigns `via` + resyncs the codec (fixes #666)\n get _viaFieldsSnapshot(): { i18nFields: Record<string, I18nTextDescriptor> | undefined; lookupFields: Record<string, LookupDescriptor> | undefined } { return { i18nFields: this.i18nFields, lookupFields: this.lookupFields } } // @internal reconcile.ts's presentForJoin-rebuild union reader (#671 item 3)\n async _assertWriteGates(): Promise<void> { await this.schemaUpdateGate?.assertWritable(); await this.schemaFence?.assertWritable(this.name) } // @internal #906 — the two refusals `put()`/`delete()` assert BEFORE anything else: the schema-update gate (an opt-in but persistent `reject` decision) and the schema fence (stale generation → MigrationRequiredError; draining/migrating vault or pending per-collection cutover → SchemaFenceError). Neither lives in the prepare halves, and the atomic commit path calls those directly — so it asserts here, per op, mirroring put()/delete() exactly (the fence does a fresh store read per call, so per-op matches today's cost model). Deliberately NOT moved into the prepare halves: that would double-assert on the OCC path.\n\n /**\n * @internal #931 — the after-write OBSERVERS `put()`/`delete()` fire in\n * their wrappers (user `onAfterWrite` hooks, then the `afterPut`/\n * `afterDelete` observe bus), replayed for one atomic-path leg after its\n * finalize. Neither can refuse a completed write, so since #931 they no\n * longer gate `_txAtomicSafe`; skipping them silently would still be a\n * policy hole (forget's subject index and the cross-tab write relay are\n * both wired this way), so the atomic path calls this per leg. The\n * WriteEvent is built from the prepared carrier — same prior basis the\n * wrappers use — and the same re-entrancy guards apply (`runAfter`\n * suppresses nested hook firing; the bus gate checks `dispatching`).\n */\n async _fireAtomicAfterWrite(opType: 'put' | 'delete', prepared: PreparedPut<T> | PreparedDelete<T>): Promise<void> {\n const hooksActive = this.#hooksActive()\n const busPoint = opType === 'put' ? 'afterPut' as const : 'afterDelete' as const\n const busActive = (this.subsystemBus?.hasHandlers(busPoint) ?? false) && !(this.subsystemBus?.dispatching ?? false)\n if (!hooksActive && !busActive) return\n const base = { vault: this.vault, collection: this.name, userId: this.keyring.userId, timestamp: Date.now(), txId: this.#txIdForHook() }\n const event: WriteEvent = opType === 'put'\n ? { ...base, op: (prepared as PreparedPut<T>).prior ? 'update' : 'create', docId: prepared.id, before: (prepared as PreparedPut<T>).prior?.record ?? null, after: (prepared as PreparedPut<T>).event, baseVersion: (prepared as PreparedPut<T>).prior?.version ?? 0, version: (prepared as PreparedPut<T>).version }\n : { ...base, op: 'delete', docId: prepared.id, before: (prepared as PreparedDelete<T>).existing?.record ?? null, after: null, baseVersion: (prepared as PreparedDelete<T>).existing?.version ?? 0, version: ((prepared as PreparedDelete<T>).existing?.version ?? 0) + 1 }\n if (hooksActive) await this.writeHooks!.runAfter(event)\n if (busActive) await this.subsystemBus!.dispatch(busPoint, event)\n }\n _txAtomicSafe(opType: 'put' | 'delete'): boolean { if ((this.materializedViewSource !== undefined && this.materializedViewSource.registry().mvsForSource(this.name).length > 0) || (this.derivationSource !== undefined && this.derivationSource.registry().strategiesForSource(this.name).length > 0) || this.crdtMode !== undefined || this.uniqueConstraints !== null || (this.writeHooks !== undefined && this.writeHooks.hasBeforeHandlers && !this.writeHooks.suppressed)) return false; return opType === 'put' ? Object.keys(this._refs).length === 0 : this.refEnforcer === undefined || !this.refEnforcer._deleteCascadesPossible(this.name) } // @internal #893/#906-prep atomic-commit eligibility gate (Task 4) — false on any derivation/MV source (any lifecycle), CRDT mode, unique constraints, or refs on this write direction. Put uses precise outbound `_refs`; delete (#922) consults the enforcer's `_deleteCascadesPossible(name)` — Vault unions ALL THREE cascade sources `enforceRefsOnDelete` (with-shape/links/vault-facade.ts) fires from (lookup-ref edges, classic inbound refs, managed links); anything narrower (e.g. `getInbound` alone) would admit unsafe atomic deletes, because `_prepareDelete` runs those cascades DURING prepare. #931 narrows #906's hooks blanket: only BEFORE-hooks gate (they can REFUSE a write, which only `put()`/`delete()` honors); after-hooks and the `afterPut`/`afterDelete` observe bus cannot refuse, so the atomic path fires them itself post-finalize via `_fireAtomicAfterWrite` instead of forfeiting the batch (the pre-#931 db-global blanket cost multi-tab write-relay and forget-subject apps the atomic path entirely). See atomic-eligibility.ts.\n _reconcileReadState(patch: { dictKeyFields?: Record<string, DictKeyDescriptor | StaticDictDescriptor>; i18nFields?: Record<string, I18nTextDescriptor>; lookupFields?: Record<string, LookupDescriptor>; getDictionary?: (name: string) => Promise<DictionaryHandle>; presentForJoin?: (record: unknown, locale: string) => unknown }): void { // @internal reconcile.ts's ONE late-attach writer for #671 items 1-3 — descriptor maps merge (construction wins on collision), getDictionary/presentForJoin assign (getDictionary never clobbers a live closure)\n if (patch.dictKeyFields) this.dictKeyFields = { ...patch.dictKeyFields, ...this.dictKeyFields }\n if (patch.i18nFields) this.i18nFields = { ...patch.i18nFields, ...this.i18nFields }\n if (patch.lookupFields) this.lookupFields = { ...patch.lookupFields, ...this.lookupFields }\n if (patch.getDictionary && this.getDictionary === undefined) this.getDictionary = patch.getDictionary\n if (patch.presentForJoin) this.presentForJoin = patch.presentForJoin\n }\n /**\n * Bind the {@link TiersContext} the tier ops need — `cekCache` by reference (same `Lru` the read/write path owns) for a synchronous re-wrap; `syncDerived` closes over `this` for {@link syncDerivedOutputs} (#722).\n */\n private tiersContext(): TiersContext<T> {\n return {\n name: this.name,\n vault: this.vault,\n adapter: this.adapter,\n keyring: this.keyring,\n codec: this.codec,\n cekCache: this.cekCache,\n syncCache: (id: string, e: { record: T; version: number } | null) => { if (e) this.cache.set(id, e); else this.cache.delete(id); this.lru?.remove(id) },\n syncIndexes: (id: string, rec: T | null, version: number, priorEnvelope?: EncryptedEnvelope) => syncTierIndexesImpl(this.indexingContext(), id, rec, version, priorEnvelope),\n syncSearch: (id: string, rec: T | null, version?: number) => syncTierSearchImpl(this.searchContext(), id, rec, version),\n syncHistory: async (id: string, fromDek: EnclaveKey, toDek: EnclaveKey) => this.strategies.history.rewrapHistory(this.adapter, this.vault, this.name, id, fromDek, toDek, await this.getDEK(this.name)),\n saveHistorySnapshot: async (id: string, envelope: EncryptedEnvelope) => { // #728: gate folded in here so tiers/index.ts stays simple; review fix — mirror put()'s save→emit→prune parity (maxVersions was unbounded on tier moves)\n if (this.historyConfig.enabled === false) return\n await this.strategies.history.saveHistory(this.adapter, this.vault, this.name, id, envelope)\n this.emitter.emit('history:save', { vault: this.vault, collection: this.name, id, version: envelope._v })\n if (this.historyConfig.maxVersions) await this.strategies.history.pruneHistory(this.adapter, this.vault, this.name, id, { keepVersions: this.historyConfig.maxVersions })\n },\n historyEnabled: this.historyConfig.enabled !== false && this.strategies.history !== NO_HISTORY, // #728/#737: lets putAtTier skip decrypting `existing` when no real history strategy is wired\n syncBlobs: (id: string, fromTier: number, toTier: number) => this.strategies.blobs !== NO_BLOBS ? this.blob(id).syncTierMove(fromTier, toTier, this.blobTierPolicy) : Promise.resolve(), // #724 I1: gate on blob storage enabled (not on declared blobFields) so undeclared-field blobs still rehome; #746: syncTierMove mints/resumes the rehome journal marker; self-no-ops on an empty slot map\n syncLedger: async (id: string) => { await this.ledger?.purgeRecordDeltas(this.name, id) },\n syncDerived: (id: string, record: T | null, elevated: boolean, version?: number) => syncDerivedOutputs(this, id, record, elevated, version),\n hasDerivedOutputs: (this.materializedViewSource !== undefined && this.materializedViewSource.registry().mvsForSource(this.name).length > 0) || (this.derivationSource !== undefined && this.derivationSource.registry().strategiesForSource(this.name).length > 0), // #737: source-grained (was vault-grained) — a derivation-free tiered collection skips the pre-move decode even when other collections in the vault have derivations\n provenance: this.provenance,\n tiers: this.tiers,\n tierMode: this.tierMode,\n getDEK: (key: string) => this.getDEK(key),\n emitCrossTierEvent: (event) => this.emitCrossTierEvent(event),\n addSubjectRef: (id: string, record: T) => this.addSubjectRef?.(id, record) ?? Promise.resolve(),\n }\n }\n\n /**\n * Bind the {@link IndexingContext} the index-maintenance surface needs. The\n * eager `cache` Map and the index / unique-constraint / persisted mirrors are\n * passed by reference (the SAME instances the query path reads, never\n * copied); the `persistedIndexesLoaded` flag and `ensure*` hydration stay collection-resident, reached via callbacks.\n */\n private indexingContext(): IndexingContext<T> {\n return {\n name: this.name,\n vault: this.vault,\n adapter: this.adapter,\n codec: this.codec,\n cache: this.cache,\n lazy: this.lazy,\n emitter: this.emitter,\n indexes: this.indexes,\n uniqueConstraints: this.uniqueConstraints,\n persistedIndexes: this.persistedIndexes,\n ensureHydrated: () => this.ensureHydrated(),\n ensurePersistedIndexesLoaded: () => this.ensurePersistedIndexesLoaded(),\n setPersistedIndexesLoaded: (value) => { this.persistedIndexesLoaded = value },\n }\n }\n}\n","/**\n * Export/import capability gating.\n *\n * Pure predicates over a keyring's `exportCapability` / `importCapability`: the\n * `assert*` variants throw {@link ExportCapabilityError} / {@link ImportCapabilityError}\n * when the invoking keyring is not authorised; the `can*` variants return a\n * boolean for UI affordances. They wrap the role-default resolution in\n * {@link hasExportCapability} / {@link hasImportCapability}. Behaviour is\n * byte-identical to the inline `Vault` methods they replaced — every dependency\n * is the unlocked keyring, passed in. `Vault` keeps the typed (overloaded)\n * public methods and delegates here.\n *\n * Internal — reached through `vault.assertCanExport(...)` etc.\n */\nimport { ExportCapabilityError, ImportCapabilityError } from '../../kernel/errors.js'\nimport { hasExportCapability, hasImportCapability } from '../../with-party/team/keyring.js'\nimport type { UnlockedKeyring } from '../../with-party/team/keyring.js'\nimport type { ExportFormat } from '../../kernel/types.js'\n\n/**\n * Authorize an `@noy-db/as-*` export against the keyring's `exportCapability`.\n * Throws `ExportCapabilityError` if the keyring is not authorised.\n *\n * - plaintext tier requires a `format`; defaults to empty for every role.\n * - bundle tier defaults to on for owner/admin, off for others.\n */\nexport function assertCanExport(keyring: UnlockedKeyring, tier: 'plaintext' | 'bundle', format?: ExportFormat): void {\n if (tier === 'plaintext') {\n if (format === undefined) {\n throw new Error('vault.assertCanExport: plaintext tier requires a format')\n }\n if (!hasExportCapability(keyring, 'plaintext', format)) {\n throw new ExportCapabilityError({\n tier: 'plaintext',\n userId: keyring.userId,\n format,\n })\n }\n return\n }\n if (!hasExportCapability(keyring, 'bundle')) {\n throw new ExportCapabilityError({\n tier: 'bundle',\n userId: keyring.userId,\n })\n }\n}\n\n/**\n * Authorize an `@noy-db/as-*` import against the keyring's `importCapability`.\n * Throws `ImportCapabilityError` if the keyring is not authorised.\n *\n * - plaintext tier requires a `format`; default-closed for every role.\n * - bundle tier is default-closed for every role, including owner — import is\n * more dangerous than export (corrupts vs leaks).\n */\nexport function assertCanImport(keyring: UnlockedKeyring, tier: 'plaintext' | 'bundle', format?: ExportFormat): void {\n if (tier === 'plaintext') {\n if (format === undefined) {\n throw new Error('vault.assertCanImport: plaintext tier requires a format')\n }\n if (!hasImportCapability(keyring, 'plaintext', format)) {\n throw new ImportCapabilityError({\n tier: 'plaintext',\n userId: keyring.userId,\n format,\n })\n }\n return\n }\n if (!hasImportCapability(keyring, 'bundle')) {\n throw new ImportCapabilityError({\n tier: 'bundle',\n userId: keyring.userId,\n })\n }\n}\n\n/**\n * Read-only accessor for the keyring's export capability, with role-based\n * defaults resolved. Useful for UI affordances (grey out the export button if\n * no capability) without throwing.\n */\nexport function canExport(keyring: UnlockedKeyring, tier: 'plaintext' | 'bundle', format?: ExportFormat): boolean {\n if (tier === 'plaintext') {\n if (format === undefined) return false\n return hasExportCapability(keyring, 'plaintext', format)\n }\n return hasExportCapability(keyring, 'bundle')\n}\n\n/**\n * Read-only accessor for the keyring's import capability. UI affordance —\n * returns false in every default-closed case (every role with no explicit\n * `importCapability` grant).\n */\nexport function canImport(keyring: UnlockedKeyring, tier: 'plaintext' | 'bundle', format?: ExportFormat): boolean {\n if (tier === 'plaintext') {\n if (format === undefined) return false\n return hasImportCapability(keyring, 'plaintext', format)\n }\n return hasImportCapability(keyring, 'bundle')\n}\n","/**\n * The scoped {@link ElevatedHandle} returned by `vault.elevate(...)`.\n *\n * The handle holds only a reference to its issuing {@link Vault} and delegates\n * the single elevated write back to `vault._elevatedPut`. The `Vault` type\n * is imported `type`-only so the runtime import graph stays acyclic (vault.ts\n * imports this module for the value; this module imports vault.ts only for the\n * type).\n */\nimport { ElevationExpiredError } from '../../kernel/errors.js'\nimport type { Vault } from '../../kernel/vault.js'\nimport type { TierMoveResult } from '../../with-audit/tiers/index.js'\n\n/**\n * Reserved collection that holds the audit ledger of elevation\n * sessions. One envelope per `vault.elevate(...)` call.\n */\nexport const ELEVATION_AUDIT_COLLECTION = '_elevation_audit'\n\n/**\n * Scoped handle returned by `vault.elevate(...)`. Writes through this\n * handle land at the elevated tier with `authorization: 'elevation'`\n * stamped on the audit event; reads stay on the original `Vault`.\n *\n * The handle lazily checks its TTL on every operation, so a\n * forgotten `release()` cannot keep elevated writes alive past\n * `expiresAt` — the next call simply throws\n * {@link ElevationExpiredError}.\n *\n * Naming note: the issue's spec text used `elevated.session`\n * for this field; we name the field `handle` to avoid conflicting\n * with the codebase's existing `SessionToken` value type. The\n * semantics are unchanged.\n */\nexport class ElevatedHandle {\n /** Target tier this handle writes at. */\n readonly tier: number\n /** Audit string stamped on every cross-tier event. */\n readonly reason: string\n /** Absolute expiration in ms (Date.now()). */\n readonly expiresAt: number\n private released = false\n private readonly vault: Vault\n private readonly onRelease: () => void\n\n constructor(opts: {\n vault: Vault\n tier: number\n reason: string\n expiresAt: number\n onRelease: () => void\n }) {\n this.vault = opts.vault\n this.tier = opts.tier\n this.reason = opts.reason\n this.expiresAt = opts.expiresAt\n this.onRelease = opts.onRelease\n }\n\n /**\n * Scoped collection accessor. Returns a thin wrapper exposing the\n * single elevated operation (`put`). Reads, deletes, queries —\n * everything else — should go through the original `vault`'s\n * `collection(...)`, which keeps \"writes elevated, reads\n * unprivileged\" trivially true.\n */\n collection<T>(name: string): { put(id: string, record: T): Promise<TierMoveResult> } {\n // Don't gate the wrapper itself — just the operation. Adopters\n // commonly cache `const docs = elev.collection('docs')` and the\n // lazy-check still works correctly because assertActive runs at\n // every `put` call, against a fresh `Date.now()`.\n return {\n // #779 — surface `_elevatedPut`'s `TierMoveResult` (searchResidue) instead of\n // discarding it, so a stuck search compensation on this convenience path is\n // observable by the caller, mirroring `putAtTier`'s direct-call parity (#774).\n put: async (id: string, record: T): Promise<TierMoveResult> => {\n this.assertActive()\n return await this.vault._elevatedPut<T>(name, id, record, this.tier, this.reason)\n },\n }\n }\n\n /**\n * Manually revert the elevation. Idempotent — calling twice (or\n * after the TTL expired) is a safe no-op. The vault's\n * active-elevation slot is cleared so a subsequent\n * `vault.elevate(...)` succeeds without throwing\n * {@link AlreadyElevatedError}.\n */\n async release(): Promise<void> {\n if (this.released) return\n this.released = true\n this.onRelease()\n }\n\n private assertActive(): void {\n if (this.released) {\n throw new ElevationExpiredError({ tier: this.tier, expiresAt: this.expiresAt })\n }\n if (Date.now() > this.expiresAt) {\n // Auto-release on first use past TTL so the vault's active\n // slot frees up without requiring the caller to think about\n // explicit release on expiry.\n this.released = true\n this.onRelease()\n throw new ElevationExpiredError({ tier: this.tier, expiresAt: this.expiresAt })\n }\n }\n}\n","/**\n * Record cold-storage archival engine.\n *\n * Archival relocates a sealed record's **encrypted envelope** from the\n * primary store to a cold archive store — no re-encryption, the envelope\n * is opaque ciphertext. Because relocation goes through low-level store\n * ops (and the collection's `_internalDelete`), it bypasses guards (an\n * issued/immutable record can still be archived) and never fires\n * materialized-view dispatch (finalized aggregates over a sealed period\n * don't recompute). The archive store's contents are themselves the\n * archived-set index — `listArchived` lists it; `restore` relocates an\n * envelope back to the primary store.\n *\n * A `legalHold` predicate blocks archival; `archiveWhen` (typically\n * derived from the record's fiscal period / business date) selects\n * eligible records.\n */\n\nimport type { NoydbStore, EncryptedEnvelope } from '../../kernel/types.js'\n\nexport interface ArchivePolicy<T = unknown> {\n /** Select records eligible for archival — typically a business-date / period test. */\n readonly archiveWhen: (record: T) => boolean\n /** Block archival while true (litigation / audit hold). Fail-closed on throw. */\n readonly legalHold?: (record: T) => boolean\n}\n\nexport interface ArchiveResult {\n /** Records relocated to the archive store. */\n readonly archived: number\n /** Records eligible by `archiveWhen` but retained by a `legalHold`. */\n readonly held: number\n /** Records scanned across policy collections. */\n readonly scanned: number\n readonly byCollection: Record<string, { archived: number; held: number }>\n}\n\nexport interface ArchiveRunOptions {\n /** Stop after this many archivals. `undefined` = unbounded. */\n readonly maxArchives?: number\n /** Preview without relocating. */\n readonly dryRun?: boolean\n}\n\n/**\n * Everything the engine needs from the Vault, injected so the engine\n * stays unit-testable without a live vault.\n */\nexport interface ArchiveContext {\n readonly vaultId: string\n readonly archiveStore: NoydbStore\n /** Collections that declared an `archive` policy. */\n collectionsWithPolicy(): readonly string[]\n getPolicy(collection: string): ArchivePolicy | null\n listRecordIds(collection: string): Promise<readonly string[]>\n /** Decrypted record for policy evaluation, or null if unreadable. */\n getRecord(collection: string, id: string): Promise<Record<string, unknown> | null>\n /** Raw encrypted envelope from the primary store. */\n getEnvelope(collection: string, id: string): Promise<EncryptedEnvelope | null>\n /** Remove from the primary store + cache, bypassing guards/MV (`_internalDelete`). */\n removeFromPrimary(collection: string, id: string): Promise<void>\n /** Write an envelope back to the primary store + refresh cache. */\n restoreToPrimary(collection: string, id: string, env: EncryptedEnvelope): Promise<void>\n}\n\nfunction isHeld<T>(policy: ArchivePolicy<T>, record: T): boolean {\n if (!policy.legalHold) return false\n try {\n return policy.legalHold(record)\n } catch {\n return true // fail-closed: a throwing hold predicate retains the record\n }\n}\n\n/** Sweep eligible records into the archive store. */\nexport async function runArchive(ctx: ArchiveContext, options: ArchiveRunOptions = {}): Promise<ArchiveResult> {\n const maxArchives = options.maxArchives ?? Infinity\n const dryRun = options.dryRun === true\n let archived = 0\n let held = 0\n let scanned = 0\n const byCollection: Record<string, { archived: number; held: number }> = {}\n\n outer: for (const collection of ctx.collectionsWithPolicy()) {\n const policy = ctx.getPolicy(collection)\n if (!policy) continue\n byCollection[collection] = { archived: 0, held: 0 }\n for (const id of await ctx.listRecordIds(collection)) {\n if (archived >= maxArchives) break outer\n const record = await ctx.getRecord(collection, id).catch(() => null)\n if (record === null) continue\n scanned += 1\n let eligible = false\n try {\n eligible = policy.archiveWhen(record)\n } catch {\n eligible = false // fail-closed: don't archive on predicate error\n }\n if (!eligible) continue\n if (isHeld(policy, record)) {\n held += 1\n byCollection[collection].held += 1\n continue\n }\n if (!dryRun) {\n const env = await ctx.getEnvelope(collection, id)\n if (!env) continue\n await ctx.archiveStore.put(ctx.vaultId, collection, id, env)\n await ctx.removeFromPrimary(collection, id)\n }\n archived += 1\n byCollection[collection].archived += 1\n }\n }\n\n return { archived, held, scanned, byCollection }\n}\n\n/** Relocate one archived record back to the primary store. Returns false if not archived. */\nexport async function runRestore(ctx: ArchiveContext, collection: string, id: string): Promise<boolean> {\n const env = await ctx.archiveStore.get(ctx.vaultId, collection, id)\n if (!env) return false\n await ctx.restoreToPrimary(collection, id, env)\n await ctx.archiveStore.delete(ctx.vaultId, collection, id)\n return true\n}\n\n/** List archived record ids for a collection (or all policy collections). */\nexport async function runListArchived(\n ctx: ArchiveContext,\n collection?: string,\n): Promise<Array<{ collection: string; id: string }>> {\n const collections = collection ? [collection] : ctx.collectionsWithPolicy()\n const out: Array<{ collection: string; id: string }> = []\n for (const c of collections) {\n const ids = await ctx.archiveStore.list(ctx.vaultId, c)\n for (const id of ids) out.push({ collection: c, id })\n }\n return out\n}\n","/**\n * `@noy-db/hub` record cold-storage archival service.\n *\n * `withArchive({ store })` designates a cold {@link NoydbStore} as the\n * archive target. Declare a per-collection `archive` policy, then call\n * `vault.archive()` to relocate eligible sealed records there,\n * `vault.restore(collection, id)` to pull one back, and\n * `vault.listArchived()` to enumerate the cold set.\n *\n * @see ./engine for the relocation logic.\n */\n\nimport type { NoydbStore } from '../../kernel/types.js'\n\nexport interface WithArchiveOptions {\n /** The cold store that holds archived record envelopes. */\n store: NoydbStore\n}\n\nexport interface ArchiveStrategy {\n readonly store: NoydbStore\n}\n\n/** Enable record cold-storage archival against the given cold store. */\nexport function withArchive(opts: WithArchiveOptions): ArchiveStrategy {\n return { store: opts.store }\n}\n\nexport type {\n ArchivePolicy,\n ArchiveResult,\n ArchiveRunOptions,\n ArchiveContext,\n} from './engine.js'\nexport { runArchive, runRestore, runListArchived } from './engine.js'\n","/**\n * @category capability\n * Deferred numbering engine — store-clock-ordered, gap-free serials assigned\n * at an explicit numbering pass. See the design spec.\n */\nimport type { NoydbStore, EncryptedEnvelope, StoreTime } from '../../kernel/types.js'\nimport { NOYDB_FORMAT_VERSION } from '../../kernel/types.js'\nimport { encrypt, openEnvelopeJson, type EnclaveKey } from '../../kernel/enclave/index.js'\nimport { isConflictError, NumberingUncertaintyError } from '../../kernel/errors.js'\nimport type { DeferredNumberingConfig } from './descriptor.js'\n\nexport const NUMBERING_HEAD_COLLECTION = '_numbering_head'\nexport const NUMBERING_PENDING_COLLECTION = '_numbering_pending'\n\ninterface PendingEntry {\n series: string\n recordId: string\n collection: string\n field: string\n storeEarliest: number\n storeLatest: number\n enqueuedAt: number\n}\ninterface NumberingHead { series: string; lastSerial: number; watermark: number }\nexport interface Assignment { recordId: string; serial: number }\n\ntype PendingPromise = { resolve: (n: number) => void; reject: (e: Error) => void }\n\nexport class DeferredNumberingStore {\n private readonly adapter: NoydbStore\n private readonly vault: string\n private readonly encrypted: boolean\n private readonly getDEK: (collectionName: string) => Promise<EnclaveKey>\n private readonly actor: string\n private readonly configs: Map<string, DeferredNumberingConfig>\n /**\n * Stamp a serial onto a USER record THROUGH the Collection layer (so the\n * cache, indexes, and MVs stay coherent — the engine must NOT write user\n * collections at the raw adapter level). Returns false if the record is\n * gone (the engine then skips it without burning a serial). Provided by the\n * vault; unit tests pass a Map-backed double.\n */\n private readonly stamp: (collection: string, recordId: string, field: string, serial: number) => Promise<boolean>\n /** In-process registry: `${series}::${recordId}` → resolver for the live next() Promise. */\n private readonly waiters = new Map<string, PendingPromise>()\n private readonly dekCache = new Map<string, Promise<EnclaveKey>>()\n\n constructor(opts: {\n adapter: NoydbStore\n vault: string\n encrypted: boolean\n getDEK: (collectionName: string) => Promise<EnclaveKey>\n actor: string\n configs: Map<string, DeferredNumberingConfig>\n stamp: (collection: string, recordId: string, field: string, serial: number) => Promise<boolean>\n }) {\n this.adapter = opts.adapter\n this.vault = opts.vault\n this.encrypted = opts.encrypted\n this.getDEK = opts.getDEK\n this.actor = opts.actor\n this.configs = opts.configs\n this.stamp = opts.stamp\n }\n\n has(series: string): boolean {\n return this.configs.has(series)\n }\n\n private dek(collection: string): Promise<EnclaveKey> {\n let p = this.dekCache.get(collection)\n if (!p) { p = this.getDEK(collection); this.dekCache.set(collection, p) }\n return p\n }\n\n private async readJson<T>(collection: string, id: string): Promise<{ env: EncryptedEnvelope | null; value: T | null }> {\n const env = await this.adapter.get(this.vault, collection, id)\n if (!env) return { env: null, value: null }\n const json = this.encrypted ? await openEnvelopeJson(env, await this.dek(collection)) : env._data\n return { env, value: JSON.parse(json) as T }\n }\n\n private async writeJson(collection: string, id: string, value: unknown, expectedVersion: number): Promise<void> {\n const json = JSON.stringify(value)\n let env: EncryptedEnvelope\n if (!this.encrypted) {\n env = { _noydb: NOYDB_FORMAT_VERSION, _v: expectedVersion + 1, _ts: new Date().toISOString(), _iv: '', _data: json, _by: this.actor }\n } else {\n const { iv, data } = await encrypt(json, await this.dek(collection))\n env = { _noydb: NOYDB_FORMAT_VERSION, _v: expectedVersion + 1, _ts: new Date().toISOString(), _iv: iv, _data: data, _by: this.actor }\n }\n await this.adapter.put(this.vault, collection, id, env, expectedVersion)\n }\n\n private pendingId(series: string, recordId: string): string {\n return `${series}::${recordId}`\n }\n\n /** Current last-assigned serial for a series (0 if none). */\n async peek(series: string): Promise<number> {\n const { value } = await this.readJson<NumberingHead>(NUMBERING_HEAD_COLLECTION, series)\n return value?.lastSerial ?? 0\n }\n\n /**\n * Enqueue a record for numbering: stamp it with the current store clock and\n * durably write a pending entry. The returned Promise resolves once the\n * record is durably enqueued; its `assigned` field resolves with the serial\n * at the next pass (the record's `field` is the durable source of truth —\n * `assigned` is an in-process convenience that a crash may drop).\n */\n async enqueue(series: string, recordId: string): Promise<{ assigned: Promise<number> }> {\n const cfg = this.configs.get(series)\n if (!cfg) throw new NumberingUncertaintyError(series)\n if (typeof this.adapter.getStoreTime !== 'function') throw new NumberingUncertaintyError(series)\n const st: StoreTime = await this.adapter.getStoreTime()\n const id = this.pendingId(series, recordId)\n const { env } = await this.readJson<PendingEntry>(NUMBERING_PENDING_COLLECTION, id)\n const entry: PendingEntry = {\n series, recordId, collection: cfg.collection, field: cfg.field,\n storeEarliest: st.earliest, storeLatest: st.latest, enqueuedAt: Date.now(),\n }\n await this.writeJson(NUMBERING_PENDING_COLLECTION, id, entry, env?._v ?? 0)\n const assigned = new Promise<number>((resolve, reject) => { this.waiters.set(id, { resolve, reject }) })\n return { assigned }\n }\n\n private async listPending(series: string): Promise<Array<{ id: string; entry: PendingEntry }>> {\n const ids = await this.adapter.list(this.vault, NUMBERING_PENDING_COLLECTION)\n const prefix = `${series}::`\n const out: Array<{ id: string; entry: PendingEntry }> = []\n for (const id of ids) {\n if (!id.startsWith(prefix)) continue\n const { value } = await this.readJson<PendingEntry>(NUMBERING_PENDING_COLLECTION, id)\n if (value) out.push({ id, entry: value })\n }\n return out\n }\n\n /**\n * Run a numbering pass for `series`: select entries provably settled\n * (`storeLatest ≤ now.earliest` — commit-wait), order by\n * `(storeEarliest, recordId)`, assign serials after the head, stamp each\n * record's field, advance the head with one CAS, and consume the entries.\n * Idempotent/convergent: a losing concurrent pass returns `[]` and the next\n * pass reconciles. Resolves any in-process enqueue() `assigned` Promises.\n */\n async runPass(series: string): Promise<Assignment[]> {\n const cfg = this.configs.get(series)\n if (!cfg) throw new NumberingUncertaintyError(series)\n if (typeof this.adapter.getStoreTime !== 'function') throw new NumberingUncertaintyError(series)\n\n const now = await this.adapter.getStoreTime()\n const settled = (await this.listPending(series))\n .filter(p => p.entry.storeLatest <= now.earliest) // commit-wait\n .sort((a, b) =>\n a.entry.storeEarliest - b.entry.storeEarliest ||\n (a.entry.recordId < b.entry.recordId ? -1 : a.entry.recordId > b.entry.recordId ? 1 : 0),\n )\n if (settled.length === 0) return []\n\n const { env: headEnv, value: head } = await this.readJson<NumberingHead>(NUMBERING_HEAD_COLLECTION, series)\n let serial = head?.lastSerial ?? 0\n const assignments: Assignment[] = []\n\n // Stamp each user record THROUGH the Collection layer (cache-coherent).\n for (const { entry } of settled) {\n serial += 1\n const ok = await this.stamp(entry.collection, entry.recordId, entry.field, serial)\n if (!ok) { serial -= 1; continue } // record gone — skip, do not burn a number\n assignments.push({ recordId: entry.recordId, serial })\n }\n\n // Advance the head with one CAS. On conflict another pass ran; bail — the\n // next pass reconciles (idempotent: consumed entries won't reappear).\n try {\n await this.writeJson(NUMBERING_HEAD_COLLECTION, series, { series, lastSerial: serial, watermark: now.earliest }, headEnv?._v ?? 0)\n } catch (err) {\n if (isConflictError(err)) return []\n throw err\n }\n\n // Consume pending entries + resolve in-process waiters.\n for (const { id, entry } of settled) {\n await this.adapter.delete(this.vault, NUMBERING_PENDING_COLLECTION, id)\n const a = assignments.find(x => x.recordId === entry.recordId)\n if (a) { this.waiters.get(id)?.resolve(a.serial); this.waiters.delete(id) }\n }\n return assignments\n }\n}\n","/**\n * Vault-side accounting-periods facade.\n *\n * Holds the period close/open/list/get entry points, the write-time guard\n * (`assertTsWritable`, called by the service gate bus before put/delete via\n * the thin `vault._assertTsWritable` delegator), and the period-record cache\n * (`periodCache`). Every `Vault` dependency arrives via\n * {@link VaultPeriodsDeps}.\n *\n * Internal service — reached through `vault.closePeriod(...)` etc.\n */\nimport { ValidationError } from '../../kernel/errors.js'\nimport { NOYDB_FORMAT_VERSION } from '../../kernel/types.js'\nimport { encrypt, openEnvelopeJson, type EnclaveKey } from '../../kernel/enclave/index.js'\nimport type { EncryptedEnvelope, NoydbStore } from '../../kernel/types.js'\nimport type { LedgerStore } from '../../with-commit/history/ledger/store.js'\nimport type { Collection } from '../../kernel/collection.js'\nimport type { PeriodsStrategy } from './strategy.js'\nimport {\n PERIODS_COLLECTION,\n PERIOD_FREEZES_COLLECTION,\n PERIOD_ARCHIVES_COLLECTION,\n PERIOD_TARGET_PURGES_COLLECTION,\n periodExclusiveUpperBound,\n type PeriodRecord,\n type PeriodFreezeRecord,\n type PeriodArchiveRecord,\n type PeriodTargetPurgeRecord,\n type TargetPurgeCount,\n type ClosePeriodOptions,\n type OpenPeriodOptions,\n} from './periods.js'\n\n/** Everything the moving period methods touched on the vault's `this.*`. */\nexport interface VaultPeriodsDeps {\n /** Resolved periods strategy (NO_PERIODS when not configured). */\n readonly strategy: PeriodsStrategy\n /** The ciphertext store. */\n readonly adapter: NoydbStore\n /** Vault namespace name. */\n readonly vault: string\n /** Whether records are encrypted (vs debug-plaintext). */\n readonly encrypted: boolean\n /** The invoking keyring's user id (read fresh per call). */\n userId(): string\n /** Per-collection DEK resolver (bound `vault.getDEK`). */\n getDEK(collection: string): Promise<EnclaveKey>\n /** The vault's ledger store, or null when history is off. */\n getLedgerOrNull(): LedgerStore | null\n /** Collection accessor (used by `openPeriod`'s carry-forward writes). */\n collection<T = unknown>(name: string): Collection<T>\n /** #604: physically purge delete markers with `_ts < before`. Bound to `vault._purgeDeleteMarkers`. */\n purgeDeleteMarkers(before: string): Promise<number>\n /** #613: relocate a closed period's in-window records hot → cold. Bound to `vault._archiveClosedPeriod`. */\n archiveRecords(before: string): Promise<number>\n /** #615: sweep delete markers off the vault's push-only sync targets. Bound to `vault._purgePeriodTargets`. */\n purgeTargets(before: string): Promise<readonly TargetPurgeCount[]>\n /**\n * #822: mark a reserved-collection write dirty so the sync engine pushes\n * it. Bound to the vault's `onDirty` when sync is configured, `undefined`\n * otherwise. Only `_periods` uses it — see `writeReserved`.\n */\n onDirty?: ((collection: string, id: string, action: 'put', version: number) => Promise<void>) | undefined\n}\n\nexport class VaultPeriods {\n /**\n * Loaded period records, lazily populated on first close/open/list/get/guard\n * and kept in sync by the write paths. `null` until first touched — the\n * write-guard fast-path avoids a full adapter scan for vaults that never use\n * periods.\n */\n private periodCache: PeriodRecord[] | null = null\n\n constructor(private readonly deps: VaultPeriodsDeps) {}\n\n async closePeriod(options: ClosePeriodOptions): Promise<PeriodRecord> {\n const existing = await this.loadPeriodsCache()\n this.deps.strategy.validatePeriodName(options.name, existing)\n if (typeof options.endDate !== 'string' || options.endDate.length === 0) {\n throw new ValidationError('closePeriod: endDate must be a non-empty ISO string.')\n }\n const anchor = await this.deps.strategy.chainAnchor(existing)\n const record: PeriodRecord = {\n name: options.name,\n kind: 'closed',\n endDate: options.endDate,\n closedAt: new Date().toISOString(),\n closedBy: this.deps.userId(),\n priorPeriodHash: anchor.priorPeriodHash,\n ...(anchor.priorPeriodName !== undefined && { priorPeriodName: anchor.priorPeriodName }),\n ...(options.dateField !== undefined && { dateField: options.dateField }),\n }\n const envelope = await this.writeReserved(PERIODS_COLLECTION, record.name, record)\n await this.deps.strategy.appendPeriodLedgerEntry(this.deps.getLedgerOrNull(), this.deps.userId(), envelope, record.name)\n existing.push(record)\n this.periodCache = existing\n return record\n }\n\n async openPeriod<TCollections extends Record<string, Record<string, unknown>>>(\n options: OpenPeriodOptions<TCollections>,\n ): Promise<PeriodRecord> {\n const existing = await this.loadPeriodsCache()\n this.deps.strategy.validatePeriodName(options.name, existing)\n const prior = existing.find((p) => p.name === options.fromPeriod)\n if (!prior) {\n throw new ValidationError(\n `openPeriod: fromPeriod \"${options.fromPeriod}\" does not exist in this vault.`,\n )\n }\n if (prior.kind !== 'closed') {\n throw new ValidationError(\n `openPeriod: fromPeriod \"${options.fromPeriod}\" is of kind \"${prior.kind}\" — only closed periods can be carried forward.`,\n )\n }\n\n // Build a read-only facade over CURRENT state + the prior\n // period's endDate; after close, records dated <= endDate are\n // frozen so current state equals closing state. The caller\n // filters by business date via their own query against this\n // facade.\n const ctx = {\n priorEndDate: prior.endDate,\n collection: <T = unknown>(name: string) => {\n const c = this.deps.collection<T>(name)\n return {\n get: (id: string) => c.get(id),\n list: () => c.list(),\n }\n },\n }\n const openings = await options.carryForward(ctx)\n\n // Write opening entries via the normal Collection path so they\n // get encryption, ledger entries, and change events. Each record\n // is timestamped NOW (outside every closed period) — that's why\n // the guard permits them.\n const openingCollections: string[] = []\n for (const [collName, records] of Object.entries(openings)) {\n if (!records || typeof records !== 'object') continue\n const recordEntries = Object.entries(records)\n if (recordEntries.length === 0) continue\n const coll = this.deps.collection(collName)\n for (const [id, record] of recordEntries) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n await coll.put(id, record as any)\n }\n openingCollections.push(collName)\n }\n\n const anchor = await this.deps.strategy.chainAnchor(existing)\n const record: PeriodRecord = {\n name: options.name,\n kind: 'opened',\n startDate: options.startDate,\n endDate: prior.endDate, // sealing boundary inherited from prior close\n closedAt: new Date().toISOString(),\n closedBy: this.deps.userId(),\n priorPeriodHash: anchor.priorPeriodHash,\n priorPeriodName: anchor.priorPeriodName ?? prior.name,\n ...(openingCollections.length > 0 && { openingCollections }),\n }\n const envelope = await this.writeReserved(PERIODS_COLLECTION, record.name, record)\n await this.deps.strategy.appendPeriodLedgerEntry(this.deps.getLedgerOrNull(), this.deps.userId(), envelope, record.name)\n existing.push(record)\n this.periodCache = existing\n return record\n }\n\n /**\n * Freeze a closed period: physically purges delete markers whose `_ts`\n * falls inside the period's window (#604) and records the fact in a\n * companion `_period_freezes/<name>` record. NEVER mutates the\n * hash-chained `_periods/<name>` record's stored bytes — `frozenAt` /\n * `frozenBy` / `purgedMarkerCount` are merged into `PeriodRecord`s on\n * read only. Idempotent: a second call is a no-op that returns the\n * same merged record without re-purging or re-appending a ledger entry.\n */\n async freezePeriod(name: string): Promise<PeriodRecord> {\n const existing = await this.loadPeriodsCache()\n const period = existing.find((p) => p.name === name)\n if (!period) throw new ValidationError(`freezePeriod: no period named \"${name}\".`)\n if (period.kind !== 'closed') {\n throw new ValidationError(\n `freezePeriod: period \"${name}\" is \"${period.kind}\"; only a closed period can be frozen.`,\n )\n }\n // #610: refuse a period whose purge window reaches into the future. Markers\n // are bounded by write-time `_ts`, so a not-yet-elapsed window would purge\n // deletes written seconds ago that cannot have converged to any peer.\n const before = periodExclusiveUpperBound(period.endDate)\n if (Date.parse(before) > Date.now()) {\n throw new ValidationError(\n `freezePeriod: period \"${name}\" purge window ends at ${before}, in the future; ` +\n `only a period whose window is fully in the past can be frozen (recent delete markers may not have converged).`,\n )\n }\n const prior = await this.readReserved<PeriodFreezeRecord>(PERIOD_FREEZES_COLLECTION, name)\n if (prior) return this.mergeFreeze(period, prior) // idempotent no-op\n\n const purgedMarkerCount = await this.deps.purgeDeleteMarkers(before)\n const freeze: PeriodFreezeRecord = {\n period: name,\n frozenAt: new Date().toISOString(),\n frozenBy: this.deps.userId(),\n purgedMarkerCount,\n }\n const envelope = await this.writeReserved(PERIOD_FREEZES_COLLECTION, name, freeze)\n await this.deps.strategy.appendPeriodLedgerEntry(\n this.deps.getLedgerOrNull(),\n this.deps.userId(),\n envelope,\n name,\n PERIOD_FREEZES_COLLECTION,\n )\n return this.mergeFreeze(period, freeze)\n }\n\n /**\n * Archive a closed period (#613): physically relocates its in-window\n * records (those with `_ts < periodExclusiveUpperBound(endDate)`) from the\n * hot store to the configured cold tier via `archiveRecords`, and records\n * the fact in a companion `_period_archives/<name>` record. NEVER mutates\n * the hash-chained `_periods/<name>` record. Non-destructive (reads fall\n * through to cold) and idempotent: a second call is a no-op returning the\n * same merged record.\n */\n async archivePeriod(name: string): Promise<PeriodRecord> {\n const existing = await this.loadPeriodsCache()\n const period = existing.find((p) => p.name === name)\n if (!period) throw new ValidationError(`archivePeriod: no period named \"${name}\".`)\n if (period.kind !== 'closed') {\n throw new ValidationError(\n `archivePeriod: period \"${name}\" is \"${period.kind}\"; only a closed period can be archived.`,\n )\n }\n const prior = await this.readReserved<PeriodArchiveRecord>(PERIOD_ARCHIVES_COLLECTION, name)\n if (prior) return this.mergeArchive(period, prior) // idempotent no-op\n\n const before = periodExclusiveUpperBound(period.endDate)\n const archivedRecordCount = await this.deps.archiveRecords(before)\n const archive: PeriodArchiveRecord = {\n period: name,\n archivedAt: new Date().toISOString(),\n archivedBy: this.deps.userId(),\n archivedRecordCount,\n }\n const envelope = await this.writeReserved(PERIOD_ARCHIVES_COLLECTION, name, archive)\n await this.deps.strategy.appendPeriodLedgerEntry(\n this.deps.getLedgerOrNull(),\n this.deps.userId(),\n envelope,\n name,\n PERIOD_ARCHIVES_COLLECTION,\n )\n return this.mergeArchive(period, archive)\n }\n\n /**\n * Target-purge a closed period (#615): sweeps delete markers off the vault's\n * PUSH-ONLY sync targets (`backup`/`archive`) via `purgeTargets`, recording a\n * companion `_period_target_purges/<name>` record. `sync-peer` targets are\n * skipped (resurrection risk). NEVER mutates the chained `_periods/<name>`\n * record. Requires the period be frozen first (closed → frozen → target-purged).\n * Idempotent once run; with no push-only targets it writes no companion and\n * is re-runnable.\n */\n async purgePeriodTargets(name: string): Promise<PeriodRecord> {\n const existing = await this.loadPeriodsCache()\n const period = existing.find((p) => p.name === name)\n if (!period) throw new ValidationError(`purgePeriodTargets: no period named \"${name}\".`)\n if (period.kind !== 'closed') {\n throw new ValidationError(\n `purgePeriodTargets: period \"${name}\" is \"${period.kind}\"; only a closed period can be target-purged.`,\n )\n }\n const frozen = await this.readReserved<PeriodFreezeRecord>(PERIOD_FREEZES_COLLECTION, name)\n if (!frozen) {\n throw new ValidationError(\n `purgePeriodTargets: period \"${name}\" must be frozen first (closed → frozen → target-purged).`,\n )\n }\n const prior = await this.readReserved<PeriodTargetPurgeRecord>(PERIOD_TARGET_PURGES_COLLECTION, name)\n if (prior) return this.mergeTargetPurge(period, prior) // idempotent no-op\n\n const before = periodExclusiveUpperBound(period.endDate)\n const targets = await this.deps.purgeTargets(before)\n if (targets.length === 0) return period // no push-only targets → no companion, re-runnable\n\n const record: PeriodTargetPurgeRecord = {\n period: name,\n purgedAt: new Date().toISOString(),\n purgedBy: this.deps.userId(),\n targets,\n }\n const envelope = await this.writeReserved(PERIOD_TARGET_PURGES_COLLECTION, name, record)\n await this.deps.strategy.appendPeriodLedgerEntry(\n this.deps.getLedgerOrNull(),\n this.deps.userId(),\n envelope,\n name,\n PERIOD_TARGET_PURGES_COLLECTION,\n )\n return this.mergeTargetPurge(period, record)\n }\n\n /** Merge target-purge companion fields into a fresh `PeriodRecord` copy — never mutates `periodCache`. */\n private mergeTargetPurge(period: PeriodRecord, record: PeriodTargetPurgeRecord): PeriodRecord {\n return {\n ...period,\n targetsPurgedAt: record.purgedAt,\n targetsPurgedBy: record.purgedBy,\n targetsPurged: record.targets,\n }\n }\n\n /** Merge archive companion fields into a fresh `PeriodRecord` copy — never mutates `periodCache`. */\n private mergeArchive(period: PeriodRecord, archive: PeriodArchiveRecord): PeriodRecord {\n return {\n ...period,\n archivedAt: archive.archivedAt,\n archivedBy: archive.archivedBy,\n archivedRecordCount: archive.archivedRecordCount,\n }\n }\n\n /** Merge freeze companion fields into a fresh `PeriodRecord` copy — never mutates `periodCache`. */\n private mergeFreeze(period: PeriodRecord, freeze: PeriodFreezeRecord): PeriodRecord {\n return {\n ...period,\n frozenAt: freeze.frozenAt,\n frozenBy: freeze.frozenBy,\n purgedMarkerCount: freeze.purgedMarkerCount,\n }\n }\n\n /** Return every closed / opened period in `closedAt` order, merged with any freeze + archive companions. */\n async listPeriods(): Promise<readonly PeriodRecord[]> {\n // #807: always re-read `_periods` from the adapter — a period-scoped pull\n // applies freshly synced period envelopes UNDERNEATH this cache, then\n // resolves its windows through this very method (the engine's\n // PeriodPullSource). Repopulating the shared cache here also refreshes the\n // write guard's view, so a pulled closure seals writes without a reopen.\n // (The companions below were already re-read fresh on every call.)\n this.periodCache = null\n const all = await this.loadPeriodsCache()\n const freezeIds = await this.deps.adapter.list(this.deps.vault, PERIOD_FREEZES_COLLECTION)\n const freezes = new Map<string, PeriodFreezeRecord>()\n for (const id of freezeIds) {\n const f = await this.readReserved<PeriodFreezeRecord>(PERIOD_FREEZES_COLLECTION, id)\n if (f) freezes.set(f.period, f)\n }\n const archiveIds = await this.deps.adapter.list(this.deps.vault, PERIOD_ARCHIVES_COLLECTION)\n const archives = new Map<string, PeriodArchiveRecord>()\n for (const id of archiveIds) {\n const a = await this.readReserved<PeriodArchiveRecord>(PERIOD_ARCHIVES_COLLECTION, id)\n if (a) archives.set(a.period, a)\n }\n const targetPurgeIds = await this.deps.adapter.list(this.deps.vault, PERIOD_TARGET_PURGES_COLLECTION)\n const targetPurges = new Map<string, PeriodTargetPurgeRecord>()\n for (const id of targetPurgeIds) {\n const tp = await this.readReserved<PeriodTargetPurgeRecord>(PERIOD_TARGET_PURGES_COLLECTION, id)\n if (tp) targetPurges.set(tp.period, tp)\n }\n return all.map((p) => {\n const f = freezes.get(p.name)\n let merged = f ? this.mergeFreeze(p, f) : p\n const a = archives.get(p.name)\n if (a) merged = this.mergeArchive(merged, a)\n const tp = targetPurges.get(p.name)\n if (tp) merged = this.mergeTargetPurge(merged, tp)\n return merged\n })\n }\n\n /** Look up a single period by name, merged with its freeze + archive + target-purge companions if any. Returns `null` if not found. */\n async getPeriod(name: string): Promise<PeriodRecord | null> {\n const all = await this.loadPeriodsCache()\n const period = all.find((p) => p.name === name)\n if (!period) return null\n const freeze = await this.readReserved<PeriodFreezeRecord>(PERIOD_FREEZES_COLLECTION, name)\n const archive = await this.readReserved<PeriodArchiveRecord>(PERIOD_ARCHIVES_COLLECTION, name)\n let merged = freeze ? this.mergeFreeze(period, freeze) : period\n if (archive) merged = this.mergeArchive(merged, archive)\n const targetPurge = await this.readReserved<PeriodTargetPurgeRecord>(PERIOD_TARGET_PURGES_COLLECTION, name)\n if (targetPurge) merged = this.mergeTargetPurge(merged, targetPurge)\n return merged\n }\n\n /** Called by the gate bus before put/delete. */\n async assertTsWritable(\n existing: { ts: string | null; record: Record<string, unknown> | null } | null,\n incoming: Record<string, unknown> | null,\n ): Promise<void> {\n // Fast path: nothing to check, and no periods ever touched this\n // vault — avoid a full adapter scan for every put.\n if (existing === null && incoming === null) return\n if (this.periodCache === null) {\n this.periodCache = await this.deps.strategy.loadPeriods(\n this.deps.adapter,\n this.deps.vault,\n (env) => this.decryptPeriodRecord(env),\n )\n }\n if (this.periodCache.length === 0) return\n this.deps.strategy.assertTsWritable(existing, incoming, this.periodCache)\n }\n\n private async loadPeriodsCache(): Promise<PeriodRecord[]> {\n if (this.periodCache !== null) return this.periodCache\n const loaded = await this.deps.strategy.loadPeriods(\n this.deps.adapter,\n this.deps.vault,\n (env: EncryptedEnvelope) => this.decryptPeriodRecord(env),\n )\n this.periodCache = loaded\n return loaded\n }\n\n /** Generic reserved-collection writer — serves `_periods` and `_period_freezes` alike. */\n private async writeReserved(collection: string, key: string, value: object): Promise<EncryptedEnvelope> {\n const json = JSON.stringify(value)\n let envelope: EncryptedEnvelope\n if (this.deps.encrypted) {\n const dek = await this.deps.getDEK(collection)\n const { iv, data } = await encrypt(json, dek)\n envelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: 1,\n _ts: new Date().toISOString(),\n _iv: iv,\n _data: data,\n _by: this.deps.userId(),\n }\n } else {\n envelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: 1,\n _ts: new Date().toISOString(),\n _iv: '',\n _data: json,\n _by: this.deps.userId(),\n }\n }\n await this.deps.adapter.put(this.deps.vault, collection, key, envelope)\n // #822: the period summaries are vault-wide state — period-scoped pull\n // (#807) treats `_periods` as always-sync precisely because it is the\n // navigation index a thin client needs first. Pull symmetry without push\n // symmetry meant a closure never left the device that made it. The other\n // reserved collections deliberately stay local: freezes are marker-\n // convergence state (#589/#590 territory), archives record a per-\n // deployment hot→cold relocation, and target-purges describe the very\n // targets they would be pushed to.\n if (collection === PERIODS_COLLECTION && this.deps.onDirty) {\n await this.deps.onDirty(collection, key, 'put', envelope._v)\n }\n return envelope\n }\n\n /** Generic reserved-collection reader — serves `_period_freezes` companion reads. */\n private async readReserved<T>(collection: string, key: string): Promise<T | null> {\n const env = await this.deps.adapter.get(this.deps.vault, collection, key)\n if (!env) return null\n const json = this.deps.encrypted ? await openEnvelopeJson(env, await this.deps.getDEK(collection)) : env._data\n return JSON.parse(json) as T\n }\n\n private async decryptPeriodRecord(envelope: EncryptedEnvelope): Promise<PeriodRecord> {\n let json: string\n if (this.deps.encrypted) {\n const dek = await this.deps.getDEK(PERIODS_COLLECTION)\n json = await openEnvelopeJson(envelope, dek)\n } else {\n json = envelope._data\n }\n return JSON.parse(json) as PeriodRecord\n }\n}\n","/**\n * Foreign-key references — the soft-FK mechanism.\n *\n * A collection declares its references as metadata at construction\n * time:\n *\n * ```ts\n * import { ref } from '@noy-db/hub'\n *\n * const invoices = company.collection<Invoice>('invoices', {\n * refs: {\n * clientId: ref('clients'), // default: strict\n * categoryId: ref('categories', 'warn'),\n * parentId: ref('invoices', 'cascade'), // self-reference OK\n * },\n * })\n * ```\n *\n * Three modes:\n *\n * - **strict** — the default. `put()` rejects records whose\n * reference target doesn't exist, and `delete()` of the target\n * rejects if any strict-referencing records still exist.\n * Matches SQL's default FK semantics.\n *\n * - **warn** — both operations succeed unconditionally. Broken\n * references surface only through\n * `vault.checkIntegrity()`, which walks every collection\n * and reports orphans. Use when you want soft validation for\n * imports from messy sources.\n *\n * - **cascade** — `put()` is same as warn. `delete()` of the\n * target deletes every referencing record. Cycles are detected\n * and broken via an in-progress set, so mutual cascades\n * terminate instead of recursing forever.\n *\n * Cross-vault refs are explicitly rejected: if the target\n * name contains a `/`, `ref()` throws `RefScopeError`. Cross-\n * vault refs need an auth story (multi-keyring reads) that\n * doesn't ship — tracked for.\n */\n\nimport { NoydbError } from './errors.js'\n\n/** The three enforcement modes. Default for new refs is `'strict'`. */\nexport type RefMode = 'strict' | 'warn' | 'cascade'\n\n/**\n * Descriptor returned by `ref()`. Collections accept a\n * `Record<string, RefDescriptor>` in their options. The key is the\n * field name on the record (top-level only — dotted paths are out of\n * scope), the value describes which target collection the\n * field references and under what mode.\n *\n * The descriptor carries only plain data so it can be serialized,\n * passed around, and introspected without any class machinery.\n */\nexport interface RefDescriptor {\n readonly target: string\n readonly mode: RefMode\n /**\n * Present and `true` only for an array ref (`refArray()`): the\n * field holds an ARRAY of ids, each validated against `target`\n * independently (M:N). Absent for a scalar `ref()`. The same `mode`\n * semantics apply per element — strict rejects on a missing element at\n * put + blocks delete of a referenced target; cascade deletes every\n * record whose array contains the deleted id; warn surfaces orphans\n * only via `checkIntegrity()`.\n */\n readonly isArray?: true\n}\n\n/** Runtime predicate: is this an array ref (`refArray()`) vs a scalar `ref()`? */\nexport function isRefArray(desc: RefDescriptor): boolean {\n return desc.isArray === true\n}\n\n/**\n * Thrown when a strict reference is violated — either `put()` with a\n * missing target id, or `delete()` of a target that still has\n * strict-referencing records.\n *\n * Carries structured detail so UI code (and a potential future\n * devtools panel) can render \"client X cannot be deleted because\n * invoices 1, 2, and 3 reference it\" instead of a bare error string.\n */\nexport class RefIntegrityError extends NoydbError {\n readonly collection: string\n readonly id: string\n readonly field: string\n readonly refTo: string\n readonly refId: string | null\n\n constructor(opts: {\n collection: string\n id: string\n field: string\n refTo: string\n refId: string | null\n message: string\n }) {\n super('REF_INTEGRITY', opts.message)\n this.name = 'RefIntegrityError'\n this.collection = opts.collection\n this.id = opts.id\n this.field = opts.field\n this.refTo = opts.refTo\n this.refId = opts.refId\n }\n}\n\n/**\n * Thrown when `ref()` is called with a target name that looks like\n * a cross-vault reference (contains a `/`). Separate error\n * class because the fix is different: RefIntegrityError means \"data\n * is wrong\"; RefScopeError means \"the ref declaration is wrong\".\n */\nexport class RefScopeError extends NoydbError {\n constructor(target: string) {\n super(\n 'REF_SCOPE',\n `Cross-vault references are not supported in — got target \"${target}\". ` +\n `Use a simple collection name (e.g. \"clients\"), not a path. ` +\n `Cross-vault refs are tracked for a future release.`,\n )\n this.name = 'RefScopeError'\n }\n}\n\n/**\n * Helper constructor. Thin wrapper around the object literal so user\n * code reads like `ref('clients')` instead of `{ target: 'clients',\n * mode: 'strict' }` — this is the only ergonomics reason it exists.\n *\n * Validates the target name eagerly so a misconfigured ref declaration\n * fails at collection construction time, not at the first put.\n */\nexport function ref(target: string, mode: RefMode = 'strict'): RefDescriptor {\n if (target.includes('/')) {\n throw new RefScopeError(target)\n }\n if (!target || target.startsWith('_')) {\n throw new Error(\n `ref(): target collection name must be non-empty and cannot start with '_' (reserved for internal collections). Got \"${target}\".`,\n )\n }\n return { target, mode }\n}\n\n/**\n * Array reference — the many-to-many soft-FK. The field holds an\n * array of ids; each element is validated against `target` independently.\n *\n * ```ts\n * const orders = company.collection<Order>('orders', {\n * refs: { productIds: refArray('products', 'warn') },\n * })\n * ```\n *\n * Same three `mode` semantics as `ref()`, applied per element:\n * - **strict** — `put()` rejects if ANY element's target is missing;\n * `delete()` of a target is blocked while any record's array still\n * contains its id.\n * - **warn** — both succeed; orphaned elements surface via\n * `vault.checkIntegrity()` (one violation per dangling element).\n * - **cascade** — `delete()` of a target deletes every record whose\n * array contains its id (cycle-safe, like scalar cascade).\n *\n * A `null`/`undefined` field is allowed (no links). Non-array values, or\n * non-string/number elements, are an integrity error. Cross-vault targets\n * are rejected exactly as in `ref()`.\n */\nexport function refArray(target: string, mode: RefMode = 'strict'): RefDescriptor {\n if (target.includes('/')) {\n throw new RefScopeError(target)\n }\n if (!target || target.startsWith('_')) {\n throw new Error(\n `refArray(): target collection name must be non-empty and cannot start with '_' (reserved for internal collections). Got \"${target}\".`,\n )\n }\n return { target, mode, isArray: true }\n}\n\n/**\n * Per-vault registry of reference declarations.\n *\n * The registry is populated by `Collection` constructors (which pass\n * their `refs` option through the Vault) and consulted by the\n * Vault on every `put` / `delete` and by `checkIntegrity`. A\n * single instance lives on the Vault for its lifetime; there's\n * no global state.\n *\n * The data structure is two parallel maps:\n *\n * - `outbound`: `collection → { field → RefDescriptor }` — what\n * refs does `collection` declare? Used on put to check\n * strict-target-exists and on checkIntegrity to walk each\n * collection's outbound refs.\n *\n * - `inbound`: `target → Array<{ collection, field, mode }>` —\n * which collections reference `target`? Used on delete to find\n * the records that might be affected by cascade / strict.\n *\n * The two views are kept in sync by `register()` and never mutated\n * otherwise — refs can't be unregistered at runtime in.\n */\nexport class RefRegistry {\n private readonly outbound = new Map<string, Record<string, RefDescriptor>>()\n private readonly inbound = new Map<\n string,\n Array<{ collection: string; field: string; mode: RefMode; isArray?: true }>\n >()\n\n /**\n * Register the refs declared by a single collection. Idempotent in\n * the happy path — calling twice with the same data is a no-op.\n * Calling twice with DIFFERENT data throws, because silent\n * overrides would be confusing (\"I changed the ref and it doesn't\n * update\" vs \"I declared the same collection twice with different\n * refs and the second call won\").\n */\n register(collection: string, refs: Record<string, RefDescriptor>): void {\n const existing = this.outbound.get(collection)\n if (existing) {\n // Compare shallowly — if any field disagrees, reject.\n const existingKeys = Object.keys(existing).sort()\n const newKeys = Object.keys(refs).sort()\n if (existingKeys.join(',') !== newKeys.join(',')) {\n throw new Error(\n `RefRegistry: conflicting ref declarations for collection \"${collection}\"`,\n )\n }\n for (const k of existingKeys) {\n const a = existing[k]\n const b = refs[k]\n if (!a || !b || a.target !== b.target || a.mode !== b.mode || a.isArray !== b.isArray) {\n throw new Error(\n `RefRegistry: conflicting ref declarations for collection \"${collection}\" field \"${k}\"`,\n )\n }\n }\n return\n }\n this.outbound.set(collection, { ...refs })\n for (const [field, desc] of Object.entries(refs)) {\n const list = this.inbound.get(desc.target) ?? []\n list.push({ collection, field, mode: desc.mode, ...(desc.isArray ? { isArray: true } : {}) })\n this.inbound.set(desc.target, list)\n }\n }\n\n /** Get the outbound refs declared by a collection (or `{}` if none). */\n getOutbound(collection: string): Record<string, RefDescriptor> {\n return this.outbound.get(collection) ?? {}\n }\n\n /** Get the inbound refs that target a given collection (or `[]`). */\n getInbound(\n target: string,\n ): ReadonlyArray<{ collection: string; field: string; mode: RefMode; isArray?: true }> {\n return this.inbound.get(target) ?? []\n }\n\n /**\n * Iterate every (collection → refs) pair that has at least one\n * declared reference. Used by `checkIntegrity` to walk the full\n * universe of outbound refs without needing to track collection\n * names elsewhere.\n */\n entries(): Array<[string, Record<string, RefDescriptor>]> {\n return [...this.outbound.entries()]\n }\n\n /** Clear the registry. Test-only escape hatch; never called from production code. */\n clear(): void {\n this.outbound.clear()\n this.inbound.clear()\n }\n}\n\n/**\n * Shape of a single violation reported by `vault.checkIntegrity()`.\n *\n * `refId` is the value we saw in the referencing field — it's the\n * ID we expected to find in `refTo`, but didn't. Left as `unknown`\n * because records are loosely typed at the integrity-check layer.\n */\nexport interface RefViolation {\n readonly collection: string\n readonly id: string\n readonly field: string\n readonly refTo: string\n readonly refId: unknown\n readonly mode: RefMode\n}\n","/**\n * Vault-side refs / managed-links enforcement facade.\n *\n * Holds the foreign-key enforcement entry points the collection write path\n * reaches through the `refEnforcer` facade closure (`enforceRefsOnPut` /\n * `enforceRefsOnDelete`), the managed-link `onDelete` policy\n * (`enforceLinksOnDelete`), the `joinResolver` half (`resolveRef` /\n * `resolveSource`), the `checkIntegrity()` reporter, and the cascade-cycle\n * breaker set (`cascadeInProgress`). The ref/link registries stay\n * vault-resident (they are populated by `vault.collection()` / `vault.link()`\n * and read by the backup path) and arrive by reference through\n * {@link VaultLinksDeps}; every other `Vault` dependency arrives via the deps\n * interface.\n *\n * Internal service — reached through `vault.enforceRefsOnPut(...)` etc.\n */\nimport { RefIntegrityError, isRefArray, type RefDescriptor, type RefViolation, type RefRegistry } from '../../kernel/refs.js'\nimport {\n linkCollectionName,\n linkRowKey,\n LinkIntegrityError,\n type LinkSpec,\n type LinkSetHandle,\n} from './names.js'\n// Type-only -- the LinkSet storage engine loads via dynamic import in the\n// Vault's lazy links() handle (#553); this facade only needs its shape.\nimport type { LinkSet } from './link-set.js'\nimport type { JoinableSource } from '../../kernel/query/index.js'\nimport type { Collection } from '../../kernel/collection.js'\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { TxContext } from '../../with-commit/tx/transaction.js'\nimport type { ViaGraph } from '../../kernel/via/graph.js'\nimport type { NoydbEventEmitter } from '../../kernel/events.js'\nimport { DictKeyInUseError, RestrictRefUnresolvableError } from '../../kernel/errors.js'\nimport { coerceLookupKey, matchesReferencingValue } from '../../port/with/lookup-strategy.js'\n\n/** Everything the moving refs/links methods touched on the vault's `this.*`. */\nexport interface VaultLinksDeps {\n /** Per-vault foreign-key registry (vault-resident; read by reference). */\n readonly refRegistry: RefRegistry\n /** Registered link specs, keyed by link name (vault-resident; read by reference). */\n readonly linkRegistry: ReadonlyMap<string, LinkSpec>\n /** The ciphertext store. */\n readonly adapter: NoydbStore\n /** Vault namespace name. */\n readonly vault: string\n /** Collection accessor (bound `vault.collection`). */\n collection<T = unknown>(name: string): Collection<T>\n /** Declared link-set accessor (bound `vault.links`). */\n links(name: string): LinkSetHandle\n /** Cache lookup for an already-opened collection (used by `resolveSource`). */\n getCachedCollection(name: string): Collection<unknown> | undefined\n /** The active transaction context, or null outside a tx. */\n getActiveTxContext(): TxContext | null\n /** The vault's event emitter — the `lookup:propagation-residue` channel (#654). */\n readonly emitter: NoydbEventEmitter\n}\n\nexport class VaultLinks {\n /**\n * Set of collection record-ids currently being deleted as part of a cascade.\n * Populated on entry to `enforceRefsOnDelete` and drained on exit. Used to\n * break mutual-cascade cycles: deleting A → cascade to B → cascade back to A\n * would otherwise recurse forever, so we short-circuit when we see an\n * already-in-progress delete on the same (collection, id) pair.\n */\n private readonly cascadeInProgress = new Set<string>()\n\n constructor(private readonly deps: VaultLinksDeps) {}\n\n /**\n * Enforce strict outbound refs on a `put()`. Called by Collection\n * just before it writes to the adapter. For every strict ref\n * declared on the collection, check that the target id exists in\n * the target collection; throw `RefIntegrityError` if not.\n *\n * `warn` and `cascade` modes don't affect put semantics — they're\n * enforced at delete time or via `checkIntegrity()`.\n */\n async enforceRefsOnPut(collectionName: string, record: unknown): Promise<void> {\n const outbound = this.deps.refRegistry.getOutbound(collectionName)\n if (Object.keys(outbound).length === 0) return\n if (!record || typeof record !== 'object') return\n const obj = record as Record<string, unknown>\n\n for (const [field, descriptor] of Object.entries(outbound)) {\n if (descriptor.mode !== 'strict') continue\n const rawId = obj[field]\n // Nullish ref values are allowed — treat them as \"no reference\".\n // Users who want \"always required\" should express it in their\n // Standard Schema validator via a non-optional field.\n if (rawId === null || rawId === undefined) continue\n\n // Array ref: validate each element against the target.\n if (isRefArray(descriptor)) {\n if (!Array.isArray(rawId)) {\n throw new RefIntegrityError({\n collection: collectionName,\n id: (obj['id'] as string | undefined) ?? '<unknown>',\n field,\n refTo: descriptor.target,\n refId: null,\n message: `Array ref field \"${collectionName}.${field}\" must be an array, got ${typeof rawId}.`,\n })\n }\n const arrTarget = this.deps.collection<Record<string, unknown>>(descriptor.target)\n for (const el of rawId) {\n if (typeof el !== 'string' && typeof el !== 'number') {\n throw new RefIntegrityError({\n collection: collectionName,\n id: (obj['id'] as string | undefined) ?? '<unknown>',\n field,\n refTo: descriptor.target,\n refId: null,\n message: `Array ref \"${collectionName}.${field}\" elements must be strings or numbers, got ${typeof el}.`,\n })\n }\n const elId = String(el)\n if (!(await arrTarget.get(elId))) {\n throw new RefIntegrityError({\n collection: collectionName,\n id: (obj['id'] as string | undefined) ?? '<unknown>',\n field,\n refTo: descriptor.target,\n refId: elId,\n message:\n `Strict array ref \"${collectionName}.${field}\" → \"${descriptor.target}\" ` +\n `cannot be satisfied: element id \"${elId}\" not found in \"${descriptor.target}\".`,\n })\n }\n }\n continue\n }\n\n // Refs must be strings or numbers — anything else (object,\n // array, boolean) is a programming error and should fail\n // loudly rather than serialize as \"[object Object]\".\n if (typeof rawId !== 'string' && typeof rawId !== 'number') {\n throw new RefIntegrityError({\n collection: collectionName,\n id: (obj['id'] as string | undefined) ?? '<unknown>',\n field,\n refTo: descriptor.target,\n refId: null,\n message:\n `Ref field \"${collectionName}.${field}\" must be a string or number, got ${typeof rawId}.`,\n })\n }\n const refId = String(rawId)\n const target = this.deps.collection<Record<string, unknown>>(descriptor.target)\n const exists = await target.get(refId)\n if (!exists) {\n throw new RefIntegrityError({\n collection: collectionName,\n id: (obj['id'] as string | undefined) ?? '<unknown>',\n field,\n refTo: descriptor.target,\n refId,\n message:\n `Strict ref \"${collectionName}.${field}\" → \"${descriptor.target}\" ` +\n `cannot be satisfied: target id \"${refId}\" not found in \"${descriptor.target}\".`,\n })\n }\n }\n }\n\n /**\n * Enforce inbound ref modes on a `delete()`. Called by Collection\n * just before it deletes from the adapter. Walks every inbound\n * ref that targets this (collection, id) and:\n *\n * - `strict`: throws if any referencing records exist\n * - `cascade`: deletes every referencing record\n * - `warn`: no-op (checkIntegrity picks it up)\n *\n * Cascade cycles are broken via `cascadeInProgress` — re-entering\n * for the same (collection, id) returns immediately so two\n * mutually-cascading collections don't recurse forever.\n */\n async enforceRefsOnDelete(graph: ViaGraph, collectionName: string, id: string): Promise<void> {\n const key = `${collectionName}/${id}`\n if (this.cascadeInProgress.has(key)) return\n this.cascadeInProgress.add(key)\n\n try {\n // #650 Task 5 (#648) — lookup-ref restrict/cascade/nullify (a matrix dimension's own\n // collection IS an ordinary Collection, so its `.delete()` already routes through here).\n await this.enforceLookupRefsOnDelete(graph, collectionName, collectionName, id)\n const inbound = this.deps.refRegistry.getInbound(collectionName)\n for (const rule of inbound) {\n const fromCollection = this.deps.collection<Record<string, unknown>>(rule.collection)\n // Scan the referencing collection for records whose ref\n // field matches this id. For eager-mode collections this\n // is an in-memory filter; for lazy-mode it requires a scan.\n const allRecords = await fromCollection.list()\n const matches = allRecords.filter((rec) => {\n const raw = rec[rule.field]\n // Array ref: match when any element equals the deleted id.\n if (rule.isArray) {\n return Array.isArray(raw) && raw.some(\n (el) => (typeof el === 'string' || typeof el === 'number') && String(el) === id,\n )\n }\n // Scalar: same string/number-only restriction as enforceRefsOnPut.\n // Anything else can't have been a valid ref to begin with,\n // so it can't match.\n if (typeof raw !== 'string' && typeof raw !== 'number') return false\n return String(raw) === id\n })\n if (matches.length === 0) continue\n\n if (rule.mode === 'strict') {\n const first = matches[0]\n throw new RefIntegrityError({\n collection: rule.collection,\n id: (first?.['id'] as string | undefined) ?? '<unknown>',\n field: rule.field,\n refTo: collectionName,\n refId: id,\n message:\n `Cannot delete \"${collectionName}\"/\"${id}\": ` +\n `${matches.length} record(s) in \"${rule.collection}\" still reference it via strict ref \"${rule.field}\".`,\n })\n }\n if (rule.mode === 'cascade') {\n // Atomicity: if a transaction is active, register each\n // child's prior envelope on it BEFORE the delete so a later\n // mid-batch failure rolls the cascade back alongside the\n // parent. Mirrors how derivation outputs self-register on the\n // active ctx. Outside a tx the context is null and we skip it.\n const txCtx = this.deps.getActiveTxContext()\n for (const match of matches) {\n const matchId = (match['id'] as string | undefined) ?? null\n if (matchId === null) continue\n if (txCtx !== null) {\n const prior = await this.deps.adapter.get(this.deps.vault, rule.collection, matchId)\n if (prior !== null) {\n txCtx._executed.push({\n op: {\n type: 'delete',\n vaultName: this.deps.vault,\n collectionName: rule.collection,\n id: matchId,\n },\n priorEnvelope: prior,\n })\n }\n }\n // Recursive delete — the cycle breaker above catches\n // infinite loops.\n await fromCollection.delete(matchId)\n }\n }\n // warn: no-op\n }\n // Managed link sets: apply each link's onDelete to its rows\n // touching the deleted endpoint. Runs inside the same cascade guard /\n // before the adapter delete, so a 'strict' link blocks the delete.\n await this.enforceLinksOnDelete(collectionName, id)\n } finally {\n this.cascadeInProgress.delete(key)\n }\n }\n\n /**\n * Find the records in `collection` whose `field` currently equals `key` — the SAME\n * list()+filter machinery `enforceRefsOnDelete`'s classic ref-restrict/cascade loop above\n * already uses (bounded by the referencing collection's size, never by the whole vault or by\n * \"which collections reference this\" — that part is the graph's O(1) `_out` reverse index).\n */\n private async findLookupReferencingRecords(\n collection: Collection<Record<string, unknown>>,\n field: string,\n key: string,\n ): Promise<Record<string, unknown>[]> {\n const all = await collection.list()\n return all.filter((rec) => matchesReferencingValue(rec, field, key))\n }\n\n /**\n * Resolve the VALUE a referencing field actually stores for the row being deleted (`rawKey`,\n * the backing row's PUT-id) under a given edge's `keyField` — a referencing field always stores\n * `row[keyField]`, never the PUT-id when the two differ (matrix tier's `lookup(dim, {key})`;\n * mirrors Task 3's `checkLookupMembership` review fix, Important 1). `keyField === 'id'`\n * (reserved/static tiers, and the matrix default) needs no row read: `rawKey` IS the value.\n * Reads the backing row AT MOST ONCE per distinct non-`'id'` `keyField`, even across multiple\n * edges — `backingCollection` is only `.get()`-able for the matrix tier, which is exactly the\n * only tier that can ever have `keyField !== 'id'`.\n */\n private async resolveLookupCompareKey(\n backingCollection: string,\n rawKey: string,\n keyField: string,\n cache: Map<string, string | undefined>,\n ): Promise<string | undefined> {\n if (keyField === 'id') return rawKey\n if (cache.has(keyField)) return cache.get(keyField)\n const row = await this.deps.collection<Record<string, unknown>>(backingCollection).get(rawKey)\n const resolved = coerceLookupKey(row?.[keyField])\n cache.set(keyField, resolved)\n return resolved\n }\n\n /**\n * Phase 1 (#650 Task 5, #648) — restrict check, never mutates. Throws\n * `DictKeyInUseError(dimension, key, usedBy, count)` naming the FIRST referencing collection\n * still holding a matching record, for every `onDelete:'restrict'` edge the graph's O(1)\n * `referencingEdgesOf(backingCollection)` reverse lookup finds pointing at this dimension. A\n * dimension with no declared lookup-referencing edges is a no-op — undeclared refs keep\n * dangling (today's behavior, unaffected). Called by `Vault.forget()` BEFORE any shred (the\n * spec §4 \"restrict refuses before any shred\" design decision) — cascade/nullify propagation\n * for the SAME edges happens separately, after the shred, via `forgetDerivedFanout`.\n *\n * Also resolves (and RETURNS) the live compare-key for EVERY referencing edge, restrict AND\n * cascade/nullify alike (#650 Task 5 review, Important fix): `forgetDerivedFanout`'s cascade/\n * nullify propagation runs AFTER `_writeTombstone`, when a non-`'id'` `keyField`'s value can no\n * longer be read off the (now-shredded) row — resolving it HERE, at the one point every\n * referencing edge's backing row is still guaranteed live, eliminates that post-shred\n * dependency.\n *\n * #654: a `restrict` edge whose compare-key CANNOT be resolved (the backing row is missing the\n * `keyField` or holds a non-scalar value — corruption-class rarity) THROWS\n * `RestrictRefUnresolvableError` naming the unresolvable edge, fail-closed — whether a\n * referencer exists can't be proven, so the delete/forget is refused rather than silently\n * allowed through. Non-restrict edges keep `continue`ing on an unresolvable compare-key (their\n * `undefined` still lands in the returned map so `forgetDerivedFanout`'s cascade/nullify twin\n * can report it as residue instead of silently skipping — unchanged from before #654).\n */\n async checkLookupRefsRestrict(graph: ViaGraph, dimension: string, backingCollection: string, key: string): Promise<ReadonlyMap<string, string | undefined>> {\n const keyCache = new Map<string, string | undefined>()\n for (const { referencing, onDelete, keyField } of graph.referencingEdgesOf(backingCollection)) {\n const compareKey = await this.resolveLookupCompareKey(backingCollection, key, keyField, keyCache)\n if (onDelete !== 'restrict') continue\n if (compareKey === undefined) {\n throw new RestrictRefUnresolvableError(dimension, key, `${referencing.collection}.${referencing.field}`)\n }\n const coll = this.deps.collection<Record<string, unknown>>(referencing.collection)\n const matches = await this.findLookupReferencingRecords(coll, referencing.field, compareKey)\n if (matches.length > 0) {\n throw new DictKeyInUseError(dimension, key, referencing.collection, matches.length)\n }\n }\n return keyCache\n }\n\n /**\n * Phase 2 (#650 Task 5, #648) — apply `cascade`/`nullify` propagation for this dimension's\n * non-restrict referencing edges (restrict edges are skipped — phase 1 above already refused\n * or the caller already checked). `cascade` deletes each matching record through its ordinary\n * `collection.delete()` (an origin-tagged, fanout-visible delete — participates in sync/history/\n * the graph dispatch wave exactly like any other delete); `nullify` clears the referencing field\n * via an ordinary `collection.put()`. Returns the counts so callers (forget's `ForgetFanoutStats`)\n * can report the propagation additively.\n *\n * #654: an edge whose compare-key can't be resolved is no longer a bare silent `continue` — it\n * pushes a `backing:key:collection.field` entry onto `residue` (mirroring\n * `applyLookupRefsFanout`'s forget-path residue format, `kernel/via/dispatch.ts`) so the caller\n * (`enforceLookupRefsOnDelete` below) can surface it instead of dropping it on the floor.\n */\n async applyLookupRefsPropagation(graph: ViaGraph, backingCollection: string, key: string): Promise<{ cascaded: number; nullified: number; residue: string[] }> {\n let cascaded = 0\n let nullified = 0\n const residue: string[] = []\n const keyCache = new Map<string, string | undefined>()\n for (const { referencing, onDelete, keyField } of graph.referencingEdgesOf(backingCollection)) {\n if (onDelete === 'restrict') continue\n const compareKey = await this.resolveLookupCompareKey(backingCollection, key, keyField, keyCache)\n if (compareKey === undefined) {\n residue.push(`${backingCollection}:${key}:${referencing.collection}.${referencing.field}`)\n continue\n }\n const coll = this.deps.collection<Record<string, unknown>>(referencing.collection)\n const matches = await this.findLookupReferencingRecords(coll, referencing.field, compareKey)\n for (const rec of matches) {\n const id = rec['id'] as string | undefined\n if (id === undefined) continue\n if (onDelete === 'cascade') {\n await coll.delete(id)\n cascaded++\n } else if (onDelete === 'nullify') {\n await coll.put(id, { ...rec, [referencing.field]: null })\n nullified++\n }\n }\n }\n return { cascaded, nullified, residue }\n }\n\n /**\n * Convenience: the full restrict-then-propagate sequence for an ORDINARY (non-forget) delete of\n * a lookup-referenced row — `checkLookupRefsRestrict` then `applyLookupRefsPropagation`. Used by\n * `enforceRefsOnDelete` above (matrix-tier: the backing row IS an ordinary `Collection` record)\n * and by `LookupHandle.delete()`'s injected `checkReferencesOnDelete` callback (reserved tier).\n *\n * #654: when `applyLookupRefsPropagation` reports residue, it is emitted here as a structured\n * `lookup:propagation-residue` event — the delete/put return shape both callers consume stays\n * `void`/unrelated, so an event is the additive channel that keeps the skip from ever being\n * silent (mirrors the forget path's `ForgetResult.lookupReferencesResidue` channel).\n */\n async enforceLookupRefsOnDelete(graph: ViaGraph, dimension: string, backingCollection: string, key: string): Promise<{ cascaded: number; nullified: number; residue: string[] }> {\n await this.checkLookupRefsRestrict(graph, dimension, backingCollection, key)\n const result = await this.applyLookupRefsPropagation(graph, backingCollection, key)\n if (result.residue.length > 0) {\n this.deps.emitter.emit('lookup:propagation-residue', { vault: this.deps.vault, dimension, key, residue: result.residue })\n }\n return result\n }\n\n /**\n * @internal — apply link `onDelete` policy when an endpoint record is\n * deleted. `'strict'` throws (blocks the delete), `'cascade'`\n * removes the touching link rows (tx-atomic when a transaction is active),\n * `'warn'` leaves orphans for `checkIntegrity()`.\n */\n private async enforceLinksOnDelete(collectionName: string, id: string): Promise<void> {\n for (const [name, spec] of this.deps.linkRegistry) {\n if (spec.a !== collectionName && spec.b !== collectionName) continue\n const handle = this.deps.links(name) as LinkSet\n const touching = await handle._rowsTouchingEndpoint(collectionName, id)\n if (touching.length === 0) continue\n const mode = spec.onDelete ?? 'cascade'\n if (mode === 'warn') continue\n if (mode === 'strict') {\n throw new LinkIntegrityError(name, collectionName, id, touching.length)\n }\n // cascade — remove every touching link row.\n const linkColl = handle._collectionName\n const txCtx = this.deps.getActiveTxContext()\n for (const row of touching) {\n const rowKey = linkRowKey(row.a, row.b)\n if (txCtx !== null) {\n const prior = await this.deps.adapter.get(this.deps.vault, linkColl, rowKey)\n if (prior !== null) {\n txCtx._executed.push({\n op: { type: 'delete', vaultName: this.deps.vault, collectionName: linkColl, id: rowKey },\n priorEnvelope: prior,\n })\n }\n }\n await handle.disconnect(row.a, row.b)\n }\n }\n }\n\n /**\n * Look up the `RefDescriptor` the left collection declared for a\n * given field name. Returns `null` when the field has no ref\n * declaration — the Query builder turns that into an actionable\n * error at plan time (before any records are touched).\n *\n * Implements the `joinResolver.resolveRef` half of the structural\n * interface that `Collection.query()` consumes. See\n * `query/join.ts` for the full design.\n */\n resolveRef(leftCollection: string, field: string): RefDescriptor | null {\n const outbound = this.deps.refRegistry.getOutbound(leftCollection)\n return outbound[field] ?? null\n }\n\n /**\n * Resolve a right-side join source by target collection name.\n * Returns `null` for unknown collections so the Query executor can\n * surface an actionable error naming the missing target.\n *\n * Implements the `joinResolver.resolveSource` half of the\n * structural interface. The returned JoinableSource is a thin\n * wrapper that reads the target collection's in-memory cache via\n * `list()` / `get()` synchronously — the cache is populated by an\n * earlier `ensureHydrated()` call through the target's query/list\n * path. If the target has not been opened yet in this session the\n * join will see an empty snapshot; consumers who hit this can\n * open the target collection explicitly before running the query.\n *\n * Only same-vault targets are resolvable — cross-vault\n * joins are explicitly forbidden by the architecture`).\n */\n resolveSource(collectionName: string): JoinableSource | null {\n // Reject internal / reserved collection names — joins against\n // `_ledger/`, `_keyring/`, `_deltas/`, etc. are never legitimate.\n if (collectionName.startsWith('_')) return null\n const coll = this.deps.getCachedCollection(collectionName)\n if (!coll) return null\n // Collection exposes a structural `querySourceForJoin()` method\n // that returns a lightweight snapshot/lookupById view backed by\n // its in-memory cache. Typed as unknown here because\n // Collection<T> is covariant on T — the join executor only\n // reads fields by name and doesn't care about the concrete type.\n return (coll as unknown as {\n querySourceForJoin(): JoinableSource\n }).querySourceForJoin()\n }\n\n /**\n * Walk every collection that has declared refs, load its records,\n * and report any reference whose target id is missing. Modes are\n * reported alongside each violation so the caller can distinguish\n * \"this is a warning the user asked for\" from \"this should never\n * have happened\" (strict violations produced by out-of-band\n * writes).\n *\n * Returns `{ violations: [...] }` instead of throwing — the whole\n * point of `checkIntegrity()` is to surface a list for display\n * or repair, not to fail noisily.\n */\n async checkIntegrity(): Promise<{ violations: RefViolation[] }> {\n const violations: RefViolation[] = []\n for (const [collectionName, refs] of this.deps.refRegistry.entries()) {\n const coll = this.deps.collection<Record<string, unknown>>(collectionName)\n const records = await coll.list()\n for (const record of records) {\n const recId = (record['id'] as string | undefined) ?? '<unknown>'\n for (const [field, descriptor] of Object.entries(refs)) {\n const rawId = record[field]\n if (rawId === null || rawId === undefined) continue\n const target = this.deps.collection<Record<string, unknown>>(descriptor.target)\n\n // Array ref: report one violation per dangling element.\n if (isRefArray(descriptor)) {\n if (!Array.isArray(rawId)) {\n violations.push({ collection: collectionName, id: recId, field, refTo: descriptor.target, refId: rawId, mode: descriptor.mode })\n continue\n }\n for (const el of rawId) {\n if (typeof el !== 'string' && typeof el !== 'number') {\n violations.push({ collection: collectionName, id: recId, field, refTo: descriptor.target, refId: el, mode: descriptor.mode })\n continue\n }\n if (!(await target.get(String(el)))) {\n violations.push({ collection: collectionName, id: recId, field, refTo: descriptor.target, refId: el, mode: descriptor.mode })\n }\n }\n continue\n }\n\n // Non-scalar ref values are flagged as a violation rather\n // than thrown — `checkIntegrity` is a \"report what's wrong\"\n // tool, not a \"block on first failure\" tool. The thrown\n // version lives in `enforceRefsOnPut`.\n if (typeof rawId !== 'string' && typeof rawId !== 'number') {\n violations.push({\n collection: collectionName,\n id: recId,\n field,\n refTo: descriptor.target,\n refId: rawId,\n mode: descriptor.mode,\n })\n continue\n }\n const refId = String(rawId)\n const exists = await target.get(refId)\n if (!exists) {\n violations.push({\n collection: collectionName,\n id: recId,\n field,\n refTo: descriptor.target,\n refId: rawId,\n mode: descriptor.mode,\n })\n }\n }\n }\n }\n\n // Managed link sets: a link row whose endpoint no longer exists\n // is an orphan (the common 'warn'-mode outcome). Report one violation per\n // dangling endpoint, field 'a'/'b', mode = the link's onDelete policy.\n for (const [name, spec] of this.deps.linkRegistry) {\n const linkColl = linkCollectionName(name)\n const rows = await this.deps.links(name).list()\n for (const row of rows) {\n const rowKey = linkRowKey(row.a, row.b)\n if ((await this.deps.collection(spec.a).get(row.a)) === null) {\n violations.push({ collection: linkColl, id: rowKey, field: 'a', refTo: spec.a, refId: row.a, mode: spec.onDelete ?? 'cascade' })\n }\n if ((await this.deps.collection(spec.b).get(row.b)) === null) {\n violations.push({ collection: linkColl, id: rowKey, field: 'b', refTo: spec.b, refId: row.b, mode: spec.onDelete ?? 'cascade' })\n }\n }\n }\n return { violations }\n }\n}\n","/**\n * Lazy link-set handle factory (#553).\n *\n * `vault.links(name)` is a SYNC accessor, but every method on the handle\n * it returns is async — so the handle can defer loading the `LinkSet`\n * storage engine to the first actual link I/O. This keeps `link-set.ts`\n * out of the floor bundle for consumers that never use links, while the\n * handle object itself stays cached and referentially stable per name.\n *\n * Besides the public {@link LinkSetHandle} surface, the handle carries\n * the two cascade internals the ref/link enforcement facade consults\n * (`vault-facade.ts` casts the handle to `LinkSet` and duck-types them).\n */\nimport { linkCollectionName, type LinkRow, type LinkSpec, type LinkSetHandle } from './names.js'\nimport type { LinkSet } from './link-set.js'\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { NoydbEventEmitter } from '../../kernel/events.js'\nimport type { EnclaveKey } from '../../kernel/enclave/index.js'\n\n/** @internal The lazy handle: public surface + facade cascade internals. */\nexport type LazyLinkSetHandle = LinkSetHandle & {\n readonly _collectionName: string\n _rowsTouchingEndpoint(collection: string, id: string): Promise<LinkRow[]>\n}\n\n/** @internal Constructor args for the deferred {@link LinkSet}. */\nexport interface LazyLinkSetDeps {\n readonly adapter: NoydbStore\n readonly vault: string\n readonly name: string\n readonly spec: LinkSpec\n readonly encrypted: boolean\n readonly getDEK: (collectionName: string) => Promise<EnclaveKey>\n readonly actor: string\n readonly emitter: NoydbEventEmitter\n readonly endpointExists: (collection: string, id: string) => Promise<boolean>\n}\n\n/** @internal Build the handle; the LinkSet engine dynamic-imports on first use. */\nexport function makeLazyLinkSetHandle(d: LazyLinkSetDeps): LazyLinkSetHandle {\n let engine: Promise<LinkSet> | null = null\n const load = (): Promise<LinkSet> =>\n (engine ??= import('./link-set.js').then(\n ({ LinkSet }) =>\n new LinkSet(d.adapter, d.vault, d.name, d.spec, d.encrypted, d.getDEK, d.actor, d.emitter, d.endpointExists),\n ))\n return {\n _collectionName: linkCollectionName(d.name),\n connect: async (aId, bId, meta) => (await load()).connect(aId, bId, meta),\n disconnect: async (aId, bId) => (await load()).disconnect(aId, bId),\n has: async (aId, bId) => (await load()).has(aId, bId),\n of: async (id) => (await load()).of(id),\n list: async () => (await load()).list(),\n _rowsTouchingEndpoint: async (collection, id) => (await load())._rowsTouchingEndpoint(collection, id),\n }\n}\n","// kernel/via/taint-binding.ts — the kernel-resident `taint` ViaBinding\n// (#638 Task 3, closes the reproduced #636 leak).\n//\n// Bridges `ViaGraph`'s assigned effective postures (Task 1/2) into the SAME\n// phase-B enforcement surfaces (`ViaPipeline.postureFor` → query gate +\n// `redactForExport`) and, for the subset the graph marks sealed, seals the\n// field's VALUE at rest via `ctx.sealedSlots` — byte-for-byte the same\n// capability `via/classified/binding.ts` uses, no new crypto path.\n//\n// This file owns two independent things:\n// 1. `buildTaintOverlay` — a PURE transform from the graph's raw per-field\n// postures to the enforcement-facing map `ViaPipeline.build`'s `taint`\n// param consumes (dropping untainted entries, clamping a sealed\n// field's `queryable` to `'none'`).\n// 2. `taintBinding` — the `ViaBinding` that actually performs the sealing,\n// keyed on the graph's `taintSealedFields` set (never a brand-specific\n// field list the way classified/money declare their own).\n//\n// Neither is registered via `installViaBinder`/`viaBinder('taint')` — unlike\n// money/i18n/classified/blob, a `taint` binding is never user-declared; it is\n// constructed directly by `via/graph-wiring.ts#applyTaintOverlay`, the one\n// caller, right after the graph has this collection's edges.\nimport type { ViaBinding, ViaCryptoCtx, SealedSlotRef, ViaPosture } from './index.js'\nimport { SealedHandle } from '../types.js'\nimport { DEFAULT_POSTURE } from './graph.js'\nimport { EXPORT_REDACTION_MARKER } from './pipeline.js'\n\nconst EMPTY_STRING_SET: ReadonlySet<string> = new Set()\n\n/** Whether `p` is exactly the plain, non-taint baseline. */\nfunction isDefaultPosture(p: ViaPosture): boolean {\n return p.encryptedAtRest === DEFAULT_POSTURE.encryptedAtRest && p.queryable === DEFAULT_POSTURE.queryable &&\n p.exportable === DEFAULT_POSTURE.exportable && p.forgettable === DEFAULT_POSTURE.forgettable\n}\n\n/**\n * Narrow the graph's raw per-field effective postures (`ViaGraph.\n * taintedPostures`) down to the enforcement-facing overlay `ViaPipeline.\n * build`'s `taint.postures` carries:\n * - entries whose effective posture equals `DEFAULT_POSTURE` are DROPPED —\n * nothing to enforce, and (#553) keeping `postureFor` returning\n * `undefined` for an all-plain-sourced computed field matters: it is what\n * lets a collection with ONLY plain-sourced computed fields keep\n * `this.via === undefined` (see `applyTaintOverlay`'s no-op-when-empty\n * contract below).\n * - a `sealed` entry's `queryable` is clamped to `'none'`, regardless of\n * what the graph's fold inherited (e.g. classified's own `'det-exact'`):\n * `'det-exact'` presumes a purpose-built blind index the SOURCE binding\n * (classified) builds for its own declared fields — this generic\n * taint-seal never builds an equivalent index for the DERIVED field, so a\n * derived+sealed field is, in truth, unqueryable by any means. This\n * matches the query DSL's existing PARITY behavior for classified's own\n * `'det-exact'` fields (`.where()` silently matches nothing, never\n * throws) — a derived field has no such fallback because its stored form\n * is opaque ciphertext, not a plain (if index-less) value, so `'none'`\n * (explicit refusal) is the honest posture, not `'det-exact'`.\n *\n * Returns `undefined` when nothing survives the filter (equivalent to \"no\n * taint on this collection\").\n */\nexport function buildTaintOverlay(\n rawPostures: ReadonlyMap<string, ViaPosture>,\n sealFields: ReadonlySet<string>,\n): ReadonlyMap<string, ViaPosture> | undefined {\n let out: Map<string, ViaPosture> | undefined\n for (const [field, posture] of rawPostures) {\n if (isDefaultPosture(posture)) continue\n out ??= new Map()\n out.set(field, sealFields.has(field) ? { ...posture, queryable: 'none' } : posture)\n }\n return out\n}\n\n/**\n * Seal every named field present with a defined value into its own sealed\n * slot via `crypto.sealedSlots`, peeling it out of the record. Mirrors\n * `via/classified/binding.ts#encodeClassifiedAtRest` exactly (same\n * capability, different field list — duplicated rather than imported so\n * this file never reaches into `via/**`, matching `via/graph-wiring.ts`'s\n * own documented-duplication precedent for `CLASSIFIED_POSTURE`).\n */\nasync function encodeTaintAtRest(\n record: Record<string, unknown>,\n crypto: ViaCryptoCtx,\n fields: readonly string[],\n): Promise<{ record: Record<string, unknown>; sealed?: Record<string, SealedSlotRef> }> {\n let open = record\n let sealed: Record<string, SealedSlotRef> | undefined\n for (const field of fields) {\n if (!(field in record)) continue\n const value = record[field]\n if (value === undefined) continue\n const ref = await crypto.sealedSlots.seal(field, value)\n if (open === record) open = { ...record }\n delete open[field]\n sealed ??= {}\n sealed[field] = ref\n }\n return sealed ? { record: open, sealed } : { record }\n}\n\n/**\n * Restore every named field's sealed slot back onto the record: an opaque\n * `SealedHandle` under `asHandles` (never materialises plaintext into the\n * cache — matches classified's own `decodeAtRest`), the plaintext value\n * otherwise. A field named in `fields` but absent from a PARTICULAR record's\n * `sealed` map (over-taint / phantom graph registration — see cm8) is simply\n * skipped: this loop only ever reads keys `sealed` actually carries.\n */\nasync function decodeTaintAtRest(\n record: Record<string, unknown>,\n sealed: Record<string, SealedSlotRef>,\n crypto: ViaCryptoCtx,\n opts: { asHandles: boolean },\n fields: readonly string[],\n): Promise<Record<string, unknown>> {\n let out = record\n for (const field of fields) {\n const ref = sealed[field]\n if (ref === undefined) continue\n if (out === record) out = { ...record }\n out[field] = opts.asHandles\n ? new SealedHandle(() => crypto.sealedSlots.unseal(field, ref))\n : await crypto.sealedSlots.unseal(field, ref)\n }\n return out\n}\n\n/**\n * #642 `sealAllFields` mode — seal EVERY own field carrying a defined value,\n * except reserved/internal keys (`_`-prefixed, e.g. `_derivedFrom` — the\n * derivation/MV output provenance tag, which must stay a plain metadata\n * object, never sealed). Mirrors {@link encodeTaintAtRest} but iterates\n * `Object.keys(record)` instead of a fixed field list — a `'*'`-defaulted\n * output collection's field names are runtime `derive()` products, unknown\n * at declare time.\n */\nasync function encodeTaintAtRestAll(\n record: Record<string, unknown>,\n crypto: ViaCryptoCtx,\n): Promise<{ record: Record<string, unknown>; sealed?: Record<string, SealedSlotRef> }> {\n let open = record\n let sealed: Record<string, SealedSlotRef> | undefined\n for (const field of Object.keys(record)) {\n if (field.startsWith('_')) continue\n const value = record[field]\n if (value === undefined) continue\n const ref = await crypto.sealedSlots.seal(field, value)\n if (open === record) open = { ...record }\n delete open[field]\n sealed ??= {}\n sealed[field] = ref\n }\n return sealed ? { record: open, sealed } : { record }\n}\n\n/**\n * #642 `sealAllFields` mode — restore every key PRESENT IN THE RECORD'S OWN\n * `sealed` map (no fixed field list to consult — the field set is whatever\n * {@link encodeTaintAtRestAll} actually sealed for this particular record).\n */\nasync function decodeTaintAtRestAll(\n record: Record<string, unknown>,\n sealed: Record<string, SealedSlotRef>,\n crypto: ViaCryptoCtx,\n opts: { asHandles: boolean },\n): Promise<Record<string, unknown>> {\n let out = record\n for (const [field, ref] of Object.entries(sealed)) {\n if (out === record) out = { ...record }\n out[field] = opts.asHandles\n ? new SealedHandle(() => crypto.sealedSlots.unseal(field, ref))\n : await crypto.sealedSlots.unseal(field, ref)\n }\n return out\n}\n\n/**\n * The `taint` binding: seals `sealFields` at rest via `ctx.sealedSlots`,\n * presenting them as sealed handles on read — exactly as classified does,\n * reusing the same phase-B capability. `covers` = membership in `sealFields`\n * OR `presentRedactFields` (the brief's contract) — used by\n * `hasAtRestHooks`/`eraseSealed`'s posture-driven bookkeeping, NEVER by\n * `postureFor` (the taint OVERLAY short-circuits `postureFor` before any\n * binding's `covers`/`.posture` is consulted — see `ViaPipeline.postureFor`).\n * `erase` is intentionally unimplemented: today's crypto-shred\n * (`Collection._writeTombstone`) overwrites the whole envelope — `_sealed`\n * included — regardless of via bindings, so a taint-sealed field is already\n * erased on `forget()` with no extra participation; per-field erasure\n * bookkeeping (residue/shredded counts) is Task 6's (#622 forget fanout)\n * concern if ever needed.\n *\n * `presentRedactFields` (#638 Task 7, default empty) — tainted VIRTUAL\n * computed fields (never sealed — nothing to encodeAtRest/decodeAtRest;\n * `via/graph-wiring.ts#applyTaintOverlay` computes this set as\n * `graph.virtualFields(name) ∩ { field : postures.get(field).exportable ===\n * false }`). This binding is appended AFTER whatever `compileViaBindings`\n * built (including the `computed` binding), so its `present` hook — when\n * `presentRedactFields` is non-empty — runs LAST and overwrites a virtual\n * field's freshly-computed value with `EXPORT_REDACTION_MARKER`,\n * unconditionally, closing the read-time leak the same way `SealedHandle`\n * closes it for a materialized-sealed field. `encodeAtRest`/`decodeAtRest`/\n * `present` are all conditionally OMITTED (not just no-op) when their\n * respective field set is empty — a collection with ONLY a tainted virtual\n * field (no materialized-sealed field) must NOT flip\n * `ViaPipeline.hasAtRestHooks`, which would wrongly route it onto the async\n * at-rest-hook codec path for nothing to seal.\n *\n * `sealAllFields` (#642, default `false`) — whole-record seal for a\n * `'*'`-defaulted derivation/MV/overlay OUTPUT collection: `covers` claims\n * every non-`_`-prefixed field, and `encodeAtRest`/`decodeAtRest` route\n * through {@link encodeTaintAtRestAll}/{@link decodeTaintAtRestAll} instead\n * of the fixed `sealFields` list (moot in this mode — sealing everything is\n * already a superset of any field-specific taint on the same collection).\n */\nexport function taintBinding(\n sealFields: ReadonlySet<string>,\n presentRedactFields: ReadonlySet<string> = EMPTY_STRING_SET,\n sealAllFields = false,\n): ViaBinding {\n const fields = [...sealFields]\n const redactFields = [...presentRedactFields]\n return {\n brand: 'taint',\n posture: { encryptedAtRest: 'sealed', queryable: 'none', exportable: false, forgettable: true },\n covers: (field) => sealAllFields ? !field.startsWith('_') : (sealFields.has(field) || presentRedactFields.has(field)),\n ...((sealAllFields || fields.length > 0) ? {\n encodeAtRest: (record: Record<string, unknown>, crypto: ViaCryptoCtx) =>\n sealAllFields ? encodeTaintAtRestAll(record, crypto) : encodeTaintAtRest(record, crypto, fields),\n decodeAtRest: (record: Record<string, unknown>, sealed: Record<string, SealedSlotRef>, crypto: ViaCryptoCtx, opts: { asHandles: boolean }) =>\n sealAllFields ? decodeTaintAtRestAll(record, sealed, crypto, opts) : decodeTaintAtRest(record, sealed, crypto, opts, fields),\n } : {}),\n ...(redactFields.length > 0 ? {\n present: (record: Record<string, unknown>) => {\n let out = record\n for (const field of redactFields) {\n if (field in out) {\n if (out === record) out = { ...record }\n out[field] = EXPORT_REDACTION_MARKER\n // Money's presentLate (#669, `via/money/normalize.ts#presentVirtualMoneyFields`)\n // dresses a virtual money field's fresh output into `<field>Formatted`/\n // `<field>Number` companions BEFORE this present() (taint's) runs. Redacting\n // only `field` leaves those companions holding the un-redacted value — DELETE\n // them (not overwrite with the marker: the marker on `field` is the leak\n // signal, and inventing a `${field}Formatted` marker key that an un-redacted\n // read wouldn't always carry would be its own lie). Reviewed #669 finding.\n // `${field}Label` is the SAME companion shape for dictKey/lookup's label\n // dressing (`via/i18n`/`via/lookup`'s `present()` hooks, same emission\n // convention, same BEFORE-taint ordering) — a dict/lookup key is a closed\n // vocabulary, so the label reveals the sealed value exactly (#671 review\n // finding: `statusLabel: 'PAID-TH'` beside a redacted `status: '[sealed]'`).\n // Deliberate over-redaction: a user-authored STORED field that happens to be\n // named `${field}Formatted`/`${field}Number`/`${field}Label` beside a redacted\n // virtual field is also stripped here — fails closed, no leak; the collision is\n // pathological and narrowing it would require money/i18n/lookup-field knowledge\n // this generic taint binding deliberately doesn't have.\n const formattedKey = `${field}Formatted`\n const numberKey = `${field}Number`\n const labelKey = `${field}Label`\n if (formattedKey in out) delete out[formattedKey]\n if (numberKey in out) delete out[numberKey]\n if (labelKey in out) delete out[labelKey]\n }\n }\n return out\n },\n } : {}),\n }\n}\n","// kernel/via/graph-wiring.ts — thin per-vault wiring that feeds `ViaGraph`\n// from the collection-declare edge sources (via bindings' `deps`, `computed`)\n// at collection-construction time (#638 Task 2). The with-formula (derivation/\n// MV/overlay) edge sources are registered directly by `Vault._initDerivations`/\n// `_initMaterializedViews`/`_initOverlayedViews` from their registries' own\n// `edges()` accessors — this file only covers the per-collection sources,\n// which fire on every `Vault.collection()` call, not just vaults that declare\n// a derivation/MV/overlay strategy.\nimport type { ViaGraph } from './graph.js'\nimport type { ViaPosture } from './index.js'\nimport {\n resolveCollectionConfig, resolveComputedEdges, computedEntryParts, collectKnownFieldNames,\n type CollectionOpts, type GraphEdge,\n} from '../collection-config.js'\nimport { resolveClassifiedFields, type ClassifiedEntry } from '../../port/with/classified-strategy.js'\nimport { ValidationError } from '../errors.js'\nimport { ViaPipeline, type ViaTaintOverlay, type HasWritableViaPipeline } from './pipeline.js'\nimport { buildTaintOverlay, taintBinding } from './taint-binding.js'\n\n// `ComputedFields` is a with-formula/computed type; the kernel spine may not\n// statically import a with-* service (S5 port-layering — see\n// scripts/check-architecture.mjs's checkPortLayering). Derive the type from\n// the already-permitted `resolveComputedEdges` signature (collection-config.ts\n// is grandfathered for the real with-formula import) instead of importing it\n// directly here.\ntype ComputedFieldsParam = NonNullable<Parameters<typeof resolveComputedEdges>[1]>\n\n// The classified via-binding's fixed posture (`via/classified/binding.ts`'s\n// `classifiedBinding().posture` — byte-for-byte duplicate, uniform across every\n// storage form, stable since #629 Task 5). Duplicated here rather than\n// imported: the reconcile commit path (unlike fresh construction) has no\n// compiled `ViaPipeline` to read `binding.posture` off of, and the kernel\n// spine may not statically reach a with-*/shape service for it. Same\n// documented-duplication-risk class as `WHOLE_RECORD`\n// (`with-formula/materialized-views/registry.ts`) — keep in sync by hand.\nconst CLASSIFIED_POSTURE: ViaPosture = { encryptedAtRest: 'sealed', queryable: 'det-exact', exportable: false, forgettable: true }\n\n/**\n * Register one collection's field postures (`binding.posture` + `covers()`)\n * and computed/via-binding-deps edges onto the vault's shared graph. Called\n * from `Vault.collection()`'s fresh-construction path, right after the real\n * `Collection` is built from the SAME `opts` — `resolveCollectionConfig` is a\n * pure function, so re-running it here (Collection's constructor already ran\n * it once internally) costs a one-time, side-effect-free recomputation at\n * collection-declare time, not a per-write cost.\n */\nexport function registerCollectionGraphSources<T>(graph: ViaGraph, name: string, opts: CollectionOpts<T>): void {\n const cfg = resolveCollectionConfig(opts)\n const bindings = cfg.via?.bindings ?? []\n const knownFields = new Set<string>([\n ...Object.keys(cfg.moneyFields ?? {}),\n ...Object.keys(cfg.i18nFields ?? {}),\n ...Object.keys(cfg.dictKeyFields ?? {}),\n // #650 Task 2 — native lookup()/enumOf()/dict() fields register their\n // posture (`lookupBinding().posture`) the same generic way every other\n // binding does; no `'ref'` EdgeKind / graph edge yet (Task 5).\n ...Object.keys(cfg.lookupFields ?? {}),\n ...(cfg.classified !== undefined ? Object.keys(cfg.classified.byField) : []),\n ])\n for (const field of knownFields) {\n for (const binding of bindings) {\n if (binding.covers?.(field)) {\n graph.registerField(name, field, binding.posture)\n break\n }\n }\n }\n // #638 Task 7 — `edge.grain` defaults to 'record' (with-formula edges and\n // materialized computed edges never set it); a virtual computed field's\n // edge carries `grain: 'virtual'` (`resolveComputedEdges`).\n for (const edge of cfg.computedEdges) graph.registerDerived(edge.target, edge.sources, 'computed', edge.grain ?? 'record')\n for (const edge of cfg.viaDepsEdges) graph.registerDerived(edge.target, edge.sources, 'computed', edge.grain ?? 'record')\n\n // #638 Task 2 fix wave 2 — record the combined-state leak-guard memory\n // (Finding I1) a LATER, separate reconcile call needs: which raw\n // user-declared computed fields have no declared `deps` (depless — legal\n // here since no classified field is present yet, so nothing to register\n // an edge against), and whether this collection has any classified field\n // at all. `cfg.computedFieldNames` (#638 Task 7) is EVERY declared\n // computed field name across both modes/surfaces — not just\n // `opts.computed`'s sugar keys — so a `via(computed(...))`-declared field\n // participates in this guard identically to a sugar-declared one.\n if (cfg.classified !== undefined) graph.markClassified(name)\n const depFields = new Set(cfg.computedEdges.map((edge) => edge.target.field))\n for (const field of cfg.computedFieldNames) {\n if (!depFields.has(field)) graph.markDepslessComputed(name, field)\n }\n}\n\n/** The slice of `Vault.collection()`'s reconcile-path options relevant to\n * graph registration — money/computed/classifiedFields are the only\n * options `Vault.collection()`'s reconcile branches actually attach\n * (i18nFields/dictKeyFields are construction-only, never reconciled). */\nexport interface ReconcileGraphOptions {\n readonly moneyFields?: Record<string, unknown>\n readonly classifiedFields?: Record<string, ClassifiedEntry>\n readonly computed?: ComputedFieldsParam\n}\n\n/** Phase 1's output — what phase 2 (`commitReconcileGraphEdges`) applies once\n * every `_apply*` mutation for this reconcile call has succeeded. */\nexport interface ReconcilePlan {\n readonly edges: readonly GraphEdge[]\n readonly depslessComputedFields: readonly string[]\n readonly classifiedFieldNames: readonly string[]\n}\n\n/**\n * Phase 1 (validate) of the reconcile-path's two-phase graph wiring (#638\n * Task 2 fix wave 2). Pure — throws `ValidationError`, never mutates `graph`.\n *\n * Evaluates the COMBINED existing+incoming computed/classified state, using\n * `graph` as the vault-side memory of what a PRIOR, separate\n * `vault.collection()` call already registered (review Finding I1): a\n * depsless computed field declared while no classified field existed yet\n * registers no edge (`registerCollectionGraphSources` marks it instead), so a\n * LATER call newly introducing a PERSISTABLE (`recoverable`/`digest-only`)\n * classified field must still see it and refuse, regardless of which call\n * declared which piece first. `storage: 'never'` fields are exempt from this\n * specific check: `enforceClassifiedWrite` rejects the whole write BEFORE\n * computed fields ever evaluate (`Collection._putInternal`'s pipeline order —\n * enforceWrite, then computed), so a `never`-stored value structurally cannot\n * reach a computed field's output. (`resolveComputedEdges` below, unchanged,\n * still blanket-refuses a depsless field THIS SAME call introduces alongside\n * ANY classified field regardless of storage — same as fresh construction.)\n * Given that, once a PERSISTABLE classified field is successfully committed\n * for a collection, no depsless computed field can survive uncaught (this\n * very check, or the identical fresh-construction one, would already have\n * refused it) — so this check only needs THIS call's own incoming\n * `classifiedFields`, never `graph`'s classified memory.\n *\n * Each `computed` entry's own `deps` (#638 Task 7 — the reconcile path only ever sees the\n * `computed:` sugar option, per `ReconcileGraphOptions`'s doc comment; `via(computed(...))`\n * is construction-only like i18nFields/dictKeyFields) are resolved via `resolveComputedEdges`\n * exactly like the fresh-construction path — Finding I2ii's original knownFields-sharing\n * concern is back in play for the Task 7 review's CRITICAL fix: on a collection that\n * declares classified fields, `resolveComputedEdges` now checks every `deps` entry against\n * a `knownFields` universe built via the SAME `collectKnownFieldNames` helper the fresh path\n * uses (never a hand-rolled second universe), scoped to THIS call's own\n * `moneyFields`/`classifiedFields`/`computed` options (see `resolveComputedEdges`'s own doc\n * comment for the full rationale and its documented residual limit). On a non-classified\n * collection a plain, non-via field is still a legal dep, unchanged from Task 7.\n *\n * Callers MUST call this BEFORE any `_apply*` mutation runs, and must only\n * call `commitReconcileGraphEdges` with the result AFTER every `_apply*` for\n * this call has succeeded (Finding M2 — no partial graph state may survive a\n * reconcile call whose config is ultimately rejected).\n */\nexport function validateReconcileGraphEdges(graph: ViaGraph, name: string, options: ReconcileGraphOptions): ReconcilePlan {\n const resolvedClassified = options.classifiedFields !== undefined\n ? resolveClassifiedFields(name, options.classifiedFields)\n : undefined\n\n if (resolvedClassified !== undefined && Object.values(resolvedClassified.byField).some((spec) => spec.storage !== 'never')) {\n // A pre-existing depless field whose name collides with one of THIS\n // call's classified rider companions is exempt. Two DIFFERENT existing\n // mechanisms make this safe, depending on whether classified was already\n // attached before this call — the rider-companion collision check in\n // `_applyClassifiedFields` (collection.ts) is NOT unconditional; it sits\n // AFTER that same method's first-wins early return, so it only runs on the\n // FIRST-EVER classified attach: (a) first attach — that collision check\n // runs and refuses the combination outright; (b) classified ALREADY\n // attached — the early return drops THIS call's whole incoming\n // declaration, rider companions included, before the collision check is\n // ever reached, so nothing new is merged for it to collide with. Either\n // way the dangerous state (an opaque depsless computed field silently\n // colliding with a rider name) never forms — no need for this guard to\n // preempt it with a less specific error (`classified/threading.test.ts`'s\n // \"reconcile collision\" fixture pins case (a)'s exact, more specific,\n // ClassifiedConfigError).\n const riderNames = new Set(Object.keys(resolvedClassified.riderComputed))\n const leaking = [...graph.depslessComputedFields(name)].filter((field) => !riderNames.has(field))\n if (leaking.length > 0) {\n const field = leaking[0]\n throw new ValidationError(\n `Collection \"${name}\": computed field \"${field}\" has no declared \\`deps\\` and the ` +\n `collection declares classified fields — an opaque computed function could silently copy a ` +\n `classified field's plaintext into an ordinary, unredacted field. Declare \\`deps\\` naming the ` +\n `source fields it reads, e.g. computed: { ${field}: { fn, deps: [...] } }.`,\n )\n }\n }\n\n const combinedHasClassified = graph.isClassified(name) || resolvedClassified !== undefined\n\n let edges: readonly GraphEdge[] = []\n let depslessComputedFields: readonly string[] = []\n if (options.computed !== undefined) {\n // #638 Task 7 — `mode: 'virtual'` has no late-attach reconcile door: unlike a\n // materialized entry (folded into `this.computed` by `_applyComputed`, no pipeline\n // rebuild needed), a virtual field needs the computed via-binding to exist in\n // `coll.via.bindings` — which only `compileViaBindings` (construction time) builds.\n // Declaring it here would silently fall through `_applyComputed` and get MATERIALIZED\n // (stored) instead, defeating \"never stored\". Same construction-only rule as i18nFields/\n // dictKeyFields/viaFields (`ReconcileGraphOptions`'s doc comment).\n for (const [field, entry] of Object.entries(options.computed)) {\n if (computedEntryParts(entry).mode === 'virtual') {\n throw new ValidationError(\n `Collection \"${name}\": computed field \"${field}\" declares mode: 'virtual' on a reconcile call — ` +\n `virtual computed fields are construction-only (no late-attach reconcile door); declare them in ` +\n `the collection's first vault.collection(\"${name}\", { ... }) call.`,\n )\n }\n }\n // #638 Task 7 review CRITICAL fix, #645 fix — THIS reconcile call's own options\n // (mirrors the fresh path's `knownFields`, built once per `vault.collection()` call)\n // UNIONED with `graph.knownFieldNames`'s cross-call memory of fields an EARLIER,\n // separate `vault.collection()` call already registered — without the union, a\n // computed field attached here whose `deps` correctly names a field declared\n // earlier (and never re-declared, since re-declaring is unnecessary) was\n // spuriously refused as unknown. `resolveComputedEdges`'s doc comment covers the\n // remaining residual known-but-wrong limits (unchanged by this fix).\n const knownFields = new Set([\n ...collectKnownFieldNames({\n moneyFields: options.moneyFields,\n classifiedFields: resolvedClassified?.byField,\n computed: options.computed,\n }),\n ...graph.knownFieldNames(name),\n ])\n edges = resolveComputedEdges(name, options.computed, combinedHasClassified, knownFields)\n const depFields = new Set(edges.map((edge) => edge.target.field))\n depslessComputedFields = Object.keys(options.computed).filter((field) => !depFields.has(field))\n }\n\n return {\n edges,\n depslessComputedFields,\n classifiedFieldNames: resolvedClassified !== undefined ? Object.keys(resolvedClassified.byField) : [],\n }\n}\n\n/**\n * Phase 2 (commit) — call ONLY after every `_apply*` mutation belonging to\n * this reconcile call has succeeded (see {@link validateReconcileGraphEdges}'s\n * doc comment, Finding M2). Registers `plan`'s edges, skipping any target\n * already registered so `registerDerived`'s at-most-once contract holds\n * across repeated identical `vault.collection()` calls, not just within one\n * (Finding I2i); registers the late-attached classified field(s)' sealed\n * posture (Finding M1 — fresh construction gets this for free from\n * `registerCollectionGraphSources`'s compiled-binding loop, which the\n * reconcile path has no equivalent of); and updates the depless-computed /\n * classified graph memory {@link validateReconcileGraphEdges} reads.\n */\nexport function commitReconcileGraphEdges(graph: ViaGraph, name: string, plan: ReconcilePlan): void {\n for (const edge of plan.edges) {\n // `edge.grain` is always 'record' here — `validateReconcileGraphEdges` refuses any\n // 'virtual' entry before this phase runs (#638 Task 7) — `?? 'record'` mirrors the\n // fresh-construction path's own defaulting for consistency, not because it fires.\n if (!graph.hasDerived(edge.target)) graph.registerDerived(edge.target, edge.sources, 'computed', edge.grain ?? 'record')\n }\n for (const field of plan.depslessComputedFields) graph.markDepslessComputed(name, field)\n for (const field of plan.classifiedFieldNames) graph.registerField(name, field, CLASSIFIED_POSTURE)\n if (plan.classifiedFieldNames.length > 0) graph.markClassified(name)\n}\n\n/**\n * Rebuild `coll`'s Via pipeline with the graph's taint overlay layered on\n * (#638 Task 3 — the assignment→enforcement bridge): `postureFor` (query\n * gate + `redactForExport`, `kernel/via/pipeline.ts`) enforces it with zero\n * new surface, and any field the overlay resolves to `encryptedAtRest:\n * 'sealed'` gets the `taint` binding added so it is ACTUALLY sealed at rest\n * via `ctx.sealedSlots` (the same mechanism classified uses).\n *\n * No-op when the collection has no tainted fields — `coll.via` stays exactly\n * what `resolveCollectionConfig` built, preserving `this.via === undefined`\n * for an all-plain collection (#553's sync-stack guarantee). Called once\n * after `registerCollectionGraphSources` (fresh construction) and once after\n * `commitReconcileGraphEdges` (reconcile) — a late-attached classified/\n * computed field can newly taint a field an EARLIER call already built the\n * pipeline for, so both call sites must refresh.\n *\n * Writes through `Collection._setVia` (`kernel/collection.ts`, #666) rather\n * than the old untyped structural-cast reach-in — `_setVia` does both of the\n * cast site's old two steps itself: reassigns `this.via` AND resyncs the\n * codec's OWN `via` snapshot (captured at construction, `collection.ts`'s\n * `this.codec = new RecordCodec({..., via: this.via})`, which does not\n * automatically follow a later `this.via` reassignment) so `encryptRecord`/\n * `decryptRecord` seal/unseal through the taint binding too, not a stale\n * pre-taint pipeline.\n *\n * #642 — `graph.taintedPostures(name)` also carries the collection's `'*'`\n * target (a derivation/MV/overlay OUTPUT collection's whole-record fold,\n * `via/graph.ts`'s `taintedPostures`/`taintSealedFields` already surface it\n * under the literal key `'*'`, no `via/graph.ts` change needed). Split it off\n * BEFORE building the field-specific overlay — `'*'` is never a real record\n * field — and re-derive it as `defaultPosture` through the SAME\n * `buildTaintOverlay` sealed→`queryable:'none'` clamp (reused, not\n * duplicated, by feeding it a one-entry map). A sealed default folds into\n * the SAME single `taintBinding` call via `sealAllFields` — every field\n * (present-time, at-rest) is covered without a second binding.\n */\nexport function applyTaintOverlay(coll: HasWritableViaPipeline, graph: ViaGraph, name: string): void {\n const raw = graph.taintedPostures(name)\n const rawDefault = raw.get('*')\n const rawFields = rawDefault === undefined ? raw : new Map([...raw].filter(([field]) => field !== '*'))\n const allSealFields = graph.taintSealedFields(name)\n const sealFields = allSealFields.has('*') ? new Set([...allSealFields].filter((f) => f !== '*')) : allSealFields\n const postures = buildTaintOverlay(rawFields, sealFields)\n const defaultPosture = rawDefault === undefined\n ? undefined\n : buildTaintOverlay(new Map([['*', rawDefault]]), allSealFields)?.get('*')\n if (!postures && defaultPosture === undefined) return\n const provenance = graph.taintProvenance(name)\n // #638 Task 7 — a virtual computed field is never sealed (`taintSealedFields` already\n // excludes `grain: 'virtual'` — nothing is stored, so nothing to seal), but a TAINTED\n // one (exportable:false, i.e. its deps include a classified/sealed source) still needs\n // its value replaced on every READ: `present()` is the only place a virtual field's\n // value ever exists (never stored, so `redactForExport`'s export-only pass is not\n // enough — the plain `get()`/`list()` path must be closed too).\n const virtualFields = graph.virtualFields(name)\n const virtualExportRedact = new Set<string>()\n if (postures) {\n for (const [field, posture] of postures) {\n if (posture.exportable === false && virtualFields.has(field)) virtualExportRedact.add(field)\n }\n }\n const sealAll = defaultPosture?.encryptedAtRest === 'sealed'\n const needsTaintBinding = sealFields.size > 0 || virtualExportRedact.size > 0 || sealAll\n // #642 Fix wave 1 — strip a PRIOR 'taint' binding before (maybe) appending a fresh one: a\n // base config compiled by `compileViaBindings` never carries 'taint' itself (only this\n // function ever constructs one), so any 'taint' entry already on `coll._via.bindings` is a\n // leftover from an earlier `applyTaintOverlay` call on THIS SAME collection (fresh-open +\n // every `reapplyDependentOverlays` refresh) — without stripping it first, each re-apply\n // accumulated one more binding onto the list (harmless in effect, since every lookup only\n // ever consults the LAST match, but unbounded and wrong).\n const existingBindings = (coll._via?.bindings ?? []).filter((b) => b.brand !== 'taint')\n const bindings = needsTaintBinding\n ? [...existingBindings, taintBinding(sealFields, virtualExportRedact, sealAll)]\n : existingBindings\n const taint: ViaTaintOverlay = {\n postures: postures ?? EMPTY_POSTURE_MAP, sealFields, provenance,\n ...(defaultPosture !== undefined ? { defaultPosture } : {}),\n }\n coll._setVia(ViaPipeline.build(bindings, taint))\n}\n\n/**\n * #642 — the cross-collection re-apply gap (seam map finding 4/10): when the\n * OUTPUT/parent collection was opened (its overlay built) BEFORE the\n * classified SOURCE collection ever registered a field, the output's `'*'`\n * fold (or a rollup's real-field fold) was computed against an empty/stale\n * source posture. `applyTaintOverlay` alone never re-fires for an already-\n * open dependent — this hook closes that: after `name` registers its OWN\n * field postures (called right after `applyTaintOverlay(coll, graph, name)`\n * at each collection-construction call site), re-run `applyTaintOverlay` for\n * every OPEN collection that graph-depends on `name`.\n *\n * Pure wiring — re-applies OVERLAYS only (a pipeline rebuild), never\n * re-registers a graph edge (`registerDerived`'s at-most-once contract, D-2\n * wave-2 law, is untouched). `graph.dependentsOf(name)` already excludes\n * `'ref'` edges (a referencing field must not seal just because its backing\n * dimension changed — the phase-D lookup identity contract). A dependent\n * collection that hasn't been opened yet (`getOpenCollection` returns\n * `undefined`) is skipped — it will fold correctly on its OWN first-open\n * `applyTaintOverlay` call, which reads the graph fresh.\n */\nexport function reapplyDependentOverlays(\n graph: ViaGraph, name: string,\n getOpenCollection: (n: string) => HasWritableViaPipeline | undefined,\n): void {\n const targets = new Set(graph.dependentsOf(name).map((edge) => edge.target.collection))\n for (const target of targets) {\n const coll = getOpenCollection(target)\n if (coll !== undefined) applyTaintOverlay(coll, graph, target)\n }\n}\n\nconst EMPTY_POSTURE_MAP: ReadonlyMap<string, ViaPosture> = new Map()\n","/**\n * kernel/via/reconcile.ts — #664 the late-attach reconcile-path dispatch.\n *\n * `vault.ts`'s reconcile branch (a SECOND-OR-LATER `vault.collection(name, {...})` call on an\n * already-open collection) used to be a flat 5-branch `if (coll && X) coll._applyX(...)` ladder\n * with no collision guard and no i18n/dictKey machinery at all (i18nFields/dictKeyFields were\n * silently ignored on re-open — only the fresh-construction branch ever wired them). This module\n * moves that whole ladder OUT of `vault.ts` (a kernel-surface-ceiling-guarded file) into ONE\n * dispatch entry point, {@link reconcileViaAttach}, that:\n *\n * 1. runs the late-attach collision guard ({@link guardReconcileCollisions}, via/compose.ts)\n * BEFORE any mutation — both the incoming×incoming and existing×incoming recipes;\n * 2. routes the FIVE pre-existing reconciles (money/computed/fieldMeta/meta/classified) through\n * their unchanged `Collection._applyX` methods (collection.ts is NOT touched — this dispatch\n * only orchestrates, matching the pre-#664 call order exactly);\n * 3. commits the two-phase graph-edge reconcile (`via/graph-wiring.ts`) + taint overlay, exactly\n * as before;\n * 4. wires i18n/dictKey late-attach via {@link reconcileI18nFields}/{@link reconcileDictKeyFields}\n * — rebuilding the pipeline through {@link Collection._setVia} (#666's writer seam), mirroring\n * the fresh-construction wiring (`collection-config.ts#compileViaBindings`'s i18n slot +\n * `vault.ts`'s registry population) without duplicating it in a second place;\n * 5. (#664 Part 2b) wires lookup()/enumOf()/dict() late-attach via {@link reconcileLookupFields}\n * — tier-scoped: enum/static tiers are a clean, self-contained attach; the reserved (dict)\n * tier additionally updates the SAME vault registries the fresh path populates\n * (`dictKeyFieldRegistry`/`reservedLookupCollections`/`staticDescriptorByField`/`staticByName`/\n * `staticDictNames`, via `collectLookupDictCompat`); the matrix (`backing:'collection'`) tier\n * is gated by {@link refuseUnattachableMatrixLookupFields} — refuses with a `ValidationError`\n * unless the backing collection is already open (this vault session) and prefetch-enabled.\n *\n * `ViaReconcileVaultCtx` takes the vault-resident registry Maps/closures the i18n/dictKey wiring\n * needs as a plain structural bag of ARGUMENTS (mirroring `via/lookup/registry.ts`'s own\n * \"#650 Task 1\" extraction pattern) — never a `Vault` import (this file is part of the kernel\n * spine's `port/with/`-only import discipline — S5 port-layering, `scripts/check-architecture.mjs`\n * `checkPortLayering`), so `vault.ts` passes `this` once its relevant fields are readable from\n * outside the class (see `Vault`'s field declarations).\n */\nimport type { Collection } from '../collection.js'\nimport { ViaPipeline, type HasWritableViaPipeline } from './pipeline.js'\nimport { viaBinder, type ViaBinding } from './index.js'\nimport { guardReconcileCollisions, type MergedViaFields } from './compose.js'\nimport type { ViaGraph } from './graph.js'\nimport {\n validateReconcileGraphEdges, commitReconcileGraphEdges, applyTaintOverlay,\n type ReconcileGraphOptions,\n} from './graph-wiring.js'\nimport { ValidationError } from '../errors.js'\nimport { resolveClassifiedFields } from '../../port/with/classified-strategy.js'\nimport {\n isStaticDictDescriptor,\n type I18nStrategy, type I18nTextDescriptor, type DictKeyDescriptor, type StaticDictDescriptor, type DictionaryHandle,\n} from '../../port/with/i18n-strategy.js'\nimport {\n resolveLabelFromMap, dictCollectionName, collectLookupDictCompat, checkLookupMembership, buildLookupAltIndex,\n buildLookupSnapshotRows, registerLookupRefEdges, buildPresentForJoin, type LookupDescriptor,\n} from '../../port/with/lookup-strategy.js'\n\ntype AnyCollection = Collection<Record<string, unknown>>\n\n/**\n * Structural reconcile-capable collection handle: `_via`/`_setVia` (#666's writer seam) plus the\n * five pre-existing `_applyX` late-attach methods (#623/#629/#638). Every parameter type is\n * DERIVED off `Collection` itself via `Parameters<...>` rather than imported by name — several\n * (`FieldMeta`, `CollectionMeta`, `ComputedFields`) are with-* service types the kernel spine may\n * not statically import (S5 port-layering); deriving them off the already-typed `Collection`\n * method avoids a second, duplicate type declaration too (mirrors `via/graph-wiring.ts`'s\n * `ComputedFieldsParam` trick).\n */\nexport interface ReconcilableCollection extends HasWritableViaPipeline {\n _applyMoneyFields(moneyFields: Parameters<AnyCollection['_applyMoneyFields']>[0]): void\n _applyComputed(computed: Parameters<AnyCollection['_applyComputed']>[0]): void\n _applyFieldMeta(fieldMeta: Parameters<AnyCollection['_applyFieldMeta']>[0]): void\n _applyMeta(meta: Parameters<AnyCollection['_applyMeta']>[0]): void\n _applyClassifiedFields(classifiedFields: Parameters<AnyCollection['_applyClassifiedFields']>[0]): void\n /** #671 items 1-3 — the reader + writer seam for `getDictionary`/legacy describe() lists/`presentForJoin`. */\n readonly _viaFieldsSnapshot: AnyCollection['_viaFieldsSnapshot']\n _reconcileReadState(patch: Parameters<AnyCollection['_reconcileReadState']>[0]): void\n}\n\n/** The vault-resident state/closures the i18n/dictKey late-attach wiring reads and writes —\n * the SAME registries `vault.ts`'s fresh-construction branch populates (`i18nFieldRegistry`\n * :884-886, the dictKeyFields split :903-940, `dictLabelResolver`/`i18nPutValidator`/\n * `autoTranslateHook` :1111-1155), passed as plain values (never `this: Vault`) so this module\n * never imports the `Vault` class. */\nexport interface ViaReconcileVaultCtx {\n readonly i18nStrategy: I18nStrategy\n /** — named `locale`, not `defaultLocale`, to match `Vault`'s own field name 1:1 (so `this`\n * satisfies this interface structurally with zero adapter object at the call site). */\n readonly locale: string | undefined\n readonly translateText:\n | ((text: string, from: string, to: string, field: string, collection: string) => Promise<string>)\n | undefined\n readonly i18nFieldRegistry: Map<string, Record<string, I18nTextDescriptor>>\n readonly dictKeyFieldRegistry: Map<string, Record<string, string>>\n readonly staticDescriptorByField: Map<string, Record<string, StaticDictDescriptor>>\n readonly reservedLookupCollections: Map<string, string>\n readonly staticByName: Map<string, StaticDictDescriptor>\n readonly staticDictNames: Set<string>\n dictionary(name: string): DictionaryHandle\n enforceI18nOnPut(collectionName: string, record: unknown): void\n enforceStaticDictOnPut(collectionName: string, record: unknown): void\n /** #664 Part 2b — the matrix-tier lookup late-attach gate: \"is this dimension already open in\n * this vault session\" (never constructs a fresh collection) — `Vault._getCollection`. */\n getOpenCollection(name: string): AnyCollection | undefined\n /** #664 Part 2b — the vault's CONSTRUCTING collection accessor the lookup binding's lazy\n * closures (`getLookupBacking`/`membership`/`getAltIndex`/`snapshotFor`) read through — mirrors\n * `vault.ts`'s fresh-construct `(n) => this.collection<Record<string, unknown>>(n)` closure\n * verbatim. Only ever invoked, for a matrix-tier dimension, once {@link getOpenCollection}'s\n * gate has already confirmed it is open — never the door that opens it. */\n getCollection(name: string): AnyCollection\n}\n\nfunction hasI18nBinding(coll: ReconcilableCollection): boolean {\n return (coll._via?.bindings ?? []).some((b) => b.brand === 'i18n')\n}\n\n/** money-after / lookup-before — the SAME slot `compileViaBindings` (collection-config.ts)\n * compiles the i18n binding into (money→i18n→lookup→classified→blob→computed, taint appended\n * last by `applyTaintOverlay`). Late-attach only ever INSERTS one i18n binding (first-wins —\n * see {@link hasI18nBinding}), so a plain \"before the first post-i18n family\" scan is enough;\n * no money-prepend/classified-append juggling like `_applyMoneyFields`/`_applyClassifiedFields`\n * need (those two mutate around an i18n binding that might already be there; i18n itself never\n * needs to reorder around a LATER family, since none of money/i18n/lookup/classified/blob/\n * computed's own late-attach paths re-sort on insert). */\nfunction insertI18nBinding(existing: readonly ViaBinding[], i18nBinding: ViaBinding): ViaBinding[] {\n const idx = existing.findIndex((b) =>\n b.brand === 'lookup' || b.brand === 'classified' || b.brand === 'blob' || b.brand === 'computed' || b.brand === 'taint')\n return idx === -1 ? [...existing, i18nBinding] : [...existing.slice(0, idx), i18nBinding, ...existing.slice(idx)]\n}\n\nfunction hasLookupBinding(coll: ReconcilableCollection): boolean {\n return (coll._via?.bindings ?? []).some((b) => b.brand === 'lookup')\n}\n\n/** lookup slots right after i18n, before classified/blob/computed/taint — the SAME\n * money→i18n→lookup→classified→blob→computed compile order (collection-config.ts:554).\n * Late-attach only ever inserts ONE lookup binding (first-wins — see {@link hasLookupBinding}),\n * so scanning for the first binding that must come AFTER lookup is enough (mirrors\n * {@link insertI18nBinding}'s own reasoning); an i18n binding present at insert time is already\n * earlier in `existing` (either compiled fresh, or late-attached by an EARLIER reconcile call —\n * {@link insertI18nBinding}'s own stop-list includes `'lookup'`, so the reverse ordering is\n * symmetric regardless of which family attaches first). */\nfunction insertLookupBinding(existing: readonly ViaBinding[], lookupBindingObj: ViaBinding): ViaBinding[] {\n const idx = existing.findIndex((b) => b.brand === 'classified' || b.brand === 'blob' || b.brand === 'computed' || b.brand === 'taint')\n return idx === -1 ? [...existing, lookupBindingObj] : [...existing.slice(0, idx), lookupBindingObj, ...existing.slice(idx)]\n}\n\n/**\n * #664 Part 2b — the matrix (`backing:'collection'`) tier's late-attach gate. Unlike enum/static\n * (self-contained) or reserved (vault-registry-backed), matrix reads ANOTHER live collection's\n * cache via `querySourceForJoin()` — `getLookupBacking`/`membership`/`getAltIndex`/`snapshotFor`\n * (built below in {@link reconcileLookupFields}) are all vault-built closures that stay lazy,\n * mirroring the fresh-construct path exactly. At FRESH construction that laziness is harmless —\n * the backing dimension may simply not exist yet, and the closures only ever fire once it does.\n * A LATE attach is different: the vault is already mid-session, so silently deferring would let a\n * matrix field attach onto a dimension that never opens (or opens lazy) this session, surfacing\n * the confusing join-branded lazy-mode error on some UNRELATED later put()/read() instead of at\n * the point of declaration — the exact silent-deferral failure class `getAltIndexOrThrow`\n * (`via/lookup/binding.ts:252-264`) already refuses for altKeys specifically. This closes it\n * for the field's very existence: REFUSE eagerly, at attach time, with a `ValidationError` naming\n * the field, the dimension, and the remedy, unless the backing dimension is ALREADY open (in THIS\n * vault session — `vaultCtx.getOpenCollection`, which never constructs) AND prefetch-enabled\n * (probed via `querySourceForJoin()` itself — the SAME lazy-mode signal `getAltIndexOrThrow`\n * reads, never a private `Collection` field reach-around; `collection.ts` is untouched by #664).\n *\n * Callers MUST run this BEFORE any `_apply*` mutation for the WHOLE reconcile call (Finding-M2\n * ordering law, `via/graph-wiring.ts#validateReconcileGraphEdges`'s doc comment) — see\n * {@link reconcileViaAttach}'s own early call, which runs this ahead of money/computed/classified\n * apply so a combined call (e.g. `moneyFields` + a not-yet-open matrix `lookupFields` entry) never\n * partially mutates money state before the whole call is refused. Also re-run at the top of\n * {@link reconcileLookupFields} itself (cheap, pure, idempotent) so a direct/standalone caller of\n * that function stays self-protecting too.\n */\nfunction refuseUnattachableMatrixLookupFields(\n vaultCtx: ViaReconcileVaultCtx,\n lookupFields: Record<string, LookupDescriptor>,\n): void {\n for (const [field, desc] of Object.entries(lookupFields)) {\n if (desc.backing !== 'collection') continue\n const backing = vaultCtx.getOpenCollection(desc.dimension)\n if (!backing) {\n throw new ValidationError(\n `lookup: matrix field \"${field}\" (backing dimension \"${desc.dimension}\") cannot be late-attached — ` +\n `\"${desc.dimension}\" is not open in this vault session yet. Open it first, e.g. ` +\n `vault.collection('${desc.dimension}', { ... }), with prefetch enabled (the default) before ` +\n `attaching \"${field}\" via a later vault.collection() call.`,\n )\n }\n try {\n backing.querySourceForJoin()\n } catch (err) {\n if (err instanceof Error && err.message.includes('lazy-mode')) {\n throw new ValidationError(\n `lookup: matrix field \"${field}\" (backing dimension \"${desc.dimension}\") cannot be late-attached — ` +\n `\"${desc.dimension}\" is open in lazy mode ({ prefetch: false }). Re-open \"${desc.dimension}\" ` +\n `without { prefetch: false } (eager mode, the default) before attaching \"${field}\".`,\n )\n }\n throw err\n }\n }\n}\n\n/** Mirrors `vault.ts`'s `collOpts.dictLabelResolver` closure (:1117-1125) verbatim — a static\n * dict resolves from its in-memory table, a plain dictKey resolves through the encrypted\n * `_dict_*` handle. */\nfunction buildDictLabelResolver(vaultCtx: ViaReconcileVaultCtx) {\n return async (dictName: string, key: string, locale: string, fallback?: string | readonly string[]): Promise<string | undefined> => {\n const stat = vaultCtx.staticByName.get(dictName)\n if (stat) {\n const labels = stat.table[key]\n return labels ? resolveLabelFromMap(labels, locale, fallback) : undefined\n }\n return vaultCtx.dictionary(dictName).resolveLabel(key, locale, fallback)\n }\n}\n\n/** Mirrors `vault.ts`'s dictKeyFields registry-population loop (:909-939) — split into the\n * rename-tracked (`dictKeyFieldRegistry`) vs static-table (`staticDescriptorByField`) forms,\n * registering each referenced dictionary into `reservedLookupCollections` for sync. */\nfunction registerDictKeyRegistries(\n vaultCtx: ViaReconcileVaultCtx, name: string,\n dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor>,\n): void {\n const dictFieldMap: Record<string, string> = {}\n const staticFieldMap: Record<string, StaticDictDescriptor> = {}\n for (const [field, desc] of Object.entries(dictKeyFields)) {\n if (isStaticDictDescriptor(desc)) {\n staticFieldMap[field] = desc\n vaultCtx.staticDictNames.add(desc.name)\n vaultCtx.staticByName.set(desc.name, desc)\n } else {\n dictFieldMap[field] = desc.name\n }\n }\n if (Object.keys(dictFieldMap).length > 0) {\n vaultCtx.dictKeyFieldRegistry.set(name, dictFieldMap)\n for (const dictName of new Set(Object.values(dictFieldMap))) {\n vaultCtx.reservedLookupCollections.set(dictCollectionName(dictName), dictName)\n }\n }\n if (Object.keys(staticFieldMap).length > 0) {\n vaultCtx.staticDescriptorByField.set(name, staticFieldMap)\n }\n}\n\n/** Mirrors `compileViaBindings`'s i18n slot (collection-config.ts:702-723) — same densify-subset\n * computation, same config shape handed to `viaBinder('i18n')`. `defaultPosture`/taint is\n * preserved across the rebuild, same as `_applyMoneyFields`/`_applyClassifiedFields`\n * (`kernel/collection.ts`, #671 item 4 fix) — every rebuild path threads `coll._via?.taint`\n * through its own `ViaPipeline.build(...)` call now, so none of them depends on a same-call\n * `applyTaintOverlay` re-run to avoid silently un-tainting an already-tainted field. */\nfunction rebuildI18nBinding(\n coll: ReconcilableCollection, vaultCtx: ViaReconcileVaultCtx, name: string,\n i18nFields: Record<string, I18nTextDescriptor> | undefined,\n dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined,\n): void {\n const densify = i18nFields\n ? Object.fromEntries(Object.entries(i18nFields).filter(([, d]) => d.options.densifyOnWrite === true))\n : {}\n const i18nDensifyFields = Object.keys(densify).length > 0 ? densify : undefined\n const binding = viaBinder('i18n')({\n ...(i18nFields !== undefined ? { i18nFields } : {}),\n ...(dictKeyFields !== undefined ? { dictKeyFields } : {}),\n ...(i18nDensifyFields !== undefined ? { i18nDensifyFields } : {}),\n strategy: vaultCtx.i18nStrategy,\n ...(vaultCtx.locale !== undefined ? { defaultLocale: vaultCtx.locale } : {}),\n ...(i18nFields !== undefined && vaultCtx.translateText !== undefined ? { autoTranslateHook: vaultCtx.translateText } : {}),\n ...(dictKeyFields !== undefined ? { dictLabelResolver: buildDictLabelResolver(vaultCtx) } : {}),\n i18nPutValidator: (record: unknown) => { vaultCtx.enforceI18nOnPut(name, record); vaultCtx.enforceStaticDictOnPut(name, record) },\n collectionName: name,\n })\n const existing = coll._via?.bindings ?? []\n coll._setVia(ViaPipeline.build(insertI18nBinding(existing, binding), coll._via?.taint))\n}\n\n/**\n * #664 Part 2 — late-attach i18nText fields. First-wins (mirrors `_applyMoneyFields`'s own\n * first-wins convention): a no-op once the collection already has an 'i18n' binding, whether\n * that binding came from fresh construction or an earlier reconcile call. `dictKeyFields` is an\n * optional SECOND family arriving in the SAME `vault.collection()` call (`mergeViaFields` already\n * combined them for this one call) — passed through so ONE binding rebuild covers both, exactly\n * like `compileViaBindings` builds ONE 'i18n' binding from both maps at fresh construction.\n */\nexport function reconcileI18nFields(\n coll: ReconcilableCollection, vaultCtx: ViaReconcileVaultCtx, name: string,\n i18nFields: Record<string, I18nTextDescriptor> | undefined,\n dictKeyFields?: Record<string, DictKeyDescriptor | StaticDictDescriptor>,\n): void {\n if (i18nFields === undefined) return\n if (hasI18nBinding(coll)) return\n vaultCtx.i18nFieldRegistry.set(name, i18nFields)\n if (dictKeyFields !== undefined) registerDictKeyRegistries(vaultCtx, name, dictKeyFields)\n rebuildI18nBinding(coll, vaultCtx, name, i18nFields, dictKeyFields)\n}\n\n/**\n * #664 Part 2 — late-attach dictKeyFields (dictKey()/staticDict()) with NO i18nFields in the same\n * call — the dictKey-only late-attach door. First-wins, same convention as\n * {@link reconcileI18nFields} (and, transitively, a no-op if that sibling function already\n * handled a combined i18nFields+dictKeyFields call for this collection).\n */\nexport function reconcileDictKeyFields(\n coll: ReconcilableCollection, vaultCtx: ViaReconcileVaultCtx, name: string,\n dictKeyFields: Record<string, DictKeyDescriptor | StaticDictDescriptor> | undefined,\n): void {\n if (dictKeyFields === undefined) return\n if (hasI18nBinding(coll)) return\n registerDictKeyRegistries(vaultCtx, name, dictKeyFields)\n rebuildI18nBinding(coll, vaultCtx, name, undefined, dictKeyFields)\n}\n\n/**\n * #664 Part 2b — late-attach lookup()/enumOf()/dict() fields, tier-scoped (issue #664, spec-\n * ratified tier policy):\n *\n * - **enum** (`backing:'static'`, no `table`) / **static** (`+table`) — self-contained:\n * membership/labels come from the declared `keys`/`table` alone, no vault registry touch, no\n * cross-collection read. Clean attach, same shape as i18n/dictKey's own reconcile door.\n * - **reserved** (`dict()` / `lookup(dim, { backing:'reserved' })`) — additionally registers into\n * the SAME vault registries the fresh path populates (`vault.ts`'s dictKeyFields/lookupFields\n * registry-population loop) — `dictKeyFieldRegistry`/`reservedLookupCollections` for a bare\n * dict field; `staticDescriptorByField`/`staticByName`/`staticDictNames` for a table-bearing\n * static field — via `collectLookupDictCompat` (#650 Task 2's alias-equivalence bridge, the\n * SAME helper the fresh path already calls), reused verbatim, not duplicated.\n * - **matrix** (`backing:'collection'`) — gated by {@link refuseUnattachableMatrixLookupFields}.\n *\n * First-wins (mirrors {@link reconcileI18nFields}): a no-op once the collection already has a\n * 'lookup' binding, whether from fresh construction or an earlier reconcile call.\n *\n * Post-attach, registers the SAME cross-collection `'ref'` graph edges the fresh path does\n * (`registerLookupRefEdges` — internally skips the static tier, which has no backing collection to\n * reference-check) — `ViaGraph.referencingEdgesOf` sees them immediately, so delete-time\n * restrict/cascade/nullify semantics are live post-attach too, same as a fresh declaration.\n */\nexport function reconcileLookupFields(\n coll: ReconcilableCollection, vaultCtx: ViaReconcileVaultCtx, graph: ViaGraph, name: string,\n lookupFields: Record<string, LookupDescriptor> | undefined,\n): void {\n if (lookupFields === undefined) return\n if (hasLookupBinding(coll)) return\n refuseUnattachableMatrixLookupFields(vaultCtx, lookupFields) // standalone-caller safety net — see its own doc comment\n\n const compat = collectLookupDictCompat(lookupFields)\n if (Object.keys(compat.dictFieldMap).length > 0) {\n vaultCtx.dictKeyFieldRegistry.set(name, { ...(vaultCtx.dictKeyFieldRegistry.get(name) ?? {}), ...compat.dictFieldMap })\n for (const dictName of new Set(Object.values(compat.dictFieldMap))) {\n vaultCtx.reservedLookupCollections.set(dictCollectionName(dictName), dictName)\n }\n }\n if (compat.staticEntries.length > 0) {\n const staticFieldMap = { ...(vaultCtx.staticDescriptorByField.get(name) ?? {}) }\n for (const [field, desc] of compat.staticEntries) {\n staticFieldMap[field] = desc\n vaultCtx.staticDictNames.add(desc.name)\n vaultCtx.staticByName.set(desc.name, desc)\n }\n vaultCtx.staticDescriptorByField.set(name, staticFieldMap)\n }\n\n // must move together with collection-config.ts:642-651's lookup slot (#664) — same\n // viaBinder('lookup') option-shape contract.\n const binding = viaBinder('lookup')({\n lookupFields,\n // must move together with vault.ts:1133-1139's five lookup closures (#664) — same\n // lookupLabelResolver/getLookupBacking/membership/getAltIndex/snapshotFor construction.\n lookupLabelResolver: buildDictLabelResolver(vaultCtx),\n getLookupBacking: (desc: LookupDescriptor) => async (key: string) =>\n buildLookupSnapshotRows(desc, (n) => vaultCtx.reservedLookupCollections.has(dictCollectionName(n)), (n) => vaultCtx.dictionary(n), (n) => vaultCtx.getCollection(n))?.get(key) ??\n (desc.key === 'id' ? ((await vaultCtx.getCollection(desc.dimension).get(key)) ?? undefined) : undefined),\n membership: (field: string, key: string) => checkLookupMembership(lookupFields[field]!, key, (n) => vaultCtx.dictionary(n), (n) => vaultCtx.getCollection(n)),\n getAltIndex: (d: LookupDescriptor) => buildLookupAltIndex(d, (n) => vaultCtx.dictionary(n), (n) => vaultCtx.getCollection(n)),\n snapshotFor: (d: LookupDescriptor) =>\n buildLookupSnapshotRows(d, (n) => vaultCtx.reservedLookupCollections.has(dictCollectionName(n)), (n) => vaultCtx.dictionary(n), (n) => vaultCtx.getCollection(n)),\n collectionName: name,\n })\n const existing = coll._via?.bindings ?? []\n coll._setVia(ViaPipeline.build(insertLookupBinding(existing, binding), coll._via?.taint))\n registerLookupRefEdges(graph, name, lookupFields)\n}\n\n/** Vault-resident lookup-row source for {@link buildPresentForJoin}'s label dressing — factors out\n * the SAME `reservedLookupCollections`/`dictionary`/`getCollection` wiring {@link reconcileLookupFields}\n * builds inline for its own `snapshotFor`/`getLookupBacking`, so {@link reconcileCollectionReadState}\n * (which may run when only i18n — not lookup — was newly attached, over a PRE-EXISTING lookup\n * family) can reuse it without duplicating the vaultCtx plumbing. */\nfunction buildSnapshotFor(vaultCtx: ViaReconcileVaultCtx) {\n return (d: LookupDescriptor) =>\n buildLookupSnapshotRows(d, (n) => vaultCtx.reservedLookupCollections.has(dictCollectionName(n)), (n) => vaultCtx.dictionary(n), (n) => vaultCtx.getCollection(n))\n}\n\n/**\n * #671 items 1-3 — refresh the THREE construction-frozen `Collection` read-side residuals a\n * late-attach used to leave stale: `getDictionary` (describe()'s dict-label resolution / the\n * search-index's label pre-computation), the legacy `describe()` top-level dictKeyFields/\n * i18nFields/lookupFields KEY LISTS (the PER-FIELD `describeFragment` is already correct — this is\n * specifically the separately-frozen list feeding `buildDescription`'s field-list/widget\n * derivation), and `presentForJoin` (`querySourceForJoin()`'s join-dressing hook).\n *\n * No-op unless THIS call actually attached a NEW family — `i18nJustAttached`/`lookupJustAttached`\n * mirror {@link reconcileI18nFields}/{@link reconcileLookupFields}'s own first-wins gate (a\n * redundant re-declare must stay a no-op here too, or an already-refused field would smuggle its\n * way into the read-state via this side door). `getDictionary` mirrors `vault.ts`'s\n * construction-time gate (`dictKeyFields || lookupFields`, never bare i18nText alone).\n * `presentForJoin` is rebuilt via {@link buildPresentForJoin} (the `port/with/lookup-strategy.js`\n * re-export — the SAME Check-14-legal channel `collection-config.ts` uses for the fresh-\n * construction build) over the UNION of the collection's PRE-existing i18nFields/lookupFields\n * ({@link Collection._viaFieldsSnapshot}, read BEFORE this call's own writes below) and whatever\n * this call just attached — covering the mixed case (e.g. lookup already present at construction,\n * i18n late-attached now) as well as the bare-then-declare one the test suite exercises.\n */\nfunction reconcileCollectionReadState(\n coll: ReconcilableCollection, vaultCtx: ViaReconcileVaultCtx,\n plan: ReconcileLateAttachPlan, hadI18n: boolean, hadLookup: boolean,\n): void {\n const i18nJustAttached = !hadI18n && hasI18nBinding(coll)\n const lookupJustAttached = !hadLookup && hasLookupBinding(coll)\n if (!i18nJustAttached && !lookupJustAttached) return\n const dictKeyFields = i18nJustAttached ? plan.effectiveViaFields.dictKeyFields : undefined\n const i18nFieldsLate = i18nJustAttached ? plan.effectiveViaFields.i18nFields : undefined\n const lookupFieldsLate = lookupJustAttached ? plan.effectiveViaFields.lookupFields : undefined\n const snap = coll._viaFieldsSnapshot\n const presentForJoin = buildPresentForJoin({ ...snap.i18nFields, ...i18nFieldsLate }, { ...snap.lookupFields, ...lookupFieldsLate }, buildSnapshotFor(vaultCtx))\n coll._reconcileReadState({\n ...(dictKeyFields !== undefined ? { dictKeyFields } : {}),\n ...(i18nFieldsLate !== undefined ? { i18nFields: i18nFieldsLate } : {}),\n ...(lookupFieldsLate !== undefined ? { lookupFields: lookupFieldsLate } : {}),\n ...(dictKeyFields !== undefined || lookupFieldsLate !== undefined ? { getDictionary: async (n: string) => vaultCtx.dictionary(n) } : {}),\n ...(presentForJoin !== undefined ? { presentForJoin } : {}),\n })\n}\n\n/** The late-attach reconcile call's field-declaring options — the slice of `vault.collection()`'s\n * `options` a reconcile call may carry, plus the `mergeViaFields` output that feeds both the\n * guard and the money/i18n/dictKey/lookup reconciles. `blobFields` has no `_apply*` door (guard\n * visibility only — an incoming×incoming collision with `blobFields` must still refuse, even\n * though a bare blobFields late-attach is otherwise silently inert, matching pre-#664 behavior). */\nexport interface ReconcileLateAttachPlan {\n readonly effectiveViaFields: MergedViaFields\n readonly computed?: Parameters<AnyCollection['_applyComputed']>[0]\n readonly fieldMeta?: Parameters<AnyCollection['_applyFieldMeta']>[0]\n readonly meta?: Parameters<AnyCollection['_applyMeta']>[0]\n readonly classifiedFields?: Parameters<AnyCollection['_applyClassifiedFields']>[0]\n readonly blobFields?: Record<string, unknown>\n}\n\n/**\n * #664 — the ONE late-attach reconcile dispatch `vault.ts` calls, replacing its former 5-branch\n * `_apply*` ladder. Order: guard (before any mutation) → the matrix-tier lookup gate (also before\n * any mutation — see below) → the five pre-existing reconciles, UNCHANGED call order/semantics →\n * graph-edge commit + taint overlay (unchanged) → i18n/dictKey → lookup (#664 Part 2b).\n */\nexport function reconcileViaAttach(\n coll: ReconcilableCollection, graph: ViaGraph, name: string,\n vaultCtx: ViaReconcileVaultCtx, plan: ReconcileLateAttachPlan,\n): void {\n guardReconcileCollisions(coll._via, {\n moneyFields: plan.effectiveViaFields.moneyFields,\n i18nFields: plan.effectiveViaFields.i18nFields,\n dictKeyFields: plan.effectiveViaFields.dictKeyFields,\n lookupFields: plan.effectiveViaFields.lookupFields,\n classifiedFields: plan.classifiedFields !== undefined ? resolveClassifiedFields(name, plan.classifiedFields).byField : undefined,\n blobFields: plan.blobFields,\n computed: { ...(plan.computed ?? {}), ...(plan.effectiveViaFields.computedFields ?? {}) },\n })\n // #664 Part 2b — the matrix-tier lookup gate must run here, BEFORE money/computed/classified\n // apply below (Finding-M2 ordering law — see `refuseUnattachableMatrixLookupFields`'s own doc\n // comment): deferring it to `reconcileLookupFields`'s own call site near the bottom of this\n // function would let a combined call (e.g. `moneyFields` + a not-yet-open matrix `lookupFields`\n // entry) partially mutate money state before the whole call is ultimately refused.\n if (plan.effectiveViaFields.lookupFields !== undefined && !hasLookupBinding(coll)) {\n refuseUnattachableMatrixLookupFields(vaultCtx, plan.effectiveViaFields.lookupFields)\n }\n\n const reconcilePlan = (plan.computed || plan.classifiedFields)\n ? validateReconcileGraphEdges(graph, name, {\n // `moneyFields` here is the MERGED view (`plan.effectiveViaFields.moneyFields`), not the\n // raw incoming `moneyFields` option — intentional (controller ruling, #664a review): a\n // via()-spelled money field must count in this call's `knownFields` for computed `deps`\n // validation exactly like a sugar-keyed one does, the #627-consistent semantics. Pre-#664\n // this reconciled via a blind `options as unknown as ReconcileGraphOptions` cast, which\n // silently read the RAW option instead — never intentional, just uncovered before now.\n moneyFields: plan.effectiveViaFields.moneyFields, classifiedFields: plan.classifiedFields, computed: plan.computed,\n } as ReconcileGraphOptions)\n : undefined\n\n if (plan.effectiveViaFields.moneyFields) coll._applyMoneyFields(plan.effectiveViaFields.moneyFields)\n if (plan.computed) coll._applyComputed(plan.computed)\n if (plan.fieldMeta) coll._applyFieldMeta(plan.fieldMeta)\n if (plan.meta) coll._applyMeta(plan.meta)\n if (plan.classifiedFields) coll._applyClassifiedFields(plan.classifiedFields)\n if (reconcilePlan) {\n commitReconcileGraphEdges(graph, name, reconcilePlan)\n applyTaintOverlay(coll, graph, name)\n }\n const hadI18n = hasI18nBinding(coll)\n const hadLookup = hasLookupBinding(coll)\n if (plan.effectiveViaFields.i18nFields !== undefined) {\n reconcileI18nFields(coll, vaultCtx, name, plan.effectiveViaFields.i18nFields, plan.effectiveViaFields.dictKeyFields)\n } else if (plan.effectiveViaFields.dictKeyFields !== undefined) {\n reconcileDictKeyFields(coll, vaultCtx, name, plan.effectiveViaFields.dictKeyFields)\n }\n // Deliberately a separate `if`, not another `else if` on the i18n/dictKey pair above: lookup is\n // a THIRD, independent binding family (compileViaBindings compiles it in its own `if\n // (lookupFields !== undefined)` block, collection-config.ts:642-651 — not folded into the i18n\n // binding the way dictKeyFields is) — a single `vault.collection()` call may legally declare\n // BOTH i18nFields (or dictKeyFields) on one field AND lookupFields on another, and chaining this\n // onto the SAME else-if ladder would silently drop the lookupFields half of such a call.\n if (plan.effectiveViaFields.lookupFields !== undefined) {\n reconcileLookupFields(coll, vaultCtx, graph, name, plan.effectiveViaFields.lookupFields)\n }\n reconcileCollectionReadState(coll, vaultCtx, plan, hadI18n, hadLookup)\n}\n","import { SatelliteConfigError } from '../../kernel/errors.js'\nimport type { SatelliteSpec } from './types.js'\n\nexport class SatelliteRegistry {\n private readonly byBase = new Map<string, SatelliteSpec>()\n private readonly bySat = new Map<string, SatelliteSpec>()\n private readonly byJoin = new Map<string, SatelliteSpec>()\n private readonly poisoned = new Map<string, string>()\n private readonly locks = new Map<string, Promise<unknown>>()\n\n register(spec: SatelliteSpec): void {\n if (this.byBase.has(spec.base)) {\n throw new SatelliteConfigError(`R-S10: base \"${spec.base}\" already has satellite \"${this.byBase.get(spec.base)!.satellite}\" — v1 allows exactly one satellite per base.`)\n }\n // R-S3, order-inverted direction: `spec.satellite` was already declared as\n // a BASE (some other satellite is satelliteOf it) — registering it as a\n // satellite of `spec.base` too would form a satellite-of-satellite chain.\n // The other direction (satelliteOf pointing straight at a satellite) is\n // caught synchronously in validate.ts BEFORE register() is ever called.\n if (this.byBase.has(spec.satellite)) {\n throw new SatelliteConfigError(`R-S3: \"${spec.satellite}\" is itself registered as a base (of \"${this.byBase.get(spec.satellite)!.satellite}\") — no satellite-of-satellite chains.`)\n }\n const taken = (n: string) => this.byBase.has(n) || this.bySat.has(n) || this.byJoin.has(n)\n if (spec.joined !== undefined && taken(spec.joined)) {\n throw new SatelliteConfigError(`R-S5: joined name \"${spec.joined}\" collides with an existing pair member or joined name.`)\n }\n this.byBase.set(spec.base, spec)\n this.bySat.set(spec.satellite, spec)\n if (spec.joined !== undefined) this.byJoin.set(spec.joined, spec)\n }\n\n satelliteOf(base: string): SatelliteSpec | null { return this.byBase.get(base) ?? null }\n bySatellite(name: string): SatelliteSpec | null { return this.bySat.get(name) ?? null }\n byJoined(name: string): SatelliteSpec | null { return this.byJoin.get(name) ?? null }\n isPairMember(name: string): boolean { return this.byBase.has(name) || this.bySat.has(name) }\n allSpecs(): readonly SatelliteSpec[] { return [...this.byBase.values()] }\n\n expandNames(names: readonly string[]): string[] {\n const out = new Set(names)\n for (const n of names) {\n const asBase = this.byBase.get(n); if (asBase) out.add(asBase.satellite)\n const asSat = this.bySat.get(n); if (asSat) out.add(asSat.base)\n }\n return [...out]\n }\n\n poison(satellite: string, reason: string): void { this.poisoned.set(satellite, reason) }\n assertNotPoisoned(satellite: string): void {\n const reason = this.poisoned.get(satellite)\n if (reason !== undefined) throw new SatelliteConfigError(reason)\n }\n\n /** Per-base async mutex: chains sections on a stored promise tail. */\n async withPairLock<R>(base: string, fn: () => Promise<R>): Promise<R> {\n const tail = this.locks.get(base) ?? Promise.resolve()\n let release!: () => void\n const gate = new Promise<void>(res => { release = res })\n this.locks.set(base, tail.then(() => gate))\n await tail\n try { return await fn() } finally { release() }\n }\n}\n","/**\n * Satellite declaration wiring (#591, archetype-③) — the full body behind\n * `Vault.collection()`'s thin call-site: in-session reconcile (idempotent\n * identical redeclare / R-S9 divergent refusal), sync validation\n * (R-S3/R-S5/R-S8), the R-S7 forget-coverage gate, lazy registry + poison\n * write-gate creation, registration, and the fire-and-forget postRegister\n * (marker persistence + R-S1 cross-check). Kept dependency-narrow: no\n * `Vault` import — the kernel supplies a {@link SatelliteDeclareContext}.\n */\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { EnclaveKey } from '../../kernel/enclave/index.js'\nimport { SatelliteConfigError } from '../../kernel/errors.js'\nimport { SatelliteRegistry } from './registry.js'\nimport { validateSatelliteDeclaration, hashFields } from './validate.js'\n\n/** The narrow slice of Vault that declaration wiring needs. */\nexport interface SatelliteDeclareContext {\n readonly adapter: NoydbStore\n readonly vaultName: string\n /** `forgetStrategy.subjects` — collection → subject field (R-S7 gate input). */\n readonly forgetSubjects: Record<string, string>\n readonly getDEK: (collectionName: string) => Promise<EnclaveKey>\n /** The base collection's attached Standard Schema validator, if constructed. */\n readonly getBaseSchema: (base: string) => unknown\n /** The base collection's constructed crdt mode, if any (R-S8 direction i). */\n readonly getBaseCrdt: (base: string) => unknown\n /** True when `name` is an already-constructed collection (R-S5 joined-name guard). */\n readonly collectionExists: (name: string) => boolean\n /** Registers the vault-wide poison write-gate; invoked at most once per vault. */\n readonly registerPoisonHook: (hook: (e: { readonly vault: string; readonly collection: string }) => void) => void\n /**\n * Iterates the vault's SyncEngine(s) (#591 Task 11) — used to wire the\n * live pair-expander (once per vault, alongside `registerPoisonHook`; the\n * closure captures the registry itself, not a snapshot, so pairs declared\n * later are still picked up by push/pull filters) and to retroactively\n * re-mirror conflict resolvers on every successful pair registration.\n * No-op when sync is not configured.\n */\n readonly forEachSyncEngine: (fn: (engine: PairSyncEngine) => void) => void\n}\n\n/** The narrow slice of SyncEngine that satellite declaration wiring drives (#591 Task 11). */\ninterface PairSyncEngine {\n setPairExpander(expander: (names: readonly string[]) => readonly string[]): void\n remirrorPairResolvers(names: readonly string[]): void\n}\n\nexport interface SatelliteDeclarationOptions {\n readonly satelliteOf: string\n readonly fields?: readonly string[] | undefined\n readonly joined?: string | undefined\n readonly perRecordKeys?: boolean | undefined\n readonly crdt?: unknown\n}\n\n/**\n * Register `collectionName` as a satellite per `options`. Returns the\n * (possibly newly created) registry — the caller stores it back on the vault.\n * A refused declaration throws {@link SatelliteConfigError} and leaves NO\n * side effect (no registry created, no hook registered).\n */\nexport function declareSatellite(\n ctx: SatelliteDeclareContext,\n collectionName: string,\n options: SatelliteDeclarationOptions,\n existingRegistry: SatelliteRegistry | null,\n): SatelliteRegistry {\n if (existingRegistry !== null) {\n const existing = existingRegistry.bySatellite(collectionName)\n if (existing) { // in-session reconcile: identical redeclare is a no-op, divergent refuses (R-S9)\n const same = existing.base === options.satelliteOf\n && hashFields(existing.fields) === hashFields(options.fields ?? [])\n && (existing.joined ?? null) === (options.joined ?? null)\n if (!same) {\n throw new SatelliteConfigError(`R-S9: \"${collectionName}\" re-declared divergently within this session (base/fields/joined mismatch).`)\n }\n return existingRegistry\n }\n }\n // Validate FIRST — a refused declaration must leave no side effect (no registry, no hook).\n const spec = validateSatelliteDeclaration({\n satellite: collectionName, satelliteOf: options.satelliteOf, fields: options.fields, joined: options.joined,\n baseIsSatellite: (existingRegistry?.bySatellite(options.satelliteOf) ?? null) !== null,\n // R-S8 direction (i): refuse if EITHER this declaration sets crdt, OR the\n // base was already constructed with crdt mode before this pairing.\n crdtMode: options.crdt !== undefined || ctx.getBaseCrdt(options.satelliteOf) !== undefined,\n joinedCollidesWithCollection: options.joined !== undefined && ctx.collectionExists(options.joined),\n })\n if (ctx.forgetSubjects[spec.base] !== undefined && options.perRecordKeys !== true) {\n throw new SatelliteConfigError(`R-S7: satellite \"${collectionName}\" of forget-covered base \"${spec.base}\" must declare perRecordKeys.`)\n }\n let reg = existingRegistry\n if (reg === null) {\n const created = new SatelliteRegistry()\n ctx.registerPoisonHook((e) => { // gate writes against the poison map (R-S1 cross-check)\n if (e.vault === ctx.vaultName) created.assertNotPoisoned(e.collection)\n })\n ctx.forEachSyncEngine(e => e.setPairExpander(names => created.expandNames(names))) // #591 Task 11: sync push/pull + conflict resolvers treat a pair as a unit\n reg = created\n }\n reg.register(spec)\n // #591 Task 11: retroactive resolver mirroring — a conflictPolicy resolver\n // registered on either member BEFORE this pair existed is copied to both now.\n ctx.forEachSyncEngine(e => e.remirrorPairResolvers([spec.base, spec.satellite]))\n const registry = reg // const alias — closure below must not capture the `let`\n const baseSchema = ctx.getBaseSchema(spec.base)\n void import('./post-register.js') // .catch: never-throw-async, independent of postRegister internals\n .then((m) => m.postRegister(ctx.adapter, ctx.vaultName, spec, ctx.getDEK, baseSchema, registry))\n .catch(() => {})\n return reg\n}\n","/**\n * Escape hatch: `proxied[RAW_TARGET]` returns the unwrapped collection — no\n * existence check, no pair lock, no fan-out. Needed by callers (`fanout.ts`,\n * a proxy's own internals) that already hold the pair mutex themselves;\n * going back through a proxy's `put`/`delete` would re-enter\n * `registry.withPairLock` on the same base and deadlock (non-reentrant —\n * see `registry.ts:withPairLock`) or recurse forever (the base proxy's\n * `delete` calls `pairDelete`, which must not call back into it).\n *\n * Lives in its own module (not `proxy.ts`) so `fanout.ts` can import it\n * without creating a `proxy.ts` ⇄ `fanout.ts` import cycle — `proxy.ts`\n * imports `pairDelete` from `fanout.ts` for `makeBaseProxy`.\n */\nexport const RAW_TARGET: unique symbol = Symbol('noydb.satellite.rawTarget')\n","/**\n * Fan-out writes for a base↔satellite pair (#591, Task 6): a joined `put`\n * splits the record across both collections and writes base-then-satellite;\n * a pair `delete` removes satellite-then-base. Either function reverts every\n * already-executed leg (best-effort, raw adapter writes) and compensates\n * each reverted collection's cache/dirty-tracking/change-stream on failure.\n *\n * Both legs are driven through `Collection.put`/`.delete` (encryption,\n * ledger, history, cache, sync-dirty, change-emit all fire normally); only\n * the REVERT writes go straight to the raw adapter, via the shared\n * `bestEffortRevert` helper (`kernel/best-effort-revert.ts`) also used by\n * `revertExecuted` (`with-commit/tx/transaction.ts`) — a neutral kernel-level\n * home so this always-on satellite path can share the revert shape without\n * depending on with-commit, a gated service.\n *\n * `deps.base()`/`deps.satellite()` may return either a raw `Collection` or\n * one of this package's proxies (`makeSatelliteProxy` / `makeBaseProxy`) —\n * every handle is unwrapped via `RAW_TARGET` before use so fan-out never\n * re-enters a proxy's own `put`/`delete` override. Re-entering would either\n * deadlock (the satellite proxy's `put` takes the same non-reentrant\n * `registry.withPairLock` this module already holds) or recurse forever\n * (the base proxy's `delete` calls straight back into `pairDelete`).\n */\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { SatelliteSpec } from './types.js'\nimport type { SatelliteRegistry } from './registry.js'\nimport { RAW_TARGET } from './raw-target.js'\nimport { bestEffortRevert } from '../../kernel/best-effort-revert.js'\nimport type { BestEffortRevertLeg } from '../../kernel/best-effort-revert.js'\n\nexport interface FanoutDeps {\n readonly spec: SatelliteSpec\n readonly base: () => unknown\n readonly satellite: () => unknown\n // Widened to the full `NoydbStore` (#591 review M2): every caller already\n // hands in the full adapter (vault.ts's `this.adapter` / a proxy's own\n // `target.adapter`) — narrowing to fan-out's own get/put/delete needs just\n // forced `joined.ts` to re-widen it back with a double cast to reach\n // `isBaseLive`/`liveBaseIdSet`, which also call `.list`.\n readonly adapter: NoydbStore\n readonly vaultName: string\n readonly registry: SatelliteRegistry\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype CollectionHandle = any\n\n/** Escape any proxy — see file header. Plain (non-proxy) handles pass through unchanged. */\nfunction unwrap(handle: unknown): CollectionHandle {\n return (handle as Record<symbol, unknown>)[RAW_TARGET] ?? handle\n}\n\ninterface Leg extends BestEffortRevertLeg {\n readonly handle: CollectionHandle\n /**\n * True once this leg's `put`/`delete` actually completed (#596). A leg is\n * snapshotted (for the raw-envelope revert) BEFORE its write is attempted,\n * so a leg whose write THROWS is still in `executed` with `wrote: false` —\n * its envelope-revert is a harmless no-op (nothing changed), but it must\n * NOT be dirty-compensated: `_compensateRevertedWrite` → `removeDirty`\n * keys only on (collection, id) and would otherwise drop a pre-existing,\n * unrelated dirty entry for the same id.\n *\n * KNOWN LIMITATION (#687), accepted: the reverse hazard is inherent. A leg\n * whose `put`/`delete` COMMITS its dirty entry (via `onDirty`) but then\n * THROWS in the post-`onDirty` dispatch phase — a strict-mode `withFormula`\n * derivation / materialized-view recompute run inside `_putInternal`/\n * `_doDelete` with no try/catch — leaves `wrote: false`, so\n * `revertAndCompensate` skips compensation and this leg's OWN just-created\n * dirty entry is orphaned (the raw envelope still reverts correctly).\n * Reachable only with satellites + a strict formula/MV on the same\n * collection whose recompute throws mid-fan-out; the sole harm is one\n * self-healing sync-push cycle (a redundant no-op push or ordinary conflict\n * resolution — no data loss; the entry is spliced out every cycle). A\n * precise fix would diff the dirty log before/after each leg regardless of\n * whether the write threw (needs `FanoutDeps` plumbing) — deferred as\n * disproportionate to the harm.\n */\n wrote: boolean\n}\n\n/** Best-effort revert of every executed leg, in reverse order, then per-leg compensation. */\nasync function revertAndCompensate(deps: FanoutDeps, executed: readonly Leg[]): Promise<void> {\n await bestEffortRevert(executed, deps.adapter, async (leg) => {\n // #596: only a leg whose write actually landed needs dirty-compensation.\n if (leg.wrote) await leg.handle._compensateRevertedWrite(leg.id)\n })\n}\n\n/** Split `record` across the pair by `spec.fields`, base leg first, satellite leg second. */\nexport async function joinedPut(deps: FanoutDeps, id: string, record: Record<string, unknown>): Promise<void> {\n deps.registry.assertNotPoisoned(deps.spec.satellite)\n const base = unwrap(deps.base())\n const satellite = unwrap(deps.satellite())\n const satFields = new Set(deps.spec.fields)\n const baseRec: Record<string, unknown> = {}\n const satRec: Record<string, unknown> = {}\n for (const [k, v] of Object.entries(record)) (satFields.has(k) ? satRec : baseRec)[k] = v\n // Pre-validate BOTH legs before any adapter write — an invalid satellite\n // field must abort with zero writes, not a half-applied base leg.\n await base.validateInput(baseRec)\n await satellite.validateInput(satRec)\n return deps.registry.withPairLock(deps.spec.base, async () => {\n const executed: Leg[] = []\n const run = async (handle: CollectionHandle, coll: string, rec: Record<string, unknown>): Promise<void> => {\n const leg: Leg = {\n vaultName: deps.vaultName,\n collectionName: coll,\n id,\n prior: await deps.adapter.get(deps.vaultName, coll, id),\n handle,\n wrote: false,\n }\n executed.push(leg)\n await handle.put(id, rec)\n leg.wrote = true // #596: only mark dirty-compensation-eligible once the write lands\n }\n try {\n await run(base, deps.spec.base, baseRec) // base leg FIRST (convergence rule 3)\n await run(satellite, deps.spec.satellite, satRec)\n } catch (err) {\n await revertAndCompensate(deps, executed)\n throw err\n }\n })\n}\n\n/** Remove both legs of the pair, satellite first, base second. */\nexport async function pairDelete(deps: FanoutDeps, id: string): Promise<void> {\n const base = unwrap(deps.base())\n const satellite = unwrap(deps.satellite())\n return deps.registry.withPairLock(deps.spec.base, async () => {\n const executed: Leg[] = []\n const run = async (handle: CollectionHandle, coll: string): Promise<void> => {\n const leg: Leg = {\n vaultName: deps.vaultName,\n collectionName: coll,\n id,\n prior: await deps.adapter.get(deps.vaultName, coll, id),\n handle,\n wrote: false,\n }\n executed.push(leg)\n await handle.delete(id)\n leg.wrote = true // #596: only mark dirty-compensation-eligible once the delete lands\n }\n try {\n await run(satellite, deps.spec.satellite) // satellite leg FIRST (convergence rule 3)\n await run(base, deps.spec.base)\n } catch (err) {\n await revertAndCompensate(deps, executed)\n throw err\n }\n })\n}\n","import { SatelliteConfigError } from '../../kernel/errors.js'\nimport { findByDet as detFindByDet, queryByDet as detQueryByDet } from '../../kernel/enclave/index.js'\nimport { isBaseLive, liveBaseIdSet } from './existence.js'\nimport { pairDelete } from './fanout.js'\nimport { RAW_TARGET } from './raw-target.js'\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { SatelliteSpec } from './types.js'\nimport type { SatelliteRegistry } from './registry.js'\n\nexport { RAW_TARGET }\n\n/**\n * Correlates a collection handle's `list()` output with the ids implied by\n * cache-insertion order — `list()` returns bare records (no `id` field\n * unless the caller put one), so ids are recovered positionally against the\n * cache's own key order instead. Read AFTER `target.list()` resolves, so a\n * not-yet-hydrated cache on the first read doesn't race a still-empty key\n * snapshot. Invariant: `list()` must preserve cache-insertion order\n * (collection.ts `list()` maps `[...cache.values()]`) — positional\n * correlation depends on it. Drops any record whose position has no\n * corresponding cache key (should not happen in practice; defensive only).\n * Exported so `joined.ts` (#591, Task 7) can get the same [id, record]\n * correlation for the base side without duplicating this logic.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function listWithIds(target: any): Promise<Array<[string, unknown]>> {\n const records = await target.list()\n const ids = [...(target.cache as Map<string, unknown>).keys()]\n const out: Array<[string, unknown]> = []\n for (let i = 0; i < records.length; i++) {\n const id = ids[i]\n if (id !== undefined) out.push([id, records[i]])\n }\n return out\n}\n\n/**\n * Existence-filter a search/retrieve hit array in place, id-scoped to the\n * hits actually returned (never a full `liveBaseIdSet` scan — #591 Task 9).\n * `search()`/`retrieve()`/`similarTo()` answer from the facade's own eager\n * cache / lexical index (`with-lookup/search/collection-facade.ts`), which\n * never observes the proxy's existence check — this closes that leak as a\n * pure post-filter: the persisted `_ftindex` posting is never touched.\n */\nasync function filterLiveHits<H extends { id: string }>(\n hits: readonly H[],\n adapter: NoydbStore,\n vaultName: string,\n base: string,\n): Promise<H[]> {\n const live = await Promise.all(hits.map((h) => isBaseLive(adapter, vaultName, base, h.id)))\n return hits.filter((_, i) => live[i])\n}\n\n/**\n * Wraps a satellite's real `Collection<T>` in a `Proxy` that enforces\n * existence authority (spec § Convergence & existence authority, rule 1)\n * and R-S6 on top of it. Every member not explicitly overridden below\n * falls through to the real collection unchanged — this is why the full\n * ~50-member surface (describe, count, putMany, …) survives without\n * hand-stubbing. Caches nothing: every call re-checks live base state.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function makeSatelliteProxy(target: any, spec: SatelliteSpec, registry: SatelliteRegistry): any {\n // Same private internals `Collection.putManyAtomic` reaches for\n // (collection.ts:3223) — TypeScript `private` is compile-time only.\n const adapter = target.adapter\n const vaultName = target.vault\n\n const queryNotExistenceFiltered = (): never => {\n throw new SatelliteConfigError(\n `satellite \"${spec.satellite}\": query() is not existence-filtered. Query's terminal ` +\n `methods (toArray/first/count) read the in-memory cache synchronously, while existence ` +\n `authority (§ Convergence & existence authority, rule 1) requires an async, undecrypted ` +\n `check against live base state — the two shapes don't compose without either breaking ` +\n `query()'s synchronous contract or accepting a check that misses out-of-band base ` +\n `mutations. Use list() (or get()) for existence-safe reads on satellite collections.`,\n )\n }\n\n // Pulled out of the `overrides` object literal (rather than inlined) so\n // `getMany`/`putMany` below can loop through the SAME existence/lock/poison\n // logic a single get/put applies — the real `Collection.getMany`/`putMany`\n // bind their internal `this.get`/`this.put` calls to the RAW target (see\n // `listWithIds` header + I1, #591 review), which is exactly how a bulk call\n // through this proxy used to bypass existence filtering and R-S6/poison/lock.\n const getOne = async (id: string): Promise<unknown> => {\n if (!(await isBaseLive(adapter, vaultName, spec.base, id))) return null\n return target.get(id)\n }\n const putOne = async (id: string, record: unknown): Promise<unknown> => {\n return registry.withPairLock(spec.base, async () => {\n // Poison check INSIDE the lock: a put queued behind a section that\n // poisons the pair (e.g. a fan-out's failure path) must observe the\n // poison after acquiring, not race past a pre-lock check.\n registry.assertNotPoisoned(spec.satellite)\n if (!(await isBaseLive(adapter, vaultName, spec.base, id))) {\n throw new SatelliteConfigError(\n `R-S6: satellite \"${spec.satellite}\" put for \"${id}\" with no live base record in ` +\n `\"${spec.base}\" — create the base first (or write through the joined handle).`,\n )\n }\n return target.put(id, record)\n })\n }\n\n const overrides: Record<string, unknown> = {\n get: getOne,\n async list() {\n const live = await liveBaseIdSet(adapter, vaultName, spec.base)\n const pairs = await listWithIds(target)\n return pairs.filter(([id]) => live.has(id)).map(([, record]) => record)\n },\n query: queryNotExistenceFiltered,\n put: putOne,\n // #591 review I1: the real `getMany` loops `this.get(id)` bound to the raw\n // target, never this proxy's existence-filtered `get` — same Map<id, T|null>\n // shape, built from the overridden single-get instead.\n async getMany(ids: readonly string[]) {\n const result = new Map<string, unknown>()\n for (const id of ids) result.set(id, await getOne(id))\n return result\n },\n // #591 review I1: the real `putMany` (non-atomic) loops `this.put(id, record)`\n // bound to the raw target, bypassing R-S6/pair-lock/poison per item; looping\n // through the overridden single-put here restores that per-item enforcement\n // while preserving the real putMany's { ok, success, failures } shape — a\n // refused item becomes a failure entry, not a thrown error. Atomic mode is a\n // single transaction by design (looping per-item `put` would break its\n // all-or-nothing revert guarantee), so instead the WHOLE call is refused\n // with R-S6 up front, under the pair lock + poison check, if any id lacks a\n // live base — only then does it delegate to the real atomic executor.\n async putMany(entries: ReadonlyArray<readonly [string, unknown, unknown?]>, options?: { atomic?: boolean }) {\n if (options?.atomic) {\n return registry.withPairLock(spec.base, async () => {\n registry.assertNotPoisoned(spec.satellite)\n for (const [id] of entries) {\n if (!(await isBaseLive(adapter, vaultName, spec.base, id))) {\n throw new SatelliteConfigError(\n `R-S6: satellite \"${spec.satellite}\" putMany(atomic) refused — \"${id}\" has no live base record in \"${spec.base}\".`,\n )\n }\n }\n return target.putMany(entries, options)\n })\n }\n const success: string[] = []\n const failures: Array<{ id: string; error: Error }> = []\n for (const [id, record] of entries) {\n try {\n await putOne(id, record)\n success.push(id)\n } catch (error) {\n failures.push({ id, error: error as Error })\n }\n }\n return { ok: failures.length === 0, success, failures }\n },\n // No `deleteMany` override: the real `deleteMany` loops the raw\n // `this.delete(id)` too, but this proxy never overrides single `delete`\n // (satellite delete is legal, unguarded — see makeBaseProxy for the leg\n // that DOES need fan-out) — there is nothing for a bulk delete to bypass.\n // #591 Task 9: search/retrieve/similarTo answer from the search facade's\n // own cache/index (never the get/list overrides above), so they need\n // their own existence post-filter — every retrieval surface the facade\n // exposes is covered here.\n async search(field: string, query: string, opts?: unknown) {\n const hits = await target.search(field, query, opts)\n return filterLiveHits(hits, adapter, vaultName, spec.base)\n },\n async retrieve(query: string, opts?: unknown) {\n const hits = await target.retrieve(query, opts)\n return filterLiveHits(hits, adapter, vaultName, spec.base)\n },\n async similarTo(vector: Float32Array, opts?: unknown) {\n const hits = await target.similarTo(vector, opts)\n return filterLiveHits(hits, adapter, vaultName, spec.base)\n },\n // #591 Task 9 review fix: findByDet/queryByDet scan envelopes straight\n // off the adapter (kernel/enclave/record-keys/deterministic.ts) and\n // return BARE records (no id), so a post-filter can't correlate a match\n // back to its base row. Instead the scan itself is scoped: re-run the\n // same det functions over the collection's own DeterministicContext\n // (`detContext()` is private like `adapter`/`cache` above) with its\n // `adapter.list` narrowed to live-base ids — a dead-base match is then\n // never visited, so findByDet correctly continues to a later live match\n // rather than short-circuiting on a ghost.\n async findByDet(field: string, value: unknown) {\n return detFindByDet(liveScopedDetContext(), field, value)\n },\n async queryByDet(field: string, value: unknown) {\n return detQueryByDet(liveScopedDetContext(), field, value)\n },\n }\n\n const liveScopedDetContext = () => {\n const ctx = target.detContext()\n const raw = ctx.adapter as NoydbStore\n return {\n ...ctx,\n adapter: {\n ...raw,\n get: raw.get.bind(raw),\n async list(v: string, c: string) {\n const ids = await raw.list(v, c)\n const live = await Promise.all(ids.map((id) => isBaseLive(adapter, vaultName, spec.base, id)))\n return ids.filter((_, i) => live[i])\n },\n },\n }\n }\n\n return new Proxy(target, {\n get(t, prop, _recv) {\n if (prop === RAW_TARGET) return t\n if (typeof prop === 'string' && prop in overrides) return overrides[prop]\n const v = Reflect.get(t, prop, t)\n return typeof v === 'function' ? v.bind(t) : v\n },\n })\n}\n\n/**\n * Wraps a satellite's BASE collection in a `Proxy` whose overrides are\n * `delete` and `deleteMany` — both routed through `pairDelete` (this task) so\n * removing a base record also removes its satellite row, in order, with\n * revert-on-failure. `satellite()` is a thunk, not a resolved handle: at the\n * moment a base is first requested the paired satellite may not exist yet in\n * some call orders, and `fanout.ts` re-resolves + unwraps it lazily per call\n * anyway.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function makeBaseProxy(target: any, spec: SatelliteSpec, registry: SatelliteRegistry, satellite: () => unknown): any {\n const adapter = target.adapter\n const vaultName = target.vault\n\n // #591 review I1: the real `deleteMany` loops `this.delete(id)` bound to the\n // raw target, bypassing this proxy's own `delete` override entirely — a\n // base deleteMany would silently orphan every satellite row instead of\n // fanning out. Pulled out so both `delete` and `deleteMany` share it.\n const deleteOne = async (id: string): Promise<void> => {\n return pairDelete({ spec, base: () => target, satellite, adapter, vaultName, registry }, id)\n }\n\n const overrides: Record<string, unknown> = {\n delete: deleteOne,\n async deleteMany(ids: readonly string[]) {\n const success: string[] = []\n const failures: Array<{ id: string; error: Error }> = []\n for (const id of ids) {\n try {\n await deleteOne(id)\n success.push(id)\n } catch (error) {\n failures.push({ id, error: error as Error })\n }\n }\n return { ok: failures.length === 0, success, failures }\n },\n }\n\n return new Proxy(target, {\n get(t, prop, _recv) {\n if (prop === RAW_TARGET) return t\n if (typeof prop === 'string' && prop in overrides) return overrides[prop]\n const v = Reflect.get(t, prop, t)\n return typeof v === 'function' ? v.bind(t) : v\n },\n })\n}\n","/**\n * JoinedHandle — the full-record access point for a base↔satellite pair\n * declared with `joined:` (#591, Task 7). Deliberately narrow (spec § The\n * model): get/put/delete/list/describe only, never a `Collection<T>` cast —\n * reactive members (`subscribe`, `live`, …) are simply absent from the\n * returned object, not stubbed.\n *\n * Reads compose under existence authority (spec § Convergence & existence\n * authority, rule 1): the base row alone decides whether a record exists at\n * all — `get`/`list` check it via an undecrypted adapter read\n * (`isBaseLive`/`liveBaseIdSet`) before merging in the satellite side, so a\n * base-absent-or-tombstoned id reads as fully gone even if a satellite\n * envelope still lingers. Writes/deletes delegate wholesale to the Task 6\n * fan-out (`joinedPut`/`pairDelete`), which already holds the pair lock and\n * reverts on partial failure — this module adds no write logic of its own.\n */\nimport type { JoinedHandle, SatelliteSpec } from './types.js'\nimport type { FanoutDeps } from './fanout.js'\nimport { joinedPut, pairDelete } from './fanout.js'\nimport { isBaseLive, liveBaseIdSet } from './existence.js'\nimport { listWithIds } from './proxy.js'\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype CollectionHandle = any\n\nexport function makeJoinedHandle<T extends Record<string, unknown>>(spec: SatelliteSpec, deps: FanoutDeps): JoinedHandle<T> {\n const base = (): CollectionHandle => deps.base()\n const satellite = (): CollectionHandle => deps.satellite()\n const adapter = deps.adapter // `FanoutDeps.adapter` is the full `NoydbStore` (#591 review M2)\n\n // Every declared satellite field defaults to null — a record with no\n // satellite row yet (or a not-yet-populated field) reads as null rather\n // than simply missing.\n const nullSat = (): Record<string, null> => Object.fromEntries(spec.fields.map(f => [f, null]))\n // Base spread last: R-S1 guarantees satellite `fields` never overlap the\n // base schema (postRegister's cross-check), so this is inert on satellite\n // keys — base wins ties defensively only.\n const merge = (b: Record<string, unknown>, s: Record<string, unknown> | null): T =>\n ({ ...nullSat(), ...(s ?? {}), ...b }) as T\n\n return {\n async get(id) {\n if (!(await isBaseLive(adapter, deps.vaultName, spec.base, id))) return null\n const b = await base().get(id)\n if (b === null) return null\n const s = await satellite().get(id) // proxied handle: existence-safe, lock-free\n return merge(b, s)\n },\n async put(id, record) {\n await joinedPut(deps, id, record)\n },\n async delete(id) {\n await pairDelete(deps, id)\n },\n async list() {\n const live = await liveBaseIdSet(adapter, deps.vaultName, spec.base)\n const pairs = await listWithIds(base())\n const out: T[] = []\n for (const [id, b] of pairs) {\n if (!live.has(id)) continue\n out.push(merge(b as Record<string, unknown>, await satellite().get(id)))\n }\n return out\n },\n async describe() {\n const [b, s] = await Promise.all([base().describe({}), satellite().describe({})])\n return {\n collection: spec.joined ?? `${spec.base}+${spec.satellite}`,\n fields: [...b.fields, ...s.fields],\n meta: { label: spec.joined ?? spec.base },\n }\n },\n }\n}\n","/**\n * Forget fan-out (#591, Task 8): expands the base refs resolved from the\n * encrypted subject index with a synthesized same-id ref for every base ref\n * whose collection has a declared satellite.\n *\n * A satellite record is NEVER itself indexed in `_subject_index` (its writes\n * only ever go through `joinedPut`, which never touches the subject-field\n * write hook — see `noydb.ts#registerForgetHooks`), so `lookupSubject` alone\n * would leave the satellite half of a pair permanently un-erasable. The\n * synthesized ref carries `satelliteOf` (the base collection name) so:\n * - `vault.forget()`'s classification line can inherit `perRecordKeys`\n * from the BASE's forget-strategy entry (the satellite itself is never a\n * `subjects` key), and\n * - the synthesized ref's tombstone write can be held to R-S4 fail-loud\n * semantics distinct from a base ref's existing resilient handling.\n *\n * The synthesized ref is INTERLEAVED into the SAME list the caller iterates —\n * immediately BEFORE its base ref, not appended after the whole list — so it\n * traverses every purge stage below the tombstone (history, `_idx`/`_ftindex`,\n * blobs, `_sealed`/`_sealed_cek`, vectors) identically to a base ref — there\n * is no separate satellite-only code path.\n *\n * Ordering is load-bearing (retry black hole, #591 review C1): `vault.forget()`'s\n * per-ref loop removes each ref's subject-index entry (the retry anchor) only\n * at the END of that ref's own iteration. If the satellite ref instead ran\n * AFTER its base ref (as a simple append), an R-S4 abort mid-satellite-ref (or\n * a crash) would leave the base ref already fully processed — including its\n * subject-index entry already removed — so a retried `forget(subjectId)` finds\n * nothing to resolve and returns a clean, empty result while the satellite's\n * heavy data stays un-shredded forever. Interleaving the satellite ref BEFORE\n * its base ref means any R-S4 abort happens before the base's subject-index\n * anchor is touched, so a retry re-discovers the same base ref (and\n * re-synthesizes its satellite ref) until both actually shred.\n */\nimport type { SubjectRef } from '../../with-audit/forget/subject-index.js'\nimport type { SatelliteRegistry } from './registry.js'\n\n/** A subject ref synthesized from a base ref via a declared satellite pairing. */\nexport interface SatelliteSubjectRef extends SubjectRef {\n readonly satelliteOf: string\n}\n\n/**\n * Expand `refs` (as resolved by `lookupSubject`) with one synthesized ref per\n * base ref whose collection has a registered satellite. `registry` may be\n * `null` (no satellite ever declared in this vault) — returns `refs`\n * unchanged, byte-identical to pre-#591 behaviour.\n */\nexport function expandRefsWithSatellites(\n refs: readonly SubjectRef[],\n registry: SatelliteRegistry | null,\n): ReadonlyArray<SubjectRef | SatelliteSubjectRef> {\n if (registry === null) return refs\n const out: Array<SubjectRef | SatelliteSubjectRef> = []\n let anySat = false\n for (const ref of refs) {\n const spec = registry.satelliteOf(ref.collection)\n if (spec) {\n anySat = true\n out.push({ collection: spec.satellite, id: ref.id, satelliteOf: ref.collection })\n }\n out.push(ref)\n }\n return anySat ? out : refs\n}\n","/**\n * Satellite per-record-CEK migration (#599) — the R-S7 retro-coverage\n * unblock.\n *\n * R-S7 (`declare.ts:89-91`) correctly refuses declaring/redeclaring a\n * satellite of a forget-covered base without `perRecordKeys: true` — but\n * `perRecordKeys` is construction-only (`kernel/collection.ts:402`), so an\n * app that shipped a satellite BEFORE its base gained forget coverage has\n * no way past the refusal: the existing records must be re-encrypted under\n * fresh per-record CEKs before the satellite can reopen in\n * `perRecordKeys: true` mode, and the only re-encrypt primitive\n * (`Collection._applyCutoverTransform`) needs the collection already\n * constructed in that mode — chicken-and-egg.\n *\n * The break: `Vault.migrateSatellitePerRecordKeys` (`kernel/vault.ts`)\n * opens the satellite collection via `vault.collection(name, {\n * perRecordKeys: true })` WITHOUT `satelliteOf` — that never enters\n * `declareSatellite`, so R-S7's gate (which only fires on the `satelliteOf`\n * declaration path) never runs for the migration pass. R-S7 stays fully\n * enforced for every NORMAL `satelliteOf` declaration; this module and its\n * call-site never touch `declare.ts`.\n *\n * `migrateSatelliteCek` then reuses `_applyCutoverTransform` verbatim (an\n * identity transform — no field/shape change, only the encryption wrapper\n * changes) rather than duplicating its mint-or-reuse-CEK logic\n * (`resolveRecordCek`/`resolveStableCek`, `collection.ts:2537-2545`): a\n * record with no `_cek` yet gets a freshly minted per-record CEK; a record\n * that already carries `_cek` (already migrated, e.g. a prior interrupted\n * run) reuses its existing CEK unchanged. That mint-or-reuse discrimination\n * is what makes re-running this after a mid-migration failure safe for\n * free — no separate resumability marker needed, no double-mint, no\n * plaintext write, no shared-DEK write.\n *\n * **Mode-assertion guard (review Important 1):** `perRecordKeys` is\n * construction-only and the vault's collection cache is first-wins with no\n * mismatch guard. If `coll`'s name was already opened THIS SESSION without\n * `perRecordKeys` (e.g. an incidental bare `vault.collection(name)` call\n * before the migration ran), `vault.collection(name, { perRecordKeys: true\n * })` cache-HITS that instance instead of constructing a fresh one — the\n * returned handle is silently NOT in per-record-CEK mode. Without a check,\n * `_applyCutoverTransform` would then pass `cek: undefined` for every\n * record (`this.perRecordCek` false) and RE-ENCRYPT EVERY RECORD UNDER THE\n * SHARED COLLECTION DEK while still reporting `{ migrated: N }` as success\n * — a security migration that silently mints nothing. `migrateSatelliteCek`\n * reads the opened handle's own `getConfig()` (the same accessor\n * `dumpSchema()` uses) to confirm `perRecordKeys` is genuinely `true`\n * before walking, and throws `SatelliteConfigError` instead of proceeding\n * if not.\n *\n * **No-quiesce precondition (review Important 2):** `_applyCutoverTransform`\n * is documented as fence-phase-only (`collection.ts:2517-2522`) — the\n * generic schema-cutover caller (`Vault.runSchemaCutover` →\n * `SchemaFenceController`) always runs it under the vault-wide schema fence,\n * which blocks concurrent writes. This migration does NOT fence: it calls\n * `_applyCutoverTransform` directly, with no fence and CAS-less\n * (`adapter.put` with no `expectedVersion`) writes. A concurrent write to\n * the same satellite collection racing the walk's `await`s can be\n * clobbered by (or clobber) a migration write. Callers MUST run this before\n * the collection serves traffic — e.g. at v2 boot, before declaring the\n * pair, before any client can write — or otherwise ensure the vault is\n * quiescent for this collection for the duration of the call.\n */\nimport { SatelliteConfigError } from '../../kernel/errors.js'\n\n/** The narrow slice of `Collection` the migration pass needs (mirrors `fanout.ts`'s `CollectionHandle` narrowing). */\nexport interface SatelliteCekMigrationTarget {\n /** Public config snapshot (`Collection.getConfig()`) — used to confirm the handle is genuinely in per-record-CEK mode before walking. */\n getConfig(): { readonly perRecordKeys?: boolean } | undefined\n _applyCutoverTransform(transform: (doc: Record<string, unknown>) => Record<string, unknown>): Promise<number>\n}\n\nexport interface SatelliteCekMigrationResult {\n /** Records touched by this call (both freshly minted and already-migrated re-touches on a resumed run). */\n readonly migrated: number\n}\n\n/**\n * Re-encrypt every record in `coll` under a per-record CEK. `coll` must be\n * a collection handle already opened with `perRecordKeys: true` — see the\n * file header for how the caller gets one past R-S7. Throws\n * `SatelliteConfigError` (does NOT proceed) if `coll` is not genuinely in\n * per-record-CEK mode — see the file header's mode-assertion note.\n * Idempotent/resumable: safe to call again after a partial failure. NOT\n * fenced against concurrent writers — see the file header's no-quiesce\n * precondition; run this before the collection serves traffic.\n *\n * @param name The satellite collection's name — used only for the error\n * message below; identical to what the caller passed to `vault.collection()`.\n */\nexport async function migrateSatelliteCek(name: string, coll: SatelliteCekMigrationTarget): Promise<SatelliteCekMigrationResult> {\n if (coll.getConfig()?.perRecordKeys !== true) {\n throw new SatelliteConfigError(\n `migrateSatellitePerRecordKeys: collection \"${name}\" was already opened this session without ` +\n `perRecordKeys (construction-only); migrate before its first open, or restart the session.`,\n )\n }\n // Ledger reason (review Minor): the walk below reuses _applyCutoverTransform's\n // hardcoded 'schema:coordinated-cutover' ledger reason — it has no reason/label\n // param, and this migration is not itself a schema cutover. Not threaded through\n // (would touch collection.ts's own ceilinged surface for a cosmetic label);\n // flagged here so the audit trail's shared reason string is documented, not silent.\n const migrated = await coll._applyCutoverTransform((doc) => doc)\n return { migrated }\n}\n","/**\n * Vault-level schema-fence controller.\n *\n * Owns the open-time generation snapshot, the pending-cutover registry,\n * and the cutover orchestration. 3a: single-client (the caller is the\n * migrator). 3b: a cooperative ack-barrier — after `draining`, the\n * migrator waits for the active client set (registry heartbeats) to ack\n * the draining generation before transforming. No leader election.\n *\n * The transport is the injected {@link CoordinationProvider} port: the\n * default {@link StoreCoordinationProvider} maps it onto today's\n * `_meta/schema-fence` store ops, so behavior is byte-for-byte the same;\n * `by-tabs` / `by-peer` swap in real-time push transports.\n */\nimport { type FenceState } from './fence.js'\nimport { SchemaFenceError, MigrationRequiredError } from '../../kernel/errors.js'\nimport type { TransformFn } from './types.js'\nimport { runDrainBarrier, type CoordinationProvider } from '../../port/by/index.js'\n\n/** Runs one collection's transform; supplied by the Vault (binds to a Collection). */\nexport type RunTransform = (collection: string, transform: TransformFn) => Promise<void>\n\nexport class SchemaFenceController {\n readonly #coordination: CoordinationProvider\n readonly #vault: string\n readonly #onFlush: () => Promise<void>\n readonly #writerId: string\n readonly #now: () => number\n readonly #staleMs: number\n readonly #quiesceTimeoutMs: number\n readonly #emit: (e: { currentSchemaVersion: number; fenceState: FenceState }) => void\n #snapshot = 0\n readonly #pending = new Map<string, TransformFn>()\n\n constructor(opts: {\n coordination: CoordinationProvider\n vault: string\n onFlush: () => Promise<void>\n /** Stable per-instance id; the migrator excludes itself from the barrier. */\n clientId?: string\n /**\n * Accepted for wiring symmetry with {@link FenceWatcher}, but the migrator\n * never reports its own presence (it excludes itself from the barrier), so\n * it carries no session of its own.\n */\n sessionId?: string\n now?: () => number\n staleMs?: number\n quiesceTimeoutMs?: number\n emit?: (e: { currentSchemaVersion: number; fenceState: FenceState }) => void\n }) {\n this.#coordination = opts.coordination\n this.#vault = opts.vault\n this.#onFlush = opts.onFlush\n this.#writerId = opts.clientId ?? 'migrator'\n this.#now = opts.now ?? (() => Date.now())\n this.#staleMs = opts.staleMs ?? 30_000\n this.#quiesceTimeoutMs = opts.quiesceTimeoutMs ?? 60_000\n this.#emit = opts.emit ?? (() => {})\n }\n\n /** Capture the generation snapshot at vault-open. */\n async init(): Promise<void> {\n this.#snapshot = (await this.#coordination.readFence(this.#vault)).currentSchemaVersion\n }\n\n /** Record a per-collection pending cutover (from a registration `cutover` decision). */\n registerPendingCutover(collection: string, transform: TransformFn): void {\n this.#pending.set(collection, transform)\n }\n\n /** Write-path gate. Throws when behind, fenced, or this collection is cutover-pending. */\n async assertWritable(collection: string): Promise<void> {\n // Fresh one-shot read (not an observeFence snapshot) — avoids a staleness\n // window and keeps the timing-sensitive cutover gate exact.\n const fence = await this.#coordination.readFence(this.#vault)\n if (fence.currentSchemaVersion > this.#snapshot) {\n throw new MigrationRequiredError(\n `Vault \"${this.#vault}\" advanced to schema generation ${fence.currentSchemaVersion} ` +\n `(this client opened at ${this.#snapshot}). Reload to continue.`,\n )\n }\n if (fence.fenceState === 'draining' || fence.fenceState === 'migrating') {\n throw new SchemaFenceError(`Vault \"${this.#vault}\" is mid-cutover (${fence.fenceState}); writes are paused.`)\n }\n if (this.#pending.has(collection)) {\n throw new SchemaFenceError(\n `Collection \"${collection}\" has a pending schema cutover; run vault.runSchemaCutover() before writing.`,\n )\n }\n }\n\n /**\n * Admin trigger. Drain → wait for the active set to quiesce (or time out)\n * → migrate each pending transform → bump → complete → normal. The\n * migrator excludes itself from the barrier (it drained synchronously\n * inside {@link runDrainBarrier}). `onPoll` (tests) advances other clients\n * between barrier checks; production falls back to a short real delay.\n */\n async runCutover(\n run: RunTransform,\n opts?: { onPoll?: () => Promise<void> },\n ): Promise<{ migrated: number }> {\n if (this.#pending.size === 0) return { migrated: 0 }\n const base = await this.#coordination.readFence(this.#vault)\n const generation = base.currentSchemaVersion\n\n // The barrier sets the fence to `draining` + flushes us internally (no\n // emit). Mirror the legacy controller's `draining` transition event so\n // same-instance subscribers (UI) still see all four states.\n this.#emit({ currentSchemaVersion: generation, fenceState: 'draining' })\n\n let migrated = 0\n await runDrainBarrier(\n this.#coordination,\n {\n vault: this.#vault,\n generation,\n writerId: this.#writerId,\n onFlush: this.#onFlush,\n staleMs: this.#staleMs,\n quiesceTimeoutMs: this.#quiesceTimeoutMs,\n now: this.#now,\n ...(opts?.onPoll ? { onPoll: opts.onPoll } : {}),\n },\n async () => {\n // Barrier resolved: everyone (but us) has quiesced at `generation`.\n await this.#setState(generation, 'migrating')\n for (const [collection, transform] of this.#pending) {\n await run(collection, transform)\n migrated++\n }\n const nextVersion = generation + 1\n await this.#setState(nextVersion, 'complete')\n this.#pending.clear()\n await this.#setState(nextVersion, 'normal')\n this.#snapshot = nextVersion\n },\n )\n return { migrated }\n }\n\n /** Recover a stuck drain: reset fenceState to normal at the current version (no bump). */\n async abort(): Promise<void> {\n const fence = await this.#coordination.readFence(this.#vault)\n await this.#setState(fence.currentSchemaVersion, 'normal')\n }\n\n async #setState(currentSchemaVersion: number, fenceState: FenceState): Promise<void> {\n await this.#coordination.setFence(this.#vault, { currentSchemaVersion, fenceState })\n this.#emit({ currentSchemaVersion, fenceState })\n }\n}\n","/**\n * Vault-side attestation facade.\n *\n * Holds the per-collection attestation field-schema registry and the issue/\n * revoke entry points (`issueAttestation` / `getDocumentSigningPublicKey` /\n * `revoke` / `unrevoke` / `getRevokedDocIds` / `publishRevocationList`). The\n * `*Core` implementations live beside this file; the facade only builds the\n * {@link IssueContext} / {@link RevokeContext} closures and delegates. Every\n * `Vault` dependency arrives via {@link VaultAttestationDeps}.\n *\n * Internal service — reached through `vault.issueAttestation(...)` etc.\n */\nimport { AttestationError } from '../../kernel/errors.js'\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { EnclaveKey } from '../../kernel/enclave/index.js'\nimport type { AttestationFieldSchema, RevocationList } from '@noy-db/attestation'\nimport type { IssueContext } from './issue.js'\nimport type { RevokeContext } from './revoke.js'\nimport type { AttestationStrategy } from './strategy.js'\nexport { NO_ATTESTATION, type AttestationStrategy } from './strategy.js'\n\n/** Everything the moving attestation methods touched on the vault's `this.*`. */\nexport interface VaultAttestationDeps {\n /** The ciphertext store. */\n readonly adapter: NoydbStore\n /** Vault namespace name. */\n readonly vault: string\n /** Per-collection DEK resolver (bound `vault.getDEK`). */\n readonly getDEK: (collection: string) => Promise<EnclaveKey>\n /** The invoking keyring's role (read fresh per call). */\n role(): string\n /** Decrypt a collection record at `locale: 'raw'` (issue side reads the live record). */\n getRawRecord(collection: string, id: string): Promise<Record<string, unknown> | null>\n}\n\nexport class VaultAttestation {\n /**\n * Per-collection attestation field-schema (issue side). Populated on\n * `collection({ attestation })` via {@link register} and read by\n * {@link issue}. Indexed by collection name.\n */\n private readonly registry = new Map<string, AttestationFieldSchema>()\n\n constructor(\n private readonly deps: VaultAttestationDeps,\n /**\n * Opt-in capability gate. `NO_ATTESTATION` when\n * `createNoydb({ attestationStrategy })` was omitted — every issue/revoke/\n * signer call then throws `AttestationNotEnabledError`. The facade always\n * exists (it holds the per-collection field-schema registry populated at\n * `collection()` time); only the capability methods are gated.\n */\n private readonly strategy: AttestationStrategy,\n ) {}\n\n /** Register a collection's attestation field-schema (from `vault.collection`). */\n register(collection: string, schema: AttestationFieldSchema): void {\n this.registry.set(collection, schema)\n }\n\n async issue(collectionName: string, id: string): Promise<{ docId: string; qr: string; keyId: string; publicKeyB64: string }> {\n const fieldSchema = this.registry.get(collectionName)\n if (!fieldSchema) {\n throw new AttestationError(`issueAttestation: collection '${collectionName}' has no attestation field-schema. Declare it via vault.collection('${collectionName}', { attestation: { fields: [...] } }).`)\n }\n const out = await this.strategy.issueAttestation(this.makeIssueContext(), { collection: collectionName, id, fieldSchema })\n return { docId: out.docId, qr: out.qr, keyId: out.keyId, publicKeyB64: out.publicKeyB64 }\n }\n\n async getDocumentSigningPublicKey(): Promise<{ keyId: string; publicKeyB64: string }> {\n return this.strategy.getDocumentSigningPublicKey({\n adapter: this.deps.adapter,\n vault: this.deps.vault,\n role: this.deps.role(),\n getDEK: this.deps.getDEK,\n })\n }\n\n private makeIssueContext(): IssueContext {\n const adapter = this.deps.adapter, vaultName = this.deps.vault\n return {\n store: adapter,\n vault: vaultName,\n role: this.deps.role(),\n getDEK: async () => this.deps.getDEK('_attestations'),\n readRecord: async (collection: string, recId: string) => {\n const env = await adapter.get(vaultName, collection, recId)\n if (!env) return null\n const record = await this.deps.getRawRecord(collection, recId)\n if (record === null) return null\n return { record, version: env._v }\n },\n }\n }\n\n async revoke(docId: string): Promise<void> {\n await this.strategy.revokeAttestation(this.makeRevokeContext(), docId)\n }\n\n async unrevoke(docId: string): Promise<void> {\n await this.strategy.unrevokeAttestation(this.makeRevokeContext(), docId)\n }\n\n async getRevokedDocIds(): Promise<string[]> {\n return this.strategy.getRevokedDocIds(this.makeRevokeContext())\n }\n\n async publishRevocationList(): Promise<RevocationList> {\n return this.strategy.publishRevocationList(this.makeRevokeContext())\n }\n\n private makeRevokeContext(): RevokeContext {\n return {\n store: this.deps.adapter,\n vault: this.deps.vault,\n role: this.deps.role(),\n getDEK: async () => this.deps.getDEK('_attestations'),\n }\n }\n}\n","import type { OpenCollectionOptions } from '../port/with/collection-options.js'\nimport { populateCollectionRegistries } from '../port/with/collection-registries.js'\nimport { NO_BLOBS } from '../port/with/blob-strategy.js'\nimport type { StrategyBag } from '../port/with/strategies.js'\nimport type {\n NoydbStore,\n EncryptedEnvelope,\n HistoryConfig,\n ExportStreamOptions,\n ExportChunk,\n CollectionConflictResolver,\n CrossTierAccessEvent,\n Role,\n VaultUserApi,\n CollectionShape, SensitiveOf, IndexedOf, MoneyOf,\n} from './types.js'\nimport type { Noydb } from './noydb.js'\nimport type { IssueDelegationOptions, DelegationToken } from '../with-party/team/delegation.js'\nimport { NOYDB_FORMAT_VERSION } from './types.js'\nimport { Collection } from './collection.js'\nimport type { JoinableSource } from './query/index.js'\nimport type { OnDirtyCallback } from './collection.js'\nimport type { UnlockedKeyring, BundleRecipient } from '../with-party/team/keyring.js'\nimport type { MaterializedViewRegistry } from '../with-formula/materialized-views/registry.js'\nimport type { MaterializedViewStrategy, MVQueryContext } from '../with-formula/materialized-views/types.js'\nimport type { OverlayedViewRegistry } from '../with-formula/overlay-views/registry.js'\nimport type { OverlayedViewStrategy } from '../with-formula/overlay-views/types.js'\nimport { OverlayedCollection } from '../with-formula/overlay-views/virtual-collection.js'\nimport type { Cover } from '../with-party/directory/cover/types.js'\nimport { buildRecipientKeyringFile } from '../with-party/team/keyring.js'\nimport { ensureCollectionDEK, hasAccess } from '../with-party/team/keyring.js'\nimport { isSecretBearingReservedCollection } from '../with-party/team/reserved-secret-collections.js'\nimport {\n assertCanExport as assertCanExportCapability,\n assertCanImport as assertCanImportCapability,\n canExport as canExportCapability,\n canImport as canImportCapability,\n} from '../port/with/capabilities.js'\nimport type { ExportFormat, KeyringFile } from './types.js'\nimport {\n ValidationError,\n AlreadyElevatedError,\n TierNotGrantedError,\n} from './errors.js'\nimport { ElevatedHandle, ELEVATION_AUDIT_COLLECTION } from '../with-commit/tx/elevated-handle.js'\nimport type { NoydbEventEmitter } from './events.js'\nimport type { ObjectProjection } from '../with-shape/blobs/object-projection.js'\nimport type { ArchivePolicy, ArchiveContext, ArchiveResult, ArchiveRunOptions } from '../with-fork/archive/index.js'\nimport { runArchive, runRestore, runListArchived } from '../with-fork/archive/index.js'\nimport { type SequenceStore, type SequenceHandle, type FormattedSequenceHandle, type SequenceOptions, resolveSequenceKey, compileSequenceFormat, SEQUENCE_COLLECTION } from '../with-commit/sequence/index.js'\nimport { DeferredNumberingStore, type Assignment } from '../with-commit/numbering/index.js'\nimport type { DeferredNumberingConfig } from '../with-commit/numbering/descriptor.js'\nimport type { TierMoveResult } from '../with-audit/tiers/strategy.js'\nimport { type CargoStrategy } from '../with-cargo/strategy.js'\nimport { buildCredentialBrokerHandle, type CredentialBrokerHandle } from '../port/with/broker-strategy.js'\n// — import from leaf modules (NOT from ./history/ledger/index.js\n// or store.js) so the LedgerStore class never reaches the floor\n// bundle. The leaf files hold pure constants + a tiny hash helper;\n// the class lives behind the history strategy seam.\nimport type { LedgerStore } from '../with-commit/history/ledger/store.js'\nimport { sha256Hex } from '../with-commit/history/ledger/entry.js'\nimport type { VaultInstant } from '../with-commit/history/time-machine.js'\nimport { type ForgetResult } from '../with-audit/forget/strategy.js'\nimport {\n addSubjectRef, readDottedPath, coerceSubjectId,\n removeSubjectRef,\n lookupSubject,\n rebuildSubjectIndex as rebuildSubjectIndexImpl,\n type SubjectRef,\n} from '../with-audit/forget/subject-index.js'\nimport { ForgetStrategyNotConfiguredError } from './errors.js'\nimport type { VaultFrame } from '../with-fork/shadow/vault-frame.js'\nimport type { ConsentContext, ConsentAuditEntry, ConsentAuditFilter, ConsentOp } from '../with-audit/consent/consent.js'\nimport { VaultPeriods } from '../with-audit/periods/vault-facade.js'\nimport { VaultLinks } from '../with-shape/links/vault-facade.js'\nimport {\n RefRegistry,\n type RefDescriptor,\n type RefViolation,\n} from './refs.js'\nimport type { DictionaryHandle, DictionaryOptions, StaticDictDescriptor } from '../port/with/i18n-strategy.js'\nimport { isDictCollectionName } from '../port/with/i18n-strategy.js'\n// #650 Task 1 (via-lookup extraction) — the pure dict-registry helpers now live in\n// via/lookup/registry.ts, reached only through this port seam (never via/lookup/*\n// directly — Check 14 via-layering). Aliased to avoid colliding with Vault's own same-named\n// public delegator methods below. Task 2's resolveLabelFromMap/collectLookupDictCompat is the\n// alias-equivalence bridge shared by the i18n + lookup bindings.\nimport {\n enforceStaticDictOnPut as enforceStaticDictOnPutHelper,\n resolveDictSource as resolveDictSourceHelper,\n updateReferencingRecords,\n resolveLabelFromMap,\n checkLookupMembership, buildLookupAltIndex,\n dictCollectionName, registerLookupRefEdges, // #650 Task 4/5\n buildLookupSnapshotRows, // #650 Task 6\n reservedDictDepsOf, // #653\n type LookupDescriptor,\n} from '../port/with/lookup-strategy.js'\nimport { isLinkCollectionName, type LinkSpec, type LinkSetHandle } from '../with-shape/links/names.js'\nimport { makeLazyLinkSetHandle, type LazyLinkSetHandle } from '../with-shape/links/lazy-handle.js'\nimport { getAtPath } from './paths.js'\nimport type { ComputedFields } from '../with-formula/computed/index.js'\nimport { type I18nTextDescriptor } from '../port/with/i18n-strategy.js'\nimport { isViaInstalled } from './via/index.js'\nimport { mergeViaFields } from './via/compose.js'\nimport { exportRedact } from './via/pipeline.js'\nimport { ViaGraph } from './via/graph.js'\nimport { registerCollectionGraphSources, applyTaintOverlay, reapplyDependentOverlays } from './via/graph-wiring.js'\nimport { reconcileViaAttach, type ViaReconcileVaultCtx } from './via/reconcile.js'\nimport { runGraphDispatchWave, putDerivedOutput, ledgerAuditHook, forgetDerivedFanout, touchFor, type GraphBatch, type ForgetFanoutStats, type RollupDeleteIntent } from './via/dispatch.js'\n// Type-only imports for the guard + derivation services. The\n// runtime classes are loaded on demand via `await import(...)` inside\n// `_initGuards` / `_initDerivations` (and the read-only-facade\n// accessor below) so consumers that never register a guard or\n// derivation strategy don't pay the chunk cost. This seam prevents\n// the bundle regression that motivated the lazy-import pattern.\nimport type { GuardRegistry } from '../with-audit/guards/registry.js'\nimport type { GuardStrategyAny } from '../with-audit/guards/types.js'\nimport type { ReadOnlyVaultFacade } from '../with-audit/guards/read-only-facade.js'\nimport type { DerivationRegistry } from '../with-formula/derivations/registry.js'\nimport type { DerivationStrategy } from '../with-formula/derivations/types.js'\nimport { ReservedCollectionNameError, StaticDictReadonlyError, SatelliteConfigError } from './errors.js'\nimport { declareSatellite } from '../with-shape/satellites/declare.js'\nimport { makeSatelliteProxy, makeBaseProxy } from '../with-shape/satellites/proxy.js'\nimport type { SatelliteRegistry } from '../with-shape/satellites/registry.js'\nimport { makeJoinedHandle } from '../with-shape/satellites/joined.js'\nimport type { JoinedHandle } from '../with-shape/satellites/types.js'\nimport { expandRefsWithSatellites } from '../with-shape/satellites/forget.js'\nimport { migrateSatelliteCek } from '../with-shape/satellites/migrate-cek.js'\nimport {\n type PeriodRecord,\n type ClosePeriodOptions,\n type OpenPeriodOptions,\n} from '../with-audit/periods/index.js'\nimport { encrypt, openEnvelopeJson, hasPerRecordKey, SEALED_CEK_NS, type SealingContext, type EnclaveKey, isDeleteMarker, buildDeleteMarker, makeReservedEnvelopes } from './enclave/index.js'\nimport type { RecipientSealer } from '../with-party/team/managed-secret.js'\nimport {\n createExportBlobsHandle,\n EXPORT_AUDIT_COLLECTION,\n type ExportBlobsOptions,\n type ExportBlobsHandle,\n type ExportBlobsAuditEntry,\n} from '../with-shape/blobs/export-blobs.js'\nimport { runCompaction, type BlobFieldsConfig, type CompactRunOptions, type CompactionResult } from '../with-shape/blobs/blob-compaction.js'\nimport {\n writeMagicLinkGrant,\n type IssueMagicLinkGrantOptions,\n type MagicLinkGrantRecord,\n} from '../with-party/team/magic-link-grant.js'\nimport { CustodyApi } from '../with-party/custody/index.js'\n// #553: gate + controller + fence-doc reader stay static (a REMOTE cutover must fence this client even without local declarations, and schemaFenceState() is a thin live read that UI bindings seed from in one tick); the decision engine + watcher load lazily.\nimport type { FenceWatcher } from '../with-shape/schema-update/fence-watcher.js'\nimport { SchemaUpdateGate } from '../with-shape/schema-update/gate.js'\nimport { SchemaFenceController } from '../with-shape/schema-update/fence-controller.js'\nimport { loadFence, type FenceDoc } from '../with-shape/schema-update/fence.js'\nimport type { UpdateDecision, TransformFn } from '../with-shape/schema-update/types.js'\nimport type { RevocationList } from '@noy-db/attestation'\nimport { VaultAttestation } from '../with-audit/attestation/vault-facade.js'\nimport type { DumpSchemaOptions, VaultSchemaSnapshot, SchemaIntrospection } from '../with-shape/introspection/types.js'\nimport type { VaultIntrospectState } from '../with-shape/introspection/walk.js'\nimport type { VaultMeta } from '../with-shape/introspection/meta.js'\nimport { USER_ENVELOPE_COLLECTION } from './constants.js'\n\n/** A vault (tenant namespace) containing collections. */\n/**\n * Collection options that `vault.collection()` threads straight through to\n * `CollectionOpts` under the same name, with no transformation (#841).\n *\n * These were 28 hand-written `if (options?.X !== undefined) collOpts.X =\n * options.X` lines. Adding a pass-through option is now one entry here.\n * Options needing any logic — `refs`, `attestation`, `satelliteOf`, the\n * forget-subject `perRecordKeys` override — deliberately stay explicit below.\n */\nconst COLLECTION_PASSTHROUGH_KEYS = [\n 'indexes', 'reconcileOnOpen', 'prefetch', 'cache', 'schema', 'conflictPolicy', 'crdt',\n 'deterministicFields', 'acknowledgeDeterministicRisk', 'acknowledgeEquatableRisk',\n 'sensitive', 'perRecordKeys', 'provenance', 'ramCiphertext', 'tiers', 'tierMode',\n 'blobTierPolicy', 'i18nFields', 'embeddings', 'textIndexes', 'warmIndexOnOpen',\n 'textIndexPersist', 'moneyFields', 'viaFields', 'computed', 'classifiedFields',\n 'fieldMeta', 'meta',\n] as const\n\n/** Copy `keys` from `src` onto `dst`, skipping any that are `undefined`. */\nfunction copyDefined(dst: Record<string, unknown>, src: Record<string, unknown> | undefined, keys: readonly string[]): void {\n if (src === undefined) return\n for (const key of keys) {\n const value = src[key]\n if (value !== undefined) dst[key] = value\n }\n}\n\nexport class Vault {\n private readonly adapter: NoydbStore\n /** The vault's name as passed to `openVault()`. Stable for the instance lifetime. */\n public readonly name: string\n /** Backreference to the parent `Noydb` — lets vault-scoped services reach the strategy seam\n * without threading `db` through every API (type-only import keeps the module graph acyclic). */\n public readonly noydb: Noydb\n /** The active in-memory keyring. NOT readonly — `load()` refreshes it after restoring a\n * different keyring file, or in-memory/on-disk DEKs drift apart and decrypt fails with TamperedError. */\n private keyring: UnlockedKeyring\n private readonly encrypted: boolean\n private readonly emitter: NoydbEventEmitter\n private readonly onDirty: OnDirtyCallback | undefined\n private readonly onRegisterConflictResolver: ((name: string, resolver: CollectionConflictResolver) => void) | undefined\n private readonly syncAdapter: NoydbStore | undefined\n private readonly getPurgeableTargets: () => readonly { store: NoydbStore; role: 'backup' | 'archive'; label?: string }[]\n private readonly historyConfig: HistoryConfig\n /**\n * Every opt-in service, resolved once by `createNoydb` (#838). Shared by\n * reference with the owning `Noydb` and with every `Collection` this vault\n * opens, so all three always agree about which services are enabled.\n */\n private readonly strategies: StrategyBag\n private readonly objectStore: ObjectProjection | undefined\n\n /** Per-collection record archival policies. Indexed by collection name. */\n private readonly archiveRegistry = new Map<string, ArchivePolicy>()\n private readonly periods: VaultPeriods\n private readonly linksEnforcer: VaultLinks\n\n /** Cargo (partition extraction) strategy — `NO_CARGO` (throwing) unless `withCargo()` was passed.\n * Public so the `extractPartition` free function (which takes a `Vault`) routes through it. */\n get cargoStrategy(): CargoStrategy {\n return this.strategies.cargo\n }\n /** Per-vault guard registry; `null` until `_initGuards()` runs (or for vaults that never register\n * one) — the runtime class is dynamic-imported on demand to keep it out of the floor bundle. */\n private guardRegistry: GuardRegistry | null = null\n /** Per-vault derivation/MV/overlay registries — same lazy-load contract as\n * `guardRegistry`: each stays `null` until its `_init*()` runs with at\n * least one strategy/MV/overlay handle. */\n private derivationRegistry: DerivationRegistry | null = null\n private materializedViewRegistry: MaterializedViewRegistry | null = null\n private overlayedViewRegistry: OverlayedViewRegistry | null = null\n /** Per-vault dependency graph (#638) — field postures + derivation/MV/overlay/\n * computed/via-deps edges. Metadata-only (field names, postures, grains —\n * never values or key material); always present, unlike the registries above. */\n readonly graph: ViaGraph\n /** #638 Task 4 — open sync/cutover/restore touch collector, or `undefined` between batches. */\n private _graphBatch: GraphBatch | undefined\n /** Cached read-only facades for guard/derivation callbacks — split by\n * resolution layer (`layer:'guard'` vs `'derivation'`, each field's\n * `onMissing` policy differs). Allocated eagerly inside `_initGuards()`/\n * `_initDerivations()` so read accessors stay synchronous; `null` for\n * vaults without that service. */\n private guardFacade: ReadOnlyVaultFacade | null = null\n private derivationFacade: ReadOnlyVaultFacade | null = null\n private getDEK: (collectionName: string) => Promise<EnclaveKey>\n\n /**\n * Per-principal user envelope API.\n *\n * - Write-self: `me()`, `updateMe(patch)`, `setMe(payload)` — always\n * target this vault session's keyringId. There is no method to write\n * another principal's envelope (own-only write rule, structural).\n * - Read-anyone: `get(keyringId)`, `list()` — read other principals'\n * envelopes, subject to the `view-team-profiles` policy gate.\n * - Reactive: `subscribe(id, cb)`, `live(id)` — fire on local writes.\n *\n * @see docs/superpowers/specs/2026-05-05-user-envelope-design.md\n */\n public readonly user: VaultUserApi\n\n /**\n * FR-6 custody API — the sovereign-custody surface, mirroring `vault.user.*`.\n *\n * - `grantCustodian(opts)` / `revokeCustodian(opts)` — owner-only: mint /\n * remove a `custodian` who operates the vault fully but can never grant /\n * rotate / sever / extract.\n * - `liberate(opts)` — custodian-only: the audited claim of ownership over a\n * sealed-owner (Deed) vault (mints a DISTINCT new owner; ledger-audited).\n *\n * @see docs/superpowers/specs/2026-06-17-fr6-deed-custodian-liberate-design.md\n */\n public readonly custody: CustodyApi\n\n /** Re-derives an UnlockedKeyring from the adapter using the active user's secret; called by\n * `load()` after the on-disk keyring file has been replaced. Provided by Noydb at openVault()\n * time; `undefined` in tests that construct Vault directly (load() then skips the refresh). */\n private readonly reloadKeyring: (() => Promise<UnlockedKeyring>) | undefined\n private readonly collectionCache = new Map<string, Collection<unknown>>()\n private satelliteRegistry: SatelliteRegistry | null = null // spec #591, archetype-③\n /** Vault-level schema cutover fence/controller. */\n readonly schemaFence: SchemaFenceController\n /** Per-client heartbeat/watcher; started lazily on cutover registration. */\n #fenceWatcher: FenceWatcher | undefined\n #fenceCoordinationStarted = false\n /** Per-collection registered schema-update strategy names. */\n readonly #schemaUpdateNames = new Map<string, string[]>()\n\n /**\n * per-collection `blobFields` retention/TTL config.\n * Populated on `collection({ blobFields })` and read by\n * `vault.compact()`. Indexed by collection name.\n */\n private readonly blobFieldsRegistry = new Map<string, BlobFieldsConfig<unknown>>()\n\n /**\n * Attestation facade (issue/revoke + the per-collection field-schema\n * registry). Built in the constructor.\n */\n private readonly attestation!: VaultAttestation\n\n /**\n * Per-vault ledger store. Lazy-initialized on first\n * `collection()` call (which passes it through to the Collection)\n * or on first `ledger()` call from user code.\n *\n * One LedgerStore is shared across all collections in a vault\n * because the hash chain is vault-scoped: the chain head is a\n * single \"what did this vault do last\" identifier, not a\n * per-collection one. Two collections appending concurrently is the\n * single-writer concurrency concern documented in the LedgerStore\n * docstring.\n */\n private ledgerStore: LedgerStore | null = null\n\n /** Lazily-built atomic-sequence store. See {@link sequence}. */\n private sequenceStore: SequenceStore | null = null\n /** Lazily-built deferred-numbering engine. See {@link runNumberingPass}. */\n private deferredNumbering: DeferredNumberingStore | null = null\n /** Registered deferred-numbering series, keyed by series name. */\n private readonly numberingConfigs: Map<string, DeferredNumberingConfig>\n\n /**\n * Background writes for persisted-schema envelopes (#schema-dump v0\n * slice 1). One promise per `collection({ persistJsonSchema: true })`\n * registration that actually fired a derive call. Fire-and-forget\n * from the collection factory; tests await\n * {@link _drainPendingSchemaWrites} before asserting on storage.\n * Production code does not need to drain — the writes are\n * idempotent fingerprints, not correctness invariants.\n */\n private _pendingSchemaWrites: Promise<void>[] = []\n\n /**\n * Per-vault foreign-key reference registry. Collections\n * register their `refs` option here on construction; the\n * vault uses the registry on every put/delete/checkIntegrity\n * call. One instance lives for the compartment's lifetime.\n */\n private readonly refRegistry = new RefRegistry()\n\n /**\n * Vault-default locale. Set via\n * `openVault(name, { locale })`. Used as the fallback locale\n * when per-call `{ locale }` options are not specified on individual\n * `get()`/`list()` calls.\n */\n private locale: string | undefined\n\n /**\n * Vault-level descriptive metadata. Set once at construction via\n * `openVault(name, { meta })`. First-wins: re-opening a cached vault\n * with different meta leaves the original untouched.\n */\n private readonly vaultMeta: VaultMeta | undefined\n\n /**\n * Current consent scope. Set by `withConsent()` and\n * restored in its finally block. When non-null, every collection\n * access inside the scope writes one entry to `_consent_audit`.\n *\n * Single-slot by design — two concurrent withConsent calls on the\n * same Vault stomp each other. Adopters needing per-flight scoping\n * should use separate Vault instances.\n */\n private consentContext: ConsentContext | null = null\n\n /** dictKeyField registry: collection name → field name → dictionary name — `DictionaryHandle.rename()`'s reference-update source; populated by `collection()` from `dictKeyFields`. */\n private readonly dictKeyFieldRegistry = new Map<string, Record<string, string>>()\n\n /** Names of `staticDict()`-backed dictionaries (skip rename tracking; `vault.dictionary(name)` refuses mutation on these via `StaticDictReadonlyError`). Populated at `collection()` config time. */\n private readonly staticDictNames = new Set<string>()\n\n /** Static-dict descriptors by dictionary name — backs the read-path label resolver and the `resolveDictSource` snapshot. Last writer wins across collections (tables match by construction). */\n private readonly staticByName = new Map<string, StaticDictDescriptor>()\n\n /** Per-collection field name → StaticDictDescriptor, validated by `enforceStaticDictOnPut`. */\n private readonly staticDescriptorByField = new Map<string, Record<string, StaticDictDescriptor>>()\n\n /** i18nText fields: collection name → field name → descriptor. Used by `applyI18nLocale`/`validateI18nTextValue`; populated by `collection()` from `i18nFields`. Private — the #664 `via/reconcile.ts` dispatch reads these through {@link _viaReconcileCtx}'s structural bag, not `this` directly (a plain structural bag, never a `Vault` import — S5 port-layering forbids the kernel spine from reaching a with-* service, and this file's own reconcile-ladder logic moved OUT into that unguarded module). */\n private readonly i18nFieldRegistry = new Map<string, Record<string, I18nTextDescriptor>>()\n\n /** Cache of DictionaryHandle instances, one per dictionary name. */\n private readonly dictionaryCache = new Map<string, DictionaryHandle>()\n\n /** #650 Task 4 (#647) — declared reserved-lookup collection name → dimension name, for dimensions\n * with `backing:'reserved'` (dict()/dictKey()). The explicit sync-pull registry: NOT a blanket\n * underscore-glob — populated at `collection()`-declare time and at `dictionary()`-call time. */\n private readonly reservedLookupCollections = new Map<string, string>()\n\n /** Registered link specs, keyed by link name; set by `vault.link()`. */\n private readonly linkRegistry = new Map<string, LinkSpec>()\n /** Cache of link-set handles, one per link name (lazy -- see links()). */\n private readonly linkSetCache = new Map<string, LazyLinkSetHandle>()\n\n /** — subscribers for cross-tier access events. */\n private readonly crossTierSubs = new Set<(event: CrossTierAccessEvent) => void>()\n\n /** — currently-active elevation, or null. One per vault. */\n private activeElevation: {\n readonly tier: number\n readonly expiresAt: number\n readonly reason: string\n readonly handle: ElevatedHandle\n } | null = null\n\n /**\n * Optional translator callback threaded from `Noydb.invokeTranslator`.\n * Present only when `plaintextTranslator` was configured on `createNoydb()`.\n */\n private readonly translateText:\n | ((text: string, from: string, to: string, field: string, collection: string) => Promise<string>)\n | undefined\n\n constructor(opts: {\n adapter: NoydbStore\n name: string\n noydb: Noydb\n keyring: UnlockedKeyring\n encrypted: boolean\n emitter: NoydbEventEmitter\n onDirty?: OnDirtyCallback | undefined\n historyConfig?: HistoryConfig | undefined\n reloadKeyring?: (() => Promise<UnlockedKeyring>) | undefined\n /** Vault-default locale. */\n locale?: string | undefined\n /** Translator callback from Noydb. */\n plaintextTranslator?:\n | ((text: string, from: string, to: string, field: string, collection: string) => Promise<string>)\n | undefined\n /**\n * callback to register a per-collection envelope-level\n * conflict resolver with the SyncEngine. Present when sync is configured.\n */\n onRegisterConflictResolver?: ((name: string, resolver: CollectionConflictResolver) => void) | undefined\n /** — optional remote/sync adapter for presence broadcasting. */\n syncAdapter?: NoydbStore | undefined\n /** #615 — push-only sync targets (backup/archive) this vault may target-purge. Default: none. */\n getPurgeableTargets?: () => readonly { store: NoydbStore; role: 'backup' | 'archive'; label?: string }[]\n /**\n * tree-shake seam — strategy for optional blob storage.\n * Passed through to every `Collection` built by `vault.collection()`.\n * `undefined` => every `collection.blob(id)` throws with a pointer\n * at `@noy-db/hub/blobs`.\n */\n /**\n * Every opt-in service, already resolved by `createNoydb` (#838). Not\n * optional: a Vault cannot be built without it, which is what makes the\n * partially-populated construction path of #834 unrepresentable.\n */\n strategies: StrategyBag\n objectStore?: ObjectProjection | undefined\n guardStrategies?: ReadonlyArray<GuardStrategyAny> | undefined\n numberingConfigs?: ReadonlyArray<DeferredNumberingConfig> | undefined\n /** Vault-level descriptive metadata — set once at construction (first-wins). */\n meta?: VaultMeta | undefined\n }) {\n this.adapter = opts.adapter\n this.name = opts.name\n this.numberingConfigs = new Map((opts.numberingConfigs ?? []).map((c) => [c.series, c]))\n this.noydb = opts.noydb\n this.keyring = opts.keyring\n this.encrypted = opts.encrypted\n this.schemaFence = new SchemaFenceController({\n coordination: this.noydb.coordination,\n vault: this.name,\n onFlush: () => this.noydb._writeQueueTracker.onFlush(),\n clientId: this.noydb._clientId,\n sessionId: this.noydb._sessionId,\n emit: (e) => this.emitter.emit('schema:fence-changed', { vault: this.name, ...e }),\n })\n this.emitter = opts.emitter\n this.onDirty = opts.onDirty\n this.onRegisterConflictResolver = opts.onRegisterConflictResolver\n this.syncAdapter = opts.syncAdapter\n this.getPurgeableTargets = opts.getPurgeableTargets ?? (() => [])\n // #838 — 20 field assignments, each re-applying a `?? NO_*` default that\n // `createNoydb` had already resolved, are one shared reference.\n this.strategies = opts.strategies\n this.objectStore = opts.objectStore\n this.periods = new VaultPeriods({\n strategy: this.strategies.periods,\n adapter: this.adapter,\n vault: this.name,\n encrypted: this.encrypted,\n userId: () => this.keyring.userId,\n getDEK: (collection) => this.getDEK(collection),\n getLedgerOrNull: () => this.getLedgerOrNull(),\n collection: (name) => this.collection(name),\n purgeDeleteMarkers: (before) => this._purgeDeleteMarkers(before),\n archiveRecords: (before) => this._archiveClosedPeriod(before),\n purgeTargets: (before) => this._purgePeriodTargets(before),\n // #822: push symmetry for the period summaries — see writeReserved.\n onDirty: this.onDirty,\n })\n this.linksEnforcer = new VaultLinks({\n refRegistry: this.refRegistry,\n linkRegistry: this.linkRegistry,\n adapter: this.adapter,\n vault: this.name,\n collection: (name) => this.collection(name),\n links: (name) => this.links(name),\n getCachedCollection: (name) => this.collectionCache.get(name),\n getActiveTxContext: () => this.noydb._activeTxContextOrNull,\n emitter: this.emitter,\n })\n this.graph = new ViaGraph()\n // Guard + derivation registries are initialised lazily via\n // `_initGuards()` / `_initDerivations()` from `Noydb.openVault()`.\n // The classes are dynamic-imported there so vaults that never\n // register a strategy don't pull the service code into the\n // floor bundle. The `opts.guardStrategies` argument is\n // intentionally accepted but unused on the constructor — the sync\n // `vault()` fallback path in `noydb.ts` does NOT call `_initGuards`,\n // matching the existing behaviour for `_initDerivations`.\n void opts.guardStrategies\n this.historyConfig = opts.historyConfig ?? { enabled: true }\n this.reloadKeyring = opts.reloadKeyring\n this.locale = opts.locale\n this.vaultMeta = opts.meta\n this.translateText = opts.plaintextTranslator\n\n // Build the lazy DEK resolver. Pulled out into a private method\n // so `load()` can rebuild it after a keyring refresh — the\n // closure captures `this.keyring` by reference, so changing the\n // field is enough, but resetting the cached `getDEKFn` ensures\n // ensureCollectionDEK runs again against the freshly-loaded\n // wrapped DEKs.\n this.getDEK = this.makeGetDEK()\n\n // Attestation facade — always built (holds the per-collection field-schema\n // registry); the capability itself is gated by the injected strategy\n // (NO_ATTESTATION default throws until `attestationStrategy: withAttestation()`).\n this.attestation = new VaultAttestation({\n adapter: this.adapter,\n vault: this.name,\n getDEK: (collection) => this.getDEK(collection),\n role: () => this.keyring.role,\n getRawRecord: async (collection, recId) =>\n (await this.collection(collection).get(recId, { locale: 'raw' })) as Record<string, unknown> | null,\n }, this.strategies.attestation)\n\n // User envelope API — frozen writerKeyringId, dynamic DEK resolver\n // (so a post-load() keyring refresh transparently rotates the DEK\n // through the rebuilt this.getDEK), and a checkGate callback that\n // delegates to Noydb's policy engine (wires edit-own-profile +\n // view-team-profiles).\n this.user = this.noydb.userApiFactory({\n adapter: this.adapter,\n vaultName: this.name,\n writerKeyringId: this.keyring.userId,\n getDek: () => this.getDEK(USER_ENVELOPE_COLLECTION),\n checkGate: (gate, presented) => this.noydb.checkGate(this.name, gate, presented),\n exportAccessible: (opts) => this.strategies.portability.exportAccessibleData(this, opts),\n unilateralWithdraw: (opts) => this.strategies.portability.withdrawAccessibleData(this, opts),\n requestWithdraw: (opts) => this.strategies.portability.requestWithdrawal(this, opts),\n listWithdrawals: (opts) => this.strategies.portability.listWithdrawalRequests(this, opts),\n approveWithdraw: (requestId, opts) => this.strategies.portability.approveWithdrawal(this, requestId, opts),\n rejectWithdraw: (requestId, opts) => this.strategies.portability.rejectWithdrawal(this, requestId, opts),\n })\n\n // FR-6 custody API — mirrors the UserApi injection pattern: vault-bound\n // closures over Noydb.grantCustodian/revokeCustodian (owner-only) and the\n // liberate ceremony (custodian-only). All three route through the opt-in\n // custodyStrategy (S4): grant/revoke via the gated Noydb methods, liberate\n // via `noydb.custodyStrategy` (which lazily imports the liberateVault\n // engine). No logic here — CustodyApi is a pure delegation shell.\n this.custody = new CustodyApi(\n (options, factors) => this.noydb.grantCustodian(this.name, options, factors),\n (options, factors) => this.noydb.revokeCustodian(this.name, options, factors),\n (opts) => this.noydb.custodyStrategy.liberate(this, opts),\n )\n }\n\n /**\n * Construct (or reconstruct) the lazy DEK resolver. Captures the\n * CURRENT value of `this.keyring` and `this.adapter` in a closure,\n * memoizing the inner getDEKFn after first use so subsequent\n * lookups are O(1).\n *\n * `load()` calls this after refreshing `this.keyring` to discard\n * the prior session's cached DEKs.\n */\n private makeGetDEK(): (collectionName: string) => Promise<EnclaveKey> {\n let getDEKFn: ((collectionName: string) => Promise<EnclaveKey>) | null = null\n return async (collectionName: string): Promise<EnclaveKey> => {\n if (!getDEKFn) {\n getDEKFn = await ensureCollectionDEK(this.adapter, this.name, this.keyring)\n }\n return getDEKFn(collectionName)\n }\n }\n\n /**\n * Open a typed collection within this vault.\n *\n * - `options.indexes` declares secondary indexes for the query DSL.\n * Indexes are computed in memory after decryption; adapters never\n * see plaintext index data.\n * - `options.prefetch` (default `true`) controls hydration. Eager mode\n * loads everything on first access; lazy mode (`prefetch: false`)\n * loads records on demand and bounds memory via the LRU cache.\n * - `options.cache` configures the LRU bounds. Required in lazy mode.\n * Accepts `{ maxRecords, maxBytes: '50MB' | 1024 }`.\n * - `options.schema` attaches a Standard Schema v1 validator (Zod,\n * Valibot, ArkType, Effect Schema, etc.). Every `put()` is validated\n * before encryption; every read is validated after decryption.\n * Failing records throw `SchemaValidationError`.\n * - `options.i18nFields` declares per-field `i18nText()` descriptors\n *. Validated on `put()` and locale-resolved on reads.\n * - `options.dictKeyFields` declares per-field `dictKey()` descriptors\n *. `put()` validates keys against the declared set; reads\n * with `{ locale }` add `<field>Label` virtual fields.\n *\n * Throws `ReservedCollectionNameError` for names starting with `_dict_` or\n * equal to `_sequences`. Use `vault.dictionary(name)` for dict collections\n * and `vault.sequence(name)` for sequence counters.\n *\n * Lazy mode + indexes is rejected at construction time — see the\n * Collection constructor for the rationale.\n */\n /** Assembles {@link ViaReconcileVaultCtx} — the plain structural bag the #664 `via/reconcile.ts`\n * dispatch reads/writes — from this vault's OWN privates, rather than passing `this` itself. */\n private _viaReconcileCtx(): ViaReconcileVaultCtx {\n return {\n i18nStrategy: this.strategies.i18n, locale: this.locale, translateText: this.translateText,\n i18nFieldRegistry: this.i18nFieldRegistry, dictKeyFieldRegistry: this.dictKeyFieldRegistry,\n staticDescriptorByField: this.staticDescriptorByField, reservedLookupCollections: this.reservedLookupCollections,\n staticByName: this.staticByName, staticDictNames: this.staticDictNames, getOpenCollection: (n) => this._getCollection(n), getCollection: (n) => this.collection<Record<string, unknown>>(n),\n dictionary: (name) => this.dictionary(name),\n enforceI18nOnPut: (collectionName, record) => this.enforceI18nOnPut(collectionName, record),\n enforceStaticDictOnPut: (collectionName, record) => this.enforceStaticDictOnPut(collectionName, record),\n }\n }\n\n /** The registries `populateCollectionRegistries` writes into (#841). */\n #registries() {\n return {\n refRegistry: this.refRegistry,\n i18nFieldRegistry: this.i18nFieldRegistry,\n blobFieldsRegistry: this.blobFieldsRegistry,\n archiveRegistry: this.archiveRegistry,\n attestation: this.attestation,\n dictKeyFieldRegistry: this.dictKeyFieldRegistry,\n staticDictNames: this.staticDictNames,\n staticByName: this.staticByName,\n staticDescriptorByField: this.staticDescriptorByField,\n reservedLookupCollections: this.reservedLookupCollections,\n schemaUpdateNames: this.#schemaUpdateNames,\n }\n }\n\n collection<T, O extends CollectionShape<T> = Record<never, never>>(\n collectionName: string,\n options?: OpenCollectionOptions<T, SensitiveOf<T, O>, IndexedOf<T, O>, MoneyOf<T, O>>,\n ): Collection<T, SensitiveOf<T, O>, IndexedOf<T, O>, MoneyOf<T, O>> {\n type S = SensitiveOf<T, O>; type Q = IndexedOf<T, O>; type M = MoneyOf<T, O> // #839\n // Overlay intercept. When the requested collection name\n // matches a registered `withOverlayedView`, return the virtual\n // proxy that merges base + overlay on read and routes writes to\n // the overlay collection. The proxy implements the core\n // Collection<T> read/write surface (get, list, put, delete);\n // reactive APIs (live, subscribe) are out of scope.\n const overlayRegistry = this.overlayedViewRegistry\n if (overlayRegistry !== null && overlayRegistry.isOverlay(collectionName)) {\n const spec = overlayRegistry.byName(collectionName)\n if (spec) {\n // Recursive call into the same method — the base + overlay\n // are real collections, so they re-enter this method without\n // hitting the overlay intercept (their names won't match).\n const base = this.collection<T>(spec.base)\n const overlay = this.collection<T>(spec.overlay)\n const baseRowKey = overlayRegistry.resolveBaseRowKey(collectionName, this.materializedViewRegistry)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n return new OverlayedCollection<any>(spec, base, overlay, baseRowKey) as unknown as Collection<T, S, Q, M>\n }\n }\n // Guard: reject reserved _dict_* names\n if (isDictCollectionName(collectionName)) throw new ReservedCollectionNameError(collectionName)\n // Guard: reject the internal _sequences collection — use vault.sequence() instead.\n if (collectionName === SEQUENCE_COLLECTION) throw new ReservedCollectionNameError(collectionName)\n // Guard: reject reserved _links_* names — use vault.link()/vault.links() instead.\n if (isLinkCollectionName(collectionName)) throw new ReservedCollectionNameError(collectionName)\n // Guard: reject secret-bearing reserved names (`_sync_credentials`,\n // `_broker`). Their record CONTENTS are directly-usable secrets, so they\n // must never be reachable through the generic public collection handle —\n // they are served only by their dedicated, owner/admin-gated API. Serving\n // them here would decrypt with whatever DEK the caller's keyring holds,\n // bypassing that gate. See reserved-secret-collections.ts.\n if (isSecretBearingReservedCollection(collectionName)) throw new ReservedCollectionNameError(collectionName)\n\n if (this.satelliteRegistry?.byJoined(collectionName)) { // #591: joined handle — not a directly reachable collection\n throw new SatelliteConfigError(`\"${collectionName}\" is a joined handle — use vault.joined('${collectionName}'), not vault.collection().`)\n }\n // R-S8 direction (ii): refuse constructing (fresh OR already-cached) either\n // pair member with crdt mode AFTER the pairing already exists.\n if (options?.crdt !== undefined && this.satelliteRegistry?.isPairMember(collectionName)) {\n throw new SatelliteConfigError('R-S8: crdtMode is refused on either member of a satellite pair in v1 (revert cannot compensate a merge).')\n }\n if (options?.satelliteOf !== undefined) { // #591 thin call-site (archetype-③) — wiring lives in with-shape/satellites/declare.ts\n this.satelliteRegistry = declareSatellite({\n adapter: this.adapter, vaultName: this.name, forgetSubjects: this.strategies.forget.subjects, getDEK: this.getDEK,\n getBaseSchema: (base) => this.collectionCache.get(base)?.getSchema(),\n getBaseCrdt: (base) => this.collectionCache.get(base)?.getConfig()?.crdt,\n collectionExists: (name) => this.collectionCache.has(name),\n registerPoisonHook: (hook) => { this.noydb._writeHooks.onBeforeWrite(hook) },\n forEachSyncEngine: (fn) => { this.noydb._forEachSyncEngine(this.name, fn) },\n }, collectionName, { ...options, satelliteOf: options.satelliteOf }, this.satelliteRegistry)\n }\n\n let coll = this.collectionCache.get(collectionName)\n const effectiveViaFields = mergeViaFields({ moneyFields: options?.moneyFields, i18nFields: options?.i18nFields, dictKeyFields: options?.dictKeyFields, lookupFields: options?.lookupFields, viaFields: options?.viaFields }) // #627: merged view feeds both late-attach reconcile (below) and fresh construct\n // #664 — the whole late-attach reconcile ladder (collision guard, the five pre-existing\n // _apply* reconciles, the two-phase graph-edge/taint commit, and the new i18n/dictKey\n // machinery) now lives behind ONE dispatch call in the unguarded via/reconcile.ts, not\n // inlined here. `Collection._applyX`'s own first-wins semantics are unchanged; this file\n // only threads the field-declaring options + this vault's registries through.\n if (coll) {\n reconcileViaAttach(coll, this.graph, collectionName, this._viaReconcileCtx(), {\n effectiveViaFields,\n ...(options?.computed !== undefined ? { computed: options.computed as ComputedFields } : {}),\n ...(options?.fieldMeta !== undefined ? { fieldMeta: options.fieldMeta } : {}),\n ...(options?.meta !== undefined ? { meta: options.meta } : {}),\n ...(options?.classifiedFields !== undefined ? { classifiedFields: options.classifiedFields } : {}),\n ...(options?.blobFields !== undefined ? { blobFields: options.blobFields } : {}),\n })\n }\n if (!coll) {\n // Fan the declaration out into the vault's ten registries (#841).\n // Runs BEFORE the Collection is constructed so the first put() already\n // sees its refs through vault.enforceRefsOnPut.\n populateCollectionRegistries(this.#registries(), collectionName, options, effectiveViaFields)\n\n // Schema-update gate. Built only when persistence + strategies\n // are on. Detection runs in the same work pushed to the drain; the\n // gate caches the decision and the write path (put/delete) enforces it.\n let schemaUpdateGate: SchemaUpdateGate | undefined\n if (\n options?.persistJsonSchema === true &&\n options.schema !== undefined &&\n (options.schemaUpdate?.length ?? 0) > 0\n ) {\n const validator: unknown = options.schema\n const strategies = options.schemaUpdate ?? []\n const work = (async (): Promise<UpdateDecision> => {\n const dek = await this.getDEK(collectionName)\n const { persistSchemaIfNeeded } = await import('../with-shape/persisted-schemas/register.js') // lazy (#553)\n const result = await persistSchemaIfNeeded({\n store: this.adapter, vault: this.name, collectionName, validator, dek, strategies,\n })\n const decision = result.decision ?? { action: 'allow' as const }\n if (decision.action === 'cutover') {\n this.schemaFence.registerPendingCutover(collectionName, decision.transform)\n await this._ensureFenceCoordination()\n }\n return decision\n })()\n this._pendingSchemaWrites.push(work.then(() => {}, () => {}))\n schemaUpdateGate = new SchemaUpdateGate(work)\n }\n\n // Per-collection history/ledger scoping. A per-call\n // `historyConfig` overrides the vault-wide config wholesale for this\n // collection; `ledger: false` excludes it from the tamper chain.\n const effectiveHistoryConfig = options?.historyConfig ?? this.historyConfig\n\n const collOpts: ConstructorParameters<typeof Collection<T>>[0] = {\n adapter: this.adapter,\n vault: this.name,\n name: collectionName,\n keyring: this.keyring,\n encrypted: this.encrypted,\n emitter: this.emitter,\n writeQueue: this.noydb._writeQueueTracker,\n writeHooks: this.noydb._writeHooks,\n subsystemBus: this.noydb._subsystemBus,\n activeTxId: () => this.noydb._activeTxContextOrNull?.txId ?? null,\n schemaUpdateGate,\n schemaFence: this.schemaFence,\n getDEK: this.getDEK,\n onDirty: this.onDirty,\n tabCoordinated: () => this.noydb._tabCoordinationActive, // #693: re-create gate fallback\n historyConfig: effectiveHistoryConfig,\n historyConfigExplicit: options?.historyConfig !== undefined,\n ...(this.objectStore !== undefined ? { objectStore: this.objectStore } : {}),\n ...(options?.blobFields !== undefined ? { blobFields: options.blobFields as BlobFieldsConfig<unknown> } : {}),\n strategies: this.strategies,\n // Per-collection ledger opt-out: when this collection sets\n // `historyConfig.ledger: false`, withhold the ledger reference so all\n // four `if (this.ledger)` append sites in Collection no-op. The chain\n // stays valid — it simply never receives this collection's entries.\n ledger: effectiveHistoryConfig.ledger === false ? undefined : (this.getLedgerOrNull() ?? undefined),\n refEnforcer: this,\n joinResolver: this,\n defaultLocale: this.locale,\n onRegisterConflictResolver: this.onRegisterConflictResolver,\n onAccess: (op, id) => this._logConsent(op, collectionName, id),\n graphDispatch: { collect: (collection, id) => this._collectGraphTouch(collection, id), collectDelete: (collection, id, intents) => this._collectGraphDelete(collection, id, intents) },\n // Derivation source is only wired when the corresponding registry\n // has been initialised. Guard source was removed in Track A slice 3b\n // — guards now run via the gate bus in Noydb.#registerGuardGate.\n // Vaults without derivations skip this so `Collection.put`'s\n // `if (this.derivationSource)` branch no-ops without touching the\n // derivation service code.\n ...(this.derivationRegistry !== null\n ? {\n derivationSource: {\n registry: () => this.derivationRegistry as DerivationRegistry,\n getCollection: (name: string) =>\n this.collection(name) as unknown as Collection<Record<string, unknown>>,\n getReadOnlyFacade: () => this._ensureReadOnlyFacade(),\n getActiveTxContext: () => this.noydb._activeTxContextOrNull,\n createTxContext: () => this.noydb._createTxContext(),\n setActiveTxContext: (ctx) => this.noydb._setActiveTxContext(ctx),\n clearActiveTxContext: (ctx) => this.noydb._clearActiveTxContext(ctx),\n },\n }\n : {}),\n ...(this.materializedViewRegistry !== null\n ? {\n materializedViewSource: {\n \n registry: () => this.materializedViewRegistry!,\n getCollection: (name: string) => this.collection(name),\n getActiveTxContext: () => this.noydb._activeTxContextOrNull,\n getQueryContext: () => this as unknown as MVQueryContext,\n },\n }\n : {}),\n }\n // #841 — 28 pass-through options in one call. Anything needing logic\n // stays explicit; the forget-subject rule below still overrides\n // `perRecordKeys` because it runs after this.\n copyDefined(collOpts as unknown as Record<string, unknown>, options as unknown as Record<string, unknown> | undefined, COLLECTION_PASSTHROUGH_KEYS)\n // A collection declared in `withForget({ subjects })` MUST\n // use per-record CEKs: crypto-shred can only guarantee erasure of a body\n // keyed off a per-record CEK. Force it on (and warn if the caller\n // explicitly set it false — that would silently defeat erasure).\n const subjectKey = this.strategies.forget.subjects[collectionName]\n if (subjectKey !== undefined) {\n if (options?.perRecordKeys === false) {\n console.warn(\n `[noy-db] Collection \"${collectionName}\" is declared in withForget ` +\n `but opened with perRecordKeys: false. Forcing perRecordKeys: true — ` +\n `GDPR crypto-shred requires per-record CEKs.`,\n )\n }\n collOpts.perRecordKeys = true\n // Classified refusal matrix R4: a digest-only field cannot be the\n // forget-subject key (the subject index would hold the plaintext).\n collOpts.subjectKeyField = subjectKey\n collOpts.addSubjectRef = async (id, record) => { const value = readDottedPath(record as Record<string, unknown>, subjectKey); if (value !== undefined && value !== null) await this._addSubjectRef(coerceSubjectId(value), { collection: collectionName, id }) } // #766: putAtTier's raw write bypasses onAfterWrite — register the first-write subject ref directly\n }\n collOpts.onCrossTierAccess = (event) => this.emitCrossTier(event)\n if (this.syncAdapter !== undefined) collOpts.syncAdapter = this.syncAdapter\n if (effectiveViaFields.dictKeyFields !== undefined || effectiveViaFields.lookupFields !== undefined) {\n // Build the label resolver callback for this collection. A static dict resolves from\n // its in-memory table — no dictionary() lookup, no _dict_* read — while a plain dictKey\n // resolves through the encrypted _dict_* handle as before. Shared verbatim by the lookup\n // binding (#650 Task 2) — native lookup()/dict() reserved/static(+table) dimensions\n // register into the SAME staticByName registry above, so this one resolver serves both.\n collOpts.dictLabelResolver = async (dictName, key, locale, fallback) => {\n const stat = this.staticByName.get(dictName)\n if (stat) {\n const labels = stat.table[key]\n return labels ? resolveLabelFromMap(labels, locale, fallback) : undefined\n }\n const handle = this.dictionary(dictName)\n return handle.resolveLabel(key, locale, fallback)\n }\n // Provide a handle factory for dynamic dicts so the search\n // index can call list() to build the full key→labels map.\n collOpts.getDictionary = async (name: string) => this.dictionary(name)\n collOpts.dictKeyFields = options?.dictKeyFields\n }\n if (effectiveViaFields.lookupFields !== undefined) {\n // membership/getAltIndex (#650 Task 3) are vault-built closures — never a collection handle.\n // must move together with via/reconcile.ts's five lookup closures (#664).\n collOpts.lookupLabelResolver = collOpts.dictLabelResolver\n collOpts.getLookupBacking = (desc: LookupDescriptor) => async (key: string) => // #651: snapshot-first (sole truth for key!=='id'); id-tier alone falls back to a live cold-session .get()\n buildLookupSnapshotRows(desc, (n) => this.reservedLookupCollections.has(dictCollectionName(n)), (n) => this.dictionary(n), (n) => this.collection<Record<string, unknown>>(n))?.get(key) ?? (desc.key === 'id' ? (await this.collection<Record<string, unknown>>(desc.dimension).get(key)) ?? undefined : undefined)\n collOpts.lookupFields = options?.lookupFields\n collOpts.membership = (field, key) => checkLookupMembership(effectiveViaFields.lookupFields![field]!, key, (n) => this.dictionary(n), (n) => this.collection(n))\n collOpts.getAltIndex = (d) => buildLookupAltIndex(d, (n) => this.dictionary(n), (n) => this.collection<Record<string, unknown>>(n))\n collOpts.snapshotFor = (d) => buildLookupSnapshotRows(d, (n) => this.reservedLookupCollections.has(dictCollectionName(n)), (n) => this.dictionary(n), (n) => this.collection<Record<string, unknown>>(n)) // #650 Task 6/7\n }\n // i18n / staticDict validation on put — enforced via the compartment's\n // put hook. staticDict adds put-time code validation.\n if (\n effectiveViaFields.i18nFields !== undefined ||\n effectiveViaFields.dictKeyFields !== undefined\n ) {\n collOpts.i18nPutValidator = (record: unknown) => {\n this.enforceI18nOnPut(collectionName, record)\n this.enforceStaticDictOnPut(collectionName, record)\n }\n }\n // Wire the translator for autoTranslate: true fields\n if (effectiveViaFields.i18nFields !== undefined && this.translateText) {\n collOpts.autoTranslateHook = this.translateText\n }\n // fieldMeta: thread through to the collection. Real key-validation (against\n // schema-derived fields) happens in the async describe() path where the full\n // known-field set is available. The sync path at vault-construction time cannot\n // validate schema fields, so no validate call here.\n // meta: thread through to the collection; surfaced via getMeta() / describe().\n // Pass a snapshot of the outbound refs for describe() (sync, config-only).\n if (options?.refs !== undefined) {\n collOpts.declaredRefs = this.refRegistry.getOutbound(collectionName)\n }\n coll = new Collection<T>(collOpts)\n this.collectionCache.set(collectionName, coll)\n registerCollectionGraphSources(this.graph, collectionName, collOpts)\n registerLookupRefEdges(this.graph, collectionName, effectiveViaFields.lookupFields) // #650 Task 5\n applyTaintOverlay(coll, this.graph, collectionName) // #638 Task 3: seal + gate any freshly-tainted field\n reapplyDependentOverlays(this.graph, collectionName, (n) => this._getCollection(n)) // #642: refresh dependents opened before this source\n\n // Pre-build the lexical index on open when opted in. Fire-and-forget,\n // eager-only; warmIndex() no-ops when no textIndexes are declared and throws\n // (caught here) in lazy mode, so this stays a single guarded line.\n if (options?.warmIndexOnOpen === true && options.prefetch !== false) {\n void coll.warmIndex().catch(() => {})\n }\n\n // Fire-and-forget persisted-schema write when opted in. Pushed\n // onto _pendingSchemaWrites so tests can drain before asserting;\n // production code ignores it (the writes are idempotent fingerprints).\n // When schemaUpdate strategies are present, persistence already ran\n // inside the gate's work above — skip the un-gated path here.\n if (\n options?.persistJsonSchema === true &&\n options.schema !== undefined &&\n (options.schemaUpdate?.length ?? 0) === 0\n ) {\n const validator: unknown = options.schema\n const work = (async () => {\n try {\n const dek = await this.getDEK(collectionName)\n await (await import('../with-shape/persisted-schemas/register.js')).persistSchemaIfNeeded({\n store: this.adapter,\n vault: this.name,\n collectionName,\n validator,\n dek,\n })\n } catch (err) {\n // Schema persistence is a fingerprint, not a correctness\n // invariant — log and continue. Production callers can\n // still detect failures via _drainPendingSchemaWrites.\n \n console.warn(\n `[noy-db] persisted-schema write failed for \"${collectionName}\": `\n + (err instanceof Error ? err.message : String(err)),\n )\n }\n })()\n this._pendingSchemaWrites.push(work)\n }\n }\n if (this.satelliteRegistry) { // #591: existence-authority + R-S6 read/write proxy (with-shape/satellites/proxy.ts)\n const spec = this.satelliteRegistry.bySatellite(collectionName)\n if (spec) return makeSatelliteProxy(coll, spec, this.satelliteRegistry) as Collection<T, S, Q, M>\n const baseSpec = this.satelliteRegistry.satelliteOf(collectionName) // #591 Task 6: base-side delete fan-out\n if (baseSpec) return makeBaseProxy(coll, baseSpec, this.satelliteRegistry, () => this.collection(baseSpec.satellite)) as Collection<T, S, Q, M>\n }\n return coll as unknown as Collection<T, S, Q, M>\n }\n\n /** Full-record handle for a satellite pair registered with `joined:` (spec #591). Narrow type — not a Collection. */\n joined<T extends Record<string, unknown>>(name: string): JoinedHandle<T> {\n const spec = this.satelliteRegistry?.byJoined(name)\n if (!spec) throw new SatelliteConfigError(`No joined handle \"${name}\" is registered — declare it via collection(satellite, { joined: '${name}' }).`)\n return makeJoinedHandle<T>(spec, {\n spec, base: () => this.collection(spec.base), satellite: () => this.collection(spec.satellite),\n adapter: this.adapter, vaultName: this.name, registry: this.satelliteRegistry!,\n })\n }\n\n /**\n * Migrate an existing satellite's records onto per-record CEKs (#599) —\n * unblocks R-S7 when a base gains forget coverage after its satellite was\n * already declared without `perRecordKeys`. Call BEFORE re-declaring with\n * `{ satelliteOf, perRecordKeys: true }` AND before this collection serves\n * writes (unfenced walk — see {@link migrateSatelliteCek}); resumable.\n */\n async migrateSatellitePerRecordKeys(satelliteName: string): Promise<{ migrated: number }> {\n return migrateSatelliteCek(satelliteName, this.collection(satelliteName, { perRecordKeys: true }))\n }\n\n /**\n * Await all background persisted-schema writes triggered by\n * `collection({ persistJsonSchema: true })` calls on this vault.\n * Used in tests; production code does not need to call this.\n */\n async _drainPendingSchemaWrites(): Promise<void> {\n const pending = this._pendingSchemaWrites\n this._pendingSchemaWrites = []\n await Promise.allSettled(pending)\n }\n\n /**\n * Run a coordinated schema cutover. Drains pending writes, waits\n * for the active client set to quiesce (the ack-barrier), applies every\n * pending collection transform in bulk, bumps the vault schema generation,\n * and clears the fence. Returns the count of collections migrated.\n * `opts.onPoll` (tests) advances other clients between barrier checks.\n */\n async runSchemaCutover(opts?: { onPoll?: () => Promise<void> }): Promise<{ migrated: number }> {\n return this.schemaFence.runCutover(\n (collectionName, transform) => this.#runCutoverTransform(collectionName, transform),\n opts,\n )\n }\n\n async #runCutoverTransform(collectionName: string, transform: TransformFn): Promise<void> {\n const coll = this.collectionCache.get(collectionName)\n if (!coll) return\n this._beginGraphBatch() // #638 Task 4 — cutover is a dispatch-wave origin, same as sync-apply\n await coll._applyCutoverTransform(transform)\n await this._flushGraphBatch()\n }\n\n /**\n * Refresh a loaded collection's view of one document from a peer\n * tab's broadcast. No-op when the collection isn't loaded in this tab\n * (it will read fresh on next open). Mirrors `#runCutoverTransform`'s guard.\n */\n async _applyRemoteWrite(collectionName: string, docId: string, action: 'put' | 'delete'): Promise<void> {\n const coll = this.collectionCache.get(collectionName)\n if (!coll) return\n await coll._applyRemoteChange(docId, action)\n }\n\n /** @internal #598: refresh cache entries a sync-applied write rewrote underneath us. No-op if not loaded this session.\n * #650 Task 4 (#647): a reserved-lookup collection has no `Collection` instance — instead, refresh\n * its already-warmed `LookupHandle._syncCache` (membership/altIndex/snapshot reads never see a\n * stale verdict for a pulled vocabulary edit) and collect the touch into any open graph batch\n * (the sync-apply wave-reachability seam Task 5's ref edges will use). No-op if never warmed. */\n async _invalidateSyncApplied(collection: string, id: string, action: 'put' | 'delete'): Promise<void> {\n const coll = this.collectionCache.get(collection)\n if (coll) {\n await coll._onRecordMutated(id, action, 'sync-apply')\n return\n }\n const dimName = this.reservedLookupCollections.get(collection)\n if (dimName === undefined) return\n await this.dictionaryCache.get(dimName)?._refreshSyncCache(id)\n this._collectGraphTouch(collection, id)\n }\n\n /** @internal #650 Task 4 (#647) — declared reserved-lookup collection names, for `SyncEngine.pull()`'s explicit prefix registry. */\n _reservedLookupCollectionNames(): readonly string[] {\n return [...this.reservedLookupCollections.keys()]\n }\n\n /** @internal #653 — one-hop reserved-dict deps of `names`, for `SyncEngine`'s partial-sync\n * filter expansion. Provably complete at one hop: `vault.collection()` refuses `_dict_*`\n * names, so a dict can never itself declare lookup fields (no dict-of-dict chain). */\n _reservedDictDepsOf(names: readonly string[]): readonly string[] {\n return reservedDictDepsOf(names, this.dictKeyFieldRegistry)\n }\n\n /** @internal #638 Task 4 — open a graph-dispatch touch batch (sync pull()/push()/cutover). */\n _beginGraphBatch(): void {\n this._graphBatch = new Map()\n }\n\n /** @internal #638 Task 4 — `Collection._onRecordMutated`'s sync-apply/cutover/restore hook; a\n * no-op when no batch is open (`_beginGraphBatch()` was never called for this call chain). */\n _collectGraphTouch(collection: string, id: string): void {\n if (!this._graphBatch) return\n touchFor(this._graphBatch, collection).puts.add(id)\n }\n\n /** @internal #640 — the sync-apply delete socket: `id`'s resolved rollup-parent intents. */\n _collectGraphDelete(collection: string, id: string, intents: readonly RollupDeleteIntent[]): void {\n if (!this._graphBatch) return\n touchFor(this._graphBatch, collection).deletes.set(id, intents)\n }\n\n /** @internal #638 Task 4 — close the open batch and run ONE dispatch wave over it. */\n async _flushGraphBatch(): Promise<void> {\n const batch = this._graphBatch\n this._graphBatch = undefined\n if (batch && batch.size > 0) await runGraphDispatchWave(this, batch)\n }\n\n /** @internal #638 Task 4 — cached-collection lookup for `runGraphDispatchWave` (`VaultLike`); never constructs. */\n _getCollection(name: string): Collection<Record<string, unknown>> | undefined {\n return this.collectionCache.get(name) as Collection<Record<string, unknown>> | undefined\n }\n\n /** @internal #640 (#644 item 3) — `VaultLike._emit`: the wave's structured error surfacing. */\n _emit(event: string, payload: unknown): void { (this.emitter.emit as (ev: string, pl: unknown) => void)(event, payload) }\n\n /**\n * @internal #589 → #604. Physically remove delete markers with `_ts` strictly\n * older than `before` (ISO timestamp), across `collections` (or all data\n * collections). Returns the count removed.\n *\n * SAFETY: purging a marker RE-OPENS the #589 resurrection window for any peer\n * offline since before the cutoff — never-GC is safe precisely because the marker\n * is always present to win convergence. This is an operator-asserted safe-point\n * ONLY; #604's period-close lifecycle is what earns that assertion. Do not call\n * it on live/unsettled data.\n *\n * Emits no ledger/event itself — its callers (#604's `freezePeriod`, #615's\n * `purgePeriodTargets`) own the audit record. The sweep body is shared via\n * {@link _purgeMarkersOn}, which #615 also aims at push-only sync targets.\n *\n * Purges the local adapter only. Markers already pushed to the vault's\n * push-only (`backup`/`archive`) sync targets are reclaimed by #615's\n * `vault.purgePeriodTargets`; `sync-peer` targets are left untouched (purging\n * them would re-open the resurrection window — the deferred half of #611).\n */\n async _purgeDeleteMarkers(before: string, collections?: string[]): Promise<number> {\n return this._purgeMarkersOn(this.adapter, before, collections)\n }\n\n /**\n * @internal #615. Sweep delete markers with `_ts < before` off ANY store\n * (local adapter or a push-only sync target). Returns the count removed.\n */\n private async _purgeMarkersOn(store: NoydbStore, before: string, collections?: string[]): Promise<number> {\n const snapshot = await store.loadAll(this.name)\n let removed = 0\n for (const [coll, records] of Object.entries(snapshot)) {\n if (collections && !collections.includes(coll)) continue\n for (const [id, env] of Object.entries(records)) {\n if (isDeleteMarker(env) && env._ts < before) {\n await store.delete(this.name, coll, id)\n removed++\n }\n }\n }\n return removed\n }\n\n /**\n * @internal #613. Relocate this closed period's in-window records (those\n * with `_ts < before`) from the hot store to the configured cold tier,\n * via the routeStore's `compact({ before })`. Returns the count moved.\n * Requires a `routeStore` with a cold route (the `coldArchival`\n * capability); throws a clear error otherwise. Non-destructive — reads\n * fall through to cold, so this does NOT re-open the #589 window.\n */\n async _archiveClosedPeriod(before: string): Promise<number> {\n // Inline type-only import() (no `from` clause) is the sanctioned S4 gate\n // escape hatch for the kernel spine to reference a with-* service type\n // without a static import that the port-layering architecture check would flag.\n // eslint-disable-next-line @typescript-eslint/consistent-type-imports\n const store = this.adapter as Partial<import('../with-store/route-store.js').RoutedNoydbStore>\n if (store.capabilities?.coldArchival !== true || typeof store.compact !== 'function') {\n throw new ValidationError('archivePeriod: cold archival requires a routeStore with a cold route.')\n }\n return store.compact(this.name, { before })\n }\n\n /**\n * @internal #615. Sweep delete markers with `_ts < before` off each of the\n * vault's push-only sync targets, returning a per-target count. Skips\n * `sync-peer` targets by construction (getPurgeableTargets yields only\n * backup/archive). Never touches the local adapter.\n */\n async _purgePeriodTargets(before: string): Promise<readonly { label?: string; role: 'backup' | 'archive'; purgedCount: number }[]> {\n const out: { label?: string; role: 'backup' | 'archive'; purgedCount: number }[] = []\n for (const t of this.getPurgeableTargets()) {\n const purgedCount = await this._purgeMarkersOn(t.store, before)\n out.push({ ...(t.label !== undefined ? { label: t.label } : {}), role: t.role, purgedCount })\n }\n return out\n }\n\n /**\n * For a detected conflict: capture this tab's clobbered record,\n * read the common ancestor from history, converge the cache to the store's\n * authoritative value (the re-read), and return all three for the\n * WriteConflict payload. Returns null when the collection isn't loaded.\n */\n async _captureAndConverge(\n collectionName: string,\n docId: string,\n action: 'put' | 'delete',\n baseV: number,\n ): Promise<{ local: unknown; remote: unknown; base: unknown } | null> {\n const coll = this.collectionCache.get(collectionName)\n if (!coll) return null\n // `local` is the pre-converge cached record (the clobbered write) — peek only, no store read.\n // Consumers must not mutate the returned records: in eager mode they alias live cache entries.\n const local = coll._peekCached(docId)\n let base: unknown = null\n try { base = await coll.getVersion(docId, baseV) } catch { base = null }\n await coll._applyRemoteChange(docId, action)\n // `remote` is the post-converge authoritative value via the universal read path\n // (cache in eager mode; a store read in lazy mode, where the LRU entry was just evicted).\n const remote = await coll.get(docId)\n return { local, remote, base }\n }\n\n /** Recover a stuck cutover fence — reset to normal without bumping. */\n async abortSchemaCutover(): Promise<void> {\n await this.schemaFence.abort()\n }\n\n /** Current schema-cutover fence state for this vault. Thin live read. */\n async schemaFenceState(): Promise<FenceDoc> {\n return loadFence(this.adapter, this.name)\n }\n\n /** @internal Start heartbeat + fence watcher once a cutover is registered. Async since #553: FenceWatcher dynamic-imports on demand. */\n async _ensureFenceCoordination(): Promise<void> {\n if (this.#fenceCoordinationStarted) return\n this.#fenceCoordinationStarted = true\n const { FenceWatcher } = await import('../with-shape/schema-update/fence-watcher.js')\n if (!this.#fenceCoordinationStarted) return // _stop raced the load -- don't resurrect\n this.#fenceWatcher = new FenceWatcher({\n coordination: this.noydb.coordination,\n vault: this.name,\n clientId: this.noydb._clientId,\n sessionId: this.noydb._sessionId,\n onFlush: () => this.noydb._writeQueueTracker.onFlush(),\n emit: (e) => this.emitter.emit('schema:fence-changed', { vault: this.name, ...e }),\n })\n this.#fenceWatcher.start(2_000) // heartbeat + poll; unref'd so it never holds the process open\n }\n\n /** @internal Stop the heartbeat/watcher (vault lock/close). */\n _stopFenceCoordination(): void {\n this.#fenceWatcher?.stop()\n this.#fenceWatcher = undefined\n this.#fenceCoordinationStarted = false\n }\n\n /** @internal Best-effort flush of all open collections' persisted\n * lexical indexes on close(). Called fire-and-forget from noydb.close().\n * Correctness is backstopped by the fingerprint: a missed flush → rebuild on\n * next load. Only collections with textIndexPersist have a flush(); others no-op. */\n async _flushSearchIndexes(): Promise<void> {\n for (const coll of this.collectionCache.values()) {\n await coll.flushIndex().catch(() => { /* best-effort */ })\n }\n }\n\n /** @internal Drive one heartbeat + watch cycle deterministically (tests). */\n async _fenceTick(): Promise<void> {\n await this._ensureFenceCoordination()\n await this.#fenceWatcher!.beat()\n await this.#fenceWatcher!.check()\n }\n\n /**\n * Validate i18nText fields on a `put()`. Called by Collection just\n * before the adapter write, after schema validation. Throws\n * `MissingTranslationError` when a required translation is absent.\n *\n * Delegates through the Via registry (#623) — a no-op only when i18n was\n * never declared (mirrors the registry check below).\n */\n enforceI18nOnPut(collectionName: string, record: unknown): void {\n if (!isViaInstalled('i18n')) return\n const i18nFields = this.i18nFieldRegistry.get(collectionName)\n if (!i18nFields || Object.keys(i18nFields).length === 0) return\n if (!record || typeof record !== 'object') return\n\n const obj = record as Record<string, unknown>\n for (const [field, descriptor] of Object.entries(i18nFields)) {\n const values = getAtPath(obj, field)\n for (const value of values) {\n if (value === undefined || value === null) continue\n this.strategies.i18n.validateI18nTextValue(value, field, descriptor)\n }\n }\n }\n\n /**\n * Validate staticDict codes on a `put()`. For each `staticDict()`\n * field, every stored code must be a declared key of the descriptor's\n * table, else `UnknownDictCodeError`. Opt out per descriptor with\n * `{ validateCodes: false }`.\n *\n * Delegates through the Via registry — see {@link enforceI18nOnPut}. The\n * per-field validation itself lives in `via/lookup/registry.ts`\n * (#650 Task 1 extraction), reached via `port/with/lookup-strategy.ts`.\n */\n enforceStaticDictOnPut(collectionName: string, record: unknown): void {\n if (!isViaInstalled('i18n')) return\n enforceStaticDictOnPutHelper(this.staticDescriptorByField.get(collectionName), record)\n }\n\n /**\n * Open a dictionary by name. Returns a `DictionaryHandle` for CRUD\n * operations on the `_dict_<name>/` reserved collection.\n *\n * The handle is cached — multiple calls with the same name return the\n * same instance.\n *\n * @param name The dictionary name (e.g. `'status'` → `_dict_status/`).\n * @param options Optional ACL overrides (default `writableBy: 'admin'`).\n *\n * @example\n * ```ts\n * await company.dictionary('status').putAll({\n * draft: { en: 'Draft', th: 'ฉบับร่าง' },\n * paid: { en: 'Paid', th: 'ชำระแล้ว' },\n * })\n * ```\n */\n dictionary<Keys extends string = string>(\n name: string,\n options: DictionaryOptions = {},\n ): DictionaryHandle<Keys> {\n // A staticDict has no _dict_* collection and no mutation surface —\n // its labels are code constants. Refuse the handle so put/putAll/rename/\n // delete can never be attempted against a static name.\n if (this.staticDictNames.has(name)) throw new StaticDictReadonlyError(name)\n this.reservedLookupCollections.set(dictCollectionName(name), name) // #650 Task 4 (#647)\n let handle = this.dictionaryCache.get(name)\n if (!handle) {\n handle = this.strategies.i18n.buildDictionaryHandle<Keys>({\n adapter: this.adapter,\n compartmentName: this.name,\n dictionaryName: name,\n keyring: this.keyring,\n reservedEnvelopes: makeReservedEnvelopes((collection) => this.getDEK(collection), ['_dict_'])('_dict_'),\n encrypted: this.encrypted,\n ledger: this.getLedgerOrNull() ?? undefined,\n options,\n // findAndUpdateReferences: rewrite dictKey fields in all\n // registered collections when rename() is called. Body extracted to\n // via/lookup/registry.ts (#650 Task 1) — reached via the\n // port/with/lookup-strategy.ts seam.\n findAndUpdateReferences: async (dictionaryName, oldKey, newKey) => {\n await updateReferencingRecords(\n this.dictKeyFieldRegistry,\n (collectionName) => this.collection<Record<string, unknown>>(collectionName),\n dictionaryName,\n oldKey,\n newKey,\n )\n },\n emitter: this.emitter,\n buildDeleteMarker, // #647 fix wave 1 — real kernel/enclave builder; LookupHandle can't import it directly\n // #650 Task 4 (#647) — choke-point participation for LOCAL writes: dirty-log tracking + a\n // one-shot graph-dispatch wave (local-write's `graphDispatch.collect`-equivalent; Task 5's ref edges give it dependents).\n onDirty: this.onDirty,\n onRecordMutated: async (collection, id) => { this._beginGraphBatch(); this._collectGraphTouch(collection, id); await this._flushGraphBatch() },\n checkReferencesOnDelete: (key) => this.linksEnforcer.enforceLookupRefsOnDelete(this.graph, name, dictCollectionName(name), key), // #650 Task 5\n })\n this.dictionaryCache.set(name, handle)\n }\n return handle as DictionaryHandle<Keys>\n }\n\n /**\n * Declare a managed many-to-many link set. Registers a\n * `_links_<name>` junction between two endpoint collections; access its\n * rows via `vault.links(name)`. Idempotent for an identical re-declaration;\n * a conflicting one throws. See {@link links}.\n *\n * ```ts\n * vault.link('saleLineLinks', { a: ref('saleLines'), b: ref('purchaseLines'), onDelete: 'cascade' })\n * ```\n *\n * `a` / `b` accept either a collection name or a `ref(target)` descriptor\n * (only its `target` is used — links manage their own integrity). `onDelete`\n * governs what happens to link rows when an endpoint record is deleted\n * (`'cascade'` default, `'strict'`, `'warn'`).\n */\n link(name: string, spec: { a: string | RefDescriptor; b: string | RefDescriptor; onDelete?: LinkSpec['onDelete'] }): void {\n const a = typeof spec.a === 'string' ? spec.a : spec.a.target\n const b = typeof spec.b === 'string' ? spec.b : spec.b.target\n for (const [slot, target] of [['a', a], ['b', b]] as const) {\n if (!target || target.startsWith('_') || target.includes('/')) {\n throw new ValidationError(\n `vault.link(\"${name}\"): endpoint \"${slot}\" must be a simple collection name, got \"${target}\".`,\n )\n }\n }\n const resolved: LinkSpec = { a, b, ...(spec.onDelete ? { onDelete: spec.onDelete } : {}) }\n const existing = this.linkRegistry.get(name)\n if (existing) {\n if (existing.a !== resolved.a || existing.b !== resolved.b || (existing.onDelete ?? 'cascade') !== (resolved.onDelete ?? 'cascade')) {\n throw new ValidationError(`vault.link(\"${name}\"): conflicting re-declaration.`)\n }\n return\n }\n this.linkRegistry.set(name, resolved)\n }\n\n /**\n * Access a declared link set. Throws if `name` was not first\n * declared via {@link link}. Returns a cached {@link LinkSetHandle}:\n * `connect(a, b, meta?)`, `disconnect(a, b)`, `has(a, b)`, `of(id)`, `list()`.\n */\n links(name: string): LinkSetHandle {\n let handle = this.linkSetCache.get(name)\n if (!handle) {\n const spec = this.linkRegistry.get(name)\n if (!spec) {\n throw new ValidationError(`vault.links(\"${name}\"): not declared. Call vault.link(\"${name}\", { a, b }) first.`)\n }\n // #553: handle surface is all-async, so the LinkSet engine dynamic-imports on first link I/O.\n handle = makeLazyLinkSetHandle({\n adapter: this.adapter, vault: this.name, name, spec, encrypted: this.encrypted,\n getDEK: this.getDEK, actor: this.keyring.userId, emitter: this.emitter,\n endpointExists: async (collection, id) => (await this.collection(collection).get(id)) !== null,\n })\n this.linkSetCache.set(name, handle)\n }\n return handle\n }\n\n /**\n * Build a `JoinableSource` for a dictKey field, for use in dict joins.\n * Returns a source whose snapshot contains `{ key, labels, ...labels }`\n * records — one per dictionary entry — keyed by the stable key. Returns\n * `null` when `field` is not a dictKey in `leftCollection`.\n *\n * Body extracted to `via/lookup/registry.ts` (#650 Task 1) —\n * reached via the `port/with/lookup-strategy.ts` seam. See that\n * function's doc comment for the static-vs-dynamic-dict split and the\n * cache-warming caveat.\n */\n resolveDictSource(leftCollection: string, field: string): JoinableSource | null {\n return resolveDictSourceHelper(\n leftCollection,\n field,\n this.staticDescriptorByField,\n this.dictKeyFieldRegistry,\n (name) => this.dictionary(name),\n )\n }\n\n /**\n * Set or update the vault-default locale at runtime.\n * Useful when the user switches their preferred language after opening\n * the vault.\n */\n setLocale(locale: string | undefined): void {\n this.locale = locale\n }\n\n /** Return the current vault-default locale. */\n getLocale(): string | undefined {\n return this.locale\n }\n\n /** Return the vault-level descriptive metadata (set-once at construction). */\n getMeta(): VaultMeta | undefined {\n return this.vaultMeta\n }\n\n /**\n * The user id of the keyring backing this vault session. Useful for\n * UI affordances (\"you are alice\"), audit trails, and orchestration\n * composables that need to stamp records with the current actor.\n */\n get userId(): string {\n return this.keyring.userId\n }\n\n /**\n * The role of the keyring backing this vault session — one of\n * `owner | admin | operator | viewer | client`. Useful for UI\n * affordance gates and approval workflows that need to confirm\n * the caller can perform a given action before attempting it.\n */\n get role(): Role {\n return this.keyring.role\n }\n\n /**\n * Build keyring files for bundle recipients without persisting them\n * to the source vault. Used by `writePod()` when the bundle\n * is re-keyed for distinct recipients.\n *\n * Each recipient becomes its own `KeyringFile` sealed with that\n * recipient's secret. The DEKs wrapped into each slot are\n * exactly those the recipient's role + permissions justify, and\n * never wider than the source keyring's own DEK set\n * (privilege-escalation check).\n *\n * Returns a `Record<userId, KeyringFile>` ready to substitute for\n * the `keyrings` field of a `vault.dump()` JSON. Adapter is never\n * touched; the produced files exist only in the bundle bytes.\n *\n * @public\n */\n async buildBundleRecipientKeyrings(\n recipients: readonly BundleRecipient[],\n ): Promise<Record<string, KeyringFile>> {\n const result: Record<string, KeyringFile> = {}\n for (const recipient of recipients) {\n if (recipient.id in result) {\n throw new Error(`buildBundleRecipientKeyrings: duplicate recipient id \"${recipient.id}\"`)\n }\n result[recipient.id] = await buildRecipientKeyringFile(this.keyring, recipient)\n }\n return result\n }\n\n /**\n * Authorize an `@noy-db/as-*` export against the current keyring's\n * `exportCapability`. Throws `ExportCapabilityError` if\n * the invoking keyring is not authorised.\n *\n * `as-*` packages MUST call this before invoking the underlying\n * export primitive (`exportStream()` / `writePod()` / …).\n *\n * - `assertCanExport('plaintext', 'xlsx')` — check plaintext tier\n * for a specific format. Defaults to empty for every role; owner\n * must positively grant.\n * - `assertCanExport('bundle')` — check encrypted-bundle tier.\n * Defaults to on for owner/admin, off for others.\n *\n * See `docs/patterns/as-exports.md` for the full policy.\n */\n assertCanExport(tier: 'plaintext', format: ExportFormat): void\n assertCanExport(tier: 'bundle'): void\n assertCanExport(tier: 'plaintext' | 'bundle', format?: ExportFormat): void {\n assertCanExportCapability(this.keyring, tier, format)\n }\n\n /**\n * Authorize an `@noy-db/as-*` import against the current keyring's\n * `importCapability` (issue ). Throws `ImportCapabilityError` if\n * the invoking keyring is not authorised.\n *\n * `as-*` reader entry-points (`fromString` / `fromBytes`) MUST call\n * this before parsing or building an `ImportPlan`.\n *\n * - `assertCanImport('plaintext', 'csv')` — check plaintext-tier\n * import for a specific format. Default-closed for every role.\n * - `assertCanImport('bundle')` — check `.noydb` bundle-import gate.\n * Default-closed for every role, including owner — import is more\n * dangerous than export (corrupts vs leaks).\n *\n * Owner who wants to import re-grants own keyring with\n * `importCapability` set explicitly.\n */\n assertCanImport(tier: 'plaintext', format: ExportFormat): void\n assertCanImport(tier: 'bundle'): void\n assertCanImport(tier: 'plaintext' | 'bundle', format?: ExportFormat): void {\n assertCanImportCapability(this.keyring, tier, format)\n }\n\n /**\n * Bulk blob extraction primitive.\n *\n * Returns an async-iterable handle over every blob attached to\n * records in the vault. Single capability check (`plaintext/blob`)\n * at handle creation; single audit entry to `_export_audit` before\n * the first yield. Per-blob decryption happens lazily as the\n * consumer pulls tuples.\n *\n * ```ts\n * const handle = vault.exportBlobs({\n * collections: ['invoiceScans'],\n * where: (rec) => (rec as { clientId?: string }).clientId === 'c-123',\n * })\n * for await (const { bytes, meta, recordRef } of handle) {\n * await uploadToColdStorage(bytes, recordRef)\n * }\n * ```\n *\n * @see `@noy-db/hub/store/export-blobs` for the full option surface.\n */\n /**\n * Evict blob slots per the per-collection `blobFields` retention\n * policy.\n *\n * Iterates every collection declared with `{ blobFields: {...} }`.\n * For each record, checks every configured slot against its\n * policy — `retainDays` (age-based TTL) and/or `evictWhen(record)`\n * (predicate) — and evicts matching slots. Every eviction writes\n * one entry to `_blob_eviction_audit` (actor + eTag + reason +\n * timestamp, no plaintext). Consumer-scheduled; noy-db never runs\n * this on its own.\n *\n * ```ts\n * await vault.compact() // run full pass\n * await vault.compact({ dryRun: true }) // preview counts\n * await vault.compact({ maxEvictions: 1000 }) // cap batch\n * ```\n */\n /**\n * Atomic, gap-free numbering. `vault.sequence('invoice-2026').next()`\n * returns 1, 2, 3, … with no gaps or duplicates under concurrency, via\n * an optimistic-CAS counter at `_sequences/<name>`. Each name is an\n * independent sequence.\n *\n * **Online-only:** `next()` throws `SequenceOfflineError` unless the\n * store advertises `capabilities.casAtomic` — gap-free numbering cannot\n * be serialized by an offline / non-CAS writer.\n *\n * ```ts\n * const n = await vault.sequence('invoice-2026').next() // 1, then 2, …\n * const cur = await vault.sequence('invoice-2026').peek() // current value, no allocation\n * ```\n *\n * Pass a `format` to emit a serial string instead of a bare\n * integer — `next()` then returns `{ serial, formatted }`. Per-partition\n * reset is inherent (a new partition tuple starts at 1):\n *\n * ```ts\n * const seq = vault.sequence('fatture', { partition: [2026], format: '{partition.0}/{seq:04}' })\n * await seq.next() // { serial: 1, formatted: '2026/0001' }\n * ```\n */\n sequence(series: string, opts: SequenceOptions & { format: string }): FormattedSequenceHandle\n sequence(series: string, opts?: SequenceOptions): SequenceHandle\n sequence(series: string, opts?: SequenceOptions): SequenceHandle | FormattedSequenceHandle {\n // A null byte is the structural partition separator in\n // resolveSequenceKey; a series name carrying one could forge a\n // partitioned key, so reject it.\n if (series.includes('\\x00')) {\n throw new ValidationError(`sequence(\"${series}\"): series name must not contain a null byte (\\\\x00).`)\n }\n // Deferred-numbering series route to the pass-based engine; `next({ for })`\n // resolves at `runNumberingPass`. They are keyed by series only and have\n // no CAS counter, so seedTo (CAS-only) is unavailable. All other names\n // use the CAS counter.\n if (this.numberingConfigs.has(series)) {\n if (opts?.format !== undefined) {\n // Deferred numbering stamps an auto-assigned serial onto a record\n // field at seal time; a render template there is a separate change\n // (it would alter the stamped field's type). Not supported here.\n throw new ValidationError(\n `sequence(\"${series}\") is a deferred-numbering series; the format option applies to CAS sequences only.`,\n )\n }\n const eng = this.deferred()\n return {\n next: async (nextOpts) => {\n if (!nextOpts?.for) {\n throw new ValidationError(`sequence(\"${series}\") is a deferred-numbering series; call next({ for: recordId }).`)\n }\n return (await eng.enqueue(series, nextOpts.for)).assigned\n },\n peek: () => eng.peek(series),\n seedTo: () => {\n throw new ValidationError(`sequence(\"${series}\") is a deferred-numbering series; seedTo is CAS-only.`)\n },\n }\n }\n if (!this.sequenceStore) {\n // Opt-in gate (S4): NO_SEQUENCE.createStore throws SequenceNotEnabledError\n // unless `sequenceStrategy: withSequence()` was passed to createNoydb.\n this.sequenceStore = this.strategies.sequence.createStore({\n adapter: this.adapter,\n vault: this.name,\n encrypted: this.encrypted,\n getDEK: this.getDEK,\n actor: this.keyring.userId,\n })\n }\n const handle = this.sequenceStore.handle(resolveSequenceKey(series, opts))\n if (opts?.format === undefined) return handle\n // Formatted variant: validate the template now (throws on a bad\n // token), then wrap next() to also return the rendered serial string.\n // peek/seedTo operate on the underlying integer counter, unchanged.\n const render = compileSequenceFormat(opts.format, series, opts.partition)\n return {\n next: async (nextOpts) => {\n const serial = await handle.next(nextOpts)\n return { serial, formatted: render(serial) }\n },\n peek: () => handle.peek(),\n seedTo: (n) => handle.seedTo(n),\n }\n }\n\n /** @internal — lazily build the deferred-numbering engine with a cache-coherent stamp. */\n private deferred(): DeferredNumberingStore {\n if (!this.deferredNumbering) {\n this.deferredNumbering = new DeferredNumberingStore({\n adapter: this.adapter,\n vault: this.name,\n encrypted: this.encrypted,\n getDEK: this.getDEK,\n actor: this.keyring.userId,\n configs: this.numberingConfigs,\n // Stamp THROUGH the Collection layer so cache/indexes/MVs stay coherent —\n // `this.collection(name)` returns the shared cached instance, so a\n // subsequent user `collection.get(id)` sees the assigned serial.\n stamp: async (collection, recordId, field, serial) => {\n const coll = this.collection<Record<string, unknown>>(collection)\n const rec = await coll.get(recordId)\n if (!rec) return false\n await coll.put(recordId, { ...rec, [field]: serial })\n return true\n },\n })\n }\n return this.deferredNumbering\n }\n\n /**\n * Run a deferred-numbering pass for `series`: assign gap-free serials to all\n * records whose store-commit-time interval has settled, in store-time order.\n * Returns the assignments made. See {@link sequence} / `withDeferredNumbering`.\n */\n async runNumberingPass(series: string): Promise<Assignment[]> {\n return this.deferred().runPass(series)\n }\n\n async compact(options: CompactRunOptions = {}): Promise<CompactionResult> {\n return runCompaction({\n adapter: this.adapter,\n vault: this.name,\n actor: this.keyring.userId,\n encrypted: this.encrypted,\n getDEK: this.getDEK,\n getBlobFields: <T>(name: string): BlobFieldsConfig<T> | null =>\n (this.blobFieldsRegistry.get(name) as BlobFieldsConfig<T> | undefined) ?? null,\n listCollections: () => this.collections(),\n listRecords: (name: string) => this.adapter.list(this.name, name),\n getRecord: async <T>(name: string, id: string) => {\n const coll = this.collection<T>(name)\n return coll.get(id) as unknown as T | null\n },\n listSlots: async (name: string, id: string) => {\n const coll = this.collection(name)\n return coll.blob(id).list()\n },\n deleteSlot: async (name: string, id: string, slotName: string) => {\n const coll = this.collection(name)\n await coll.blob(id).delete(slotName)\n },\n dropLocalCache: async (name: string, id: string, slotName: string) => this.collection(name).blob(id).dropLocalCache(slotName), // #808: budget pass drops device-local external cache copies\n }, options)\n }\n\n /**\n * Sweep records eligible by their collection's `archive` policy into the\n * cold archive store. Relocation is envelope-level (no re-encryption) and\n * bypasses guards + materialized-view dispatch, so issued/immutable\n * records over a sealed period can be archived without recomputing\n * finalized aggregates. A `legalHold` predicate blocks archival.\n * Requires `archiveStrategy: withArchive({ store })` in `createNoydb`.\n */\n async archive(options: ArchiveRunOptions = {}): Promise<ArchiveResult> {\n return runArchive(this._archiveContext(), options)\n }\n\n /** Relocate one archived record back to the primary store. Returns false if it was not archived. */\n async restore(collection: string, id: string): Promise<boolean> {\n return runRestore(this._archiveContext(), collection, id)\n }\n\n /** List archived record ids for a collection (or all collections with an archive policy). */\n async listArchived(collection?: string): Promise<Array<{ collection: string; id: string }>> {\n return runListArchived(this._archiveContext(), collection)\n }\n\n private _archiveContext(): ArchiveContext {\n const strategy = this.strategies.archive\n if (!strategy) {\n throw new Error(\n 'vault.archive/restore/listArchived require `archiveStrategy: withArchive({ store })` in createNoydb',\n )\n }\n const archiveStore = strategy.store\n return {\n vaultId: this.name,\n archiveStore,\n collectionsWithPolicy: () => [...this.archiveRegistry.keys()],\n getPolicy: (c) => this.archiveRegistry.get(c) ?? null,\n listRecordIds: (c) => this.adapter.list(this.name, c),\n getRecord: async (c, id) =>\n (await this.collection(c).get(id, { locale: 'raw' })) as Record<string, unknown> | null,\n getEnvelope: (c, id) => this.adapter.get(this.name, c, id),\n removeFromPrimary: async (c, id) => { await this.collection(c)._internalDelete(id) },\n restoreToPrimary: async (c, id, env) => {\n await this.adapter.put(this.name, c, id, env)\n await this.collection(c)._invalidateCacheEntry(id)\n },\n }\n }\n\n exportBlobs(options: ExportBlobsOptions = {}): ExportBlobsHandle {\n this.assertCanExport('plaintext', 'blob')\n return createExportBlobsHandle(\n this.keyring.userId,\n () => this.collections(),\n (name) => this.collection(name),\n (entry) => this.writeExportAudit(entry),\n options,\n )\n }\n\n issueAttestation(collectionName: string, id: string): Promise<{ docId: string; qr: string; keyId: string; publicKeyB64: string }> {\n return this.attestation.issue(collectionName, id)\n }\n\n getDocumentSigningPublicKey(): Promise<{ keyId: string; publicKeyB64: string }> {\n return this.attestation.getDocumentSigningPublicKey()\n }\n\n revokeAttestation(docId: string): Promise<void> {\n return this.attestation.revoke(docId)\n }\n\n unrevokeAttestation(docId: string): Promise<void> {\n return this.attestation.unrevoke(docId)\n }\n\n getRevokedDocIds(): Promise<string[]> {\n return this.attestation.getRevokedDocIds()\n }\n\n publishRevocationList(): Promise<RevocationList> {\n return this.attestation.publishRevocationList()\n }\n\n private async writeExportAudit(entry: ExportBlobsAuditEntry): Promise<void> {\n const json = JSON.stringify(entry)\n const envelope: EncryptedEnvelope = this.encrypted\n ? await (async () => {\n const dek = await this.getDEK(EXPORT_AUDIT_COLLECTION)\n const { iv, data } = await encrypt(json, dek)\n return { _noydb: NOYDB_FORMAT_VERSION, _v: 1, _ts: entry.startedAt, _iv: iv, _data: data, _by: entry.actor }\n })()\n : { _noydb: NOYDB_FORMAT_VERSION, _v: 1, _ts: entry.startedAt, _iv: '', _data: json, _by: entry.actor }\n await this.adapter.put(this.name, EXPORT_AUDIT_COLLECTION, entry.id, envelope)\n }\n\n /**\n * Read-only accessor for the invoking keyring's export capability,\n * with role-based defaults resolved. Useful for UI affordances\n * (grey out the export button if no capability) without throwing.\n */\n canExport(tier: 'plaintext', format: ExportFormat): boolean\n canExport(tier: 'bundle'): boolean\n canExport(tier: 'plaintext' | 'bundle', format?: ExportFormat): boolean {\n return canExportCapability(this.keyring, tier, format)\n }\n\n /**\n * Decrypt a single envelope using the per-collection DEK, returning\n * the parsed plaintext record. Internal helper for bundle-pipeline\n * plaintext filters — keeps DEK access encapsulated\n * inside Vault so callers don't reach into private state.\n *\n * @internal\n */\n async _decryptEnvelopeForBundleFilter(\n env: EncryptedEnvelope,\n collectionName: string,\n ): Promise<unknown> {\n if (!this.encrypted) {\n return JSON.parse(env._data)\n }\n const dek = await this.getDEK(collectionName)\n const json = await openEnvelopeJson(env, dek)\n return JSON.parse(json)\n }\n\n /**\n * Read-only accessor for the invoking keyring's import capability\n * (issue ). UI affordance — returns false in every default-closed\n * case (every role with no explicit `importCapability` grant).\n */\n canImport(tier: 'plaintext', format: ExportFormat): boolean\n canImport(tier: 'bundle'): boolean\n canImport(tier: 'plaintext' | 'bundle', format?: ExportFormat): boolean {\n return canImportCapability(this.keyring, tier, format)\n }\n\n /**\n * Enforce strict outbound refs on a `put()`. Called by Collection\n * just before it writes to the adapter. For every strict ref\n * declared on the collection, check that the target id exists in\n * the target collection; throw `RefIntegrityError` if not.\n *\n * `warn` and `cascade` modes don't affect put semantics — they're\n * enforced at delete time or via `checkIntegrity()`.\n */\n async enforceRefsOnPut(collectionName: string, record: unknown): Promise<void> {\n return this.linksEnforcer.enforceRefsOnPut(collectionName, record)\n }\n\n /**\n * Enforce inbound ref modes on a `delete()`. Called by Collection\n * just before it deletes from the adapter. Walks every inbound\n * ref that targets this (collection, id) and applies its mode\n * (`strict` throws, `cascade` deletes referencing records, `warn`\n * no-ops). Managed-link `onDelete` policy is applied in the same\n * cascade guard. See `with-shape/links/vault-facade.ts`.\n */\n async enforceRefsOnDelete(collectionName: string, id: string): Promise<void> {\n return this.linksEnforcer.enforceRefsOnDelete(this.graph, collectionName, id)\n }\n\n /**\n * #922 — can a delete on `collectionName` trigger ANY cross-record work in\n * `enforceRefsOnDelete` above? Unions ALL THREE of its cascade sources —\n * lookup-ref edges (`graph.referencingEdgesOf`), classic inbound refs\n * (`refRegistry.getInbound`), and managed link sets whose either endpoint\n * is this collection. `Collection._txAtomicSafe('delete')` consults this\n * instead of the pre-#922 blanket enforcer-presence check: `_prepareDelete`\n * runs those cascades DURING prepare (not abortable), so a delete may take\n * the atomic tx path only when all three sources are provably absent.\n * Registry state only — no store reads, safe to call at commit time.\n *\n * @internal\n */\n _deleteCascadesPossible(collectionName: string): boolean {\n if (this.graph.referencingEdgesOf(collectionName).length > 0) return true\n if (this.refRegistry.getInbound(collectionName).length > 0) return true\n for (const spec of this.linkRegistry.values()) {\n if (spec.a === collectionName || spec.b === collectionName) return true\n }\n return false\n }\n\n // ─── Join resolver) ────────────────────\n\n /**\n * Look up the `RefDescriptor` the left collection declared for a\n * given field name. Returns `null` when the field has no ref\n * declaration. Implements the `joinResolver.resolveRef` half of the\n * structural interface that `Collection.query()` consumes.\n */\n resolveRef(leftCollection: string, field: string): RefDescriptor | null {\n return this.linksEnforcer.resolveRef(leftCollection, field)\n }\n\n /**\n * Resolve a right-side join source by target collection name.\n * Returns `null` for unknown collections. Implements the\n * `joinResolver.resolveSource` half of the structural interface.\n * Only same-vault targets are resolvable — cross-vault joins are\n * explicitly forbidden by the architecture.\n */\n resolveSource(collectionName: string): JoinableSource | null {\n return this.linksEnforcer.resolveSource(collectionName)\n }\n\n /**\n * Walk every collection that has declared refs, load its records,\n * and report any reference whose target id is missing (modes\n * reported alongside each violation). Returns `{ violations: [...] }`\n * instead of throwing — the point is to surface a list for display\n * or repair, not to fail noisily.\n */\n async checkIntegrity(): Promise<{ violations: RefViolation[] }> {\n return this.linksEnforcer.checkIntegrity()\n }\n\n /**\n * Return this compartment's hash-chained audit log.\n *\n * The ledger is lazy-initialized on first access and cached for the\n * lifetime of the Vault instance. Every LedgerStore instance\n * shares the same adapter and DEK resolver, so `vault.ledger()`\n * can be called repeatedly without performance cost.\n *\n * The LedgerStore itself is the public API: consumers call\n * `.append()` (via Collection internals), `.head()`, `.verify()`,\n * and `.entries({ from, to })`. See the LedgerStore docstring for\n * the full surface and the concurrency caveats.\n */\n ledger(): LedgerStore {\n const store = this.getLedgerOrNull()\n if (!store) {\n throw new Error(\n 'vault.ledger() requires the history strategy. Import ' +\n '`{ withHistory }` from \"@noy-db/hub/history\" and pass it to ' +\n '`createNoydb({ historyStrategy: withHistory() })`.',\n )\n }\n return store\n }\n\n /**\n * Internal accessor — returns the LedgerStore if the history\n * strategy is opted in, or `null` otherwise. Used by dump/restore/\n * verifyBackupIntegrity and by Collection write paths that already\n * gate on `if (this.ledger)`. The public `ledger()` accessor above\n * throws on null; this one stays silent so the off-path no-ops.\n */\n private getLedgerOrNull(): LedgerStore | null {\n if (!this.ledgerStore) {\n this.ledgerStore = this.strategies.history.buildLedger({\n adapter: this.adapter,\n vault: this.name,\n encrypted: this.encrypted,\n getDEK: this.getDEK,\n actor: this.keyring.userId,\n })\n }\n return this.ledgerStore\n }\n\n // ─── GDPR right-to-erasure ────────────────────────────────────────\n\n /** @internal — add a subject→record ref to the encrypted subject index. */\n async _addSubjectRef(subjectId: string, ref: SubjectRef): Promise<void> {\n await addSubjectRef(this.adapter, this.name, this.getDEK, this.encrypted, subjectId, ref)\n }\n\n /** @internal — drop a subject→record ref from the encrypted subject index. */\n async _removeSubjectRef(subjectId: string, ref: SubjectRef): Promise<void> {\n await removeSubjectRef(this.adapter, this.name, this.getDEK, this.encrypted, subjectId, ref)\n }\n\n /**\n * Rebuild the encrypted subject index from canonical records. The recovery\n * path for the documented read-modify-write race (RISK #3). Returns the\n * number of distinct subjects re-indexed.\n */\n async rebuildSubjectIndex(): Promise<number> {\n if (Object.keys(this.strategies.forget.subjects).length === 0) {\n throw new ForgetStrategyNotConfiguredError()\n }\n return rebuildSubjectIndexImpl(\n this.adapter,\n this.name,\n this.getDEK,\n this.encrypted,\n this.strategies.forget.subjects,\n async (collectionName, id, env) => {\n const coll = this.collection<Record<string, unknown>>(collectionName)\n return coll._decodeEnvelope(env, id)\n },\n )\n }\n\n /**\n * GDPR crypto-shred of a data subject. Consults the encrypted subject index and, per matching\n * record: rewrites the LIVE envelope to a tombstone (drops `_iv`/`_data`/`_cek`/`_det`), tombstones\n * every `_history` version, and fans out to derived residue via the graph (#622) — record-grain\n * artifacts (MV rows, derivation copies) ERASED, aggregate-grain rollups RECOMPUTED without the\n * forgotten contribution (skip+audit in a frozen period). The body/history become permanently\n * undecryptable while the collection DEK and every OTHER record stay intact. Then appends ONE\n * `op:'forget'` ledger entry whose `payloadHash` is `sha256Hex(subjectId)` — the chain still\n * `verify()`s, PROVING the subject existed and was erased without retaining any plaintext.\n *\n * Reports — but does not silently swallow — two completeness gaps: `unmigratedRecords` (a record\n * whose body was NOT yet migrated to a per-record CEK — still tombstoned, but pre-shred backups\n * stay decryptable; migrate, then re-forget) and `blobResidueCollections` (blob attachments, keyed\n * off a separate `_blob` DEK, out of scope here).\n *\n * @throws ForgetStrategyNotConfiguredError when no `withForget` was set.\n */\n async forget(subjectId: string): Promise<ForgetResult> {\n if (Object.keys(this.strategies.forget.subjects).length === 0) {\n throw new ForgetStrategyNotConfiguredError()\n }\n\n // #734: resolve the ledger BEFORE any shred — the loop purges each record's\n // plaintext deltas and the summary entry appends after, so a missing history\n // strategy must abort with NOTHING erased (was: shred-then-throw).\n const ledger = this.getLedgerOrNull(); if (!ledger) throw new Error('vault.forget() requires the history strategy for the erasure-proof ledger entry. Pass `historyStrategy: withHistory()` from \"@noy-db/hub/history\" to createNoydb().')\n const refs = await lookupSubject(this.adapter, this.name, this.getDEK, this.encrypted, subjectId)\n // Satellite fan-out (#591, with-shape/satellites/forget.ts) — a satellite\n // is never itself in the subject index, so synthesize its ref or it survives.\n const allRefs = expandRefsWithSatellites(refs, this.satelliteRegistry)\n\n let recordsShredded = 0; let historyVersionsShredded = 0\n const collections = new Set<string>(); const unmigratedRecords: string[] = []\n const blobResidueCollections = new Set<string>()\n let blobsShredded = 0; let blobsRetainedShared = 0; let indexPostingsPurged = 0\n let sealedFieldsShredded = 0; let sealedCekEnvelopesPurged = 0; let ledgerDeltasPurged = 0\n const sealedCekResidue: string[] = []; const sealedResidue: string[] = []; const indexResidue: string[] = []; const ledgerDeltaResidue: string[] = []\n // #838 — \"is the blob service opted in?\" is now a stub-identity check.\n // It used to be `blobsStrategy !== undefined`; with every key resolved,\n // absence is NO_BLOBS rather than `undefined`, and reading it as\n // always-enabled would drive forget() into NO_BLOBS.openSlot()'s throw.\n const blobsEnabled = this.strategies.blobs !== NO_BLOBS\n const actor = this.keyring.userId\n const fanoutStats: ForgetFanoutStats = { recordsErased: 0, aggregatesRecomputed: 0, residueFrozen: [], lookupReferencesCascaded: 0, lookupReferencesNullified: 0, lookupReferencesResidue: [], derivedResidueUndecodable: [], derivedResidueDeclined: [] }\n // #633 — scoped-purge per-collection skip accumulators (empty under the unconditional default); lazy (S4 gate: kernel spine → with-* service via dynamic import()).\n const { partitionSealedCekKeys, shouldSkipBlobScan, bumpResidueCount, residueNoticesFromMap } = await import('../with-audit/forget/purge-scope.js')\n const scopedPurge = this.strategies.forget.scopedPurge === true\n const sealedCekScopedSkipped = new Map<string, number>(); const blobScopedSkipped = new Map<string, number>()\n\n for (const ref of allRefs) {\n const coll = this.collection<Record<string, unknown>>(ref.collection)\n const satelliteOf = (ref as { satelliteOf?: string }).satelliteOf\n const perRecordKeys = this.strategies.forget.subjects[satelliteOf ?? ref.collection] !== undefined // #591 classification inheritance\n const lookupCompareKeys = await this.linksEnforcer.checkLookupRefsRestrict(this.graph, ref.collection, ref.collection, ref.id) // #650 (#648) — restrict BEFORE any shred; ALSO live-resolves every ref edge's compare-key (#650 review, Important fix — no post-shred decode needed by forgetDerivedFanout)\n\n // Detect an un-migrated record BEFORE shredding: a perRecordKeys\n // collection whose live envelope still carries a body but no `_cek`\n // means the body is keyed off the shared collection DEK (legacy /\n // not-yet-migrated), so a shred cannot guarantee erasure of pre-shred\n // ciphertext. We still tombstone it, but report the gap.\n const live = await this.adapter.get(this.name, ref.collection, ref.id)\n if (perRecordKeys && live && live._data && !hasPerRecordKey(live)) {\n unmigratedRecords.push(`${ref.collection}:${ref.id}`)\n }\n // Classify each `_sealed`/`_vdig` slot BEFORE tombstoning (#M-1, security\n // review): CEK-keyed → shreddable (tombstone erases it); collection-DEK-\n // keyed → NOT (retained → synced/backup copies stay decryptable); the\n // `_bidx` case is both (dual accounting). #629 Task 10: a compiled-in\n // classified via binding owns this via `_onViaErase`'s sealed-posture\n // fold (metadata-driven); bare-`sensitive` collections fall back below.\n if (live?._sealed !== undefined) {\n try {\n const viaReport = await coll._onViaErase(ref.id, live)\n if (viaReport) {\n sealedFieldsShredded += viaReport.shredded\n for (const entry of viaReport.residue as readonly { readonly kind?: string; readonly field?: string }[]) {\n if (entry.kind === 'classified-sealed-dek-residue' && entry.field !== undefined) sealedResidue.push(`${ref.collection}:${ref.id}:${entry.field}`)\n }\n } else {\n const cls = await coll._classifySealedShred(live)\n for (const slot of cls.slots) {\n if (slot.class === 'shreddable' || slot.class === 'live-shreddable+dekResidue-in-backups') sealedFieldsShredded += 1\n if (slot.class === 'dekResidue' || slot.class === 'live-shreddable+dekResidue-in-backups') sealedResidue.push(`${ref.collection}:${ref.id}:${slot.field}`)\n }\n }\n } catch {\n // Classification unwraps `_cek`; if that fails (corrupt/unreadable\n // envelope) do NOT abort the whole erasure mid-loop. Report every\n // sealed field as residue (conservatively un-shredded) and continue\n // tombstoning — mirrors the H-1 block's defensive posture below.\n for (const field of Object.keys(live._sealed)) sealedResidue.push(`${ref.collection}:${ref.id}:${field}`)\n }\n }\n\n // Purge the record's sealed-CEK delivery envelopes (#H-1, security\n // review). sealRecordToHost persisted the raw CEK sealed to at-* hosts at\n // `_sealed_cek/<collection>/<id>/<pid>`; crypto-shred must destroy them\n // too, or a granted host + a synced pre-forget body recovers an \"erased\"\n // record. Mirrors rotateRecordCek's prefix-delete.\n const cekPrefix = `${ref.collection}/${ref.id}/`\n try {\n const cekKeys = await this.adapter.list(this.name, SEALED_CEK_NS)\n const { toPurge, skippedCount } = partitionSealedCekKeys(cekKeys, cekPrefix, scopedPurge, coll._via?.hasAtRestHooks === true) // #633\n for (const key of toPurge) {\n await this.adapter.delete(this.name, SEALED_CEK_NS, key)\n sealedCekEnvelopesPurged++\n }\n bumpResidueCount(sealedCekScopedSkipped, ref.collection, skippedCount)\n } catch {\n sealedCekResidue.push(`${ref.collection}:${ref.id}`)\n }\n if (blobsEnabled && !shouldSkipBlobScan(scopedPurge, this.blobFieldsRegistry.has(ref.collection))) { try { await coll.blob(ref.id).mintShredIntent(live?._tier ?? 0) } catch { blobResidueCollections.add(ref.collection) } } // #753 C5 marker PRE-tombstone: crash-safety ENHANCEMENT, not an erasure precondition — mint failure degrades to residue, never blocks the shred below (whole-branch review)\n let shred: { previousVersion: number } | null\n try {\n shred = await coll._writeTombstone(ref.id, actor)\n } catch (cause) {\n if (satelliteOf === undefined) throw cause // base ref: pre-existing (unwrapped) fail-loud behavior\n throw new SatelliteConfigError( // R-S4: abort the whole forget rather than leave the heavy side un-erased\n `R-S4: forget could not fan out to satellite \"${ref.collection}\" — aborting rather than leaving the heavy side`,\n { cause },\n )\n }\n if (shred !== null) {\n recordsShredded++\n collections.add(ref.collection)\n await forgetDerivedFanout(this, { collection: ref.collection, id: ref.id }, live, fanoutStats, lookupCompareKeys)\n }\n\n // Tombstone every history version (idempotent — already-shredded skip).\n historyVersionsShredded += await this.strategies.history.tombstoneHistory(\n this.adapter, this.name, ref.collection, ref.id, actor, this.encrypted,\n )\n\n // #734: purge the record's plaintext `_ledger_deltas` rows — the erasure twin\n // of #729's elevate purge. Chain-safe: verify() never re-reads delta rows; the\n // summary `forget` entry appended below is the retained proof of erasure.\n try { ledgerDeltasPurged += await ledger.purgeRecordDeltas(ref.collection, ref.id) } catch { ledgerDeltaResidue.push(`${ref.collection}:${ref.id}`) }\n // Purge the record's persisted `_idx` side-cars: they live under\n // the retained collection DEK, so crypto-shred alone leaves the indexed\n // field VALUES readable. Content-free delete; failures → indexResidue.\n const idxPurge = await coll._purgePersistedIndexes(ref.id)\n indexPostingsPurged += idxPurge.purged\n for (const field of idxPurge.residue) indexResidue.push(`${ref.collection}:${ref.id}:${field}`)\n\n // Purge the record's encrypted _vec sidecar: a vector embedding\n // is text-invertible, so it must not survive crypto-shred of the source record.\n try {\n await coll._purgeVector(ref.id)\n } catch {\n indexResidue.push(`${ref.collection}:${ref.id}:_vec`)\n }\n\n // Blob attachments: crypto-shred the record's erasable blobs.\n // An erasable blob's chunks are under a per-blob content CEK whose only\n // copy is the BlobObject's wrapped `_cek`; deleting it at refCount 0\n // shreds the content. Legacy blobs (no `_cek`) or a session without the\n // blob service cannot be shredded → reported as residue.\n if (blobsEnabled && shouldSkipBlobScan(scopedPurge, this.blobFieldsRegistry.has(ref.collection))) {\n bumpResidueCount(blobScopedSkipped, ref.collection, 1) // #633 — perf win: no per-collection list() scan\n } else if (blobsEnabled) {\n const r = await this.collection<Record<string, unknown>>(ref.collection)\n .blob(ref.id)\n .shredAllForRecord(live?._tier ?? 0) // #724 C3: pre-tombstone tier — the tombstone this loop already wrote drops `_tier`\n blobsShredded += r.shredded.length\n blobsRetainedShared += r.retainedShared.length\n if (r.residue.length > 0) blobResidueCollections.add(ref.collection)\n } else {\n try {\n const [slotIds, verKeys] = await Promise.all([this.adapter.list(this.name, `_blob_slots_${ref.collection}`), this.adapter.list(this.name, `_blob_versions_${ref.collection}`)]) // #750: version rows are residue too when the blob service is off\n if (slotIds.includes(ref.id) || verKeys.some((k) => k.startsWith(`${ref.id}::`))) blobResidueCollections.add(ref.collection)\n } catch {\n // No blob-slots collection for this collection — nothing to report.\n }\n }\n\n // Drop the (now-shredded) ref from the subject index.\n await this._removeSubjectRef(subjectId, ref)\n }\n\n // Purge the persisted lexical-index blob for each affected collection:\n // an opaque all-records index must not survive crypto-shred.\n // Failures (transient/permission) must NOT abort forget — an unpurgeable\n // blob is erasure residue surfaced in the returned ForgetResult.\n for (const collName of collections) {\n try {\n await this.collection(collName)._purgeSearchIndex()\n } catch {\n indexResidue.push(`${collName}:_ftindex`)\n }\n }\n\n // ONE summary ledger entry for the whole subject. payloadHash =\n // sha256Hex(subjectId) so the ledger proves erasure without the subject.\n const subjectHash = await sha256Hex(subjectId)\n const ledgerEntry = await ledger.append({\n op: 'forget',\n collection: '',\n id: '',\n version: 0,\n actor,\n payloadHash: subjectHash,\n reason: JSON.stringify({\n recordsShredded,\n historyVersionsShredded,\n collections: [...collections],\n unmigratedCount: unmigratedRecords.length,\n blobsShredded,\n blobsRetainedShared,\n blobResidueCollections: [...blobResidueCollections],\n indexPostingsPurged,\n indexResidueCount: indexResidue.length,\n sealedFieldsShredded,\n sealedCekEnvelopesPurged,\n sealedCekResidueCount: sealedCekResidue.length,\n sealedResidueCount: sealedResidue.length, ledgerDeltasPurged, ledgerDeltaResidueCount: ledgerDeltaResidue.length,\n }),\n })\n\n const scopedPurgeResidue = [...residueNoticesFromMap(sealedCekScopedSkipped, 'skipped-undeclared-sealed-cek'), ...residueNoticesFromMap(blobScopedSkipped, 'skipped-undeclared-blob-scan')] // #633\n return {\n subject: subjectId,\n recordsShredded,\n historyVersionsShredded,\n collections: [...collections],\n unmigratedRecords,\n blobsShredded,\n blobsRetainedShared,\n blobResidueCollections: [...blobResidueCollections],\n indexPostingsPurged,\n indexResidue,\n sealedFieldsShredded,\n sealedCekEnvelopesPurged,\n sealedCekResidue,\n sealedResidue,\n ledgerEntry,\n derivedRecordsErased: fanoutStats.recordsErased,\n derivedAggregatesRecomputed: fanoutStats.aggregatesRecomputed,\n derivedResidueFrozen: fanoutStats.residueFrozen,\n lookupReferencesCascaded: fanoutStats.lookupReferencesCascaded, lookupReferencesNullified: fanoutStats.lookupReferencesNullified, lookupReferencesResidue: fanoutStats.lookupReferencesResidue, scopedPurgeResidue, ledgerDeltasPurged, ledgerDeltaResidue, // #650 Task 5 (+ review Important fix: residue) + #633 + #734\n derivedResidueUndecodable: fanoutStats.derivedResidueUndecodable, derivedResidueDeclined: fanoutStats.derivedResidueDeclined, // #776/#785\n }\n }\n\n // ─── Record-scoped CEK sealing ─────────────────────────────────────\n\n /**\n * Seal ONE record's content-encryption key (CEK) to an `at-*` host so that\n * host — and only that host — can decrypt exactly that record, with no\n * access to the vault DEK and no ability to read any other record.\n *\n * The grantor (this caller, who holds the collection DEK) reads the record's\n * live `_cek`, unwraps it under the collection DEK, exports the raw CEK\n * bytes, builds a {@link SealedCekBinding} `{collection, id, cek, expiresAt}`,\n * seals that binding for the recipient host via the host's published hint,\n * and persists a thin {@link SealedCekDeliveryEnvelope} at\n * `_sealed_cek/<collection>/<id>/<pid>`. The binding (not the delivery\n * envelope) is the security boundary: the host re-verifies `{collection, id}`\n * and `expiresAt` from inside the sealed payload.\n *\n * Only works on a `perRecordKeys` record — a legacy record has no `_cek` to\n * seal (its body is under the shared collection DEK, which is never exposed\n * by sealing) → {@link RecordCekNotFoundError}.\n *\n * @param collection Collection holding the record.\n * @param id Record id.\n * @param hostSealer The recipient host's {@link RecipientSealer}.\n * @param opts.expiresAt REQUIRED authoritative expiry (ISO 8601), sealed into\n * the binding the host verifies.\n * @returns `{ pid, envelopeKey }` — the host provider id and the\n * `<collection>/<id>/<pid>` key the delivery envelope was written under.\n */\n async sealRecordToHost(\n collection: string,\n id: string,\n hostSealer: RecipientSealer,\n opts: { expiresAt: string },\n ): Promise<{ pid: string; envelopeKey: string }> {\n return this.strategies.sealedRecord.sealRecordToHost(this._sealingContext(), collection, id, hostSealer, opts)\n }\n\n /**\n * Revoke a sealed-CEK grant. **Default is SOFT**: deletes the `pid` delivery\n * envelope, but a host that already fetched it KEEPS decrypt capability (stops\n * new fetches, not a cryptographic cutoff). Pass **`{ hard: true }`** to rotate\n * the record CEK ({@link rotateRecordCek}) so any prior sealed CEK can no\n * longer open the record. See `revokeSealedRecord` in `record-keys/sealing.ts`.\n */\n async revokeSealedRecord(collection: string, id: string, pid: string, opts?: { hard?: boolean }): Promise<void> {\n return this.strategies.sealedRecord.revokeSealedRecord(this._sealingContext(), collection, id, pid, opts)\n }\n\n /**\n * HARD-rotate a record's CEK: decrypt the live body under the old CEK,\n * re-encrypt it under a freshly-minted CEK, write the new live envelope, evict\n * the in-memory caches, and delete EVERY sealed-CEK delivery envelope for the\n * record. After this, any host holding a previously-sealed CEK can still\n * decrypt PRE-rotation history versions (they keep their old `_cek`) but NOT\n * the rotated live record (its body is under the new CEK → the old CEK fails\n * the AES-GCM auth tag → `TamperedError`). That asymmetry IS the revocation:\n * old grants lose the live record.\n *\n * Administrative path — bypasses `Collection.put` deliberately (no guards, no\n * history snapshot, no materialized-view refresh): rotation is a key-rotation\n * operation, not a business write, and must not version-bump history (which\n * would re-encrypt the prior version under the NEW CEK and defeat the point).\n *\n * @throws {@link RecordCekNotFoundError} if the record is missing or has no `_cek`.\n */\n async rotateRecordCek(collection: string, id: string): Promise<void> {\n return this.strategies.sealedRecord.rotateRecordCek(this._sealingContext(), collection, id)\n }\n\n /**\n * Build the {@link SealingContext} the record-keys grantor functions need:\n * the vault-bound adapter, DEK resolver, actor, and the dual-cache eviction\n * `rotateRecordCek` performs (per-record CEK cache + decrypted-record cache).\n */\n private _sealingContext(): SealingContext {\n return {\n adapter: this.adapter,\n vault: this.name,\n getDEK: (collection) => this.getDEK(collection),\n actor: this.keyring.userId,\n invalidateRecordCaches: async (collection, id) => {\n const coll = this.collection<Record<string, unknown>>(collection)\n coll._invalidateCekCacheEntry(id)\n await coll._invalidateCacheEntry(id)\n },\n }\n }\n\n /**\n * @internal — called by `Noydb.openVault` after construction.\n * Dynamic-imports `GuardRegistry` + `ReadOnlyVaultFacade` and seeds\n * the registry with the supplied strategy handles. No-op when the\n * handles array is empty — keeps the guard service out of the\n * floor bundle for consumers that don't use guards.\n *\n * The read-only facade is eagerly instantiated here so the sync\n * accessor `_getReadOnlyFacade()` (called from the tx amendment\n * runner) stays synchronous.\n */\n async _initGuards(handles: ReadonlyArray<GuardStrategyAny>): Promise<void> {\n if (handles.length === 0) return\n const [{ GuardRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([\n import('../with-audit/guards/registry.js'),\n import('../with-audit/guards/read-only-facade.js'),\n ])\n const registry = new GuardRegistry()\n for (const h of handles) registry.register(h.spec)\n this.guardRegistry = registry\n this.guardFacade = new ReadOnlyVaultFacade(this, 'guard')\n }\n\n /**\n * @internal — The gate handler in Noydb.#registerGuardGate calls into\n * this. Returns `null` for vaults that never registered any guard\n * strategy. Callers MUST gate on null.\n */\n _getGuardRegistry(): GuardRegistry | null {\n return this.guardRegistry\n }\n\n /**\n * @internal — called by `Noydb.openVault` after construction.\n * Dynamic-imports `DerivationRegistry` and registers the supplied\n * derivation strategies (async because `strategyHash` computation\n * goes through `crypto.subtle.digest`). No-op when the handles\n * array is empty — keeps the derivation service out of the floor\n * bundle for consumers that don't use derivations. Throws\n * `DerivationCycleError` if a cycle is detected after registration.\n */\n async _initDerivations(handles: ReadonlyArray<DerivationStrategy>): Promise<void> {\n if (handles.length === 0) return\n const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([\n import('../with-formula/derivations/registry.js'),\n import('../with-audit/guards/read-only-facade.js'),\n ])\n const registry = new DerivationRegistry()\n for (const h of handles) {\n await registry.register(h.spec)\n }\n for (const edge of registry.edges()) this.graph.registerDerived(edge.target, edge.sources, edge.kind, edge.grain)\n registry.validate(this.graph)\n this.derivationRegistry = registry\n // Derivation reads resolve at `layer:'derivation'` — a distinct\n // facade from the guard one, so `derive(source, ctx)` gets the\n // derivation `onMissing` policy (e.g. `'null'` → branch explicitly)\n // rather than the lenient guard default.\n if (this.derivationFacade === null) {\n this.derivationFacade = new ReadOnlyVaultFacade(this, 'derivation')\n }\n }\n\n /**\n * @internal — consumed by `Collection.put` at write-time. Returns\n * `null` for vaults that never registered any derivation strategy.\n */\n _getDerivationRegistry(): DerivationRegistry | null {\n return this.derivationRegistry\n }\n\n /**\n * @internal — called by `Noydb.openVault` after collections are\n * wired. Dynamic-imports `MaterializedViewRegistry`, registers each\n * MV spec (which invokes its `query()` once for dependency\n * analysis), then runs the unified cycle detection across the MV +\n * derivation graphs. No-op when the handles array is empty — keeps\n * the MV service out of the floor bundle (mirrors the derivation lazy-import pattern).\n * Throws `MaterializedViewCycleError` if a cycle is detected.\n */\n async _initMaterializedViews(\n \n handles: ReadonlyArray<MaterializedViewStrategy>,\n ): Promise<void> {\n if (handles.length === 0) return\n const { MaterializedViewRegistry } = await import('../with-formula/materialized-views/registry.js')\n const registry = new MaterializedViewRegistry()\n // Phase 1: publish the (empty) registry on `this` BEFORE\n // registering any spec. The user's `query(db)` callback runs at\n // registration time and may construct source Collections via\n // `db.collection(name)` — those Collections are cached in the\n // vault and their `materializedViewSource` is populated from\n // `this.materializedViewRegistry` AT CONSTRUCTION TIME. If we\n // assigned `this.materializedViewRegistry` only after the\n // register() loop, the source Collections would cache with an\n // unset source and never dispatch MV refreshes on later writes.\n this.materializedViewRegistry = registry\n // Pass `this` Vault as the MVQueryContext — its `collection<T>()`\n // method is what the user's `query(db)` callback consumes.\n \n const db = this as unknown as MVQueryContext\n for (const h of handles) {\n await registry.register(h.spec, db)\n }\n // Phase 2: unified cycle detection — `this.graph` already carries\n // `_initDerivations`'s edges (#638); add this registry's own, then\n // re-validate. Throws `MaterializedViewCycleError` on the first cycle.\n for (const edge of registry.edges()) this.graph.registerDerived(edge.target, edge.sources, edge.kind, edge.grain)\n registry.validate(this.graph)\n }\n\n /**\n * @internal — consumed by `Collection.put` at write-time. Returns\n * `null` for vaults that never registered any MV strategy.\n */\n _getMaterializedViewRegistry(): MaterializedViewRegistry | null {\n return this.materializedViewRegistry\n }\n\n /**\n * @internal — called by `Noydb.openVault` after MVs are wired.\n * Dynamic-imports `OverlayedViewRegistry`, registers each spec,\n * validates against the MV registry for name/base/overlay collisions.\n * Throws on validation failure.\n */\n async _initOverlayedViews(\n handles: ReadonlyArray<OverlayedViewStrategy>,\n ): Promise<void> {\n if (handles.length === 0) return\n const { OverlayedViewRegistry } = await import('../with-formula/overlay-views/registry.js')\n const registry = new OverlayedViewRegistry()\n const mvRegistry = this.materializedViewRegistry\n // Build the predicate set for registration validation:\n // - isOverlayName: an already-registered overlay's virtual name\n // - isMVOutput: a collection name owned by an MV\n const overlayNames = new Set<string>()\n for (const h of handles) overlayNames.add(h.spec.name)\n const isMVOutput = (name: string): boolean => {\n if (!mvRegistry) return false\n for (const reg of mvRegistry.all()) {\n if (reg.outputCollection === name) return true\n }\n return false\n }\n for (const h of handles) {\n registry.register(h.spec, {\n isOverlayName: (n) => overlayNames.has(n) && n !== h.spec.name,\n isMVOutput,\n })\n // #638 Task 2 — '*' matches the derivation/MV whole-record marker.\n this.graph.registerDerived({ collection: h.spec.name, field: '*' }, [{ collection: h.spec.base, field: '*' }], 'overlay', 'record')\n }\n this.overlayedViewRegistry = registry\n }\n\n /**\n * @internal — consumed by `Vault.collection()`. Returns `null` for\n * vaults with no overlays registered.\n */\n _getOverlayedViewRegistry(): OverlayedViewRegistry | null {\n return this.overlayedViewRegistry\n }\n\n /** @internal — ctx for `putDerivedOutput`'s frozen-period skip+audit (#638 Task 5). */\n private _dispatchCtx(source: { readonly collection: string; readonly id: string }) {\n return { emit: (e: string, p: unknown) => (this.emitter.emit as (ev: string, pl: unknown) => void)(e, p), source, audit: ledgerAuditHook(this.getLedgerOrNull() ?? undefined, this.keyring.userId) }\n }\n\n /**\n * Manual re-materialize for a single registered MV (`refresh: 'manual'` consumers,\n * stale-bit recovery on vault reopen, bulk-recompute escape hatch after a strategy\n * change). Returns `{ written, deleted, failed, residueUndecodable, residueDeclined }` (`deleted`\n * always 0 without tombstoning; #785 splits the #782 leftovers — undecodable vs #718-declined). Throws if not registered.\n */\n async refreshView(name: string): Promise<{ written: number; deleted: number; failed: number; residueUndecodable: string[]; residueDeclined: string[] }> {\n const registry = this.materializedViewRegistry\n if (registry === null) {\n return { written: 0, deleted: 0, failed: 0, residueUndecodable: [], residueDeclined: [] }\n }\n const reg = registry.byName(name)\n if (!reg) {\n throw new Error(`refreshView: no MV registered with name \"${name}\"`)\n }\n const { MaterializedViewExecutor } = await import('../with-formula/materialized-views/executor.js')\n const result = await MaterializedViewExecutor.refresh(reg, {\n getCollection: (n) => this.collection(n),\n getActiveTxContext: () => this.noydb._activeTxContextOrNull,\n getQueryContext: () => this as unknown as MVQueryContext,\n dispatchCtx: this._dispatchCtx({ collection: name, id: 'refreshView' }),\n })\n // Manual refresh clears any pending stale bit (+ persisted marker, #736) —\n // the post-refresh state matches the registered strategy.\n const { clearMVStaleFully } = await import('../with-formula/materialized-views/stale.js')\n await clearMVStaleFully(this.adapter, this.name, registry, name)\n return result\n }\n\n /**\n * Re-derive every record in the named source collection (useful after a strategy\n * change to bring previously-derived records up-to-date). Sequential in v1.\n */\n async deriveAll(sourceCollection: string): Promise<{ derived: number; failed: number; skippedFrozen: number }> {\n const registry = this._getDerivationRegistry()\n if (registry === null) return { derived: 0, failed: 0, skippedFrozen: 0 }\n const strategies = registry.strategiesForSource(sourceCollection)\n if (strategies.length === 0) return { derived: 0, failed: 0, skippedFrozen: 0 }\n\n const { DerivationExecutor } = await import('../with-formula/derivations/executor.js')\n\n const sourceColl = this.collection<Record<string, unknown>>(sourceCollection)\n const records = await sourceColl.list()\n // `_initDerivations` populates `derivationFacade` — assert non-null\n // for the closure-captured ctx. Falls back to a fresh `derivation`-layer\n // facade on the sync-fallback path (Noydb.vault() without await) for the\n // same defensive reason `_ensureReadOnlyFacade` exists.\n const ctx = { vault: this.derivationFacade ?? new (await import('../with-audit/guards/read-only-facade.js')).ReadOnlyVaultFacade(this, 'derivation') }\n let derived = 0\n let failed = 0\n let skippedFrozen = 0\n for (const record of records) {\n if (typeof record !== 'object' || record === null) continue\n const id = (record as { id?: unknown }).id\n if (typeof id !== 'string') continue\n const dispatchCtx = this._dispatchCtx({ collection: sourceCollection, id })\n for (const { spec, strategyHash } of strategies) {\n const sourceWithId = { ...record, id }\n const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx)\n let anyFailed = false, anyFrozenSkip = false\n for (const key of Object.keys(spec.outputs)) {\n const out = result.outputs[key]\n if (!out) continue\n if (out.kind === 'failed') { anyFailed = true; continue }\n const outSpec = spec.outputs[key]\n if (!outSpec) continue\n const outputColl = this.collection(outSpec.collection)\n\n // Array-shape branch — diff against the fanout sidecar.\n if (out.kind === 'array') {\n const { loadFanoutSidecar, saveFanoutSidecar } =\n await import('../with-formula/derivations/fanout-sidecar.js')\n const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key, this.getDEK, this.encrypted)\n const prevKeys = new Set<string>(prior?.keys ?? [])\n const newKeysList = out.entries.map(e => e.key)\n const newKeysSet = new Set<string>(newKeysList)\n for (const k of prevKeys) {\n if (newKeysSet.has(k)) continue\n await outputColl._internalDelete(k)\n }\n for (const entry of out.entries) {\n if (await putDerivedOutput(outputColl, entry.key, entry.value, dispatchCtx) === 'skipped-frozen') anyFrozenSkip = true\n }\n await saveFanoutSidecar(this.adapter, this.name, {\n source: spec.source,\n sourceId: id,\n outputKey: key,\n outputCollection: outSpec.collection,\n keys: newKeysList,\n }, this.getDEK, this.encrypted)\n continue\n }\n\n if (out.skipped === true) {\n // Optional output skipped — delete any prior emission.\n // No txCtx hookup needed: `deriveAll` runs outside the\n // multi-record transaction window by design. Routed\n // through `_internalDelete` so the bulk recompute does not\n // trip user `onDelete` on the output collection.\n await outputColl._internalDelete(id)\n continue\n }\n if (await putDerivedOutput(outputColl, id, out.value, dispatchCtx) === 'skipped-frozen') anyFrozenSkip = true\n }\n if (anyFailed) failed++; else if (anyFrozenSkip) skippedFrozen++; else derived++\n }\n }\n return { derived, failed, skippedFrozen }\n }\n\n /**\n * @internal — exposed for `runTransaction({ amendment: true })` so\n * the amendment invariant runner can pass the SAME read-only vault\n * facade that the gate handler in Noydb.#registerGuardGate uses.\n * Eagerly instantiated by `_initGuards()` so this accessor stays\n * synchronous; returns `null` for vaults that never registered any\n * guard (amendments require at least one guard, so the caller should\n * never see null).\n */\n _getReadOnlyFacade(): ReadOnlyVaultFacade | null {\n return this.guardFacade\n }\n\n /**\n * Internal lazy-allocator for the derivation read-only facade\n * (`layer:'derivation'`). Used as a defensive fallback; in practice\n * `_initDerivations()` eagerly instantiates this, so the lazy path is\n * a no-op.\n */\n private _ensureReadOnlyFacade(): ReadOnlyVaultFacade {\n if (this.derivationFacade !== null) return this.derivationFacade\n // Synchronous fall-back: dynamic import isn't available here,\n // but `_initDerivations` always sets the facade before any\n // derivation can fire. Reaching this branch means a Vault was\n // constructed without `_initDerivations` being awaited — e.g. via\n // the sync `Noydb.vault()` fallback path. Throw with a\n // pointer rather than silently building an invalid context.\n throw new Error(\n 'Vault: derivation hook fired before _initDerivations() completed. ' +\n 'This typically means the vault was opened via the sync ' +\n 'fallback path (Noydb.vault(name)) without first calling ' +\n 'await db.openVault(name). See issue #132.',\n )\n }\n\n /**\n * @internal — exposed for `runTransaction({ amendment: true })`\n * to append the structured `op: 'amendment'` audit entry without\n * dragging this private accessor onto the public surface or\n * forcing the tx executor to depend on the history-strategy\n * shape directly. Returns `null` when no history strategy is\n * configured, in which case the amendment commits silently\n * (the records still write through; only the multi-record\n * audit summary is skipped).\n */\n _getLedgerOrNull(): LedgerStore | null {\n return this.getLedgerOrNull()\n }\n\n /**\n * Return a read-only view of this vault as it existed at\n * `timestamp`. Time-machine queries are reconstructed from the\n * per-version history snapshots persisted by every `put()`, then\n * cross-checked against the ledger for deletes that happened\n * between the snapshot and the target timestamp.\n *\n * ```ts\n * const q1End = vault.at('2026-03-31T23:59:59Z')\n * const invoice = await q1End.collection<Invoice>('invoices').get('inv-001')\n * // → the record as it stood at the close of Q1 2026\n * ```\n *\n * `timestamp` accepts an ISO-8601 string or a `Date`. Time-machine\n * views are read-only — writes throw {@link ReadOnlyAtInstantError}.\n * Accuracy bounded by history retention: if `historyConfig.maxVersions`\n * pruned earlier versions, queries before the oldest retained\n * snapshot return null even for records that existed.\n *\n *.\n */\n at(timestamp: string | Date): VaultInstant {\n const iso = timestamp instanceof Date ? timestamp.toISOString() : timestamp\n return this.strategies.history.buildVaultInstant(\n {\n adapter: this.adapter,\n name: this.name,\n encrypted: this.encrypted,\n getDEK: this.getDEK,\n getLedger: () => (this.historyConfig.enabled === false ? null : this.getLedgerOrNull()),\n },\n iso,\n )\n }\n\n /**\n * Return a read-only \"shadow\" view of this vault. Every read method\n * on the returned {@link VaultFrame} delegates to the underlying\n * live collection; every write method throws\n * {@link ReadOnlyFrameError}.\n *\n * ```ts\n * const presentation = vault.frame()\n * const invoices = await presentation.collection<Invoice>('invoices').list()\n * ```\n *\n * Use for screen-sharing a live vault, demo mode, or compliance\n * review where the reviewer should not be able to edit. Writes are\n * blocked at the JavaScript layer — the keyring DEKs are unchanged,\n * so this is **not** a cryptographic security boundary against a\n * hostile caller in the same process. See {@link VaultFrame} for\n * the full caveat.\n *\n *.\n */\n frame(): VaultFrame {\n return this.strategies.shadow.buildFrame(this)\n }\n\n /** Credential-broker handle (#479); `NO_BROKER` throws unless `brokerStrategy: withBroker(config)` was passed to createNoydb(). */\n broker(): CredentialBrokerHandle {\n return buildCredentialBrokerHandle(this.strategies.broker, this.adapter, this.name, () => this.keyring)\n }\n\n /**\n * Run `fn` under a consent scope. Every `get` / `put` / `delete`\n * that happens inside `fn` writes one entry to `_consent_audit`\n * with the supplied `purpose` and `consentHash`. Outside a scope,\n * no entries are written — consent logging is opt-in by design.\n *\n * ```ts\n * await vault.withConsent(\n * { purpose: 'quarterly-review', consentHash: '7f3a...' },\n * async () => {\n * const invoices = await vault.collection<Invoice>('invoices').list()\n * return invoices\n * },\n * )\n * ```\n *\n * The scope is a single slot on this Vault instance — two\n * concurrent `withConsent` calls stomp each other. Use separate\n * Vault instances (or an external `AsyncLocalStorage` shim) for\n * per-flight scoping.\n *\n *.\n */\n async withConsent<T>(ctx: ConsentContext, fn: () => Promise<T>): Promise<T> {\n const prior = this.consentContext\n this.consentContext = ctx\n try {\n return await fn()\n } finally {\n this.consentContext = prior\n }\n }\n\n /**\n * Query the consent-audit log. Returns every entry matching the\n * filter, newest-first isn't enforced — entries carry ULID ids so\n * sorting by id is insertion-order stable. Caller may sort further.\n *\n *.\n */\n async consentAudit(filter: ConsentAuditFilter = {}): Promise<ConsentAuditEntry[]> {\n return this.strategies.consent.read(this.adapter, this.name, this.encrypted, this.getDEK, filter)\n }\n\n /**\n * Called by Collection after every access when a consent scope is\n * active. Internal — not part of the public API.\n *\n * @internal\n */\n async _logConsent(op: ConsentOp, collection: string, recordId: string): Promise<void> {\n const ctx = this.consentContext\n if (!ctx) return\n await this.strategies.consent.write(\n this.adapter,\n this.name,\n this.encrypted,\n {\n actor: this.keyring.userId,\n purpose: ctx.purpose,\n consentHash: ctx.consentHash,\n op,\n collection,\n recordId,\n },\n this.getDEK,\n )\n }\n\n // ─── Hierarchical access ─────────────────────────\n\n /**\n * Subscribe to cross-tier access events. The callback fires every\n * time a record at a tier above the caller's inherent clearance is\n * read, written, elevated, or demoted successfully via this vault.\n * Returns an unsubscribe function.\n */\n onCrossTierAccess(listener: (event: CrossTierAccessEvent) => void): () => void {\n this.crossTierSubs.add(listener)\n return () => this.crossTierSubs.delete(listener)\n }\n\n private emitCrossTier(event: CrossTierAccessEvent): void {\n for (const sub of this.crossTierSubs) {\n try {\n sub(event)\n } catch {\n // subscriber failures are swallowed — audit sinks must be best-effort\n }\n }\n }\n\n /**\n * issue a time-boxed cross-tier delegation. Writes an\n * encrypted envelope to the reserved `_delegations` collection that\n * the target user's runtime will pick up next time they open the\n * vault.\n *\n * Caller must hold the tier DEK for the requested tier and\n * collection.\n */\n async delegate(opts: IssueDelegationOptions): Promise<DelegationToken> {\n const { issueDelegation, DELEGATIONS_COLLECTION } = await import('../with-party/team/delegation.js')\n // The target user's KEK is derived from THEIR keyring — we read\n // the keyring file to pick up the wrapped DEKs and their KEK salt,\n // but we cannot derive their KEK from our side (we don't have\n // their secret). For the delegation wraps against the\n // grantor's own KEK as a simpler first cut; swapping to a proper\n // per-target KEK exchange (via `on-magic-link` or OIDC) is a\n // follow-up tracked in the design doc.\n if (!this.keyring.kek) {\n throw new ValidationError(\n 'issueDelegation: keyring.kek is null — issuing a delegation requires ' +\n 'a tier-1 unlock. Re-authenticate at tier 1 (secret) first.',\n )\n }\n const targetKek = this.keyring.kek\n const delegationsDek = await this.getDEK(DELEGATIONS_COLLECTION)\n return issueDelegation(\n this.adapter,\n this.name,\n this.keyring,\n targetKek,\n delegationsDek,\n opts,\n )\n }\n\n /**\n * revoke an issued delegation by id. Safe to call even\n * if the id does not exist.\n */\n async revokeDelegation(id: string): Promise<void> {\n const { revokeDelegation, DELEGATIONS_COLLECTION } = await import('../with-party/team/delegation.js')\n await revokeDelegation(this.adapter, this.name, id)\n // Trigger store to note the delete.\n void DELEGATIONS_COLLECTION\n }\n\n // ─── Scoped tier elevation ───────────────────────────\n\n /**\n * Briefly elevate this vault to a higher tier and return a scoped\n * handle whose writes land at that tier. Reads on the original\n * vault continue at the caller's inherent tier; only the returned\n * handle is privileged. Auto-reverts when `release()` is called or\n * `ttlMs` elapses, whichever comes first.\n *\n * Capability semantics:\n * - The keyring must already carry a wrap for the target tier on\n * at least one collection (or be `owner` / `admin`, who can\n * auto-mint). Otherwise throws {@link TierNotGrantedError}.\n * - Per-collection capability gates (`canExportPlaintext`,\n * `canExportBundle`) are NOT bypassed — elevation is a tier\n * projection, not a privilege escalation path.\n * - Only one elevation can be active per vault at a time.\n * Calling `elevate(...)` while another is live throws\n * {@link AlreadyElevatedError}.\n *\n * Audit:\n * - One `_elevation_audit` envelope is written at start with\n * `{ id, actor, tier, reason, ttlMs, startedAt, expiresAt }`.\n * - Each write through the elevated handle additionally fires a\n * {@link CrossTierAccessEvent} with `authorization: 'elevation'`,\n * stamped with `reason` and `elevatedFrom`.\n */\n async elevate(tier: number, options: { ttlMs: number; reason: string }): Promise<ElevatedHandle> {\n if (!Number.isInteger(tier) || tier <= 0) {\n throw new ValidationError(`elevate: tier must be a positive integer, got ${tier}`)\n }\n if (!options || typeof options.reason !== 'string' || options.reason.length === 0) {\n throw new ValidationError('elevate: reason is required (non-empty string)')\n }\n if (typeof options.ttlMs !== 'number' || options.ttlMs <= 0) {\n throw new ValidationError('elevate: ttlMs must be a positive number')\n }\n if (this.activeElevation) {\n throw new AlreadyElevatedError(this.activeElevation.tier)\n }\n // Construction-time tier-reach check: scan keyring for any\n // `*#${tier}` DEK. Owners and admins skip — they auto-mint at\n // write time per the existing `assertTierAccess` rules. FR-6:\n // custodian is admin-rank operationally and auto-mints tier DEKs\n // too (kept in lockstep with assertTierAccess in team/tiers.ts).\n if (\n this.keyring.role !== 'owner' &&\n this.keyring.role !== 'admin' &&\n this.keyring.role !== 'custodian'\n ) {\n const suffix = `#${tier}`\n let found = false\n for (const k of this.keyring.deks.keys()) {\n if (k.endsWith(suffix)) { found = true; break }\n }\n if (!found) {\n // Match the existing error class so adopters with one catch()\n // for tier-related failures don't need a second branch.\n throw new TierNotGrantedError('(any collection)', tier)\n }\n }\n\n const startedAt = new Date()\n const expiresAt = startedAt.getTime() + options.ttlMs\n const reason = options.reason\n\n const handle = new ElevatedHandle({\n vault: this,\n tier,\n reason,\n expiresAt,\n onRelease: () => {\n if (this.activeElevation && this.activeElevation.handle === handle) {\n this.activeElevation = null\n }\n },\n })\n\n this.activeElevation = { tier, expiresAt, reason, handle }\n await this.writeElevationAudit({\n actor: this.keyring.userId,\n tier,\n reason,\n ttlMs: options.ttlMs,\n startedAt: startedAt.toISOString(),\n expiresAt: new Date(expiresAt).toISOString(),\n })\n return handle\n }\n\n /**\n * Internal — invoked by an `ElevatedHandle.collection().put()` call.\n * Routes through the existing `Collection.putAtTier` code path with\n * the elevation context attached so the cross-tier event reflects\n * the right authorization class. Returns `putAtTier`'s `TierMoveResult` (#779).\n */\n async _elevatedPut<T>(\n collectionName: string,\n id: string,\n record: T,\n tier: number,\n reason: string,\n ): Promise<TierMoveResult> {\n const coll = this.collection<T>(collectionName)\n return coll.putAtTier(id, record, tier, {\n elevation: { reason, fromTier: 0 },\n })\n }\n\n private async writeElevationAudit(entry: {\n actor: string\n tier: number\n reason: string\n ttlMs: number\n startedAt: string\n expiresAt: string\n }): Promise<void> {\n const id = `elev-${Date.now().toString(36)}-${Math.random().toString(16).slice(2, 10)}`\n const json = JSON.stringify({ id, ...entry })\n const envelope: EncryptedEnvelope = this.encrypted\n ? await (async () => {\n const dek = await this.getDEK(ELEVATION_AUDIT_COLLECTION)\n const { iv, data } = await encrypt(json, dek)\n return {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: 1,\n _ts: entry.startedAt,\n _iv: iv,\n _data: data,\n _by: entry.actor,\n }\n })()\n : {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: 1,\n _ts: entry.startedAt,\n _iv: '',\n _data: json,\n _by: entry.actor,\n }\n await this.adapter.put(this.name, ELEVATION_AUDIT_COLLECTION, id, envelope)\n }\n\n /**\n * low-level escape hatch used by `@noy-db/on-magic-link`\n * to persist a magic-link-bound grant after the auth package has\n * derived the content key + KEK from `(serverSecret, token, vault)`.\n *\n * Callers outside of `@noy-db/on-magic-link` should use\n * `issueMagicLinkDelegation()` from that package instead — it handles\n * the HKDF derivation, record-id composition, and batch logic so the\n * grantor doesn't touch this method directly.\n */\n async writeMagicLinkGrant(\n contentKey: EnclaveKey,\n grantKek: EnclaveKey,\n recordId: string,\n opts: IssueMagicLinkGrantOptions,\n ): Promise<MagicLinkGrantRecord> {\n return writeMagicLinkGrant(\n this.adapter,\n this.name,\n this.keyring,\n contentKey,\n grantKek,\n recordId,\n opts,\n )\n }\n\n // ─── Accounting periods ────────────────────────\n\n /**\n * Close an accounting period. After this call every record whose\n * envelope `_ts` is at or before `endDate` is write-locked: further\n * `put` or `delete` calls against such records throw\n * {@link PeriodClosedError}. New records (with fresh timestamps)\n * remain freely writable, and records last written AFTER `endDate`\n * are unaffected.\n *\n * Each closure writes a `PeriodRecord` to the reserved `_periods`\n * collection. The record carries the hash of the prior period's\n * record, so a tamper with any closure breaks the chain visible to\n * {@link listPeriods} + `vault.ledger().verify()`.\n *\n * Correctness is tied to the `_ts` field the hub assigns on every\n * write. Backdating records by editing the envelope directly is\n * outside the threat model — see SPEC § zero-knowledge envelopes.\n *\n *.\n */\n async closePeriod(options: ClosePeriodOptions): Promise<PeriodRecord> {\n return this.periods.closePeriod(options)\n }\n\n /**\n * Open a new period that carries forward from a prior closed one\n *. The `carryForward` callback receives a read-only\n * {@link VaultInstant} view anchored at the prior period's\n * `endDate` — use it to compute opening balances, closing-trial\n * snapshots, or any aggregate the new period should inherit. The\n * returned `{ [collection]: { [id]: record } }` map is written\n * before the new `PeriodRecord` lands, so the opening entries\n * materialise with fresh `_ts` values that fall outside every\n * closed period (the guard lets them through).\n *\n * The new period is stored with `kind: 'opened'` and hash-chained\n * to the same chain the close calls build — `listPeriods()` sees\n * both closed and opened entries in `closedAt` order.\n */\n async openPeriod<TCollections extends Record<string, Record<string, unknown>>>(\n options: OpenPeriodOptions<TCollections>,\n ): Promise<PeriodRecord> {\n return this.periods.openPeriod(options)\n }\n\n /** Return every closed / opened period in `closedAt` order. */\n async listPeriods(): Promise<readonly PeriodRecord[]> {\n return this.periods.listPeriods()\n }\n\n /** Look up a single period by name. Returns `null` if not found. */\n async getPeriod(name: string): Promise<PeriodRecord | null> {\n return this.periods.getPeriod(name)\n }\n\n /**\n * Freeze a closed period (#604): purges in-window delete markers and\n * records a `_period_freezes` companion, never mutating the chained\n * `_periods` record. Idempotent. Purges the LOCAL adapter only — a\n * synced target's markers survive there and re-import on pull (benign),\n * and purging re-opens the #589 resurrection window for a peer offline\n * since before the cutoff (see periods.ts's \"Freeze\" section).\n */\n async freezePeriod(name: string): Promise<PeriodRecord> {\n return this.periods.freezePeriod(name)\n }\n\n /**\n * Archive a closed period (#613): relocates its in-window records from the\n * hot store to the configured cold tier (via the routeStore's cold route),\n * recording a `_period_archives` companion + ledger entry, never mutating\n * the chained `_periods` record. Non-destructive (reads fall through to\n * cold) and idempotent. Requires a routeStore with a cold route.\n */\n async archivePeriod(name: string): Promise<PeriodRecord> {\n return this.periods.archivePeriod(name)\n }\n\n /**\n * Target-purge a closed+frozen period (#615): sweeps delete markers off the\n * vault's push-only sync targets (`backup`/`archive`), recording a\n * `_period_target_purges` companion + ledger entry, never mutating the chained\n * `_periods` record. `sync-peer` targets are skipped. Requires the period be\n * frozen first. Idempotent; a vault with no push-only targets writes no\n * companion and is re-runnable.\n */\n async purgePeriodTargets(name: string): Promise<PeriodRecord> {\n return this.periods.purgePeriodTargets(name)\n }\n\n /** @internal — called by the gate bus before put/delete. */\n async _assertTsWritable(\n existing: { ts: string | null; record: Record<string, unknown> | null } | null,\n incoming: Record<string, unknown> | null,\n ): Promise<void> {\n return this.periods.assertTsWritable(existing, incoming)\n }\n\n /** List all collection names in this vault. */\n async collections(): Promise<string[]> {\n const snapshot = await this.adapter.loadAll(this.name)\n return Object.keys(snapshot)\n }\n\n /**\n * Emit a structured introspection snapshot of this vault — vault name,\n * service opt-in matrix, collections + their fields, materialized\n * views, overlay views, derivations. With `withStats: true`, walks\n * every collection's envelopes to compute record counts, byte totals,\n * and oldest/newest timestamps.\n *\n * Consumed by the `noydb describe` CLI to produce human-readable\n * audit YAML/JSON from a `.noydb` bundle.\n *\n * Field provenance:\n * - `persisted`: read from `_schemas/<col>` envelope (Route B opt-in)\n * - `live-validator`: derived in-process from a Zod schema attached\n * to the live `Collection`\n * - `sampled`: inferred from decrypted records (deferred to a follow-up)\n * - `unknown`: no schema info available\n *\n * @see docs/superpowers/specs/2026-05-22-schema-dump-design.md\n */\n async dumpSchema(opts: DumpSchemaOptions = {}): Promise<VaultSchemaSnapshot> {\n const { dumpVaultSchema } = await import('../with-shape/introspection/walk.js') // lazy (#553)\n return dumpVaultSchema(this, opts)\n }\n\n /**\n * Lightweight read of the vault's registered schema: collections\n * (+ doc counts), guards, materialized views, schema-update strategies,\n * and the unlocked user's grants. Cheap — one `adapter.list` per\n * collection, no decryption. For a full snapshot + stats use dumpSchema().\n * Post-unlock by construction (a Vault only exists with an unlocked keyring).\n */\n async introspect(): Promise<SchemaIntrospection> {\n const byCol = (a: { collection: string }, b: { collection: string }) =>\n a.collection.localeCompare(b.collection)\n\n // Union of collections registered this session (collectionCache) and\n // collections with persisted records (collections()), so registered-but-\n // empty collections are reported too.\n const names = [...new Set([...this.collectionCache.keys(), ...(await this.collections())])]\n .filter((n) => !n.startsWith('_'))\n .sort((a, b) => a.localeCompare(b))\n const collections: { name: string; docCount: number }[] = []\n for (const name of names) {\n const ids = await this.adapter.list(this.name, name)\n collections.push({ name, docCount: ids.length })\n }\n\n const guards = (this._getGuardRegistry()?.summary() ?? []).slice().sort(byCol)\n\n const materializedViews = (this._getMaterializedViewRegistry()?.all() ?? [])\n .map((mv) => ({ name: mv.spec.name, sourceCollections: [...mv.dependencies].sort() }))\n .sort((a, b) => a.name.localeCompare(b.name))\n\n const schemaUpdate = [...this.#schemaUpdateNames.entries()]\n .map(([collection, strategies]) => ({ collection, strategies }))\n .sort(byCol)\n\n // Grants reflect what the unlocked user can actually access: the\n // collections they hold a DEK for, with the level from `permissions`\n // (absent ⇒ implicit full access for owner/admin → 'rw').\n const grants = [...this.keyring.deks.keys()]\n .filter((collection) => !collection.startsWith('_'))\n .map((collection) => ({ collection, permission: this.keyring.permissions[collection] ?? 'rw' as const }))\n .sort(byCol)\n\n return { collections, guards, materializedViews, schemaUpdate, grants }\n }\n\n /**\n * Internal accessor for {@link dumpVaultSchema}. Exposes the structural\n * state the walker needs (collection cache, registries, ref registry,\n * adapter) without widening the public Vault surface.\n *\n * @internal\n */\n _introspectState(): VaultIntrospectState {\n return {\n name: this.name,\n adapter: this.adapter,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n collectionCache: this.collectionCache as Map<string, any>,\n refRegistry: this.refRegistry,\n getDEK: this.getDEK,\n keyring: this.keyring,\n subsystems: {\n guards: this.guardRegistry !== null,\n derivations: this.derivationRegistry !== null,\n materializedViews: this.materializedViewRegistry !== null,\n overlayViews: this.overlayedViewRegistry !== null,\n },\n ...(this.vaultMeta !== undefined ? { vaultMeta: this.vaultMeta } : {}),\n mvRegistry: this.materializedViewRegistry,\n overlayRegistry: this.overlayedViewRegistry,\n derivationRegistry: this.derivationRegistry,\n // Thread vault-level per-collection registries into the walker so\n // walk.ts can project archive/schemaUpdate into CollectionDescriptor.config\n // without coupling the walker to Vault internals.\n getCollectionSchemaUpdateNames: (col) => {\n const names = this.#schemaUpdateNames.get(col)\n return names !== undefined && names.length > 0 ? names : undefined\n },\n hasCollectionArchive: (col) => this.archiveRegistry.has(col),\n }\n }\n\n /**\n * Return the stable opaque bundle handle for this vault,\n * generating and persisting a fresh ULID on first call.\n *\n * used by `writePod()` to identify the\n * vault in the unencrypted bundle header without\n * exposing the vault name. The handle is persisted in\n * the reserved `_meta` internal collection so subsequent\n * exports of the same vault produce the same handle —\n * bundle adapters (Drive, Dropbox, iCloud) will use it\n * as their primary key.\n *\n * **Storage path:** the handle is written via the adapter\n * directly with collection name `_meta` and id `handle`. The\n * envelope's `_data` field contains a plain JSON\n * `{ handle: '...' }` payload — the handle is opaque, doesn't\n * need encryption, and the bundle header exposes the same\n * value anyway. This mirrors the storage approach `_keyring`\n * uses for its plain-JSON wrapped-DEK envelopes (also bypasses\n * the AES-GCM layer; the `_iv` field is left empty).\n *\n * **Cross-process stability:** the handle survives process\n * restarts because it's persisted on the adapter, not just\n * cached in memory. A new Vault instance opened on the\n * same adapter sees the same `_meta/handle` envelope and\n * returns the same ULID.\n *\n * **Round-trip after restore:** the receiving vault of a\n * `load()` call generates its OWN handle on first export. The\n * dump body does not include `_meta`, because handle stability\n * is per-vault-instance, not per-vault-content. Two\n * separate restorations of the same backup produce two\n * distinct handles, which is the right behavior — they're\n * separate vault instances now.\n */\n async getBundleHandle(): Promise<string> {\n const existing = await this.adapter.get(this.name, '_meta', 'handle')\n if (existing) {\n try {\n const parsed = JSON.parse(existing._data) as unknown\n if (parsed !== null && typeof parsed === 'object' && 'handle' in parsed) {\n const handle = (parsed as { handle: unknown }).handle\n if (typeof handle === 'string' && /^[0-9A-HJKMNP-TV-Z]{26}$/.test(handle)) {\n return handle\n }\n }\n } catch {\n // Fall through to regenerate — corrupted handle envelope\n // is treated as missing, not as an error. The new handle\n // overwrites the bad one.\n }\n }\n // Lazy import to avoid a top-of-file circular dependency:\n // bundle/bundle.ts imports from vault.ts (the\n // Vault type), and vault.ts can't statically\n // import from bundle/* without forming a cycle. The dynamic\n // import is invoked once per fresh handle generation, which\n // is rare enough that the cost doesn't matter.\n const { generateULID } = await import('../with-pod/ulid.js')\n const handle = generateULID()\n const envelope: EncryptedEnvelope = {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: 1,\n _ts: new Date().toISOString(),\n _iv: '',\n _data: JSON.stringify({ handle }),\n }\n await this.adapter.put(this.name, '_meta', 'handle', envelope)\n return handle\n }\n\n /**\n * Read the owner-curated cover for this vault (or `undefined` if\n * none is persisted). The cover lives in `_meta/public-envelope`\n * (the frozen wire name) as plaintext — readable without any KEK\n * — so `getBundleHandle`-style callers can label a vault before\n * unlock.\n *\n * Mirrors `Noydb.getCover(vault, opts)` but scoped to a\n * single, already-opened `Vault` instance so the\n * bundle writer can snapshot it without holding a `Noydb` reference.\n *\n * @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md\n */\n async getCover(opts: { readonly locale?: string } = {}): Promise<Cover | undefined> {\n const { readCover } = await import('../with-party/directory/cover/index.js')\n return readCover(this.adapter, this.name, opts)\n }\n\n /**\n * Dump vault as a verifiable encrypted JSON backup string.\n *\n * backups embed the current ledger head and the full\n * `_ledger` + `_ledger_deltas` internal collections so the\n * receiver can run `verifyBackupIntegrity()` after `load()` and\n * detect any tampering between dump and restore. Backups produced\n * without a ledger (older formats or hub instances built without\n * the history strategy) skip the integrity check with a warning —\n * both modes round-trip cleanly.\n */\n async dump(): Promise<string> {\n const { dumpVault } = await import('../with-pod/backup.js')\n return dumpVault(this.backupContext())\n }\n\n /**\n * Build the `BackupContext` the extracted backup module (`with-pod/backup.ts`)\n * binds to: the read paths + the post-load mutation seams (`reloadKeyring`,\n * collection-cache clear, ledger-store reset) that `load()` performs on this\n * Vault's private state.\n */\n private backupContext() {\n return {\n adapter: this.adapter,\n vault: this.name,\n userId: () => this.keyring.userId,\n getLedgerOrNull: () => this.getLedgerOrNull(),\n envelopePayloadHash: (envelope: EncryptedEnvelope) => this.strategies.history.envelopePayloadHash(envelope),\n reloadKeyringAndRebuildDEK: async () => {\n if (this.reloadKeyring) {\n this.keyring = await this.reloadKeyring()\n // Rebuild the DEK resolver against the refreshed keyring so\n // the next ensureCollectionDEK call sees the loaded wrapped\n // DEKs, not the cached pre-load ones.\n this.getDEK = this.makeGetDEK()\n }\n },\n clearCollectionCache: () => this.collectionCache.clear(),\n resetLedgerStore: () => { this.ledgerStore = null },\n exportStream: (opts: ExportStreamOptions) => this.exportStream(opts),\n }\n }\n\n /**\n * Restore a vault from a verifiable backup.\n *\n * After loading, runs `verifyBackupIntegrity()` to confirm:\n * 1. The hash chain is intact (no `prevHash` mismatches)\n * 2. The chain head matches the embedded `ledgerHead.hash`\n * from the backup\n * 3. Every data envelope's `payloadHash` matches the\n * corresponding ledger entry — i.e. nobody swapped\n * ciphertext between dump and restore\n *\n * On any failure, throws `BackupLedgerError` (chain or head\n * mismatch) or `BackupCorruptedError` (data envelope mismatch).\n * The vault state on the adapter has already been written\n * by the time we throw, so the caller is responsible for either\n * accepting the suspect state or wiping it and trying a different\n * backup.\n *\n * Legacy backups (no `ledgerHead` field, no `_internal`) load\n * with a console warning and skip the integrity check entirely\n * — there's no chain to verify against.\n */\n async load(backupJson: string): Promise<void> {\n const { loadVault } = await import('../with-pod/backup.js')\n return loadVault(this.backupContext(), backupJson)\n }\n\n /**\n * End-to-end backup integrity check. Runs both:\n *\n * 1. `ledger.verify()` — walks the hash chain and confirms\n * every `prevHash` matches the recomputed hash of its\n * predecessor.\n *\n * 2. **Data envelope cross-check** — for every (collection, id)\n * that has a current value, find the most recent ledger\n * entry recording a `put` for that pair, recompute the\n * sha256 of the stored envelope's `_data`, and compare to\n * the entry's `payloadHash`. Any mismatch means an\n * out-of-band write modified the data without updating the\n * ledger.\n *\n * Returns a discriminated union so callers can handle the two\n * failure modes differently:\n * - `{ ok: true, head, length }` — chain verified and all\n * data matches; safe to use.\n * - `{ ok: false, kind: 'chain', divergedAt, message }` — the\n * chain itself is broken at the given index.\n * - `{ ok: false, kind: 'data', collection, id, message }` —\n * a specific data envelope doesn't match its ledger entry.\n *\n * This method is exposed so users can call it any time, not just\n * during `load()`. A scheduled background check is the simplest\n * way to detect tampering of an in-place vault.\n */\n async verifyBackupIntegrity() {\n const { verifyBackupIntegrity } = await import('../with-pod/backup.js')\n return verifyBackupIntegrity(this.backupContext())\n }\n\n /**\n * Stream every collection in this vault as decrypted, ACL-scoped\n * chunks.\n *\n * ⚠ **This method decrypts your records.** noy-db's threat model assumes\n * that records on disk are encrypted; the values yielded here are\n * plaintext. The consumer is responsible for ensuring the yielded data\n * is handled in a way that matches the data's sensitivity. If your goal\n * is encrypted backup or transport between noy-db instances, use\n * `dump()` instead — it produces a tamper-evident encrypted envelope and\n * never exposes plaintext.\n *\n * ## Behavior\n *\n * - **ACL-scoped.** Collections the calling principal cannot read are\n * silently skipped (same rule as `Collection.list()`). An operator\n * with `{ invoices: 'rw', clients: 'ro' }` permissions on a\n * five-collection vault exports only `invoices` and `clients`,\n * with no error on the others.\n * - **Streaming.** Returns an `AsyncIterableIterator` so consumers can\n * process chunks as they arrive without holding the full export in\n * memory. Note: the underlying adapter call (`loadAll`) is still a\n * single bulk read — the streaming benefit is on the *output* side.\n * True per-record adapter streaming arrives with the query DSL.\n * - **Schema + refs surfaced** as metadata on every chunk so downstream\n * serializers (`@noy-db/as-csv`, `@noy-db/as-xlsx`, custom\n * exporters) can produce schema-aware output without reaching into\n * collection internals.\n * - **Internal collections filtered.** `_ledger`, `_keyring`, etc. are\n * never yielded — they're noy-db's own bookkeeping and have no value\n * in a plaintext export. Use `dump()` for full backup including\n * internal collections.\n *\n * ## Composition\n *\n * Once cross-vault queries land, fanning this out across\n * every vault the caller can unlock is `queryAcross(ids, c =>\n * c.exportStream())` — no new primitive needed. That's part of why this\n * method belongs in core: it's the single decrypt+ACL+metadata path\n * that every export-format package will build on, and pushing it into\n * a `@noy-db/as-*` package would force every format to re-solve\n * the same problems independently.\n *\n * @example\n * ```ts\n * for await (const chunk of company.exportStream()) {\n * // chunk.collection: 'invoices'\n * // chunk.schema: ZodObject | null\n * // chunk.refs: { clientId: { target: 'clients', mode: 'strict' } }\n * // chunk.records: Invoice[]\n * }\n * ```\n *\n * @example\n * ```ts\n * // Per-record streaming for arbitrarily large collections.\n * for await (const chunk of company.exportStream({ granularity: 'record' })) {\n * // chunk.records is always length 1\n * await writer.write(serialize(chunk.records[0]))\n * }\n * ```\n */\n async *exportStream(opts: ExportStreamOptions = {}): AsyncIterableIterator<ExportChunk> {\n const granularity = opts.granularity ?? 'collection'\n // Export layer: when an export locale is set, read each record at that\n // locale through the `export` layer (`resolvePolicy(onMissing, 'export')`) —\n // collapsing i18nText fields to the locale string and resolving dictKey/\n // staticDict `<field>Label`s — so the export is single-locale and the raw\n // dictionary snapshot is redundant (omitted). Unset → raw `{locale}` maps +\n // the dictionaries snapshot (a full, all-locale backup).\n const exportLocale = opts.resolveLabels\n const localeOpts = exportLocale !== undefined ? { locale: exportLocale, _layer: 'export' as const } : undefined\n\n // One bulk read to enumerate collections. `loadAll` filters out\n // underscore-prefixed internal collections, which is exactly what we\n // want — internal bookkeeping has no place in a plaintext export.\n const snapshot = await this.adapter.loadAll(this.name)\n const collectionNames = Object.keys(snapshot).sort()\n\n // Resolve the ledger head once if requested. The head is identical\n // across every yielded chunk (one ledger per vault) — we copy\n // it onto each chunk so consumers doing per-record streaming don't\n // have to thread state across yields, and so the chunk shape stays\n // forward-compatible with future per-partition ledgers where the\n // head genuinely will differ per chunk.\n const ledgerHead = opts.withLedgerHead\n ? await (async () => {\n const ledger = this.getLedgerOrNull()\n if (!ledger) return undefined\n const head = await ledger.head()\n return head\n ? { hash: head.hash, index: head.entry.index, ts: head.entry.ts }\n : undefined\n })()\n : undefined\n\n // Capture ALL dictionary snapshots upfront before the first yield.\n // Building all snapshots eagerly before yielding anything ensures that\n // concurrent mutations during streaming do not affect the snapshot — any\n // dictionary.put() that happens after the first yield sees the pre-yield\n // state here. Keyed by collection name.\n const dictSnapshotCache = new Map<\n string, // collection name\n Record<string, Record<string, Record<string, string>>> // field → key → locale → label\n >()\n // Skip the snapshot entirely when exporting at a locale — records carry\n // resolved `<field>Label`s, so the raw dictionary is redundant.\n if (exportLocale === undefined) {\n for (const collectionName of collectionNames) {\n const dictFields = this.dictKeyFieldRegistry.get(collectionName)\n if (dictFields && Object.keys(dictFields).length > 0) {\n const snap: Record<string, Record<string, Record<string, string>>> = {}\n for (const [fieldName, dictName] of Object.entries(dictFields)) {\n const entries = await this.dictionary(dictName).list()\n const keyMap: Record<string, Record<string, string>> = {}\n for (const entry of entries) {\n keyMap[entry.key] = entry.labels\n }\n snap[fieldName] = keyMap\n }\n dictSnapshotCache.set(collectionName, snap)\n }\n }\n }\n\n for (const collectionName of collectionNames) {\n // ACL gate. The same `hasAccess` check that `Collection.list()`\n // honors — silent skip, no error, matches the \"operator can read\n // some but not all\" pattern.\n if (!hasAccess(this.keyring, collectionName)) continue\n\n const coll = this.collection(collectionName)\n const schema = coll.getSchema() ?? null\n const refs = this.refRegistry.getOutbound(collectionName)\n const ids = Object.keys(snapshot[collectionName] ?? {})\n\n const dictionaries = dictSnapshotCache.get(collectionName)\n\n if (granularity === 'collection') {\n // Decrypt every record in the collection, then yield once.\n // Using `coll.get(id)` rather than the loadAll envelope directly\n // because `get()` is the canonical decrypt+schema-validate path\n // and any future cache/index plumbing rides through it.\n const records: unknown[] = []\n for (const id of ids) {\n const record = await coll.get(id, localeOpts)\n if (record !== null) records.push(exportRedact(coll, record))\n }\n const chunk: ExportChunk = {\n collection: collectionName,\n schema,\n refs,\n records,\n ...(dictionaries !== undefined ? { dictionaries } : {}),\n ...(ledgerHead ? { ledgerHead } : {}),\n }\n yield chunk\n } else {\n // Per-record yield. Memory profile: O(1 record) at a time.\n // The schema/refs metadata is repeated on every chunk so\n // consumers don't have to thread state across yields.\n for (const id of ids) {\n const record = await coll.get(id, localeOpts)\n if (record === null) continue\n const chunk: ExportChunk = {\n collection: collectionName,\n schema,\n refs,\n records: [exportRedact(coll, record)],\n ...(dictionaries !== undefined ? { dictionaries } : {}),\n ...(ledgerHead ? { ledgerHead } : {}),\n }\n yield chunk\n }\n }\n }\n }\n\n /**\n * Convenience wrapper that consumes `exportStream()` and serializes the\n * result to a single JSON string.\n *\n * ⚠ **`exportJSON()` decrypts your records and produces plaintext.**\n *\n * noy-db's threat model assumes that records on disk are encrypted.\n * This function deliberately violates that assumption: it produces a\n * JSON string in plaintext, which the consumer is then responsible for\n * protecting (filesystem permissions, full-disk encryption, secure\n * transfer, secure deletion).\n *\n * Use this function only when:\n * - You are the authorized owner of the data, **and**\n * - You have a legitimate downstream tool that requires plaintext\n * JSON, **and**\n * - You have a documented plan for how the resulting plaintext will be\n * protected and eventually destroyed.\n *\n * If your goal is encrypted backup or transport between noy-db\n * instances, use `dump()` instead — it produces a tamper-evident\n * encrypted envelope, never plaintext.\n *\n * ## Why `Promise<string>` instead of writing to a file path\n *\n * Core has zero `node:` imports — it runs unchanged in browsers, Node,\n * Bun, Deno, and edge runtimes. Accepting a file path would force a\n * `node:fs` import (breaks browsers) or a runtime dynamic import\n * (doesn't tree-shake, inflates bundles). Returning a string lets the\n * consumer choose any sink and forces the destination decision to be\n * explicit at the call site — which is also better for the security\n * warning.\n *\n * @example\n * ```ts\n * // Node: write to a file\n * import { writeFile } from 'node:fs/promises'\n * await writeFile('./backup.json', await company.exportJSON())\n * ```\n *\n * @example\n * ```ts\n * // Browser: download as a file\n * const json = await company.exportJSON()\n * const blob = new Blob([json], { type: 'application/json' })\n * const url = URL.createObjectURL(blob)\n * // ... attach to an <a download> and click\n * ```\n *\n * @example\n * ```ts\n * // Stream upload to a server\n * await fetch('/upload', {\n * method: 'POST',\n * body: await company.exportJSON(),\n * })\n * ```\n *\n * ## On-disk shape\n *\n * ```json\n * {\n * \"_noydb_export\": 1,\n * \"_compartment\": \"acme\",\n * \"_exported_at\": \"2026-04-07T12:00:00.000Z\",\n * \"_exported_by\": \"alice@acme.example\",\n * \"collections\": {\n * \"invoices\": {\n * \"schema\": null,\n * \"refs\": { \"clientId\": { \"target\": \"clients\", \"mode\": \"strict\" } },\n * \"records\": [ ... ]\n * }\n * },\n * \"ledgerHead\": { \"hash\": \"...\", \"index\": 42, \"ts\": \"...\" }\n * }\n * ```\n *\n * `schema` is included for forward compatibility but is currently\n * always `null` because Standard Schema validators are not JSON-\n * serializable. Format-package serializers that need the schema\n * should use `exportStream()` directly and read `chunk.schema` (which\n * is the live validator object, not a serialization of it).\n */\n async exportJSON(opts: ExportStreamOptions = {}): Promise<string> {\n const { exportVaultJSON } = await import('../with-pod/backup.js')\n return exportVaultJSON(this.backupContext(), opts)\n }\n}\n","import type { NoydbEventMap } from './types.js'\n\ntype EventHandler<T> = (data: T) => void\n\n/** Typed event emitter for NOYDB events. */\nexport class NoydbEventEmitter {\n private readonly listeners = new Map<string, Set<EventHandler<unknown>>>()\n\n on<K extends keyof NoydbEventMap>(\n event: K,\n handler: EventHandler<NoydbEventMap[K]>,\n ): void {\n let set = this.listeners.get(event as string)\n if (!set) {\n set = new Set()\n this.listeners.set(event as string, set)\n }\n set.add(handler as EventHandler<unknown>)\n }\n\n off<K extends keyof NoydbEventMap>(\n event: K,\n handler: EventHandler<NoydbEventMap[K]>,\n ): void {\n this.listeners.get(event as string)?.delete(handler as EventHandler<unknown>)\n }\n\n emit<K extends keyof NoydbEventMap>(event: K, data: NoydbEventMap[K]): void {\n const set = this.listeners.get(event as string)\n if (set) {\n for (const handler of set) {\n handler(data)\n }\n }\n }\n\n removeAllListeners(): void {\n this.listeners.clear()\n }\n}\n","/**\n * Observable write-queue.\n *\n * Tracks outstanding in-flight *logical* writes (a full Collection.put /\n * delete, including ledger + cache + derivation + MV dispatch — not just\n * the adapter call). The hub holds one tracker per instance; it is\n * framework-agnostic (no Vue/React dependency). UI layers subscribe via\n * onChange(); the migration drain (Slice 2) quiesces via onFlush().\n */\n\n/** Public, read-only view of the hub's write-queue. */\nexport interface WriteQueue {\n /** True while one or more writes are in flight (`depth > 0`). */\n readonly pending: boolean\n /** Count of outstanding write operations. */\n readonly depth: number\n /**\n * Subscribe to depth changes (fires on every begin and settle).\n * Returns an unsubscribe function. Intended for reactive wrappers\n * (e.g. `@noy-db/in-vue` turns this into a `ref`).\n */\n onChange(handler: () => void): () => void\n /**\n * Resolves once `depth` reaches 0. If a write settled with an error\n * while this flush was waiting, the returned promise REJECTS with that\n * error instead — so a drain caller surfaces the failure rather than\n * hanging. Resolves immediately when already idle and error-free.\n */\n onFlush(): Promise<void>\n}\n\ninterface FlushWaiter {\n resolve: () => void\n reject: (error: Error) => void\n}\n\nexport class WriteQueueTracker implements WriteQueue {\n #depth = 0\n #error: Error | null = null\n readonly #changeHandlers = new Set<() => void>()\n #flushWaiters: FlushWaiter[] = []\n\n get pending(): boolean {\n return this.#depth > 0\n }\n\n get depth(): number {\n return this.#depth\n }\n\n /** Mark one write as started. */\n begin(): void {\n this.#depth++\n this.#emitChange()\n }\n\n /** Mark one write as finished. Pass the error if it failed. */\n settle(error?: Error): void {\n this.#depth = Math.max(0, this.#depth - 1)\n if (error) this.#error = error\n this.#emitChange()\n if (this.#depth === 0) this.#drainFlush()\n }\n\n onChange(handler: () => void): () => void {\n this.#changeHandlers.add(handler)\n return () => {\n this.#changeHandlers.delete(handler)\n }\n }\n\n onFlush(): Promise<void> {\n if (this.#depth === 0) {\n const error = this.#error\n this.#error = null\n return error ? Promise.reject(error) : Promise.resolve()\n }\n return new Promise<void>((resolve, reject) => {\n this.#flushWaiters.push({ resolve, reject })\n })\n }\n\n /**\n * Run `fn` as a tracked write: depth++ on entry, depth-- on settle\n * (success or failure). The fn's resolved value is returned; a thrown\n * error is re-thrown after the queue is decremented.\n */\n async track<R>(fn: () => Promise<R>): Promise<R> {\n this.begin()\n try {\n const value = await fn()\n this.settle()\n return value\n } catch (error) {\n this.settle(error as Error)\n throw error\n }\n }\n\n #emitChange(): void {\n for (const handler of this.#changeHandlers) handler()\n }\n\n #drainFlush(): void {\n const waiters = this.#flushWaiters\n this.#flushWaiters = []\n const error = this.#error\n this.#error = null\n for (const waiter of waiters) {\n if (error) waiter.reject(error)\n else waiter.resolve()\n }\n }\n}\n","/**\n * Hub-level write lifecycle hooks. `onBeforeWrite` may abort (throw);\n * `onAfterWrite` is awaited and its errors are warned, not thrown. A\n * re-entrancy flag suppresses nested firing so a handler that writes can't\n * loop. Held on the Noydb instance, threaded into every Collection.\n */\nexport interface WriteEvent {\n readonly op: 'create' | 'update' | 'delete'\n readonly vault: string\n readonly collection: string\n readonly docId: string\n readonly before: unknown // decrypted prior record; null on 'create'\n readonly after: unknown // the record written; null on 'delete'\n readonly baseVersion: number // version the writer started from (0 on create)\n readonly version: number // version the writer wrote (baseVersion + 1)\n readonly userId: string\n readonly timestamp: number\n readonly txId: string\n}\n\nexport type WriteHook = (event: WriteEvent) => void | Promise<void>\nexport type Unsubscribe = () => void\n\nexport class WriteHookRegistry {\n readonly #before: WriteHook[] = []\n readonly #after: WriteHook[] = []\n #suppressed = false\n\n /** True while handlers are running — used by the write path to skip nested firing. */\n get suppressed(): boolean { return this.#suppressed }\n\n /** True when any hook is registered (cheap gate for the write path). */\n get hasHandlers(): boolean { return this.#before.length > 0 || this.#after.length > 0 }\n\n /**\n * True when any BEFORE hook is registered — the refusal-capable kind. #931:\n * the atomic-commit eligibility gate keys on this alone; after-hooks are\n * observers and fire post-finalize on the atomic path instead of gating it.\n */\n get hasBeforeHandlers(): boolean { return this.#before.length > 0 }\n\n onBeforeWrite(handler: WriteHook): Unsubscribe {\n this.#before.push(handler)\n return () => { const i = this.#before.indexOf(handler); if (i >= 0) this.#before.splice(i, 1) }\n }\n\n onAfterWrite(handler: WriteHook): Unsubscribe {\n this.#after.push(handler)\n return () => { const i = this.#after.indexOf(handler); if (i >= 0) this.#after.splice(i, 1) }\n }\n\n /** Run before-hooks (awaited, in order). A throw propagates and aborts the write. */\n async runBefore(event: WriteEvent): Promise<void> {\n if (this.#before.length === 0) return\n this.#suppressed = true\n try {\n for (const h of this.#before.slice()) await h(event)\n } finally {\n this.#suppressed = false\n }\n }\n\n /** Run after-hooks (awaited, in order). Per-handler errors are warned, not thrown. */\n async runAfter(event: WriteEvent): Promise<void> {\n if (this.#after.length === 0) return\n this.#suppressed = true\n try {\n for (const h of this.#after.slice()) {\n try {\n await h(event)\n } catch (err) {\n console.warn(\n `[noy-db] onAfterWrite handler failed for ${event.collection}/${event.docId}: ` +\n (err instanceof Error ? err.message : String(err)),\n )\n }\n }\n } finally {\n this.#suppressed = false\n }\n }\n}\n","/**\n * Generic per-instance **observe** bus. Observe-class\n * services (devtools inspector, audit, sync-dirty notification) register\n * handlers against named lifecycle points instead of the kernel naming each\n * service. Mirrors the registry pattern of {@link WriteHookRegistry} but is\n * internal and keyed by lifecycle point.\n *\n * OBSERVE SEMANTICS: handlers react to a write that already happened. A\n * handler throw is warned, not propagated — it can never abort a write. Write-\n * *gating* services (guards, periods) need a throw-propagating gate bus.\n * Add observe points by extending {@link LifecycleEventMap}. Write-*gating*\n * services use the sibling gate API on this same class\n * (`registerGate`/`dispatchGate`, throw-propagating); see {@link GateEventMap}.\n *\n * @module\n */\nimport type { WriteEvent } from './write-hooks.js'\nimport type { Role } from '../../kernel/types.js'\n\n/** Typed map of OBSERVE lifecycle point → event payload. Extend by adding keys. */\nexport interface LifecycleEventMap {\n afterPut: WriteEvent\n afterDelete: WriteEvent\n}\n\nexport type LifecyclePoint = keyof LifecycleEventMap\nexport type BusHandler<P extends LifecyclePoint> = (event: LifecycleEventMap[P]) => void | Promise<void>\nexport type Unsubscribe = () => void\n\ntype AnyHandler = (event: unknown) => void | Promise<void>\n\n/** Payload for a `beforePut` gate — carries the data guards and periods need to validate or reject a write. */\nexport interface GatePutEvent {\n readonly op: 'create' | 'update'\n readonly vault: string\n readonly collection: string\n readonly docId: string\n /**\n * The record about to be written (pre schema-validation). Money fields\n * are presented in their canonical decoded form — equal on both\n * sides for an unchanged value, regardless of how the caller wrote them.\n */\n readonly incoming: unknown\n /**\n * Decrypted prior record, or null on create / when prior is unreadable.\n * Money fields are decoded to the canonical decimal `get()` shape, NOT\n * the stored scaled-int — `incoming[f] === existing[f]` holds\n * for an unchanged money field.\n */\n readonly existing: unknown\n /** Prior envelope version, or 0 when none. */\n readonly existingVersion: number\n /** Prior envelope timestamp (`_ts` ISO string), or undefined when none — periods compares against this. */\n readonly existingTs: string | undefined\n readonly userId: string\n readonly role: Role\n /**\n * Names of fields whose values are schema-owned computed fields for this\n * collection. Gate handlers (e.g. `frozenFields`) must skip these: the\n * incoming record is the raw user input (computed fields not yet evaluated),\n * so comparing `existing[computedField]` vs `incoming[computedField]`\n * would always see a change even when the computed result is unchanged.\n */\n readonly computedFieldNames?: ReadonlySet<string>\n}\n\n/** Payload for a `beforeDelete` gate. Like {@link GatePutEvent} without `incoming`. */\nexport interface GateDeleteEvent {\n readonly vault: string\n readonly collection: string\n readonly docId: string\n /** True for system-internal (housekeeping) deletes — handlers branch on this. */\n readonly internal: boolean\n /** Decrypted prior record; money fields decoded to the canonical `get()` shape. */\n readonly existing: unknown\n readonly existingVersion: number\n readonly existingTs: string | undefined\n readonly userId: string\n readonly role: Role\n}\n\n/** Typed map of GATE lifecycle point → event payload. Extend by adding keys. */\nexport interface GateEventMap {\n beforePut: GatePutEvent\n beforeDelete: GateDeleteEvent\n}\n\nexport type GatePoint = keyof GateEventMap\nexport type GateHandler<P extends GatePoint> = (event: GateEventMap[P]) => void | Promise<void>\n\n/**\n * Registration options for a gate handler.\n *\n * `needsPrior` (default `true`) declares whether the handler reads the\n * prior-derived event fields — `existing`, `existingVersion`, `existingTs`,\n * and (on `beforePut`) `op`. When EVERY handler registered at a point set\n * `needsPrior: false`, the write path skips the prior-read (store get +\n * decrypt) entirely and dispatches the event with `existing: null`,\n * `existingVersion: 0`, `existingTs: undefined` (and `op: 'create'` on\n * `beforePut`; a `beforeDelete` gate then also fires for delete-of-absent).\n * A handler that opts out MUST NOT rely on those fields. (#267 prior-read\n * elision — pure perf; one prior-needing handler restores the old behavior\n * for the whole point.)\n */\nexport interface GateRegisterOptions {\n readonly needsPrior?: boolean\n}\n\ntype GateEntry = { readonly fn: AnyHandler; readonly needsPrior: boolean }\n\nexport class ServiceBus {\n readonly #handlers = new Map<LifecyclePoint, AnyHandler[]>()\n readonly #gateHandlers = new Map<GatePoint, GateEntry[]>()\n #depth = 0\n\n /** Register a handler for an observe point. Returns an unsubscribe fn. */\n register<P extends LifecyclePoint>(point: P, handler: BusHandler<P>): Unsubscribe {\n let arr = this.#handlers.get(point)\n if (!arr) { arr = []; this.#handlers.set(point, arr) }\n arr.push(handler as AnyHandler)\n return () => {\n const a = this.#handlers.get(point)\n if (!a) return\n const i = a.indexOf(handler as AnyHandler)\n if (i >= 0) a.splice(i, 1)\n }\n }\n\n /** Cheap gate for the write path — true when any handler is registered for the point. */\n hasHandlers(point: LifecyclePoint): boolean {\n const a = this.#handlers.get(point)\n return a !== undefined && a.length > 0\n }\n\n /**\n * True while one or more dispatches are in flight. Backed by a depth counter\n * so that two concurrent async dispatches (`Promise.all([put('a'), put('b')])`\n * each captured `busAfterPut=true` at their respective put() tops while depth\n * was 0) both proceed independently — the counter stays > 0 until BOTH finish,\n * so any nested write attempted by a handler still sees `dispatching === true`\n * and is suppressed by the write-path gate in `collection.ts`\n * (`busAfterPut = hasHandlers('afterPut') && !dispatching`). Re-entrancy\n * suppression lives exclusively on that write-path gate; concurrent independent\n * dispatches must not drop each other's events.\n */\n get dispatching(): boolean { return this.#depth > 0 }\n\n /**\n * Dispatch in registration order, awaited. Per-handler errors are warned, not\n * thrown — an observe handler must never abort a completed write. A\n * re-entrancy guard suppresses nested firing so a handler that itself writes\n * cannot loop (same rationale as WriteHookRegistry.#suppressed).\n */\n async dispatch<P extends LifecyclePoint>(point: P, event: LifecycleEventMap[P]): Promise<void> {\n const a = this.#handlers.get(point)\n if (!a || a.length === 0) return\n this.#depth++\n try {\n for (const h of a.slice()) {\n try {\n await h(event)\n } catch (err) {\n console.warn(\n `[noy-db] service observe handler failed at ${point}: ` +\n (err instanceof Error ? err.message : String(err)),\n )\n }\n }\n } finally {\n this.#depth--\n }\n }\n\n /**\n * Register a write-gating handler. A throw from the handler ABORTS the\n * write. Returns an unsubscribe fn. See {@link GateRegisterOptions} for\n * the `needsPrior` prior-read declaration (#267).\n */\n registerGate<P extends GatePoint>(point: P, handler: GateHandler<P>, opts?: GateRegisterOptions): Unsubscribe {\n let arr = this.#gateHandlers.get(point)\n if (!arr) { arr = []; this.#gateHandlers.set(point, arr) }\n const entry: GateEntry = { fn: handler as AnyHandler, needsPrior: opts?.needsPrior !== false }\n arr.push(entry)\n return () => {\n const a = this.#gateHandlers.get(point)\n if (!a) return\n const i = a.indexOf(entry)\n if (i >= 0) a.splice(i, 1)\n }\n }\n\n /** Cheap gate for the write path — true when any gate handler is registered for the point. */\n hasGateHandlers(point: GatePoint): boolean {\n const a = this.#gateHandlers.get(point)\n return a !== undefined && a.length > 0\n }\n\n /**\n * True when at least one gate handler at `point` needs the prior record\n * (the default). False when the point has no handlers or every handler\n * registered with `needsPrior: false` — the write path then skips the\n * prior-read before dispatching (#267 prior-read elision).\n */\n gateNeedsPrior(point: GatePoint): boolean {\n const a = this.#gateHandlers.get(point)\n if (!a) return false\n return a.some((e) => e.needsPrior)\n }\n\n /**\n * Run gate handlers in registration order, awaited. Unlike `dispatch`\n * (observe), a handler throw is NOT swallowed — it PROPAGATES, aborting the\n * write before it reaches the store. The first throw stops the remaining\n * handlers (fail-fast). This is the seam guards/periods migrate onto.\n *\n * Note: gate handlers are validators that read, not write. A gate handler\n * that writes back into the same collection would re-enter the write path\n * and re-dispatch this point; loop-suppression for that case is deferred to\n * the migration slice (contract: gate handlers must not perform writes that\n * re-trigger their own point).\n */\n async dispatchGate<P extends GatePoint>(point: P, event: GateEventMap[P]): Promise<void> {\n const a = this.#gateHandlers.get(point)\n if (!a || a.length === 0) return\n for (const e of a.slice()) {\n await e.fn(event) // throw propagates → aborts the write\n }\n }\n}\n\n/** @deprecated Use ServiceBus. */\nexport const SubsystemBus = ServiceBus\n/** @deprecated Use ServiceBus. */\nexport type SubsystemBus = ServiceBus\n","/**\n * Multi-tab coordination: primary/secondary election (Web Locks)\n * + presence heartbeat (BroadcastChannel). Browser-only; opt-in; no-op\n * when the APIs are absent. The lock/channel interfaces are hub-local\n * (structurally compatible with @noy-db/by-peer + @noy-db/by-tabs, but\n * not imported — those packages depend on hub).\n */\nexport type TabRole = 'primary' | 'secondary' | 'unknown'\nexport interface TabPresence { readonly tabId: string; readonly lastSeen: number; readonly role: TabRole }\nexport type Unsubscribe = () => void\n\n/** Structural subset of the Web Locks API / by-peer's MinimalLockManager. */\nexport interface TabLockManager {\n request<T>(name: string, options: { mode?: 'exclusive' | 'shared'; signal?: AbortSignal }, callback: (lock: unknown) => Promise<T>): Promise<T>\n}\n\n/** Structural subset of by-peer's PeerChannel / a BroadcastChannel wrapper. */\nexport interface TabChannel {\n send(payload: string): void\n on(event: 'message', listener: (payload: string) => void): Unsubscribe\n on(event: 'close', listener: () => void): Unsubscribe\n close(): void\n readonly isOpen: boolean\n}\n\nexport interface TabCoordinationOptions {\n readonly lockManager?: TabLockManager\n readonly channel?: TabChannel\n readonly tabId?: string\n readonly lockName?: string\n readonly heartbeatMs?: number\n readonly staleMs?: number\n readonly now?: () => number\n /**\n * Close the channel on `dispose()`. Set this only for a channel the\n * coordinator owns (e.g. the one `defaultChannel()` created); leave it\n * false for a caller-injected channel so the coordinator never closes a\n * channel it didn't create. Default: false.\n */\n readonly closeChannelOnDispose?: boolean\n /**\n * Also propagate committed writes to other tabs. Default true:\n * when tab coordination is enabled and a channel is available, a write in\n * one tab refreshes that document in every other tab. Set false to opt out.\n */\n readonly propagateWrites?: boolean\n /**\n * Channel for write propagation — distinct from the presence\n * channel. Default: an inline BroadcastChannel on `noydb:tab-writes`.\n */\n readonly writeChannel?: TabChannel\n}\n\ninterface PresenceMsg { readonly kind: 'tab-presence'; readonly tabId: string; readonly lastSeen: number; readonly role: TabRole }\n\nexport class TabCoordinator {\n readonly tabId: string\n role: TabRole = 'unknown'\n readonly #lockManager: TabLockManager | undefined\n readonly #channel: TabChannel | undefined\n readonly #lockName: string\n readonly #heartbeatMs: number\n readonly #staleMs: number\n readonly #now: () => number\n readonly #peers = new Map<string, TabPresence>()\n readonly #roleHandlers = new Set<(r: TabRole) => void>()\n readonly #tabsHandlers = new Set<(t: TabPresence[]) => void>()\n #ac: AbortController | undefined\n #releaseLock: (() => void) | undefined\n #unsub: Unsubscribe | undefined\n #closeUnsub: Unsubscribe | undefined\n #timer: ReturnType<typeof setInterval> | undefined\n readonly #ownsChannel: boolean\n #started = false\n #disposed = false\n #lastTabsSig = ''\n\n constructor(opts: TabCoordinationOptions = {}) {\n this.tabId = opts.tabId ?? `tab-${Math.trunc((opts.now ?? (() => 0))())}-${cheapRand()}`\n this.#lockManager = opts.lockManager\n this.#channel = opts.channel\n this.#lockName = opts.lockName ?? 'noydb:tab-primary'\n this.#heartbeatMs = opts.heartbeatMs ?? 2_000\n this.#staleMs = opts.staleMs ?? 6_000\n this.#now = opts.now ?? (() => Date.now())\n this.#ownsChannel = opts.closeChannelOnDispose ?? false\n }\n\n start(): void {\n if (this.#disposed || this.#started) return\n this.#started = true\n if (this.#channel) {\n this.#unsub = this.#channel.on('message', (p) => this.#onMessage(p))\n this.#closeUnsub = this.#channel.on('close', () => this.#onChannelClose())\n this.#beat()\n this.#timer = setInterval(() => this.#tick(), this.#heartbeatMs)\n const t = this.#timer as unknown as { unref?: () => void }\n if (typeof t.unref === 'function') t.unref()\n }\n if (this.#lockManager) {\n this.#ac = new AbortController()\n this.#setRole('secondary')\n void this.#lockManager\n .request(this.#lockName, { mode: 'exclusive', signal: this.#ac.signal }, () => {\n this.#setRole('primary')\n return new Promise<void>((resolve) => { this.#releaseLock = resolve })\n })\n .catch(() => { /* aborted on dispose */ })\n }\n }\n\n activeTabs(): TabPresence[] {\n if (!this.#channel) return []\n const cutoff = this.#now() - this.#staleMs\n const self: TabPresence = { tabId: this.tabId, lastSeen: this.#now(), role: this.role }\n const out = [self, ...[...this.#peers.values()].filter((p) => p.lastSeen >= cutoff)]\n return out.sort((a, b) => a.tabId.localeCompare(b.tabId))\n }\n\n onTabRoleChange(fn: (r: TabRole) => void): Unsubscribe { this.#roleHandlers.add(fn); return () => this.#roleHandlers.delete(fn) }\n onActiveTabsChange(fn: (t: TabPresence[]) => void): Unsubscribe { this.#tabsHandlers.add(fn); return () => this.#tabsHandlers.delete(fn) }\n\n dispose(): void {\n if (this.#disposed) return\n this.#disposed = true\n this.#releaseLock?.()\n this.#ac?.abort()\n if (this.#timer) { clearInterval(this.#timer); this.#timer = undefined }\n this.#unsub?.()\n this.#closeUnsub?.()\n if (this.#ownsChannel) this.#channel?.close()\n this.#setRole('unknown')\n }\n\n /** @internal test seam — broadcast one heartbeat now. */\n _beat(): void { this.#beat() }\n\n #tick(): void {\n this.#prune()\n this.#emitTabs()\n this.#beat()\n }\n\n #beat(): void {\n if (this.#disposed) return\n if (!this.#channel || !this.#channel.isOpen) return\n const msg: PresenceMsg = { kind: 'tab-presence', tabId: this.tabId, lastSeen: this.#now(), role: this.role }\n this.#channel.send(JSON.stringify(msg))\n }\n\n #onChannelClose(): void {\n if (this.#timer) { clearInterval(this.#timer); this.#timer = undefined }\n this.#setRole('unknown')\n }\n\n #onMessage(payload: string): void {\n let msg: unknown\n try { msg = JSON.parse(payload) } catch { return }\n if (!isPresenceMsg(msg) || msg.tabId === this.tabId) return\n this.#peers.set(msg.tabId, { tabId: msg.tabId, lastSeen: msg.lastSeen, role: msg.role })\n this.#prune()\n this.#emitTabs()\n }\n\n #prune(): void {\n const cutoff = this.#now() - this.#staleMs\n for (const [id, p] of this.#peers) if (p.lastSeen < cutoff) this.#peers.delete(id)\n }\n\n #setRole(role: TabRole): void {\n if (this.role === role) return\n this.role = role\n for (const h of this.#roleHandlers) h(role)\n this.#beat() // announce promptly\n this.#emitTabs()\n }\n\n #emitTabs(): void {\n const tabs = this.activeTabs()\n const sig = tabs.map((t) => `${t.tabId}:${t.role}`).join('|')\n if (sig === this.#lastTabsSig) return\n this.#lastTabsSig = sig\n for (const h of this.#tabsHandlers) h(tabs)\n }\n}\n\nfunction isPresenceMsg(x: unknown): x is PresenceMsg {\n if (x === null || typeof x !== 'object') return false\n const o = x as Record<string, unknown>\n return o['kind'] === 'tab-presence'\n && typeof o['tabId'] === 'string'\n && typeof o['lastSeen'] === 'number'\n && (o['role'] === 'primary' || o['role'] === 'secondary' || o['role'] === 'unknown')\n}\n\nfunction cheapRand(): string {\n // Non-crypto, non-Date id suffix for a default tabId; callers pass a stable tabId in tests.\n const g = globalThis as { crypto?: { randomUUID?: () => string } }\n return g.crypto?.randomUUID ? g.crypto.randomUUID().slice(0, 8) : 'anon'\n}\n\n/** Browser default lock manager (navigator.locks) or undefined. */\nexport function defaultLockManager(): TabLockManager | undefined {\n // Gate on `window` — a real browser signal. Node 21+ exposes a global\n // `navigator`, and Node 24+ surfaces `navigator.locks` (Web Locks), so the\n // presence of navigator.locks alone is NOT a browser signal; without this\n // gate we'd run the role election in Node. Symmetric with defaultChannel().\n if (typeof (globalThis as { window?: unknown }).window === 'undefined') return undefined\n const nav = (globalThis as { navigator?: { locks?: TabLockManager } }).navigator\n return nav?.locks\n}\n\n/** Browser default channel: an inline BroadcastChannel wrapper, or undefined. */\nexport function defaultChannel(name = 'noydb:tabs'): TabChannel | undefined {\n // Gate on `window` — a real browser signal. Modern Node exposes a global\n // BroadcastChannel (worker_threads), so presence of the constructor alone is\n // NOT a browser signal; without this gate we'd start a heartbeat in Node.\n // Symmetric with defaultLockManager()'s navigator gate.\n if (typeof (globalThis as { window?: unknown }).window === 'undefined') return undefined\n const Bc = (globalThis as { BroadcastChannel?: typeof BroadcastChannel }).BroadcastChannel\n if (!Bc) return undefined\n const bc = new Bc(name)\n const msgListeners = new Set<(p: string) => void>()\n bc.onmessage = (e: MessageEvent) => { for (const l of msgListeners) l(String(e.data)) }\n return {\n isOpen: true,\n send(payload) { bc.postMessage(payload) },\n on(event, listener) {\n if (event === 'message') { const l = listener as (p: string) => void; msgListeners.add(l); return () => msgListeners.delete(l) }\n return () => {}\n },\n close() { msgListeners.clear(); bc.close() },\n }\n}\n","/**\n * Cross-tab write propagation. A role-agnostic relay: it broadcasts\n * a ciphertext-blind signal ({vault, collection, docId, action}) for every\n * locally-committed write (via onAfterWrite), and on receiving a peer\n * tab's signal it asks the host to refresh that document's in-memory view by\n * re-reading the shared encrypted store. Nothing decrypted crosses the wire.\n */\nimport type { TabChannel, Unsubscribe } from './tab-coordination.js'\nimport type { WriteEvent } from '../port/with/write-hooks.js'\n\nexport interface TabWriteMsg {\n readonly kind: 'tab-write'\n readonly writerId: string\n readonly vault: string\n readonly collection: string\n readonly docId: string\n readonly action: 'put' | 'delete'\n readonly baseV: number\n readonly v: number\n}\n\nexport interface CrossTabWriteRelayOptions {\n /** The broadcast channel (its own — distinct from the presence channel). */\n readonly channel: TabChannel\n /** This tab's id — outgoing signals carry it; incoming self-signals are ignored. */\n readonly writerId: string\n /** Subscribe to committed writes (the host's onAfterWrite). */\n readonly subscribeAfterWrite: (handler: (e: WriteEvent) => void) => Unsubscribe\n /** Refresh a document's in-memory view from the shared store. */\n readonly applyRemoteWrite: (vault: string, collection: string, docId: string, action: 'put' | 'delete') => void | Promise<void>\n /** Report a detected conflict (host captures + converges + emits). */\n readonly reportConflict?: (vault: string, collection: string, docId: string, action: 'put' | 'delete', baseV: number, v: number, ownV: number) => void | Promise<void>\n /** Close the channel on dispose (only when the relay created it). Default false. */\n readonly closeChannelOnDispose?: boolean\n}\n\nexport class CrossTabWriteRelay {\n readonly #channel: TabChannel\n readonly #writerId: string\n readonly #subscribeAfterWrite: (handler: (e: WriteEvent) => void) => Unsubscribe\n readonly #applyRemoteWrite: (vault: string, collection: string, docId: string, action: 'put' | 'delete') => void | Promise<void>\n readonly #reportConflict: CrossTabWriteRelayOptions['reportConflict']\n readonly #ledger = new Map<string, number>()\n readonly #ownsChannel: boolean\n #unsubMsg: Unsubscribe | undefined\n #unsubWrite: Unsubscribe | undefined\n #started = false\n #disposed = false\n\n constructor(opts: CrossTabWriteRelayOptions) {\n this.#channel = opts.channel\n this.#writerId = opts.writerId\n this.#subscribeAfterWrite = opts.subscribeAfterWrite\n this.#applyRemoteWrite = opts.applyRemoteWrite\n this.#reportConflict = opts.reportConflict\n this.#ownsChannel = opts.closeChannelOnDispose ?? false\n }\n\n start(): void {\n if (this.#started || this.#disposed) return\n this.#started = true\n this.#unsubMsg = this.#channel.on('message', (p) => this.#onMessage(p))\n this.#unsubWrite = this.#subscribeAfterWrite((e) => this.#onLocalWrite(e))\n }\n\n dispose(): void {\n if (this.#disposed) return\n this.#disposed = true\n this.#unsubWrite?.()\n this.#unsubMsg?.()\n if (this.#ownsChannel) this.#channel.close()\n }\n\n #onLocalWrite(e: WriteEvent): void {\n if (this.#disposed || !this.#channel.isOpen) return\n this.#ledger.set(ledgerKey(e.vault, e.collection, e.docId), e.version)\n const action: 'put' | 'delete' = e.op === 'delete' ? 'delete' : 'put'\n const msg: TabWriteMsg = { kind: 'tab-write', writerId: this.#writerId, vault: e.vault, collection: e.collection, docId: e.docId, action, baseV: e.baseVersion, v: e.version }\n this.#channel.send(JSON.stringify(msg))\n }\n\n #onMessage(payload: string): void {\n if (this.#disposed) return\n let msg: unknown\n try { msg = JSON.parse(payload) } catch { return }\n if (!isTabWriteMsg(msg) || msg.writerId === this.#writerId) return\n const key = ledgerKey(msg.vault, msg.collection, msg.docId)\n const ownV = this.#ledger.get(key)\n if (ownV !== undefined && msg.baseV < ownV && this.#reportConflict) {\n void Promise.resolve(this.#reportConflict(msg.vault, msg.collection, msg.docId, msg.action, msg.baseV, msg.v, ownV)).catch((err) => {\n console.warn(`[noy-db] cross-tab conflict report failed for ${msg.collection}/${msg.docId}: ` + (err instanceof Error ? err.message : String(err)))\n })\n return\n }\n if (ownV !== undefined && msg.baseV >= ownV) this.#ledger.set(key, msg.v) // remote incorporated our write → advance\n void Promise.resolve(this.#applyRemoteWrite(msg.vault, msg.collection, msg.docId, msg.action)).catch((err) => {\n console.warn(`[noy-db] cross-tab apply failed for ${msg.collection}/${msg.docId}: ` + (err instanceof Error ? err.message : String(err)))\n })\n }\n}\n\nfunction ledgerKey(vault: string, collection: string, docId: string): string {\n // NUL separator: it cannot appear in a vault/collection/docId, so keys never collide.\n return `${vault}\\0${collection}\\0${docId}`\n}\n\nfunction isTabWriteMsg(x: unknown): x is TabWriteMsg {\n if (x === null || typeof x !== 'object') return false\n const o = x as Record<string, unknown>\n return o['kind'] === 'tab-write'\n && typeof o['writerId'] === 'string'\n && typeof o['vault'] === 'string'\n && typeof o['collection'] === 'string'\n && typeof o['docId'] === 'string'\n && (o['action'] === 'put' || o['action'] === 'delete')\n && typeof o['baseV'] === 'number'\n && typeof o['v'] === 'number'\n}\n","/**\n * Per-vault tier-3 (PIN / quick-resume) state.\n *\n * The hub holds a `PinResumeState`-shaped record in memory, keyed by\n * vault. `enrollUnlock` populates it; `unlockViaPin` consumes it via\n * `@noy-db/on-pin`'s `resumePin`. The cached state is wiped when the\n * idle timer fires or `db.close()` is called.\n *\n * Importantly, this module does NOT depend on `@noy-db/on-pin` — the\n * caller passes the already-built state in. That keeps the hub's\n * `peerDependencies` empty for tier-3 and lets developers swap the\n * primitive (e.g. an OS biometric in place of a PIN).\n *\n * @module\n */\n\n/**\n * Opaque `PinResumeState`-compatible record. Mirrored from\n * `@noy-db/on-pin/PinResumeState`. The hub treats the contents as\n * a black box.\n */\nexport interface QuickUnlockState {\n readonly _noydb_on_pin: 1\n readonly salt: string\n readonly iv: string\n readonly wrappedKeyring: string\n readonly expiresAt: string\n readonly maxAttempts: number\n attempts: number\n}\n\n/** In-memory store for tier-3 unlock state, keyed by vault. */\nexport class QuickUnlockStore {\n private readonly states = new Map<string, QuickUnlockState>()\n private readonly timers = new Map<string, ReturnType<typeof setTimeout>>()\n\n /**\n * Register a quick-unlock state for a vault. Replaces any existing\n * state. Schedules an automatic clear when the state's `expiresAt`\n * elapses.\n */\n set(vault: string, state: QuickUnlockState): void {\n this.clearTimer(vault)\n this.states.set(vault, state)\n const ttl = new Date(state.expiresAt).getTime() - Date.now()\n if (ttl > 0) {\n const timer = setTimeout(() => this.delete(vault), ttl)\n this.timers.set(vault, timer)\n }\n }\n\n /** Read the state for a vault. Returns undefined when none is registered. */\n get(vault: string): QuickUnlockState | undefined {\n return this.states.get(vault)\n }\n\n /** Drop the state for a vault. Cancels the auto-clear timer. */\n delete(vault: string): void {\n this.clearTimer(vault)\n this.states.delete(vault)\n }\n\n /** Drop every cached state. Called on `db.close()`. */\n clear(): void {\n for (const vault of this.states.keys()) {\n this.clearTimer(vault)\n }\n this.states.clear()\n }\n\n private clearTimer(vault: string): void {\n const t = this.timers.get(vault)\n if (t) clearTimeout(t)\n this.timers.delete(vault)\n }\n}\n","/**\n * Owns timers + unload hooks for the automatic snapshot cadence. Distinct from\n * the sync `SyncScheduler` (whose push/pull/dirty-count shape doesn't map to\n * snapshots) — it borrows only the policy vocabulary. Delegates the actual\n * snapshot work to `callbacks.fire()`.\n */\nimport type { SnapshotPolicy } from './policy.js'\n\nexport interface SnapshotSchedulerCallbacks {\n /** Fire one auto-snapshot cycle (per dirty vault). Swallows its own per-vault errors. */\n fire(): Promise<void>\n /** Number of vaults with pending writes since the last fire. */\n pendingCount(): number\n}\n\nexport class SnapshotScheduler {\n private readonly policy: SnapshotPolicy\n private readonly callbacks: SnapshotSchedulerCallbacks\n\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n private intervalTimer: ReturnType<typeof setInterval> | null = null\n private lastFireTime = 0\n private firing = false\n private started = false\n\n private readonly boundVisibility: (() => void) | null = null\n private readonly boundUnload: (() => void) | null = null\n\n constructor(policy: SnapshotPolicy, callbacks: SnapshotSchedulerCallbacks) {\n this.policy = policy\n this.callbacks = callbacks\n if (this.shouldRegisterUnload()) {\n this.boundVisibility = this.handleVisibility.bind(this)\n this.boundUnload = this.handleUnload.bind(this)\n }\n }\n\n start(): void {\n if (this.started) return\n this.started = true\n\n if (this.policy.mode === 'interval') {\n const ms = this.policy.intervalMs ?? 300_000\n this.intervalTimer = setInterval(() => { void this.execFire() }, ms)\n }\n\n if (this.boundVisibility && this.boundUnload) {\n if (typeof document !== 'undefined') {\n document.addEventListener('visibilitychange', this.boundVisibility)\n }\n if (typeof globalThis.addEventListener === 'function') {\n globalThis.addEventListener('pagehide', this.boundUnload)\n }\n if (typeof process !== 'undefined' && typeof process.on === 'function') {\n process.on('beforeExit', this.boundUnload)\n }\n }\n }\n\n stop(): void {\n if (!this.started) return\n this.started = false\n if (this.debounceTimer) { clearTimeout(this.debounceTimer); this.debounceTimer = null }\n if (this.intervalTimer) { clearInterval(this.intervalTimer); this.intervalTimer = null }\n\n if (this.boundVisibility && this.boundUnload) {\n if (typeof document !== 'undefined') {\n document.removeEventListener('visibilitychange', this.boundVisibility)\n }\n if (typeof globalThis.removeEventListener === 'function') {\n globalThis.removeEventListener('pagehide', this.boundUnload)\n }\n if (typeof process !== 'undefined' && typeof process.removeListener === 'function') {\n process.removeListener('beforeExit', this.boundUnload)\n }\n }\n }\n\n notifyChange(): void {\n if (!this.started) return\n if (this.policy.mode === 'debounce') this.resetDebounce()\n }\n\n private resetDebounce(): void {\n if (this.debounceTimer) clearTimeout(this.debounceTimer)\n const ms = this.policy.debounceMs ?? 30_000\n this.debounceTimer = setTimeout(() => {\n this.debounceTimer = null\n void this.execFire()\n }, ms)\n }\n\n private async execFire(): Promise<void> {\n if (this.firing) return\n\n const minInterval = this.policy.minIntervalMs ?? 0\n if (minInterval > 0 && Date.now() - this.lastFireTime < minInterval) {\n if (this.policy.mode === 'debounce') this.resetDebounce()\n return\n }\n if (this.callbacks.pendingCount() === 0) return\n\n this.firing = true\n try {\n await this.callbacks.fire()\n this.lastFireTime = Date.now()\n } catch {\n // fire() swallows per-vault errors; this guards the contract regardless.\n } finally {\n this.firing = false\n }\n }\n\n private handleVisibility(): void {\n if (typeof document !== 'undefined' && document.visibilityState === 'hidden') {\n this.flush()\n }\n }\n\n private handleUnload(): void {\n this.flush()\n }\n\n private flush(): void {\n if (this.callbacks.pendingCount() === 0) return\n void this.callbacks.fire().catch(() => {})\n }\n\n private shouldRegisterUnload(): boolean {\n return this.policy.onUnload ?? (this.policy.mode !== 'manual')\n }\n}\n","/**\n * Noydb-side snapshot facade.\n *\n * Holds the on-demand checkpoint (`snapshot`), listing (`listSnapshots`),\n * restore (`restoreSnapshot`), the automatic-snapshot cadence wiring\n * (`initCadence`), the dirty-vault set, and the cadence scheduler;\n * `Noydb.close()` calls {@link stop}. Every `Noydb` dependency arrives via\n * {@link NoydbSnapshotsDeps}.\n *\n * Internal service — reached through `noydb.snapshot(...)` etc.\n */\nimport { NO_SNAPSHOTS, type SnapshotsStrategy, type SnapshotMeta } from './strategy.js'\nimport { SnapshotScheduler } from './scheduler.js'\nimport { ValidationError } from '../../kernel/errors.js'\nimport type { Vault } from '../../kernel/vault.js'\nimport type { WriteHook, Unsubscribe } from '../../port/with/write-hooks.js'\n\n/** Everything the moving snapshot methods touched on the Noydb instance's `this.*`. */\nexport interface NoydbSnapshotsDeps {\n /** Resolved snapshot strategy (NO_SNAPSHOTS when not configured). */\n readonly strategy: SnapshotsStrategy\n /** Acting user id, used as the snapshot `by`. */\n readonly user: string\n /** Whether the owning instance has been closed. */\n isClosed(): boolean\n /** Resolve an open vault from the instance's vault cache. */\n getVault(name: string): Vault | undefined\n /** Subscribe to post-write events (cadence dirty-marking). */\n onAfterWrite(handler: WriteHook): Unsubscribe\n}\n\nexport class NoydbSnapshots {\n private scheduler: SnapshotScheduler | null = null\n private readonly dirtyVaults = new Set<string>()\n\n constructor(private readonly deps: NoydbSnapshotsDeps) {\n this.initCadence()\n }\n\n /**\n * Take an on-demand checkpoint of the given vault.\n * Requires `snapshotsStrategy: withSnapshots({ store })` in `createNoydb`.\n * @throws ValidationError when the vault is not open\n */\n async snapshot(vault: string, opts?: { label?: string; note?: string }): Promise<SnapshotMeta> {\n if (this.deps.isClosed()) throw new ValidationError('Instance is closed')\n const v = this.deps.getVault(vault)\n if (!v) {\n throw new ValidationError(\n `Vault \"${vault}\" is not open. Call openVault() first.`,\n )\n }\n return this.deps.strategy.snapshot(v, this.deps.user, opts)\n }\n\n /**\n * Wire the automatic-snapshot cadence when a non-manual `snapshotPolicy` is\n * configured. Subscribes to `onAfterWrite` to mark the written vault dirty and\n * nudge the scheduler; the scheduler fires `autoSnapshot()` per dirty vault.\n * No-op for `mode:'manual'` or no policy.\n */\n private initCadence(): void {\n const policy = this.deps.strategy.policy\n if (!policy || !policy.mode || policy.mode === 'manual') return\n\n const scheduler = new SnapshotScheduler(policy, {\n fire: async () => {\n const names = [...this.dirtyVaults]\n this.dirtyVaults.clear()\n for (const name of names) {\n const v = this.deps.getVault(name)\n if (!v) continue\n try {\n await this.deps.strategy.autoSnapshot(v, this.deps.user)\n } catch (err) {\n // Keep the vault pending so a later cadence tick (interval) or the\n // next write (debounce) retries; a failed auto-snapshot is logged,\n // never thrown (it runs inside the after-write hook contract).\n this.dirtyVaults.add(name)\n console.warn(\n `[noy-db] auto-snapshot failed for vault \"${name}\": ` +\n (err instanceof Error ? err.message : String(err)),\n )\n }\n }\n },\n pendingCount: () => this.dirtyVaults.size,\n })\n\n this.deps.onAfterWrite((event) => {\n this.dirtyVaults.add(event.vault)\n scheduler.notifyChange()\n })\n scheduler.start()\n this.scheduler = scheduler\n }\n\n /**\n * List all snapshots for the given vault, newest first.\n * Reads only the sidecar index — does not download snapshot bytes.\n */\n async listSnapshots(vault: string): Promise<SnapshotMeta[]> {\n if (this.deps.isClosed()) throw new ValidationError('Instance is closed')\n return this.deps.strategy.listSnapshots(vault)\n }\n\n /**\n * Restore the vault to a previously snapshotted state.\n * Runs `verifyBackupIntegrity()` automatically on restore.\n * @throws SnapshotNotFoundError when `version` doesn't exist in the store\n * @throws ValidationError when the vault is not open\n */\n async restoreSnapshot(vault: string, version: string): Promise<void> {\n if (this.deps.isClosed()) throw new ValidationError('Instance is closed')\n const v = this.deps.getVault(vault)\n if (!v) {\n throw new ValidationError(\n `Vault \"${vault}\" is not open. Call openVault() first.`,\n )\n }\n return this.deps.strategy.restoreSnapshot(v, version)\n }\n\n /** Stop the cadence scheduler (called from `Noydb.close()`). */\n stop(): void {\n this.scheduler?.stop()\n this.scheduler = null\n }\n}\n\nexport { NO_SNAPSHOTS }\n","import type { NoydbStore, VaultSnapshot, EncryptedEnvelope, StoreTime, ListPageResult } from './types.js'\nimport { ConflictError } from './errors.js'\n\n/**\n * Built-in in-memory store — the kernel's zero-config default.\n *\n * Nested `Map`s: `vault → collection → id → envelope`. Non-persistent\n * (data is lost on process exit). A conformant 6-method {@link NoydbStore}\n * with CAS atomicity and a monotonic store clock — the kernel version of\n * `@noy-db/to-memory`'s core, so `createNoydb()` works with no store package.\n *\n * Portable: imports only `types` + `errors` (no crypto primitive) — passes\n * the `stores-ciphertext-only` architecture guard.\n *\n * Implements the 6-method core only (no optional `listVaults`/`ping`/`tx`),\n * so `Noydb.listAccessibleVaults()` throws its documented capability error\n * rather than enumerating vaults under the default store.\n */\nexport function memoryStore(): NoydbStore {\n const store = new Map<string, Map<string, Map<string, EncryptedEnvelope>>>()\n let clock = 0\n const epsilon = 0 // matches @noy-db/to-memory's default clockUncertainty; non-overlapping intervals\n\n const coll = (vault: string, collection: string): Map<string, EncryptedEnvelope> => {\n let comp = store.get(vault)\n if (!comp) { comp = new Map(); store.set(vault, comp) }\n let c = comp.get(collection)\n if (!c) { c = new Map(); comp.set(collection, c) }\n return c\n }\n\n return {\n name: 'memory',\n capabilities: { casAtomic: true, serverWriteTime: true, auth: { kind: 'none', required: false, flow: 'static' } },\n\n async getStoreTime(): Promise<StoreTime> {\n const now = ++clock\n return { earliest: now - epsilon, latest: now + epsilon }\n },\n\n async get(vault, collection, id) {\n return store.get(vault)?.get(collection)?.get(id) ?? null\n },\n\n async put(vault, collection, id, envelope, expectedVersion) {\n const c = coll(vault, collection)\n const existing = c.get(id)\n if (expectedVersion !== undefined && existing && existing._v !== expectedVersion) {\n throw new ConflictError(existing._v, `Version conflict: expected ${expectedVersion}, found ${existing._v}`)\n }\n c.set(id, envelope)\n },\n\n async delete(vault, collection, id) {\n store.get(vault)?.get(collection)?.delete(id)\n },\n\n async list(vault, collection) {\n const c = store.get(vault)?.get(collection)\n return c ? [...c.keys()] : []\n },\n\n async loadAll(vault): Promise<VaultSnapshot> {\n const comp = store.get(vault)\n const snapshot: VaultSnapshot = {}\n if (comp) {\n for (const [name, c] of comp) {\n if (name.startsWith('_')) continue // system collections hydrate lazily\n const records: Record<string, EncryptedEnvelope> = {}\n for (const [id, envelope] of c) records[id] = envelope\n snapshot[name] = records\n }\n }\n return snapshot\n },\n\n async saveAll(vault, data: VaultSnapshot) {\n const comp = store.get(vault)\n if (comp) for (const k of [...comp.keys()]) if (!k.startsWith('_')) comp.delete(k)\n for (const [name, records] of Object.entries(data)) {\n const c = coll(vault, name)\n for (const [id, envelope] of Object.entries(records)) c.set(id, envelope)\n }\n },\n\n async listPage(vault, collection, cursor, limit = 100): Promise<ListPageResult> {\n const c = store.get(vault)?.get(collection)\n if (!c) return { items: [], nextCursor: null }\n const ids = [...c.keys()].sort()\n const start = cursor ? parseInt(cursor, 10) : 0\n const end = Math.min(start + limit, ids.length)\n const items: Array<{ id: string; envelope: EncryptedEnvelope }> = []\n for (let i = start; i < end; i++) {\n const id = ids[i]!\n const envelope = c.get(id)\n if (envelope) items.push({ id, envelope })\n }\n return { items, nextCursor: end < ids.length ? String(end) : null }\n },\n }\n}\n","/**\n * Noydb-side auth / recovery / enrollment facade.\n *\n * Holds the tier-2 authenticator enrollment/unlock wrappers, WebAuthn\n * enrollment, auth-config introspection, the tier-1 secret\n * rotate/recover flows, the paper/Shamir recovery rotate/enroll flows,\n * managed-secret recovery, peer-recovery, tier-3 PIN unlock, and the\n * public `getKeyring` accessor.\n *\n * The near-parallel rotate/recover variants (managed vs user vs paper vs\n * Shamir) are deliberately NOT consolidated. The\n * keyring/active-tier/quick-unlock/policy caches stay `Noydb`-resident\n * (shared by the kernel's unlock path) and arrive **by reference** through\n * {@link TeamFacadeDeps}; the keyring-unlock path (`getKeyringInternal`),\n * the policy gate (`checkGate`), the managed-recovery enrolment check\n * (`assertRecoveryEnrolled`), `openVault`, and the one-shot\n * managed-recovery skip flag stay kernel-resident and arrive as callbacks.\n *\n * Internal service — reached through `noydb.team.rotateSecret(...)` etc.\n */\nimport type { NoydbOptions, NoydbStore, KeyringAuthenticator } from '../../kernel/types.js'\nimport type { RotateResult, RotateKeysOptions } from './keyring.js'\nimport { ValidationError } from '../../kernel/errors.js'\nimport {\n rotateSecret as keyringRotateSecret,\n recoverSecret as keyringRecoverSecret,\n type RotateSecretInput,\n type RecoverSecretInput,\n type RecoverSecretResult,\n type RotateRecoveryOptions,\n type RotateRecoveryResult,\n type EnrollRecoveryResult,\n type RecoveryEnrollmentInput,\n type RecoveryProof,\n} from './rotate-recover.js'\nimport {\n recoverUser as keyringRecoverUser,\n type RecoverUserOptions,\n} from './peer-recover.js'\nimport {\n loadPaperRecoveryEntries,\n savePaperRecoveryEntries,\n mintPaperRecoveryEntry,\n type PaperRecoveryEntry,\n loadShamirRecoveryEntries,\n saveShamirRecoveryEntries,\n mintShamirRecoveryEntry,\n type ShamirRecoveryEntry,\n} from './recovery.js'\nimport { saveSealedSecret } from './managed-secret.js'\nimport type { ShamirRecoveryProvider } from './shamir-recovery-provider.js'\nimport { generateULID } from '../../with-pod/ulid.js'\nimport { RecoveryProfileNotImplementedError, PolicyDeniedError } from '../../kernel/errors.js'\nimport {\n describeAuthConfig as fnDescribeAuthConfig,\n diagramAuthConfig as fnDiagramAuthConfig,\n describeUserAuth as fnDescribeUserAuth,\n describeAllUsersAuth as fnDescribeAllUsersAuth,\n} from '../auth-introspection/index.js'\nimport type { Vault } from '../../kernel/vault.js'\nimport type { UnlockedKeyring } from './keyring.js'\nimport {\n enrollAuthenticator as keyringEnrollAuthenticator,\n removeAuthenticator as keyringRemoveAuthenticator,\n updateAuthenticator as keyringUpdateAuthenticator,\n findAuthenticator,\n type EnrollAuthenticatorOptions,\n type UpdateAuthenticatorOptions,\n} from './authenticators.js'\nimport type { QuickUnlockStore, QuickUnlockState } from '../session/unlock-state.js'\nimport type { SecretPolicy } from '../../kernel/validation.js'\nimport type {\n ActiveTier,\n FactorProofBundle,\n GateName,\n GrantOptions,\n ReAuthOperation,\n RevokeOptions,\n VaultPolicy,\n} from '../../kernel/types.js'\n\n/** NoydbOptions with the store resolved to a non-optional value (internal use only). */\ntype ResolvedNoydbOptions = NoydbOptions & { readonly store: NoydbStore }\n\n/** Everything the moving auth/recovery/enrollment methods touched on the Noydb instance's `this.*`. */\nexport interface TeamFacadeDeps {\n /** Resolved Noydb options (store, user, secretMode, sealingKey, shamirRecovery, …). */\n readonly options: ResolvedNoydbOptions\n /** Live unlocked-keyring cache (Noydb-resident; read/written by reference). */\n readonly keyringCache: Map<string, UnlockedKeyring>\n /** Per-vault active session tier (Noydb-resident; read/written by reference). */\n readonly activeTier: Map<string, ActiveTier>\n /** Per-vault tier-3 quick-unlock state (Noydb-resident; read/written by reference). */\n readonly quickUnlock: QuickUnlockStore\n /** Per-vault loaded policy cache (Noydb-resident; read/written by reference). */\n readonly policyCache: Map<string, VaultPolicy>\n /** Evaluate the policy gate for an operation (kernel-resident). */\n checkGate(vault: string, gate: GateName, factors?: FactorProofBundle): Promise<void>\n /** Legacy `requireReAuthFor` session-policy check (kernel-resident). */\n checkPolicyOperation(vault: string, op: ReAuthOperation): void\n /** Live-reference keyring unlock path (kernel-resident). */\n getKeyringInternal(\n vault: string,\n opts?: { create: boolean },\n ): Promise<UnlockedKeyring>\n /** Managed-recovery enrolment check (kernel-resident). */\n assertRecoveryEnrolled(\n vault: string,\n policy: VaultPolicy,\n opts?: { skipManagedCheck?: boolean },\n ): Promise<void>\n /** Open (or create) a vault (kernel-resident). */\n openVault(vault: string, opts?: { locale?: string }): Promise<Vault>\n /** Toggle the one-shot managed-mode strong-recovery bypass flag (kernel-resident). */\n setSkipNextManagedRecoveryCheck(value: boolean): void\n}\n\nexport class TeamFacade {\n constructor(private readonly deps: TeamFacadeDeps) {}\n\n private requireShamirProvider(): ShamirRecoveryProvider {\n const p = this.deps.options.shamirRecovery\n if (!p) {\n throw new Error(\n \"shamir recovery requires a ShamirRecoveryProvider — pass \"\n + \"shamirRecovery: shamirRecoveryProvider() from '@noy-db/on-shamir' to createNoydb()\",\n )\n }\n return p\n }\n\n // ─── Multi-user grant / revoke / rotate runners (#267 team split) ──\n //\n // The kernel's `db.grant` / `db.revoke` / `db.rotate` route through the\n // TeamStrategy seam, which calls back here with the keyring ENGINE as an\n // argument (statically linked in `active.ts`, i.e. only in the\n // `@noy-db/hub/team` subpath bundle). These runners own the policy-gate +\n // keyring plumbing so the kernel keeps single-line delegators and the\n // engines stay off the single-user floor.\n\n /** Gate + run a `grant` engine. See `Noydb.grant` for the public contract. */\n async runGrant(\n engine: (adapter: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, options: GrantOptions) => Promise<void>,\n vault: string,\n options: GrantOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n this.deps.checkPolicyOperation(vault, 'grant')\n await this.deps.checkGate(vault, 'enroll-user', factors)\n const keyring = await this.deps.getKeyringInternal(vault)\n await engine(this.deps.options.store, vault, keyring, options)\n }\n\n /** Gate + run a `revoke` engine. See `Noydb.revoke` for the public contract. */\n async runRevoke(\n engine: (adapter: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, options: RevokeOptions) => Promise<void>,\n vault: string,\n options: RevokeOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n this.deps.checkPolicyOperation(vault, 'revoke')\n await this.deps.checkGate(vault, 'revoke-user', factors)\n const keyring = await this.deps.getKeyringInternal(vault)\n await engine(this.deps.options.store, vault, keyring, options)\n }\n\n /** Gate + run a `rotateKeys` engine. See `Noydb.rotate` for the public contract. */\n async runRotate(\n engine: (store: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, opts: RotateKeysOptions) => Promise<RotateResult>,\n vault: string,\n collections: string[],\n ): Promise<RotateResult> {\n this.deps.checkPolicyOperation(vault, 'rotate')\n const keyring = await this.deps.getKeyringInternal(vault)\n const result = await engine(this.deps.options.store, vault, keyring, { collections })\n // Refresh the cached keyring so subsequent operations see the\n // freshly-rotated DEKs. Without this, `ensureCollectionDEK` on\n // the next Collection access would still hold the old ones.\n this.deps.keyringCache.set(vault, keyring)\n return result\n }\n\n // ─── Tier-2 enroll / remove ─────────────────────────────────────\n /**\n * Add a tier-2 authenticator slot to the calling user's keyring.\n * Each slot independently wraps the SAME KEK under a method-specific\n * key — adding a slot is a constant-time keyring write.\n *\n * The wrapping ciphertext is produced by the corresponding\n * `@noy-db/on-*` package (e.g. `enrollPasswordAuthenticator` from\n * `@noy-db/on-password`); the hub persists the result.\n *\n * Gated by `enroll-authenticator`; `presented` carries any factor\n * proofs the active policy demands.\n */\n async enrollAuthenticator(\n vault: string,\n options: EnrollAuthenticatorOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n await this.deps.checkGate(vault, 'enroll-authenticator', factors)\n const keyring = await this.deps.getKeyringInternal(vault)\n const next = await keyringEnrollAuthenticator(this.deps.options.store, vault, keyring, options)\n this.deps.keyringCache.set(vault, next)\n }\n\n /**\n * Remove a tier-2 authenticator slot. Idempotent — removing a\n * non-existent slot is a successful no-op. Gated by\n * `remove-authenticator`.\n */\n async removeAuthenticator(\n vault: string,\n slotId: string,\n factors?: FactorProofBundle,\n ): Promise<void> {\n await this.deps.checkGate(vault, 'remove-authenticator', factors)\n const keyring = await this.deps.getKeyringInternal(vault)\n const next = await keyringRemoveAuthenticator(this.deps.options.store, vault, keyring, slotId)\n this.deps.keyringCache.set(vault, next)\n }\n\n /** Read the slot list for a vault. Internal — `describeAuthConfig` consumes this. */\n async listAuthenticators(vault: string): Promise<ReadonlyArray<KeyringAuthenticator>> {\n const keyring = await this.deps.getKeyringInternal(vault)\n return keyring.authenticators\n }\n\n /**\n * Mutate the `meta` blob on an existing authenticator slot — slot\n * rename, label change, attachment of UI hints. The slot's `id`,\n * `method`, and wrap material (`wrapped_kek` / `wrapped_deks` + `iv`)\n * are immutable through this method. Anti-slot-swap is structural,\n * not gate-driven.\n *\n * `meta` patch semantics (top-level merge):\n * - Top-level merge — absent keys preserved\n * - `null` value — delete that meta key\n * - Other values — replace verbatim\n *\n * Use case: per-slot nickname for \"iPhone Touch ID\" vs \"MacBook\n * Touch ID\" disambiguation in admin UIs. The slot id (auto-derived\n * from credentialId prefix) is not human-friendly; `meta.nickname`\n * is.\n *\n * Gated by `update-authenticator`. PERSONAL_POLICY: tier-1 unlock\n * alone (matches enroll/remove). STRICT_POLICY: tier-1 +\n * TOTP/email-OTP factor proof — a malicious rename on a shared\n * workstation could mislead the user about which device a slot\n * corresponds to, so STRICT requires fresh factor binding.\n *\n * @throws `NoAccessError` when no slot with the given id exists.\n * @throws `ValidationError` when no patch field is provided.\n */\n async updateAuthenticator(\n vault: string,\n slotId: string,\n options: UpdateAuthenticatorOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n await this.deps.checkGate(vault, 'update-authenticator', factors)\n const keyring = await this.deps.getKeyringInternal(vault)\n const next = await keyringUpdateAuthenticator(this.deps.options.store, vault, keyring, slotId, options)\n this.deps.keyringCache.set(vault, next)\n }\n\n /**\n * Native WebAuthn enrollment using the **real** internal keyring.\n *\n * Why this exists: when a consumer is using `createNoydb({ secret })`,\n * they cannot reach the live `UnlockedKeyring` to feed it to\n * `enrollWebAuthn(keyring, vault, opts)` from `@noy-db/on-webauthn`.\n * Constructing a synthetic keyring (the previous workaround) produces\n * a slot whose `wrapped_kek` references the synthetic payload, not\n * the live session — so `unlockViaAuthenticator()` later replaces the\n * live DEK map with stale wrapped DEKs and every decrypt fails.\n *\n * This method runs `ceremony` with the REAL keyring (still in\n * `keyringCache`). The ceremony performs the WebAuthn enrollment and\n * returns the slot options that hub then persists via the standard\n * tier-2 enrollAuthenticator path.\n *\n * Layering note: hub does not import `@noy-db/on-webauthn` (that\n * would invert the dep graph). The consumer wires it in:\n *\n * ```ts\n * import { enrollWebAuthn } from '@noy-db/on-webauthn'\n *\n * await db.team.enrollWebAuthn('demo', async (keyring) => {\n * const e = await enrollWebAuthn(keyring, 'demo', { rp: {...} })\n * return {\n * id: `webauthn-${e.credentialId.slice(0, 8)}`,\n * method: 'webauthn',\n * wrapped_kek: e.wrappedPayload,\n * meta: {\n * credentialId: e.credentialId,\n * wrapIv: e.wrapIv,\n * prfUsed: e.prfUsed,\n * beFlag: e.beFlag,\n * requireSingleDevice: e.requireSingleDevice,\n * },\n * }\n * })\n * ```\n *\n * Returns the WebAuthn `credentialId` (extracted from `meta.credentialId`)\n * for the caller's lookup index (a bootstrap vault, a Cover,\n * a server-side allowlist).\n *\n * Gated by `enroll-authenticator` like `enrollAuthenticator()` itself.\n */\n async enrollWebAuthn(\n vault: string,\n ceremony: (keyring: UnlockedKeyring) => Promise<EnrollAuthenticatorOptions>,\n factors?: FactorProofBundle,\n ): Promise<{ credentialId: string }> {\n await this.deps.checkGate(vault, 'enroll-authenticator', factors)\n const keyring = await this.deps.getKeyringInternal(vault)\n const slotOptions = await ceremony(keyring)\n if (slotOptions.method !== 'webauthn') {\n throw new ValidationError(\n `enrollWebAuthn: ceremony returned method \"${slotOptions.method}\"; expected \"webauthn\". ` +\n 'Use db.team.enrollAuthenticator() for non-webauthn methods.',\n )\n }\n const credentialId = (slotOptions.meta as { credentialId?: unknown }).credentialId\n if (typeof credentialId !== 'string' || credentialId.length === 0) {\n throw new ValidationError(\n 'enrollWebAuthn: ceremony result must include `meta.credentialId` (base64 string). ' +\n 'See @noy-db/on-webauthn enrollWebAuthn() return shape.',\n )\n }\n const next = await keyringEnrollAuthenticator(this.deps.options.store, vault, keyring, slotOptions)\n this.deps.keyringCache.set(vault, next)\n return { credentialId }\n }\n\n /**\n * Filter the slot list to webauthn-method slots only. Useful for\n * \"you have N WebAuthn credentials enrolled\" UI surfaces and for\n * deciding when a new device prompt should appear. Identity is\n * `id` + `enrolled_at`; the `meta.credentialId` (base64) is used by\n * `allowCredentials` at unlock time.\n */\n async listWebAuthnSlots(vault: string): Promise<ReadonlyArray<{\n id: string\n enrolledAt: string\n credentialId: string\n }>> {\n const keyring = await this.deps.getKeyringInternal(vault)\n return keyring.authenticators\n .filter((a) => a.method === 'webauthn')\n .map((a) => {\n const credentialId = (a.meta as { credentialId?: unknown }).credentialId\n return {\n id: a.id,\n enrolledAt: a.enrolled_at,\n credentialId: typeof credentialId === 'string' ? credentialId : '',\n }\n })\n }\n\n /**\n * Resolve a slot by id, then hand the wrapped-KEK ciphertext + meta\n * to the caller-supplied verifier. The verifier is the\n * `unlockWith*` function from the corresponding `@noy-db/on-*`\n * package, e.g. `unlockWithPassword(slot, password)`.\n *\n * On success, mark the active session tier as 2 — subsequent\n * `checkGate` calls see a tier-2 unlock.\n */\n async unlockViaAuthenticator(\n vault: string,\n slotId: string,\n verify: (slot: KeyringAuthenticator) => Promise<UnlockedKeyring>,\n ): Promise<UnlockedKeyring> {\n const keyring = await this.deps.getKeyringInternal(vault)\n const slot = findAuthenticator(keyring, slotId)\n if (!slot) {\n throw new ValidationError(\n `unlockViaAuthenticator: no slot with id \"${slotId}\" in vault \"${vault}\".`,\n )\n }\n const unlocked = await verify(slot)\n this.deps.keyringCache.set(vault, unlocked)\n this.deps.activeTier.set(vault, 2)\n return unlocked\n }\n\n // ─── Auth introspection ─────────────────────────────────────────\n /** English summary of the configured auth model. */\n async describeAuthConfig(vault: string): Promise<string> {\n return fnDescribeAuthConfig(this.deps.options.store, vault)\n }\n\n /** Mermaid `flowchart TB` source for the auth graph. */\n async diagramAuthConfig(vault: string): Promise<string> {\n return fnDiagramAuthConfig(this.deps.options.store, vault)\n }\n\n /**\n * Per-user enrollment summary. Gated by `view-user-auth` (default:\n * disabled). Sanitization is allowlist-based — never renders cred\n * ids, password hashes, secrets, or any field outside the allowlist.\n */\n async describeUserAuth(\n vault: string,\n userId: string,\n factors?: FactorProofBundle,\n ): Promise<string> {\n await this.deps.checkGate(vault, 'view-user-auth', factors)\n return fnDescribeUserAuth(this.deps.options.store, vault, userId)\n }\n\n /** Bulk variant for owner dashboards. Gated by `view-user-auth`. */\n async describeAllUsersAuth(\n vault: string,\n factors?: FactorProofBundle,\n ): Promise<Array<{ userId: string; description: string }>> {\n await this.deps.checkGate(vault, 'view-user-auth', factors)\n return fnDescribeAllUsersAuth(this.deps.options.store, vault)\n }\n\n // ─── Tier-1 change flows ────────────────────────────────────────\n /**\n * Rotate the user's secret (user remembers old). Validates the\n * new phrase against the configured `secret` policy, runs the\n * `rotate-secret` gate, then re-derives + re-wraps every DEK.\n *\n * Tier-2 authenticator slots are dropped — each slot wraps the old\n * KEK and would need its derivation key to be re-presented. Re-enrol\n * via `db.enrollAuthenticator` after rotation.\n *\n * @throws `WeakSecretError` on a weak new phrase.\n * @throws `PolicyDeniedError` when the gate denies (missing factor, …).\n * @throws `InvalidKeyError` when `oldSecret` is wrong.\n */\n async rotateSecret(\n vault: string,\n input: RotateSecretInput,\n factors?: FactorProofBundle,\n ): Promise<void> {\n // Managed-secret mode: the user does NOT know the\n // current secret (hub generated it and sealed it under the\n // provider). Manual rotation via this method is impossible by\n // construction — surface a clear error rather than fail mid-way\n // with InvalidKeyError once `oldSecret` doesn't match the\n // hub-generated one. Recovery-under-managed (which mints a fresh\n // sealed secret via the provider) is the supported path; it\n // lands in a follow-up.\n if (this.deps.options.secretMode === 'managed') {\n throw new PolicyDeniedError(\n 'rotate-secret',\n 'disabled',\n { minTier: 1, enabled: false },\n 'Managed-secret mode (#14): the secret is hub-generated '\n + 'and sealed under the SealingKeyProvider — there is no '\n + 'plaintext to rotate. Use the recovery flow (follow-up issue) '\n + 'to mint a fresh sealed secret.',\n )\n }\n await this.deps.checkGate(vault, 'rotate-secret', factors)\n const userId = this.deps.options.user\n const next = await keyringRotateSecret(this.deps.options.store, vault, userId, input)\n this.deps.keyringCache.set(vault, next)\n }\n\n /**\n * Reset the secret using a recovery proof (user forgot the old).\n * Currently supports the `'paper'` profile end-to-end; the\n * other profiles throw {@link RecoveryProfileNotImplementedError}.\n *\n * Burns the used recovery entry on success.\n */\n async recoverSecret(\n vault: string,\n input: RecoverSecretInput,\n factors?: FactorProofBundle,\n ): Promise<RecoverSecretResult> {\n await this.deps.checkGate(vault, 'recover-secret', factors)\n const userId = this.deps.options.user\n\n // Snapshot the entries BEFORE recovery — the team function burns\n // exactly one entry, so post-recovery `_meta/recovery-paper`\n // contains `entriesBeforeRecovery.length - 1` entries (the ones\n // the user did NOT just consume). Those are what we replace\n // under the auto-rotation logic.\n const entriesBeforeRecovery = await loadPaperRecoveryEntries(this.deps.options.store, vault)\n\n const next = await keyringRecoverSecret(this.deps.options.shamirRecovery, this.deps.options.store, vault, userId, input)\n this.deps.keyringCache.set(vault, next)\n\n const rotateRemaining = input.rotateRemainingCodes ?? true\n const remainingAfterBurn = Math.max(0, entriesBeforeRecovery.length - 1)\n if (!rotateRemaining || remainingAfterBurn === 0) {\n return { newCodes: [] }\n }\n\n // Auto-rotate: replace the remaining entries with a fresh set\n // minted under the new keyring's DEKs. Wraps the same DEK set the\n // recovered keyring just got, so the new codes round-trip through\n // a future `db.recoverSecret` cleanly.\n //\n // If this step fails (store error mid-mint), we leave the existing\n // post-burn entries in place — the user falls back to the\n // fall back to prior behavior (remaining N-1 codes still valid). Strictly\n // safer than wiping then failing.\n const codeGen = input.codeGenerator ?? generateULID\n const newCodeCount = input.newCodeCount ?? remainingAfterBurn\n const codes: string[] = []\n const newEntries: PaperRecoveryEntry[] = []\n for (let i = 0; i < newCodeCount; i++) {\n const rawCode = codeGen()\n const entry = await mintPaperRecoveryEntry(next.deks, rawCode, generateULID())\n codes.push(rawCode)\n newEntries.push(entry)\n }\n // Single replace-all write — `savePaperRecoveryEntries` overwrites\n // `_meta/recovery-paper` atomically (one envelope `put`).\n await savePaperRecoveryEntries(this.deps.options.store, vault, newEntries)\n\n return { newCodes: codes }\n }\n\n /**\n * Deliberate paper-recovery-code regeneration. User knows their\n * secret but wants a fresh sheet — they lost the printout or\n * suspect compromise of the off-site copy.\n *\n * Symmetric to {@link rotateSecret} for the recovery profile:\n * gated, audit-trackable, ergonomic. Replaces (not appends) the\n * paper sheet under `_meta/recovery-paper` in a single envelope `put`.\n *\n * Gated by the `rotate-recovery` policy gate:\n * - PERSONAL_POLICY: `{ minTier: 1 }` — knowing the secret\n * suffices, matching the lower-level flow's bar.\n * - STRICT_POLICY: `{ minTier: 1, factors: [{ anyOf: ['totp',\n * 'email-otp', 'webauthn-roaming'] }] }` — rotation is an\n * off-site-trust event; require an off-device factor so a\n * stolen unlocked laptop cannot silently mint a sheet for the\n * attacker.\n *\n * Defaults `count` to the existing sheet size so consumers aren't\n * surprised by a different code count. Explicit `count` overrides.\n *\n * @throws {@link RecoveryProfileNotImplementedError} when `profile`\n * is anything other than `'paper'` (v1 dispatch limit).\n * @throws {@link PolicyDeniedError} when the gate denies (missing\n * factor, tier mismatch, ...).\n * @throws on missing paper sheet — \"nothing to rotate\" surfaces as\n * an error rather than silently minting an entire new sheet.\n *\n * @example Default count + show-once UI\n * ```ts\n * const { newCodes } = await db.team.rotateRecovery('acme', { profile: 'paper' })\n * showCodesToUser(newCodes)\n * ```\n *\n * @example STRICT-policy site with TOTP factor proof\n * ```ts\n * await db.team.rotateRecovery(\n * 'acme',\n * { profile: 'paper', count: 10 },\n * { factors: [{ kind: 'totp', proof: '123456' }] },\n * )\n * ```\n */\n async rotateRecovery(\n vault: string,\n options: RotateRecoveryOptions,\n factors?: FactorProofBundle,\n ): Promise<RotateRecoveryResult> {\n if (options.profile === 'paper') {\n return this.rotateRecoveryPaper(vault, options, factors)\n }\n if (options.profile === 'shamir') {\n return this.rotateRecoveryShamir(vault, options, factors)\n }\n // Defense-in-depth for `as unknown as ...` bypass.\n throw new RecoveryProfileNotImplementedError(\n (options as { profile: string }).profile,\n '#196',\n )\n }\n\n private async rotateRecoveryPaper(\n vault: string,\n options: Extract<RotateRecoveryOptions, { profile: 'paper' }>,\n factors?: FactorProofBundle,\n ): Promise<RotateRecoveryResult> {\n await this.deps.checkGate(vault, 'rotate-recovery', factors)\n\n const existing = await loadPaperRecoveryEntries(this.deps.options.store, vault)\n if (existing.length === 0) {\n throw new Error(\n `db.rotateRecovery: no recovery codes are enrolled for vault \"${vault}\". ` +\n `Call db.team.enrollRecovery({ profile: 'paper', entries }) first; ` +\n `rotateRecovery replaces an existing sheet rather than minting one from scratch.`,\n )\n }\n\n const keyring = await this.getKeyring(vault)\n const codeGen = options.codeGenerator ?? generateULID\n const count = options.count ?? existing.length\n\n const codes: string[] = []\n const newEntries: PaperRecoveryEntry[] = []\n for (let i = 0; i < count; i++) {\n const rawCode = codeGen()\n const entry = await mintPaperRecoveryEntry(keyring.deks, rawCode, generateULID())\n codes.push(rawCode)\n newEntries.push(entry)\n }\n // Atomic replace — `savePaperRecoveryEntries` overwrites\n // `_meta/recovery-paper` in a single envelope `put`.\n await savePaperRecoveryEntries(this.deps.options.store, vault, newEntries)\n\n return { newCodes: codes, entryId: 'paper-batch' }\n }\n\n private async rotateRecoveryShamir(\n vault: string,\n options: Extract<RotateRecoveryOptions, { profile: 'shamir' }>,\n factors?: FactorProofBundle,\n ): Promise<RotateRecoveryResult> {\n await this.deps.checkGate(vault, 'rotate-recovery', factors)\n\n const existing = await loadShamirRecoveryEntries(this.deps.options.store, vault)\n if (existing.length === 0) {\n throw new Error(\n `db.rotateRecovery: no Shamir recovery entry is enrolled for vault \"${vault}\". ` +\n `Call db.team.enrollRecovery({ profile: 'shamir', k, n }) first; ` +\n `rotateRecovery replaces an existing entry rather than minting one from scratch.`,\n )\n }\n\n // Pick which entry to rotate.\n let targetEntryId: string\n if (options.entryId !== undefined) {\n const found = existing.find(e => e.entryId === options.entryId)\n if (!found) {\n throw new Error(\n `db.rotateRecovery: no Shamir entry with entryId=\"${options.entryId}\" found `\n + `in vault \"${vault}\". Available: ${existing.map(e => `\"${e.entryId}\"`).join(', ')}.`,\n )\n }\n targetEntryId = options.entryId\n } else {\n if (existing.length > 1) {\n throw new Error(\n `db.rotateRecovery: vault \"${vault}\" has ${existing.length} Shamir entries `\n + `enrolled (${existing.map(e => `\"${e.entryId}\"`).join(', ')}). `\n + `Pass \\`entryId\\` to disambiguate which one to rotate; ambiguous rotation `\n + `would risk replacing the wrong entry.`,\n )\n }\n targetEntryId = existing[0]!.entryId\n }\n\n const keyring = await this.getKeyring(vault)\n const { entry, shareStrings } = await mintShamirRecoveryEntry(\n this.requireShamirProvider(),\n keyring.deks,\n targetEntryId,\n options.k,\n options.n,\n options.label,\n )\n\n // Atomic single-doc replace: drop the old entry, insert the new one.\n const next: ShamirRecoveryEntry[] = existing\n .filter(e => e.entryId !== targetEntryId)\n .concat(entry)\n await saveShamirRecoveryEntries(this.deps.options.store, vault, next)\n\n return { newShares: shareStrings, entryId: targetEntryId }\n }\n\n /**\n * **Atomic create-and-enroll for managed-mode vaults.**\n *\n * Bootstraps a managed-mode vault and enrolls strong recovery in\n * a single ceremony. Under `secretMode: 'managed'`, every\n * `openVault` call requires a strong recovery profile (Shamir\n * today) to be enrolled — otherwise it throws\n * {@link ManagedRecoveryNotEnrolledError}. This method bypasses\n * the check temporarily so the keyring can be created, enrolls\n * the supplied recovery profile(s), then returns the vault.\n *\n * For Shamir enrollments, the show-once share strings come back\n * in `recoveryEnrollments[i].shares`. The hub never retains them\n * — the caller MUST display them to the user (once) before any\n * subsequent operation.\n *\n * Paper alone is NOT a strong profile under managed mode; passing\n * `{ profile: 'paper', ... }` without an accompanying shamir entry\n * is rejected at validation time.\n *\n * ```ts\n * const db = await createNoydb({\n * store, user: 'alice',\n * secretMode: 'managed',\n * sealingKey: macosKeychainSealingProvider({ ... }),\n * })\n *\n * const { vault, recoveryEnrollments } = await db.team.openVaultAndEnrollRecovery('acme', {\n * recovery: [{ profile: 'shamir', k: 2, n: 3 }],\n * })\n * for (const r of recoveryEnrollments) {\n * if (r.shares) showSharesToUser(r.shares) // ONCE\n * }\n * ```\n *\n * @throws ValidationError if recovery is empty, or contains no\n * strong profile under managed mode.\n */\n async openVaultAndEnrollRecovery(\n vault: string,\n opts: {\n readonly recovery: ReadonlyArray<RecoveryEnrollmentInput>\n readonly locale?: string\n },\n ): Promise<{\n readonly vault: Vault\n readonly recoveryEnrollments: ReadonlyArray<EnrollRecoveryResult>\n }> {\n if (opts.recovery.length === 0) {\n throw new ValidationError(\n 'openVaultAndEnrollRecovery: at least one recovery enrollment is required.',\n )\n }\n\n // Validate \"at least one strong\" when managed mode is on.\n if (this.deps.options.secretMode === 'managed') {\n const hasStrong = opts.recovery.some(r => r.profile === 'shamir')\n if (!hasStrong) {\n throw new ValidationError(\n 'openVaultAndEnrollRecovery: managed-mode vaults require at least one strong '\n + 'recovery profile in the `recovery` array. Paper alone is not strong under '\n + 'managed mode (no user secret to fall back on). Include '\n + '{ profile: \"shamir\", k, n } in `recovery`.',\n )\n }\n }\n\n // Temporarily bypass the managed-mode strong-recovery check so\n // openVault can create the keyring. Recovery enrollment happens\n // inside this window; the check is restored at the end.\n this.deps.setSkipNextManagedRecoveryCheck(true)\n let vaultHandle: Vault\n try {\n vaultHandle = await this.deps.openVault(vault, opts.locale !== undefined ? { locale: opts.locale } : undefined)\n } finally {\n this.deps.setSkipNextManagedRecoveryCheck(false)\n }\n\n // Enroll each recovery profile.\n const recoveryEnrollments: EnrollRecoveryResult[] = []\n for (const enrollment of opts.recovery) {\n recoveryEnrollments.push(await this.enrollRecovery(vault, enrollment))\n }\n\n // Belt-and-braces final check — by now, strong recovery must be on disk.\n if (this.deps.options.secretMode === 'managed') {\n const policy = this.deps.policyCache.get(vault)\n if (policy) {\n await this.deps.assertRecoveryEnrolled(vault, policy)\n }\n }\n\n return { vault: vaultHandle, recoveryEnrollments }\n }\n\n /**\n * **Recovery flow under managed-secret mode.**\n *\n * Replaces the sealed secret of a managed-mode vault with a\n * fresh 256-bit random, sealed under the configured\n * `SealingKeyProvider`. The user never sees the new secret.\n *\n * Internally:\n * 1. Verify the recovery proof (Shamir today) and unwrap the\n * DEK set.\n * 2. Mint a fresh 256-bit random as the new effective secret.\n * 3. Rewrap the DEK set under a fresh KEK derived from the new\n * secret (via the existing `recoverSecret` path).\n * 4. Seal the random bytes under the provider and overwrite\n * `_meta/sealed-secret`.\n * 5. Drop the keyring cache so the next operation re-derives.\n *\n * The vault's strong-recovery enrollment is preserved across\n * recovery (Shamir entries are not burned on use).\n *\n * @throws ValidationError if the Noydb instance is not in managed mode.\n */\n async recoverManagedSecret(\n vault: string,\n options: {\n readonly recoveryProof: RecoveryProof\n readonly secretPolicy?: SecretPolicy\n },\n ): Promise<void> {\n if (this.deps.options.secretMode !== 'managed') {\n throw new ValidationError(\n 'recoverManagedSecret: this method only applies to vaults opened '\n + 'in managed-secret mode. For standard mode, use db.recoverSecret.',\n )\n }\n const provider = this.deps.options.sealingKey\n if (!provider) {\n throw new ValidationError(\n 'recoverManagedSecret: createNoydb({ secretMode: \"managed\" }) requires '\n + '`sealingKey` to be supplied; without it the new sealed secret cannot '\n + 'be persisted.',\n )\n }\n\n // Mint fresh 256-bit random; base64 it for use as the new\n // effective secret. AES-GCM auth-tag failures in the\n // managed-mode envelope catch tampering.\n const randomBytes = new Uint8Array(32)\n globalThis.crypto.getRandomValues(randomBytes)\n let binary = ''\n for (let i = 0; i < randomBytes.length; i++) binary += String.fromCharCode(randomBytes[i]!)\n const newSecret = btoa(binary)\n\n try {\n // Seal first; if the provider fails (KMS down, keychain locked),\n // we don't touch the keyring. Then run recoverSecret which\n // rewraps DEKs under the new KEK derived from the random bytes.\n const sealed = await provider.seal(randomBytes)\n await keyringRecoverSecret(\n this.deps.options.shamirRecovery,\n this.deps.options.store,\n vault,\n this.deps.options.user,\n {\n newSecret,\n recoveryProof: options.recoveryProof,\n // The new secret IS 256 bits of random; policy gates on\n // length/entropy don't apply.\n allowWeakSecret: true,\n ...(options.secretPolicy !== undefined\n ? { secretPolicy: options.secretPolicy }\n : {}),\n },\n )\n // Update _meta/sealed-secret with the freshly sealed random.\n // The previous envelope is overwritten by saveSealedSecret.\n await saveSealedSecret(this.deps.options.store, vault, {\n providerId: provider.id,\n sealed,\n })\n } finally {\n // Best-effort zero of the in-memory random buffer.\n randomBytes.fill(0)\n }\n\n // Drop the keyring cache so the next openVault re-derives from\n // the new sealed envelope.\n this.deps.keyringCache.delete(vault)\n }\n\n /**\n * Atomic peer-recovery — re-wraps an EXISTING user's keyring under\n * a fresh temp secret in a single store write. Closes the\n * partial-failure window (the previous compose-from-primitives\n * pattern was `db.revoke + db.grant`, two writes — if the issuer\n * cancelled between them the target was locked out entirely).\n *\n * Different from `db.revoke + db.grant`:\n *\n * - Same `userId`, role, permissions, capabilities preserved.\n * - DEKs unchanged → every other principal in the vault keeps\n * access. No key rotation.\n * - Allows owner→owner natively. The existing\n * `db.revoke` retains its block — peer-recovery is a separate,\n * intentionally-named operation.\n * - Tier-2 slots dropped (they wrap the old KEK).\n *\n * Gated by `peer-recover-user`; `STRICT_POLICY` requires a\n * recovery / TOTP / email-OTP factor proof at the moment of\n * recovery, so the issuer affirmatively re-asserts identity.\n *\n * The recipient should call `db.rotateSecret` on first session\n * to choose their own phrase — the temp acts as a single-use\n * bridge.\n *\n * ```ts\n * await db.team.recoverUser('acme', {\n * userId: 'bob',\n * secret: 'temporary-correct-horse-battery-staple-printer',\n * }, { factors: [{ kind: 'recovery' }] })\n * // Bob opens createNoydb({ user: 'bob', secret: tempPhrase })\n * // and immediately calls db.rotateSecret to set his own.\n * ```\n *\n * @throws `NoAccessError` when no keyring exists for the target.\n * @throws `PermissionDeniedError` when the caller's role can't\n * recover the target's role (admin→owner is blocked even\n * under recovery).\n * @throws `PrivilegeEscalationError` when the caller lacks a DEK\n * the target previously had access to.\n *\n */\n async recoverUser(\n vault: string,\n options: RecoverUserOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n await this.deps.checkGate(vault, 'peer-recover-user', factors)\n const callerKeyring = await this.deps.getKeyringInternal(vault)\n await keyringRecoverUser(this.deps.options.store, vault, callerKeyring, options)\n // If the caller is recovering THEIR OWN keyring (rare but\n // possible — e.g. a self-recovery flow that bypasses the password\n // ceremony), the keyringCache entry is now stale. Drop it so the\n // next access reloads with the fresh wrapping.\n if (options.userId === this.deps.options.user) {\n this.deps.keyringCache.delete(vault)\n }\n }\n\n /**\n * Persist a recovery enrollment. Accepts the `'paper'`\n * profile.\n *\n * The hub wraps the user's DEK set (not the KEK) under a code-derived\n * AES-GCM key — see `team/recovery.ts` for the rationale. The mint\n * helper {@link mintPaperRecoveryEntry} is the canonical primitive;\n * pair it with `db.team.getKeyring(vault)` to obtain the live DEK set:\n *\n * ```ts\n * import { mintPaperRecoveryEntry } from '@noy-db/hub'\n *\n * const keyring = await db.team.getKeyring('acme')\n * const codes: string[] = ['CORRECT-HORSE-1', 'BATTERY-STAPLE-2', ...]\n * const entries = await Promise.all(\n * codes.map((code, i) => mintPaperRecoveryEntry(keyring.deks, code, `code-${i}`)),\n * )\n * await db.team.enrollRecovery('acme', { profile: 'paper', entries })\n * showCodesToUser(codes)\n * ```\n *\n * `@noy-db/on-recovery`'s `generateRecoveryCodeSet`\n * delegates to `mintPaperRecoveryEntry` internally — its output is\n * fed directly to this API. Pick whichever fits your code-gen layer:\n *\n * ```ts\n * import { generateRecoveryCodeSet } from '@noy-db/on-recovery'\n * const { codes, entries } = await generateRecoveryCodeSet({ deks: keyring.deks, count: 8 })\n * await db.team.enrollRecovery('acme', { profile: 'paper', entries })\n * ```\n */\n async enrollRecovery(\n vault: string,\n enrollment: RecoveryEnrollmentInput,\n ): Promise<EnrollRecoveryResult> {\n if (enrollment.profile === 'paper') {\n const existing = await loadPaperRecoveryEntries(this.deps.options.store, vault)\n await savePaperRecoveryEntries(this.deps.options.store, vault, [\n ...existing,\n ...enrollment.entries,\n ])\n // Paper enrollments don't have a single entryId — callers\n // pre-mint with their own ids. Return a stable sentinel so the\n // result type is consistent for both profiles.\n return { entryId: 'paper-batch' }\n }\n if (enrollment.profile === 'shamir') {\n const keyring = await this.getKeyring(vault)\n const entryId = enrollment.entryId ?? generateULID()\n const { entry, shareStrings } = await mintShamirRecoveryEntry(\n this.requireShamirProvider(),\n keyring.deks,\n entryId,\n enrollment.k,\n enrollment.n,\n enrollment.label,\n )\n const existing = await loadShamirRecoveryEntries(this.deps.options.store, vault)\n // If a Shamir entry with this id already exists, replace it\n // (allows callers to be idempotent on `entryId`); otherwise append.\n const next: ShamirRecoveryEntry[] = existing.filter(e => e.entryId !== entryId).concat(entry)\n await saveShamirRecoveryEntries(this.deps.options.store, vault, next)\n return { entryId, shares: shareStrings }\n }\n // Defense-in-depth for `as unknown as ...` bypass at the call site.\n throw new RecoveryProfileNotImplementedError(\n (enrollment as { profile: string }).profile,\n '#196',\n )\n }\n\n /** Read the persisted recovery entries (paper + Shamir). Used by `describeAuthConfig`. */\n async listRecoveryEntries(\n vault: string,\n ): Promise<{\n paper: ReadonlyArray<PaperRecoveryEntry>\n shamir: ReadonlyArray<ShamirRecoveryEntry>\n }> {\n const paper = await loadPaperRecoveryEntries(this.deps.options.store, vault)\n const shamir = await loadShamirRecoveryEntries(this.deps.options.store, vault)\n return { paper, shamir }\n }\n\n // ─── Tier-3 enroll / unlock ─────────────────────────────────────\n /**\n * Register a tier-3 quick-unlock state for the vault. The state is\n * an opaque blob produced by `@noy-db/on-pin/enrollPin` (or any\n * compatible primitive). It is held in memory only — never persisted\n * — and auto-clears when its `expiresAt` elapses.\n *\n * Gated by `rotate-unlock` (the same gate covers \"set\" and \"rotate\"\n * because tier-3 is a single-slot rolling secret).\n */\n async enrollUnlock(\n vault: string,\n state: QuickUnlockState,\n factors?: FactorProofBundle,\n ): Promise<void> {\n await this.deps.checkGate(vault, 'rotate-unlock', factors)\n this.deps.quickUnlock.set(vault, state)\n }\n\n /**\n * Resume a session via the registered tier-3 state. The verifier is\n * `@noy-db/on-pin/resumePin` (or compatible). On success, mark the\n * active session tier as 3 — every operation must re-authenticate at\n * tier 2 to elevate.\n *\n * Returns `undefined` (caller should fall back to tier 2) when no\n * tier-3 state is registered.\n */\n async unlockViaPin(\n vault: string,\n resume: (state: QuickUnlockState) => Promise<UnlockedKeyring>,\n ): Promise<UnlockedKeyring | undefined> {\n const state = this.deps.quickUnlock.get(vault)\n if (!state) return undefined\n const keyring = await resume(state)\n this.deps.keyringCache.set(vault, keyring)\n this.deps.activeTier.set(vault, 3)\n return keyring\n }\n\n /** Drop the tier-3 state for a vault — explicit logout. */\n clearQuickUnlock(vault: string): void {\n this.deps.quickUnlock.delete(vault)\n }\n\n /**\n * Public accessor for the unlocked keyring of a vault.\n *\n * Returns a **defensive shallow copy** so consumers can read the DEK\n * map and authenticator list without the risk of mutating the hub's\n * internal cache. Internal hub code paths use a live reference\n * via `getKeyringInternal`; ceremonies and external consumers always\n * get a snapshot.\n *\n * The CryptoKey values inside `deks` are not cloned — Web Crypto\n * keys are opaque handles, and a shared handle is intentional\n * (encrypt / decrypt go through the same key the cache holds).\n * Only the container Map / authenticator array is fresh.\n *\n * Used by `@noy-db/on-*` ceremonies that need the live DEK set\n * (paper recovery via {@link mintPaperRecoveryEntry}, tier-3 PIN\n * enrolment via on-pin's `enrollPin`, custom on-* ceremonies that\n * don't have a hub-side wrapper).\n *\n * No new permission gate — this is an accessor over already-unlocked\n * state. The keyring is materialized only after the calling session\n * has unlocked the vault at tier 1, 2, or 3, so exposing it does not\n * widen access. Throws `ValidationError` when encryption is enabled\n * and no `secret` / `getKeyring` is configured.\n *\n * ```ts\n * const keyring = await db.team.getKeyring('acme')\n * // keyring.deks: Map<collection, CryptoKey>\n * // keyring.kek: CryptoKey | null (null for tier-3 / wrap-DEKs sessions)\n * // keyring.role / .permissions / .authenticators\n * ```\n */\n async getKeyring(vault: string): Promise<UnlockedKeyring> {\n const live = await this.deps.getKeyringInternal(vault)\n // Deep-ish defensive copy. Each container the consumer might\n // reasonably mutate is freshly cloned. CryptoKey handles inside\n // `deks` are intentionally shared — they're opaque references that\n // both encrypt and decrypt go through. `salt` (Uint8Array) is left\n // as-is: no realistic mutation path.\n return {\n ...live,\n deks: new Map(live.deks),\n permissions: { ...live.permissions },\n authenticators: live.authenticators.map((a) => ({\n ...a,\n meta: { ...a.meta },\n })),\n ...(live.policy !== undefined ? { policy: { ...live.policy } } : {}),\n ...(live.exportCapability !== undefined\n ? { exportCapability: { ...live.exportCapability } }\n : {}),\n ...(live.importCapability !== undefined\n ? { importCapability: { ...live.importCapability } }\n : {}),\n }\n }\n}\n","import { resolveStrategies, type StrategyBag } from '../port/with/strategies.js'\nimport type { RotateResult } from '../with-party/team/keyring.js'\nimport type {\n NoydbOptions,\n NoydbEventMap,\n GrantOptions,\n RevokeOptions,\n UpdateUserOptions,\n UserInfo,\n PushResult,\n PullResult,\n PushOptions,\n PullOptions,\n SyncStatus,\n SyncTarget,\n NoydbStore,\n Role,\n AccessibleVault,\n ListAccessibleVaultsOptions,\n QueryAcrossOptions,\n QueryAcrossResult,\n ReAuthOperation,\n TranslatorAuditEntry,\n WriteConflict,\n UserApiFactory,\n ActiveTier,\n FactorProofBundle,\n GateName,\n VaultPolicy,\n NoydbPolicyApi,\n PolicyCheckGateFn,\n} from './types.js'\nimport { ValidationError, NoAccessError, InvalidKeyError, KeyringCorruptError, StoreCapabilityError, PermissionDeniedError, DebugPlaintextError, RecoveryNotEnrolledError, ManagedRecoveryNotEnrolledError } from './errors.js'\nimport {\n readDirectoryConfig,\n persistDirectoryConfig,\n} from '../with-party/directory/storage.js'\nimport type { SecretPolicy } from './validation.js'\nimport { hasRecoveryEnrolled, hasStrongRecoveryEnrolled } from '../with-party/team/recovery.js'\nimport { resolveManagedSecret } from '../with-party/team/managed-secret.js'\nimport { generateULID } from '../with-pod/ulid.js'\nimport { createDefaultCoordinationProvider, type CoordinationProvider } from '../port/by/default-provider.js'\nimport type { Cover } from '../with-party/directory/cover/types.js'\nimport type { SetCoverInput } from '../with-party/directory/cover/schema.js'\nimport { Vault } from './vault.js'\nimport type { VaultMeta } from '../with-shape/introspection/meta.js'\nimport { NoydbEventEmitter } from './events.js'\nimport { WriteQueueTracker, type WriteQueue } from './write-queue.js'\nimport { WriteHookRegistry, type WriteHook, type Unsubscribe } from '../port/with/write-hooks.js'\nimport { ServiceBus } from '../port/with/service-bus.js'\nimport { TabCoordinator, defaultLockManager, defaultChannel, type TabCoordinationOptions, type TabRole, type TabPresence } from '../with-sync/tab-coordination.js'\nimport { CrossTabWriteRelay } from '../with-sync/tab-write-relay.js'\nimport {\n loadKeyring,\n createOwnerKeyring,\n assertKeyringOpenAllowed,\n changeSecret as keyringChangeSecret,\n listUsers as keyringListUsers,\n updateKeyringIdentity,\n} from '../with-party/team/keyring.js'\nimport type { UnlockedKeyring } from '../with-party/team/keyring.js'\nimport { QuickUnlockStore } from '../with-party/session/unlock-state.js'\nimport type { SyncEngine } from '../with-sync/engine.js'\nimport type { SyncTransaction } from '../with-sync/transaction.js'\nimport { type SnapshotMeta } from '../with-fork/snapshots/strategy.js'\nimport { NoydbSnapshots } from '../with-fork/snapshots/noydb-facade.js'\nimport type { AmendmentTxOptions } from '../with-commit/tx/transaction.js'\nimport { TxContext } from '../with-commit/tx/transaction.js'\nimport type { DryRunResult } from '../with-commit/tx/dry-run.js'\nimport { type ForgetStrategy } from '../with-audit/forget/strategy.js'\nimport { type CustodyStrategy, type CustodyHost } from '../with-party/custody/strategy.js'\nimport { readDottedPath, coerceSubjectId } from '../with-audit/forget/subject-index.js'\nimport { INDEXED_STORE_POLICY } from './sync-policy.js'\nimport { memoryStore } from './memory-store.js'\nimport type { PolicyEnforcer } from '../with-party/session/session-policy.js'\nimport { TeamFacade } from '../with-party/team/noydb-facade.js'\n\n/**\n * Privilege rank used by `listAccessibleVaults({ minRole })` to\n * filter the result. Higher number = more privileged. Owner is at the\n * top; client is at the bottom. Viewer outranks client because viewer\n * has read-all access while client has only explicit-collection read\n * — the ordering reflects \"how much can this principal see,\" not\n * \"how much can this principal modify.\"\n */\nconst ROLE_RANK: Record<Role, number> = {\n client: 1,\n viewer: 2,\n operator: 3,\n // FR-6: custodian is operationally admin-rank (rw + access on every\n // collection) — it ranks alongside admin for \"how much can this\n // principal see/operate.\" It is NOT above admin, and explicitly below\n // owner: a custodian can never grant/revoke/rotate/sever (those are\n // owner meta-capabilities), so it must not outrank or equal the owner.\n custodian: 4,\n admin: 4,\n owner: 5,\n}\n\n/** Dummy keyring for unencrypted mode. */\nfunction createPlaintextKeyring(userId: string, debugPlaintext = false): UnlockedKeyring {\n return {\n userId,\n displayName: userId,\n role: 'owner',\n permissions: {},\n deks: new Map(),\n kek: null,\n salt: new Uint8Array(0),\n authenticators: [],\n ...(debugPlaintext ? { debugPlaintext } : {}),\n }\n}\n\n/** NoydbOptions with the store resolved to a non-optional value (internal use only). */\ntype ResolvedNoydbOptions = NoydbOptions & { readonly store: NoydbStore }\n\n/** #616: a fresh empty pull result for push-only (backup/archive) targets that are never pulled from. */\nconst emptyPullResult = (): PullResult => ({ pulled: 0, conflicts: [], errors: [] })\n\n/** The top-level NOYDB instance. */\nexport class Noydb {\n private readonly options: ResolvedNoydbOptions\n private readonly emitter = new NoydbEventEmitter()\n private readonly writeQueueTracker = new WriteQueueTracker()\n private readonly writeHooks = new WriteHookRegistry()\n private readonly subsystemBus = new ServiceBus()\n private readonly clientId = generateULID()\n /** Session that owns this instance's writers (one user's writers across vaults). */\n private readonly sessionId: string\n /** Drain-barrier coordination transport for the schema fence. */\n private readonly coordinationProvider: CoordinationProvider\n /** Pre-resolved `vault.user` API factory (mirrors `coordinationProvider` above). Public so `Vault` can call it. */\n readonly userApiFactory: UserApiFactory\n private readonly vaultCache = new Map<string, Vault>()\n /**\n * In-flight `openVault` promise per name — concurrent opens of the same\n * vault must converge on ONE Vault instance. Without this, two callers\n * racing past the `vaultCache` miss each construct a Vault (and later two\n * Collections with independent DEKs for the same store slice), so a record\n * written through one fails decryption through the other with a spurious\n * `TamperedError` (#564).\n */\n private readonly vaultOpening = new Map<string, Promise<Vault>>()\n private readonly keyringCache = new Map<string, UnlockedKeyring>()\n private readonly syncEngines = new Map<string, SyncEngine>()\n /**\n * Per-vault active session tier — defaults to `1` after a secret\n * unlock; tier-2 / tier-3 unlocks downgrade it. Used by\n * {@link checkGate} to evaluate `gate.minTier`.\n */\n private readonly activeTier = new Map<string, ActiveTier>()\n /**\n * Per-vault loaded policy. Cached after the first\n * `_meta/policy` load; replaced by `db.updatePolicy()`.\n */\n private readonly policyCache = new Map<string, VaultPolicy>()\n /**\n * One-shot bypass for the managed-mode strong-recovery check.\n * Set true by {@link openVaultAndEnrollRecovery} for the duration of\n * the bootstrap window so the keyring can be created before the\n * strong recovery is enrolled. Always cleared (try/finally).\n * @internal\n */\n private _skipNextManagedRecoveryCheck = false\n /** Per-vault tier-3 (PIN / quick-resume) state. */\n private readonly quickUnlock = new QuickUnlockStore()\n private closed = false\n private sessionTimer: ReturnType<typeof setTimeout> | null = null\n /** Same-device multi-tab coordinator; created on `enableTabCoordination()`. */\n private tabCoordinator: TabCoordinator | undefined\n /** Cross-tab write relay; created on `enableTabCoordination()`. */\n private writeRelay: CrossTabWriteRelay | undefined\n /** Per-vault policy enforcers. */\n private readonly policyEnforcers = new Map<string, PolicyEnforcer>()\n /**\n * Every opt-in service, resolved once (#838). Shared by reference with each\n * `Vault` this instance opens and, through them, every `Collection` — so\n * there is exactly one resolution and no construction path can disagree\n * about which services are enabled (the #834 bug class).\n */\n private readonly strategies: StrategyBag\n /**\n * Opt-in sovereign-custody (FR-6) strategy — `NO_CUSTODY` (throwing) unless\n * `withCustody()` was passed. Kept as a public accessor because `Vault`\n * routes `vault.custody.liberate` through `this.noydb.custodyStrategy`.\n * @internal\n */\n get custodyStrategy(): CustodyStrategy {\n return this.strategies.custody\n }\n private readonly snapshots: NoydbSnapshots\n private readonly policyManager: NoydbPolicyApi\n /** Pre-resolved policy-gate engine function (mirrors `coordinationProvider`/`userApiFactory` above). */\n private readonly policyCheckGate: PolicyCheckGateFn\n /**\n * Credential and multi-user operations — enrolment, secret rotation,\n * recovery, quick-unlock (#846).\n *\n * Public because 23 methods on this class did nothing but restate a\n * TeamFacade signature and forward to it, so every signature had to be\n * hand-kept in sync with its counterpart. `db.team.rotateSecret(…)`\n * reads the same and has one source of truth.\n *\n * A getter, not a field, so it appears in the prototype-based kernel API\n * manifest — an instance field is invisible to it (the same reason\n * `custodyStrategy` became one in #838).\n */\n get team(): TeamFacade {\n return this.#team\n }\n\n readonly #team: TeamFacade\n /**\n * Currently-running multi-record transaction, set by\n * `runTransaction` at the start of Phase 2 (commit) and cleared in\n * the same function's `finally` block. Side-effect writes triggered\n * during a staged op's `Collection.put` (today: eager derivation\n * outputs) register their pre-write envelope on `_executed` here so\n * a mid-batch failure rolls them back alongside the main staged ops.\n * `null` outside of Phase 2.\n * @internal\n */\n private _activeTxContext: TxContext | null = null\n\n // ─── plaintextTranslator state ─────────────────────────\n /**\n * In-process translation cache. Key is `\"${field}\\x00${collection}\\x00${from}\\x00${to}\\x00${text}\"`.\n * Cleared on `close()` alongside the KEK and DEKs.\n */\n private readonly translatorCache = new Map<string, string>()\n /** Audit log for all translator invocations in this session. Cleared on `close()`. */\n private readonly _translatorAuditLog: TranslatorAuditEntry[] = []\n\n constructor(options: ResolvedNoydbOptions) {\n this.options = options\n // Debug-plaintext is an unencrypted-only inspection mode; combining it with\n // encryption is meaningless and unsafe, so reject the coupling loudly.\n if (options.debugPlaintext === true && options.encrypt !== false) throw new DebugPlaintextError()\n if (options.debugPlaintext === true) {\n console.warn(\n '[noydb] debugPlaintext is ON — records are stored UNENCRYPTED and laid ' +\n 'out for native store inspection. NEVER use this for production or client data.',\n )\n }\n this.sessionId = options.sessionId ?? generateULID()\n // createNoydb() always resolves the store-backed default before constructing.\n if (!options.coordinationStrategy) {\n throw new ValidationError(\n 'Noydb must be constructed via createNoydb(), which resolves the default coordination provider.',\n )\n }\n this.coordinationProvider = options.coordinationStrategy\n if (!options.userApiFactory) throw new ValidationError('Noydb must be constructed via createNoydb(), which resolves the default user-envelope API factory.')\n this.userApiFactory = options.userApiFactory\n if (!options.policyFactory || !options.policyCheckGateFn) throw new ValidationError('Noydb must be constructed via createNoydb(), which resolves the default policy service.')\n this.policyCheckGate = options.policyCheckGateFn\n // One resolution for the whole instance (#838) — every `?? NO_*` default\n // that used to be scattered across this constructor, the Vault option\n // block, and collection-config now lives in STRATEGY_DEFAULTS.\n this.strategies = resolveStrategies(options)\n this.snapshots = new NoydbSnapshots({\n strategy: this.strategies.snapshots,\n user: options.user,\n isClosed: () => this.closed,\n getVault: (name) => this.vaultCache.get(name),\n onAfterWrite: (h) => this.onAfterWrite(h),\n })\n this.policyManager = options.policyFactory({\n policyCache: this.policyCache,\n policyEnforcers: this.policyEnforcers,\n store: this.options.store,\n encrypted: this.options.encrypt !== false,\n sessionPolicy: this.options.sessionPolicy,\n policyOption: this.options.policy,\n isClosed: () => this.closed,\n resetSessionTimer: () => this.resetSessionTimer(),\n assertRecoveryEnrolled: (vault, policy, opts) =>\n this.assertRecoveryEnrolled(vault, policy, opts),\n onSessionRevoke: (vault) => {\n this.keyringCache.delete(vault)\n this.vaultCache.delete(vault)\n },\n })\n this.#team = new TeamFacade({\n options: this.options,\n keyringCache: this.keyringCache,\n activeTier: this.activeTier,\n quickUnlock: this.quickUnlock,\n policyCache: this.policyCache,\n checkGate: (vault, gate, factors) => this.checkGate(vault, gate, factors),\n checkPolicyOperation: (vault, op) => this.checkPolicyOperation(vault, op),\n getKeyringInternal: (vault, opts) => this._getKeyringInternal(vault, opts),\n assertRecoveryEnrolled: (vault, policy, opts) =>\n this.assertRecoveryEnrolled(vault, policy, opts),\n openVault: (vault, opts) => this.openVault(vault, opts),\n setSkipNextManagedRecoveryCheck: (value) => {\n this._skipNextManagedRecoveryCheck = value\n },\n })\n // Validate sessionPolicy at construction time (developer error if invalid).\n // The strategy's stub throws with a pointer at the subpath if the\n // consumer set a policy without opting in.\n if (options.sessionPolicy) {\n this.strategies.session.validateSessionPolicy(options.sessionPolicy)\n }\n this.#registerGuardGate()\n this.#registerPeriodGate()\n this.#registerForgetHooks()\n this.resetSessionTimer()\n }\n\n /** @internal — resolved forget strategy (NO_FORGET when not configured). */\n get _forgetStrategy(): ForgetStrategy {\n return this.strategies.forget\n }\n\n // GDPR subject-index maintenance. When `withForget` declares\n // any subject fields, keep the encrypted `_subject_index` in lock-step with\n // writes so `vault.forget(subjectId)` can find every record for a subject.\n //\n // Two consumers are required because they cover disjoint events:\n // - onAfterWrite fires on create/update (NOT delete) — add the new ref;\n // on an update that changed the subject value, drop the stale ref.\n // - the subsystemBus `afterDelete` observer fires on delete (onAfterWrite\n // does NOT) — drop the ref so a deleted record never lingers in the\n // index (RISK #2). Without it, forget() would try to shred a ghost.\n #registerForgetHooks(): void {\n const subjects = this.strategies.forget.subjects\n if (Object.keys(subjects).length === 0) return\n\n const subjectFieldFor = (collection: string): string | undefined => subjects[collection]\n\n this.writeHooks.onAfterWrite(async (event) => {\n const field = subjectFieldFor(event.collection)\n if (field === undefined) return\n const vault = this.vaultCache.get(event.vault)\n if (!vault) return\n // Add the ref for the new subject value.\n if (event.after !== null && typeof event.after === 'object') {\n const subjectValue = readDottedPath(event.after as Record<string, unknown>, field)\n if (subjectValue !== undefined && subjectValue !== null) {\n await vault._addSubjectRef(coerceSubjectId(subjectValue), { collection: event.collection, id: event.docId })\n }\n }\n // On update, if the subject value changed, drop the stale ref.\n if (event.op === 'update' && event.before !== null && typeof event.before === 'object') {\n const beforeValue = readDottedPath(event.before as Record<string, unknown>, field)\n const afterValue =\n event.after !== null && typeof event.after === 'object'\n ? readDottedPath(event.after as Record<string, unknown>, field)\n : undefined\n const beforeId = beforeValue === undefined || beforeValue === null ? undefined : coerceSubjectId(beforeValue)\n const afterId = afterValue === undefined || afterValue === null ? undefined : coerceSubjectId(afterValue)\n if (beforeId !== undefined && beforeId !== afterId) {\n await vault._removeSubjectRef(beforeId, { collection: event.collection, id: event.docId })\n }\n }\n })\n\n this.subsystemBus.register('afterDelete', async (event) => {\n const field = subjectFieldFor(event.collection)\n if (field === undefined) return\n const vault = this.vaultCache.get(event.vault)\n if (!vault) return\n if (event.before !== null && typeof event.before === 'object') {\n const subjectValue = readDottedPath(event.before as Record<string, unknown>, field)\n if (subjectValue !== undefined && subjectValue !== null) {\n await vault._removeSubjectRef(coerceSubjectId(subjectValue), { collection: event.collection, id: event.docId })\n }\n }\n })\n }\n\n // Track A — guards migration. Registers record-lock / field-freeze / onDelete\n // / amendment-collect as gate-bus handlers (only when guards are opted in, so\n // the write path is zero-cost otherwise). Resolves the live vault's\n // GuardRegistry per dispatch. Registered BEFORE the period gate so guard\n // checks run first. The amendment branch is a side-effect (collectChange),\n // NOT a throw — and runs even for internal deletes (an amendment invariant\n // must see system housekeeping tombstones); onDelete/checks run only for\n // user (non-internal) operations.\n #registerGuardGate(): void {\n if (this.options.guardStrategies === undefined) return\n this.subsystemBus.registerGate('beforePut', async (e) => {\n const v = this.vaultCache.get(e.vault)\n if (!v) return\n const registry = v._getGuardRegistry()\n if (!registry) return\n const guards = registry.guardsFor(e.collection)\n if (guards.length === 0) return\n const existing = (e.existing ?? null) as Record<string, unknown> | null\n const incoming = e.incoming as Record<string, unknown>\n if (registry.isAmendmentActive()) {\n registry.collectChange(e.collection, e.docId, existing, incoming, e.existingVersion, e.existingVersion + 1)\n return\n }\n const facade = v._getReadOnlyFacade()\n if (!facade) return\n const ctx = { existing, vault: facade, userId: e.userId, role: e.role }\n await registry.runChecks(e.collection, incoming, ctx)\n const { GuardExecutor } = await import('../with-audit/guards/executor.js')\n for (const g of guards) {\n await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming, e.computedFieldNames)\n }\n })\n this.subsystemBus.registerGate('beforeDelete', async (e) => {\n const v = this.vaultCache.get(e.vault)\n if (!v) return\n const registry = v._getGuardRegistry()\n if (!registry) return\n const guards = registry.guardsFor(e.collection)\n if (guards.length === 0) return\n const existing = (e.existing ?? null) as Record<string, unknown> | null\n if (registry.isAmendmentActive()) {\n registry.collectChange(e.collection, e.docId, existing, null as unknown as Record<string, unknown>, e.existingVersion, e.existingVersion)\n return\n }\n if (e.internal) return\n const facade = v._getReadOnlyFacade()\n if (!facade) return\n const ctx = { existing, vault: facade, userId: e.userId, role: e.role }\n await registry.runOnDelete(e.collection, existing ?? {}, ctx)\n })\n }\n\n /**\n * Register closed-period write guards on the service bus when a\n * periodsStrategy is configured. Handlers resolve the live Vault from\n * vaultCache so they always use the up-to-date period cache.\n */\n // Track A — periods migration. Registers the closed-period write guard as a\n // gate-bus handler (only when periods is opted in, so the write path is\n // zero-cost otherwise). Each handler resolves the LIVE vault from the cache\n // per dispatch and delegates to its `_assertTsWritable`, which owns all\n // period logic. Resolving the live vault makes eviction/re-creation\n // transparent. Semantics note: if a write reaches the gate through a retained\n // collection handle whose vault has been evicted from `vaultCache` (e.g. a\n // post-revocation write on a stale handle), the period check is skipped — the\n // guard binds to the live vault, not a captured instance. Periods is a\n // write-integrity guard, not a security boundary, and a re-open reloads the\n // period cache; the trade-off is intentional.\n #registerPeriodGate(): void {\n if (this.options.periodsStrategy === undefined) return\n this.subsystemBus.registerGate('beforePut', async (e) => {\n const v = this.vaultCache.get(e.vault)\n if (!v) return\n const existing = e.op === 'create'\n ? null\n : { ts: e.existingTs ?? null, record: (e.existing ?? null) as Record<string, unknown> | null }\n await v._assertTsWritable(existing, e.incoming as Record<string, unknown>)\n })\n this.subsystemBus.registerGate('beforeDelete', async (e) => {\n if (e.internal) return\n const v = this.vaultCache.get(e.vault)\n if (!v) return\n await v._assertTsWritable(\n { ts: e.existingTs ?? null, record: (e.existing ?? null) as Record<string, unknown> | null },\n null,\n )\n })\n }\n\n private resetSessionTimer(): void {\n if (this.sessionTimer) clearTimeout(this.sessionTimer)\n // Honor the new sessionPolicy.idleTimeoutMs if present, fall back to\n // the legacy sessionTimeout for backwards compatibility.\n const idleMs = this.options.sessionPolicy?.idleTimeoutMs ?? this.options.sessionTimeout\n if (idleMs && idleMs > 0) {\n this.sessionTimer = setTimeout(() => {\n this.close()\n }, idleMs)\n }\n }\n\n /**\n * Touch the policy enforcer for a vault (records activity, resets\n * idle timer). Also touches the legacy session timer. No-op if no enforcer.\n */\n private touchPolicy(vault?: string): void {\n this.policyManager.touchPolicy(vault)\n }\n\n /**\n * Check that a policy-guarded operation is permitted.\n * Throws `SessionPolicyError` if re-auth is required.\n */\n private checkPolicyOperation(vault: string, op: ReAuthOperation): void {\n this.policyManager.checkPolicyOperation(vault, op)\n }\n\n /**\n * Open a vault by name.\n *\n * @param name Vault identifier.\n * @param opts Optional settings for this session.\n * @param opts.locale Default locale for i18n/dictKey field resolution\n *. Set here to avoid passing `{ locale }`\n * on every individual `get()`/`list()` call.\n * @param opts.meta Vault descriptive metadata (label, description, etc.). First-wins: applied on first open, ignored on subsequent opens.\n */\n async openVault(\n name: string,\n opts?: { locale?: string; create?: boolean; meta?: VaultMeta },\n ): Promise<Vault> {\n if (this.closed) throw new ValidationError('Instance is closed')\n this.touchPolicy(name)\n\n let comp = this.vaultCache.get(name)\n if (!comp) {\n // Serialize concurrent opens of the same name (#564): the loser of the\n // race awaits the winner's construction instead of building a second,\n // key-divergent Vault for the same store slice.\n const pending = this.vaultOpening.get(name)\n if (pending) comp = await pending\n }\n if (comp) {\n // Update locale on existing cached vault if specified\n if (opts?.locale !== undefined) {\n comp.setLocale(opts.locale)\n }\n return comp\n }\n\n const opening = this.#openVaultFresh(name, opts)\n this.vaultOpening.set(name, opening)\n try {\n return await opening\n } finally {\n this.vaultOpening.delete(name)\n }\n }\n\n /** Uncached single-flight body of {@link openVault} — see `vaultOpening`. */\n async #openVaultFresh(\n name: string,\n opts?: { locale?: string; create?: boolean; meta?: VaultMeta },\n ): Promise<Vault> {\n const keyring = await this._getKeyringInternal(name, { create: opts?.create !== false })\n // Tier-1 unlock — secret / getKeyring callbacks both yield the\n // most-privileged tier. Tier-2 / tier-3 unlocks install\n // a lower tier here when they land.\n if (!this.activeTier.has(name)) this.activeTier.set(name, 1)\n // Load + persist the policy document. First call: persist the\n // developer-supplied policy (or default preset). Later calls: read\n // whatever's on disk and merge any developer override on top.\n if (this.options.encrypt !== false && !this.policyCache.has(name)) {\n await this.bootstrapPolicy(name)\n }\n\n // Set up sync engine(s) — handles bare NoydbStore, SyncTarget, or SyncTarget[]\n let syncEngine: SyncEngine | undefined\n const targets = normalizeSyncTargets(this.options.sync)\n if (targets.length > 0) {\n // Primary sync engine is the first sync-peer (or first target if none)\n const primary = targets.find(t => t.role === 'sync-peer') ?? targets[0]!\n // #897 — a policy is always RESOLVED (falling back to the store preset), but\n // automation only starts when one was DECLARED. `push: 'on-change'` fires an\n // unawaited push on every write; switching that on for anyone who merely\n // passed `sync:` would make previously-deterministic behaviour racy.\n const declaredPolicy = this.options.syncPolicy ?? primary.policy\n const effectivePolicy = declaredPolicy ?? INDEXED_STORE_POLICY\n syncEngine = this.strategies.sync.buildSyncEngine({\n local: this.options.store,\n remote: primary.store,\n vault: name,\n strategy: this.options.conflict ?? 'version',\n emitter: this.emitter,\n syncPolicy: effectivePolicy,\n role: primary.role,\n ...(primary.label !== undefined ? { label: primary.label } : {}),\n })\n this.syncEngines.set(name, syncEngine)\n // #897 — nothing started the scheduler, so `notifyChange()` returned at its\n // `if (!this.started)` guard on every write and no declared policy ever ran.\n // This is the moment `startScheduler`'s own JSDoc describes: the vault is open.\n if (declaredPolicy) syncEngine.startScheduler()\n\n // Additional targets get their own engines (backup/archive are push-only)\n for (const target of targets) {\n if (target === primary) continue\n const targetPolicy = target.policy ?? this.options.syncPolicy ?? INDEXED_STORE_POLICY\n const engine = this.strategies.sync.buildSyncEngine({\n local: this.options.store,\n remote: target.store,\n vault: name,\n strategy: this.options.conflict ?? 'version',\n emitter: this.emitter,\n syncPolicy: targetPolicy,\n role: target.role,\n ...(target.label !== undefined ? { label: target.label } : {}),\n })\n const key = `${name}::${target.label ?? target.role}`\n this.syncEngines.set(key, engine)\n // #897 — same for additional targets, on the same declared-policy condition.\n if (target.policy ?? this.options.syncPolicy) engine.startScheduler()\n }\n }\n\n const comp = new Vault({\n adapter: this.options.store,\n name,\n noydb: this,\n keyring,\n encrypted: this.options.encrypt !== false,\n emitter: this.emitter,\n onDirty: targets.length > 0\n ? async (coll, id, action, version) => {\n // Fan out dirty tracking to all sync engines for this vault.\n // 'revert' (satellite fan-out compensation, spec #591) un-dirties\n // instead of tracking a new change.\n for (const [key, engine] of this.syncEngines) {\n if (key === name || key.startsWith(`${name}::`)) {\n if (action === 'revert') void engine.removeDirty(coll, id)\n else void engine.trackChange(coll, id, action, version)\n }\n }\n }\n : undefined,\n onRegisterConflictResolver: syncEngine\n ? (resolverName, resolver) => syncEngine.registerConflictResolver(resolverName, resolver)\n : undefined,\n syncAdapter: targets.length > 0 ? targets[0]!.store : undefined,\n getPurgeableTargets: () =>\n targets\n .filter((t) => t.role === 'backup' || t.role === 'archive')\n .map((t) => ({ store: t.store, role: t.role as 'backup' | 'archive', ...(t.label !== undefined ? { label: t.label } : {}) })),\n historyConfig: this.options.history,\n // #838 — the 21 conditional strategy spreads that used to live here are\n // one shared reference. This block is where #834's drift happened: a\n // copy of it silently omitted six strategies, and there was nothing to\n // catch that. There is no longer a per-service line to omit.\n strategies: this.strategies,\n ...(this.options.objectStore !== undefined ? { objectStore: this.options.objectStore } : {}),\n ...(this.options.guardStrategies !== undefined ? { guardStrategies: this.options.guardStrategies } : {}),\n ...(this.options.numbering !== undefined ? { numberingConfigs: this.options.numbering } : {}),\n locale: opts?.locale,\n ...(opts?.meta !== undefined ? { meta: opts.meta } : {}),\n // Thread the translator hook so Collection.put() can invoke it\n plaintextTranslator: this.options.plaintextTranslator\n ? (text, from, to, field, collection) =>\n this.invokeTranslator(text, from, to, field, collection)\n : undefined,\n // Refresh callback used by Vault.load() to re-derive\n // the in-memory keyring from a freshly-loaded keyring file.\n // Encrypted compartments need this so post-load decrypts work\n // against the loaded session's wrapped DEKs; plaintext\n // compartments leave it null and load() skips the refresh.\n reloadKeyring:\n this.options.encrypt !== false && this.options.secret\n ? async () => {\n // Drop the cached keyring so the next loadKeyring\n // call reads fresh from the adapter, then update the\n // cache so subsequent openVault calls see the\n // refreshed keyring too.\n this.keyringCache.delete(name)\n const refreshed = await loadKeyring(this.options.store, name, {\n userId: this.options.user,\n secret: this.options.secret as string,\n })\n this.keyringCache.set(name, refreshed)\n return refreshed\n }\n : undefined,\n })\n // #598: sync-applied writes must refresh Collection in-memory views.\n this._forEachSyncEngine(name, engine => {\n engine.setCacheInvalidator((collection, id, action) => comp._invalidateSyncApplied(collection, id, action))\n engine.setGraphBatchController({ begin: () => comp._beginGraphBatch(), flush: () => comp._flushGraphBatch() })\n engine.setReservedLookupSource({ collections: () => comp._reservedLookupCollectionNames() }) // #650 Task 4\n engine.setReservedDictExpander(names => comp._reservedDictDepsOf(names)) // #653\n engine.setPeriodPullSource({ periods: () => comp.listPeriods() }) // #807 period-scoped pull windows\n })\n // Initialise the optional guard + derivation registries via dynamic-import — no-ops when the\n // corresponding strategies array is empty/unset, keeping the service code out of the floor bundle.\n await comp._initGuards(this.options.guardStrategies ?? [])\n await comp._initDerivations(this.options.derivationStrategies ?? [])\n await comp._initMaterializedViews(this.options.materializedViewStrategies ?? [])\n await comp._initOverlayedViews(this.options.overlayedViewStrategies ?? [])\n // Snapshot the schema-fence generation once per opened vault.\n await comp.schemaFence.init()\n this.vaultCache.set(name, comp)\n return comp\n }\n\n /**\n * Synchronous access to an ALREADY-OPEN vault.\n *\n * Returns the instance `openVault()` produced, or throws — it never\n * constructs. It used to fall back to building a Vault itself (once for\n * plaintext, once for encrypted-with-cached-keyring), and those copies\n * drifted from the real open path: the encrypted one silently omitted six\n * strategies, so a vault reached this way threw `*NotEnabledError` for\n * services the caller had configured (#834). Both fallbacks also skipped\n * the async registry init and schema-fence snapshot that `openVault`\n * performs, which a synchronous method cannot await. One construction\n * path is the only way that divergence stays fixed.\n */\n vault(name: string): Vault {\n const cached = this.vaultCache.get(name)\n if (cached) return cached\n throw new ValidationError(\n `Vault \"${name}\" is not open. Call \\`await db.openVault(\"${name}\")\\` first — ` +\n `vault() only returns an already-open vault, because opening involves ` +\n `async work (registry init, schema fence) that a sync accessor cannot do.`,\n )\n }\n\n /**\n * Grant access to a user for a vault.\n *\n * Gated by `enroll-user`. `STRICT_POLICY` requires a TOTP / email-OTP\n * factor proof so the operator affirmatively re-asserts identity at\n * the moment of grant; `PERSONAL_POLICY` accepts a tier-1 unlock alone.\n *\n * The legacy `requireReAuthFor: ['grant']` session-policy check still\n * fires on top — both are independent opt-ins.\n * Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.\n */\n async grant(\n vault: string,\n options: GrantOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n return this.strategies.team.grant(this.team, vault, options, factors)\n }\n\n /**\n * Revoke a user's access to a vault.\n *\n * Gated by `revoke-user`. `STRICT_POLICY` requires a TOTP / email-OTP\n * factor proof; `PERSONAL_POLICY` accepts a tier-1 unlock alone.\n *\n * The legacy `requireReAuthFor: ['revoke']` session-policy check still\n * fires on top — both are independent opt-ins.\n * Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.\n */\n async revoke(\n vault: string,\n options: RevokeOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n return this.strategies.team.revoke(this.team, vault, options, factors)\n }\n\n /**\n * Grant the FR-6 `custodian` role to a user (owner-only custody API).\n *\n * A custodian operates every collection (rw + access) but is provably\n * unable to grant / revoke / rotate / extract-and-sever. Only the Deed\n * owner may mint one. Defended in depth: the `grant-custodian` gate\n * (fail-closed) AND an explicit `keyring.role !== 'owner'` check — the\n * gate enforces host policy, the role check enforces the cryptographic\n * owner-only invariant even if a host mis-configures the gate.\n */\n async grantCustodian(\n vault: string,\n options: Omit<GrantOptions, 'role'>,\n factors?: FactorProofBundle,\n ): Promise<void> {\n // Opt-in gate (S4): NO_CUSTODY throws CustodyNotEnabledError unless\n // `custodyStrategy: withCustody()` was passed; withCustody() runs the impl.\n return this.strategies.custody.grantCustodian(this as CustodyHost, vault, options, factors)\n }\n\n /** @internal — grant-custodian engine, reached only via withCustody(); the\n * keyring engine arrives as an argument so the floor never carries it (#267). */\n async _grantCustodianImpl(\n engine: (adapter: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, options: GrantOptions) => Promise<void>,\n vault: string,\n options: Omit<GrantOptions, 'role'>,\n factors?: FactorProofBundle,\n ): Promise<void> {\n this.checkPolicyOperation(vault, 'grant')\n await this.checkGate(vault, 'grant-custodian', factors)\n const keyring = await this._getKeyringInternal(vault)\n if (keyring.role !== 'owner') throw new PermissionDeniedError('only the Deed owner can grant a custodian')\n await engine(this.options.store, vault, keyring, { ...options, role: 'custodian' })\n }\n\n /**\n * Revoke a custodian (owner-only custody API).\n *\n * Mirrors {@link revoke} but pins the caller to the Deed owner: defended\n * in depth by the `revoke-user` gate AND an explicit `keyring.role !==\n * 'owner'` check, so an admin cannot unwind a custodianship.\n */\n async revokeCustodian(\n vault: string,\n options: RevokeOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n // Opt-in gate (S4): NO_CUSTODY throws unless withCustody() was opted in.\n return this.strategies.custody.revokeCustodian(this as CustodyHost, vault, options, factors)\n }\n\n /** @internal — revoke-custodian engine, reached only via withCustody().\n * Mirrors `_grantCustodianImpl` (#267: engine passed in). */\n async _revokeCustodianImpl(\n engine: (adapter: NoydbStore, vault: string, callerKeyring: UnlockedKeyring, options: RevokeOptions) => Promise<void>,\n vault: string,\n options: RevokeOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n this.checkPolicyOperation(vault, 'revoke')\n await this.checkGate(vault, 'revoke-user', factors)\n const keyring = await this._getKeyringInternal(vault)\n if (keyring.role !== 'owner') throw new PermissionDeniedError('only the Deed owner can revoke a custodian')\n await engine(this.options.store, vault, keyring, options)\n }\n\n /**\n * Mutate post-grant identity fields on an existing keyring — `role`,\n * `displayName`, and/or `permissions`. Pure plaintext-header rewrite:\n * no DEK rewrap, no KEK required, no authenticator slots touched.\n * Tier-2 enrollments and recovery codes survive.\n *\n * Different from `db.revoke + db.grant`:\n *\n * - Same `userId`, same DEK wrappings, same `granted_by`, same\n * `_users/<keyringId>` envelope. Only the specified header\n * fields move. Last-write-wins via the standard keyring put.\n * - No cascade on role demotion (admins demoted to operator keep\n * the keyrings they previously granted; the cascade rules are\n * a `db.revoke` concern, not `db.updateUser`).\n * - Tier-2 slots NOT dropped — the wrapping is unaffected.\n *\n * Role-elevation guard: BOTH the old and new role must satisfy\n * `db.grant`'s hierarchy. Owner can do anything; admin manages\n * admin/operator/viewer/client laterally; admin cannot promote to\n * owner OR demote from owner. The guard runs regardless of the\n * `update-user` policy gate's settings — gates can only be more\n * permissive than the structural floor, never less.\n *\n * Gated by `update-user`. `STRICT_POLICY` requires a TOTP/email-OTP\n * factor proof so the operator affirmatively re-asserts identity at\n * the moment of mutation; `PERSONAL_POLICY` accepts a tier-1 unlock\n * alone.\n *\n * ```ts\n * await db.updateUser('acme', {\n * userId: 'bob',\n * role: 'operator', // promote\n * permissions: { invoices: 'rw' },\n * }, { factors: [{ kind: 'totp' }] })\n * ```\n *\n * @throws `NoAccessError` when no keyring exists for the target.\n * @throws `PermissionDeniedError` when the role hierarchy rejects.\n * @throws `ValidationError` when no field is provided.\n */\n async updateUser(\n vault: string,\n options: UpdateUserOptions,\n factors?: FactorProofBundle,\n ): Promise<void> {\n await this.checkGate(vault, 'update-user', factors)\n const keyring = await this._getKeyringInternal(vault)\n await updateKeyringIdentity(this.options.store, vault, keyring, options)\n // If the caller updated their own role / permissions, the cached\n // unlocked keyring is stale — drop it so the next access reloads\n // with the new header fields. (DEKs unchanged, so the cached\n // unlock still works; only the role-gated checks would diverge.)\n if (options.userId === this.options.user) {\n this.keyringCache.delete(vault)\n }\n }\n\n /**\n * Rotate the DEKs for the given collections in a vault.\n *\n * Generates fresh DEKs and re-encrypts every record in each collection.\n * The old DEKs become unreachable — useful as a defense-in-depth measure\n * after a suspected key leak, or as the scheduled half of a key-rotation\n * policy.\n *\n * ## Other members LOSE access to the rotated collections (#854)\n *\n * A member's DEKs are wrapped under that member's KEK, and a KEK derives\n * only from that member's secret. The caller cannot derive anyone else's\n * KEK, so re-wrapping a fresh DEK for them is impossible — that is the\n * zero-knowledge property working as designed. Rotation therefore DROPS\n * the rotated collections from every other member's keyring.\n *\n * The returned {@link RotateResult.needsRegrant} names each (member,\n * collection) pair that was dropped. Re-run `grant()` for those pairs, or\n * they stay locked out.\n *\n * Unlike `revoke({ rotateKeys: true })`, this call does not REMOVE any\n * user from the vault — they keep membership and their other collections.\n * This is the \"just rotate\" path; \"revoke and rotate\" lives in `revoke()`.\n *\n * Exposed on Noydb (rather than only on the lower-level keyring\n * module) so CLI and admin tooling can trigger rotation without\n * reaching into internals. See `noy-db rotate` for the CLI wrapper.\n * Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.\n */\n async rotate(vault: string, collections: string[]): Promise<RotateResult> {\n return this.strategies.team.rotate(this.team, vault, collections)\n }\n\n /** List all users with access to a vault. */\n async listUsers(vault: string): Promise<UserInfo[]> {\n return keyringListUsers(this.options.store, vault)\n }\n\n // ─── Cross-vault queries ──────────────────────\n\n /**\n * Enumerate every vault the calling principal can unwrap,\n * optionally filtered by minimum role.\n *\n * The walk is a two-step pipeline: first ask the adapter for the\n * universe of compartments it stores, then for each one attempt to\n * load the calling user's keyring with the in-memory secret.\n * Compartments where the user has no keyring file (`NoAccessError`)\n * or where the secret doesn't unwrap (`InvalidKeyError`) are\n * silently dropped from the result — the existence of those\n * compartments is **not** confirmed in the return value.\n *\n * Requires the optional `NoydbStore.listVaults()` capability.\n * Throws `StoreCapabilityError` against stores that don't\n * implement it (today: store-aws-dynamo, store-aws-s3, store-browser-local, store-browser-idb). For those backends the\n * consumer should either pass an explicit candidate list to\n * `queryAcross()` directly, or maintain a vault index out of\n * band.\n *\n * **Privacy note.** This method's return value never reveals the\n * existence of a vault the caller cannot unwrap. The adapter\n * sees the enumeration call (it has to — it owns the storage), but\n * downstream consumers of `listAccessibleVaults()` only see\n * the filtered list. That's the boundary the existence-leak\n * guarantee draws.\n *\n * **Known edge case.** A vault whose keyring file\n * happens to have an empty wrapped-DEKs map (because the owner\n * granted access before any collection was created) will pass the\n * `loadKeyring` probe with *any* secret — there are no DEKs to\n * unwrap, so the integrity-checked unwrap that normally rejects\n * wrong secrets never runs. The result is that an unrelated\n * principal who happens to know the user-id and the vault\n * name can show up in `listAccessibleVaults()` as having\n * access to that empty vault. They cannot read any actual\n * data (their DEK set is empty), so this is a metadata leak\n * (vault name + user-id), not a content leak. Hardening this\n * via a secret canary in the keyring file is a deferred\n * follow-up.\n *\n * **Cost.** O(compartments × keyring-load) — one `loadKeyring`\n * attempt per vault in the universe. Each attempt does one\n * adapter `get` + one PBKDF2 derivation + N AES-KW unwraps. For\n * dozens of compartments this is fine; for thousands the consumer\n * should cache the result and refresh on grant/revoke events. A\n * future optimization could batch the keyring reads via\n * `loadAll('_keyring')` if such a thing existed at the adapter\n * layer, but the contract doesn't expose that.\n *\n * @example\n * ```ts\n * // All compartments I can unwrap\n * const all = await db.listAccessibleVaults()\n *\n * // Only compartments where I'm at least admin\n * const admin = await db.listAccessibleVaults({ minRole: 'admin' })\n *\n * // Only compartments I own\n * const owned = await db.listAccessibleVaults({ minRole: 'owner' })\n * ```\n */\n async listAccessibleVaults(\n options: ListAccessibleVaultsOptions = {},\n ): Promise<AccessibleVault[]> {\n if (this.closed) throw new ValidationError('Instance is closed')\n this.resetSessionTimer()\n\n const adapter = this.options.store\n if (typeof adapter.listVaults !== 'function') {\n throw new StoreCapabilityError(\n 'listVaults',\n 'Noydb.listAccessibleVaults()',\n adapter.name,\n )\n }\n\n if (this.options.encrypt === false) {\n // Plaintext mode: no keyrings exist; every vault the\n // adapter knows about is \"accessible\" trivially as owner.\n const all = await adapter.listVaults()\n return all.map((id) => ({ id, role: 'owner' as Role }))\n }\n\n if (!this.options.secret) {\n throw new ValidationError(\n 'Noydb.listAccessibleVaults(): a secret (secret) is required ' +\n 'when encryption is enabled.',\n )\n }\n\n const minRank = ROLE_RANK[options.minRole ?? 'client']\n const universe = await adapter.listVaults()\n const accessible: AccessibleVault[] = []\n\n for (const vault of universe) {\n // Probe with loadKeyring directly (NOT getKeyring, which would\n // auto-create a fresh owner keyring on miss — that would\n // silently grant access to every empty vault in the\n // universe and is exactly the wrong shape for an enumeration\n // API). The two expected failure modes — no keyring file, or\n // wrong secret — are caught and silently dropped so the\n // return value never leaks existence.\n let keyring: UnlockedKeyring\n try {\n keyring = await loadKeyring(adapter, vault, {\n userId: this.options.user,\n secret: this.options.secret,\n })\n } catch (err) {\n if (\n err instanceof NoAccessError ||\n err instanceof InvalidKeyError ||\n err instanceof KeyringCorruptError\n ) {\n // No accessible key material for this vault. KeyringCorruptError\n // is included so a single partially-corrupted vault does NOT\n // poison the enumeration of every other healthy vault — the\n // caller can probe a corrupted vault directly via openVault()\n // / loadKeyring() if they want to act on it.\n continue\n }\n throw err // unexpected error — surface it\n }\n\n if (ROLE_RANK[keyring.role] < minRank) continue\n accessible.push({ id: vault, role: keyring.role })\n\n // Opportunistically prime the keyring cache so a subsequent\n // openVault() doesn't have to re-derive the KEK. The cost\n // is one Map.set per vault we already paid to unwrap.\n this.keyringCache.set(vault, keyring)\n }\n\n return accessible\n }\n\n /**\n * Run a per-vault callback against a list of compartments and\n * collect the results.\n *\n * Pure orchestration — there is no new crypto, no new sync, no new\n * authorization layer. Each vault is opened via the existing\n * `openVault()` path (which honors the cache primed by\n * `listAccessibleVaults`), the callback runs against the\n * resulting `Vault` instance, and the result (or thrown\n * error) is captured into the per-vault slot.\n *\n * **Per-vault errors do not abort the fan-out.** If one\n * vault's callback throws, that vault's slot carries\n * the error and the remaining compartments still run. The caller\n * decides how to handle the partition between success and failure.\n * This is the right shape for cross-tenant reports where one\n * tenant's outage shouldn't hide the other tenants' data.\n *\n * **Concurrency** is opt-in via `options.concurrency`. The default\n * is `1` (sequential) — conservative because per-vault\n * callbacks typically do their own I/O and an unbounded fan-out\n * can exhaust adapter connections (DynamoDB throughput, S3 socket\n * limits, browser fetch concurrency). Bump to 4-8 for cloud-backed\n * adapters where parallelism is the whole point.\n *\n * @example\n * ```ts\n * // Cross-tenant invoice totals as a flat list\n * const accessible = await db.listAccessibleVaults({ minRole: 'admin' })\n * const results = await db.queryAcross(\n * accessible.map((c) => c.id),\n * async (comp) => {\n * return comp.collection<Invoice>('invoices').query()\n * .where('month', '==', '2026-03')\n * .toArray()\n * },\n * { concurrency: 4 },\n * )\n * // results: Array<{ vault, result?: Invoice[], error?: Error }>\n *\n * // Compose with exportStream() — cross-vault plaintext export\n * const exports = await db.queryAcross(accessible.map((c) => c.id), async (comp) => {\n * const out: unknown[] = []\n * for await (const chunk of comp.exportStream()) out.push(chunk)\n * return out\n * })\n * ```\n */\n async queryAcross<T>(\n vaultIds: string[],\n fn: (vault: Vault) => Promise<T>,\n options: QueryAcrossOptions = {},\n ): Promise<QueryAcrossResult<T>[]> {\n if (this.closed) throw new ValidationError('Instance is closed')\n this.resetSessionTimer()\n\n const concurrency = Math.max(1, options.concurrency ?? 1)\n const results: QueryAcrossResult<T>[] = new Array(vaultIds.length)\n\n // Tiny inline p-limit. Maintains a sliding window of `concurrency`\n // in-flight promises and schedules the next vault as each\n // one settles. No external dep. Index-keyed result array so the\n // output preserves caller-supplied order even when concurrency\n // > 1 lets later compartments finish before earlier ones.\n let nextIndex = 0\n const inFlight: Set<Promise<void>> = new Set()\n\n const launch = (): Promise<void> | null => {\n if (nextIndex >= vaultIds.length) return null\n const idx = nextIndex++\n const vaultId = vaultIds[idx]!\n const task = (async () => {\n try {\n const comp = await this.openVault(vaultId, { create: options.create !== false })\n const result = await fn(comp)\n results[idx] = { vault: vaultId, result }\n } catch (err) {\n results[idx] = {\n vault: vaultId,\n error: err instanceof Error ? err : new Error(String(err)),\n }\n }\n })()\n inFlight.add(task)\n // Fire-and-forget cleanup. The task itself never rejects (the\n // try/catch above swallows everything into the result slot), so\n // there's no rejection to handle here — `void` tells the linter\n // we know what we're doing.\n void task.finally(() => inFlight.delete(task))\n return task\n }\n\n // Prime the window.\n for (let i = 0; i < concurrency; i++) {\n if (launch() === null) break\n }\n\n // Drain. As each task settles, kick off the next one until the\n // input is exhausted. `Promise.race` against the live set is the\n // simplest way to \"wake up on whichever finishes first\" without\n // pulling in p-limit / async-pool / etc.\n while (inFlight.size > 0) {\n await Promise.race(inFlight)\n while (inFlight.size < concurrency && nextIndex < vaultIds.length) {\n if (launch() === null) break\n }\n }\n\n return results\n }\n\n /**\n * @internal True once `close()` has been called. Read by outward\n * orchestration frameworks whose entry points can't see the private\n * `closed` field.\n */\n get isClosed(): boolean {\n return this.closed\n }\n\n /**\n * @internal — true when an encrypted shard vault is provisioned\n * (its keyring exists in the store).\n */\n async _shardVaultProvisioned(vaultId: string): Promise<boolean> {\n return (await this.options.store.list(vaultId, '_keyring')).length > 0\n }\n\n /**\n * @internal — the physical backend store a vault id maps to. A\n * `routeStore` resolves the vault-prefix route via its `resolveBackend`;\n * a plain store is its own backend. Used by the federation data-residency\n * guard to read the placement backend's `capabilities.region`.\n */\n _resolveBackend(vaultId: string): NoydbStore {\n const store = this.options.store as NoydbStore & {\n resolveBackend?: (vaultId: string) => NoydbStore\n }\n return store.resolveBackend ? store.resolveBackend(vaultId) : this.options.store\n }\n\n /**\n * Change the current user's secret for a vault.\n *\n * Validates the new secret against the strength rules. Pass\n * `{ allowWeakSecret: true }` to skip — typically only useful for\n * fixtures and migrations. Pass a `SecretPolicy` to override the\n * default rules (e.g. consumer-tunable `pattern` / `customValidator`).\n */\n async changeSecret(\n vault: string,\n newSecret: string,\n options?: SecretPolicy & { allowWeakSecret?: boolean },\n ): Promise<void> {\n this.checkPolicyOperation(vault, 'changeSecret')\n const keyring = await this._getKeyringInternal(vault)\n const updated = await keyringChangeSecret(this.options.store, vault, keyring, {\n ...options,\n newSecret,\n })\n this.keyringCache.set(vault, updated)\n }\n\n // ─── Sync ──────────────────────────────────────────────────────\n\n /** Push local changes to remote for a vault. */\n async push(vault: string, options?: PushOptions): Promise<PushResult> {\n const engine = this.getSyncEngine(vault)\n return engine.push(options)\n }\n\n /**\n * Pull remote changes to local for a vault. A `backup`/`archive` primary is a\n * push-only sink and is never pulled from (#616) — returns an empty result.\n */\n async pull(vault: string, options?: PullOptions): Promise<PullResult> {\n const engine = this.getSyncEngine(vault)\n if (engine.role !== 'sync-peer') return emptyPullResult()\n return engine.pull(options)\n }\n\n /**\n * Bidirectional sync: pull then push for all targets.\n * `sync-peer` targets do pull+push; `backup`/`archive` targets do push-only.\n */\n async sync(vault: string, options?: { push?: PushOptions; pull?: PullOptions }): Promise<{ pull: PullResult; push: PushResult }> {\n const primary = this.getSyncEngine(vault)\n const result: { pull: PullResult; push: PushResult } =\n primary.role === 'sync-peer'\n ? await primary.sync(options)\n : { pull: emptyPullResult(), push: await primary.push(options?.push) }\n\n // Fan out push to backup/archive targets (fire-and-mark-dirty)\n for (const [key, engine] of this.syncEngines) {\n if (key === vault) continue\n if (!key.startsWith(`${vault}::`)) continue\n if (engine.role === 'sync-peer') {\n await engine.sync(options).catch((err: Error) => {\n this.emitter.emit('sync:backup-error', {\n vault,\n target: engine.label ?? engine.role,\n error: err,\n })\n })\n } else {\n // backup/archive: push-only\n await engine.push(options?.push).catch((err: Error) => {\n this.emitter.emit('sync:backup-error', {\n vault,\n target: engine.label ?? engine.role,\n error: err,\n })\n })\n }\n }\n\n return result\n }\n\n /**\n * Multi-record atomic transaction.\n *\n * The callback stages writes across any number of vaults /\n * collections; on return the hub pre-flights version checks, then\n * commits every staged op. If the body throws, nothing is\n * persisted. If any staged op fails its `expectedVersion` check,\n * the batch throws `ConflictError` with zero writes performed. If a\n * mid-commit failure occurs after one or more ops have already\n * written, each executed op is reverted best-effort (see\n * `runTransaction` for the crash-window caveat).\n *\n * Distinct from `transaction(vault: string) → SyncTransaction`\n * which batches push/pull across sync peers.\n */\n transaction<T>(fn: (tx: TxContext) => Promise<T> | T): Promise<T>\n /**\n * Open an amendment-mode transaction. Requires `admin` or `owner`\n * role on every vault touched by the body; throws\n * `AmendmentForbiddenError` on first non-privileged `tx.vault(name)`\n * call. Guard `check` callbacks are SKIPPED inside an amendment —\n * the staged change-set is fed to each guard's `amendment.invariant`\n * after the body returns, and the multi-record summary is appended\n * to the vault's ledger as `op: 'amendment'`.\n */\n transaction<T>(\n options: AmendmentTxOptions,\n fn: (tx: TxContext) => Promise<T> | T,\n ): Promise<T>\n /**\n * Dry-run a transaction: run the body to stage ops, then return\n * the directly-affected diff + collected guard violations WITHOUT\n * committing (no adapter writes, no write hooks). MV/derivation cascade\n * is not simulated. Requires `withTransactions()`.\n */\n transaction(\n options: { readonly dryRun: true },\n fn: (tx: TxContext) => unknown,\n ): Promise<DryRunResult>\n /**\n * Create a sync transaction for the given vault.\n * The vault must already be open via `openVault()`.\n * Call `tx.put()` / `tx.delete()` to stage changes, then `tx.commit()`\n * to write all locally and push atomically to remote.\n */\n transaction(vault: string): SyncTransaction\n transaction<T>(\n arg: string | AmendmentTxOptions | { readonly dryRun: true } | ((tx: TxContext) => Promise<T> | T),\n maybeFn?: (tx: TxContext) => Promise<T> | T,\n ): SyncTransaction | Promise<T> | Promise<DryRunResult> {\n if (typeof arg === 'function') {\n return this.strategies.transactions.runTransaction(this, arg)\n }\n if (typeof arg === 'object' && arg !== null && (arg as { dryRun?: boolean }).dryRun === true) {\n // Dry-run form: stage + diff, no commit.\n if (typeof maybeFn !== 'function') {\n throw new ValidationError(\n 'db.transaction({ dryRun: true }, fn) requires the callback as the second argument.',\n )\n }\n return this.strategies.transactions.runDryRun(this, maybeFn)\n }\n if (typeof arg === 'object' && arg !== null && (arg as { amendment?: boolean }).amendment === true) {\n // Two-arg amendment form. We forward `arg` as the options bag —\n // the executor handles reason validation + per-vault role check.\n if (typeof maybeFn !== 'function') {\n throw new ValidationError(\n 'db.transaction({ amendment: true }, fn) requires the callback as the second argument.',\n )\n }\n return this.strategies.transactions.runTransaction(this, maybeFn, arg as AmendmentTxOptions)\n }\n const vault = arg as string\n const comp = this.vaultCache.get(vault)\n if (!comp) {\n throw new ValidationError(\n `Vault \"${vault}\" is not open. Call openVault() first.`,\n )\n }\n const engine = this.getSyncEngine(vault)\n return this.strategies.sync.buildSyncTransaction(comp, engine)\n }\n\n /**\n * Internal accessor for the primary store — used by the tx\n * executor to perform raw adapter reads for pre-flight CAS and\n * raw writes for rollback. Not part of the public API.\n *\n * @internal\n */\n get _store(): NoydbStore {\n return this.options.store\n }\n\n /**\n * Currently-running multi-record transaction, or `null` outside\n * Phase 2. `Collection.dispatchDerivations` consults this so a\n * recursive derived-output write inside `Collection.put` can register\n * its envelope onto `ctx._executed` and roll back with the main\n * staged ops on mid-batch failure.\n *\n * @internal\n */\n get _activeTxContextOrNull(): TxContext | null {\n return this._activeTxContext\n }\n\n /**\n * Called by `runTransaction` at Phase 2 start, and by\n * `Collection.putManyAtomic` (via `derivationSource.setActiveTxContext`)\n * for its own Phase 2 loop. Nested or concurrent (non-nested)\n * transactions on the same Noydb instance are NOT supported —\n * overwriting an active context means another transaction is still\n * running and its `_executed` list would be cross-contaminated by\n * the nested writes. We tolerate the overwrite (best-effort, no\n * throw) to keep the rare interleaving from breaking consumers who\n * currently get lucky with timing, but applications should ensure\n * their multi-record commits are serialised on a single Noydb.\n *\n * @internal\n */\n _setActiveTxContext(ctx: TxContext): void {\n this._activeTxContext = ctx\n }\n\n /**\n * Factory for a transient `TxContext` bound to this Noydb. Used by\n * `Collection.putManyAtomic` (via `derivationSource.createTxContext`)\n * to publish an active context for the duration of its bulk-atomic\n * Phase 2 loop, so recursive derivation-output writes register on\n * `ctx._executed` and roll back together with the source ops.\n *\n * @internal\n */\n _createTxContext(): TxContext {\n return new TxContext(this)\n }\n\n /**\n * Called by `runTransaction` in its `finally`. Only clears when the\n * passed ctx matches the active one — a defensive no-op if some\n * other code path already cleared it.\n *\n * @internal\n */\n _clearActiveTxContext(ctx: TxContext): void {\n if (this._activeTxContext === ctx) {\n this._activeTxContext = null\n }\n }\n\n /** Get sync status for a vault. */\n syncStatus(vault: string): SyncStatus {\n const engine = this.syncEngines.get(vault)\n if (!engine) {\n return { dirty: 0, lastPush: null, lastPull: null, online: true }\n }\n return engine.status()\n }\n\n private getSyncEngine(vault: string): SyncEngine {\n const engine = this.syncEngines.get(vault)\n if (!engine) {\n throw new ValidationError('No sync adapter configured. Pass a `sync` adapter to createNoydb().')\n }\n return engine\n }\n\n _forEachSyncEngine(vault: string, fn: (engine: SyncEngine) => void): void {\n for (const [key, engine] of this.syncEngines) if (key === vault || key.startsWith(`${vault}::`)) fn(engine)\n }\n\n // ─── Events ────────────────────────────────────────────────────\n\n on<K extends keyof NoydbEventMap>(event: K, handler: (data: NoydbEventMap[K]) => void): void {\n this.emitter.on(event, handler)\n }\n\n off<K extends keyof NoydbEventMap>(event: K, handler: (data: NoydbEventMap[K]) => void): void {\n this.emitter.off(event, handler)\n }\n\n /**\n * Observable write-queue for this hub instance. Reflects outstanding\n * in-flight writes across all collections. See {@link WriteQueue}.\n *\n * @example\n * window.addEventListener('beforeunload', (e) => {\n * if (db.writeQueue.pending) { e.preventDefault(); e.returnValue = '' }\n * })\n */\n get writeQueue(): WriteQueue {\n return this.writeQueueTracker\n }\n\n /**\n * @internal Mutable tracker behind {@link writeQueue}. Threaded into\n * each Collection (via Vault) so `put`/`delete` can `track()` writes.\n * Not part of the public surface — consumers use `writeQueue`.\n */\n get _writeQueueTracker(): WriteQueueTracker {\n return this.writeQueueTracker\n }\n\n /**\n * Register a hook that runs before each write. Awaited; a throw\n * aborts the write. Returns an unsubscribe function.\n */\n onBeforeWrite(handler: WriteHook): Unsubscribe {\n return this.writeHooks.onBeforeWrite(handler)\n }\n\n /**\n * Register a hook that runs after each committed write. Awaited;\n * a handler error is warned, never rolled back. Returns an unsubscribe fn.\n */\n onAfterWrite(handler: WriteHook): Unsubscribe {\n return this.writeHooks.onAfterWrite(handler)\n }\n\n /** Subscribe to cross-tab write conflicts. Returns an unsubscribe. */\n onWriteConflict(fn: (c: WriteConflict) => void): Unsubscribe {\n this.on('write:conflict', fn)\n return () => this.off('write:conflict', fn)\n }\n\n /**\n * Enable same-device multi-tab coordination: primary/secondary\n * election + presence. Browser-only — a graceful no-op (role 'unknown')\n * when Web Locks / BroadcastChannel are unavailable and nothing is\n * injected. Idempotent; returns a disposer.\n */\n enableTabCoordination(opts: TabCoordinationOptions = {}): { dispose: () => void } {\n if (this.tabCoordinator) return { dispose: () => this.disableTabCoordination() }\n const lockManager = opts.lockManager ?? defaultLockManager()\n const channel = opts.channel ?? defaultChannel()\n const c = new TabCoordinator({\n ...opts,\n ...(lockManager ? { lockManager } : {}),\n ...(channel ? { channel } : {}),\n // We own the channel only when we created the default; never close a caller-injected one.\n closeChannelOnDispose: opts.channel === undefined && channel !== undefined,\n })\n this.tabCoordinator = c\n c.start()\n if (opts.propagateWrites !== false) {\n const writeChannel = opts.writeChannel ?? defaultChannel('noydb:tab-writes')\n if (writeChannel) {\n const relay = new CrossTabWriteRelay({\n channel: writeChannel,\n writerId: c.tabId,\n subscribeAfterWrite: (h) => this.onAfterWrite(h),\n applyRemoteWrite: (vault, collection, docId, action) => this.#applyRemoteWrite(vault, collection, docId, action),\n reportConflict: (vault, collection, docId, action, baseV, v, ownV) => this.#reportWriteConflict(vault, collection, docId, action, baseV, v, ownV),\n // Own the channel only when we created the default (mirrors the presence channel).\n closeChannelOnDispose: opts.writeChannel === undefined && writeChannel !== undefined,\n })\n this.writeRelay = relay\n relay.start()\n }\n }\n return { dispose: () => this.disableTabCoordination() }\n }\n\n #applyRemoteWrite(vaultName: string, collectionName: string, docId: string, action: 'put' | 'delete'): Promise<void> {\n const v = this.vaultCache.get(vaultName)\n if (!v) return Promise.resolve()\n return v._applyRemoteWrite(collectionName, docId, action)\n }\n\n async #reportWriteConflict(vaultName: string, collectionName: string, docId: string, action: 'put' | 'delete', baseV: number, v: number, ownV: number): Promise<void> {\n const vault = this.vaultCache.get(vaultName)\n if (!vault) return\n const cap = await vault._captureAndConverge(collectionName, docId, action, baseV)\n if (!cap) return\n const conflict: WriteConflict = {\n vault: vaultName, collection: collectionName, docId,\n local: cap.local, remote: cap.remote, base: cap.base,\n localVersion: ownV, remoteVersion: v, baseVersion: baseV,\n }\n this.emitter.emit('write:conflict', conflict)\n }\n\n private disableTabCoordination(): void {\n this.tabCoordinator?.dispose()\n this.tabCoordinator = undefined\n this.writeRelay?.dispose()\n this.writeRelay = undefined\n }\n\n get tabRole(): TabRole { return this.tabCoordinator?.role ?? 'unknown' }\n activeTabs(): TabPresence[] { return this.tabCoordinator?.activeTabs() ?? [] }\n onTabRoleChange(fn: (r: TabRole) => void): Unsubscribe { return this.tabCoordinator?.onTabRoleChange(fn) ?? (() => {}) }\n onActiveTabsChange(fn: (t: TabPresence[]) => void): Unsubscribe { return this.tabCoordinator?.onActiveTabsChange(fn) ?? (() => {}) }\n\n /** @internal The write-hook registry, threaded into each Collection. */\n get _writeHooks(): WriteHookRegistry {\n return this.writeHooks\n }\n\n /** @internal The observe bus, threaded into every Collection. */\n get _subsystemBus(): ServiceBus {\n return this.subsystemBus\n }\n\n /** @internal Stable per-instance id for schema-cutover coordination. */\n get _clientId(): string {\n return this.clientId\n }\n\n /** @internal Session that owns this instance's writers. */\n get _sessionId(): string {\n return this.sessionId\n }\n\n /**\n * @internal Drain-barrier coordination transport for the schema fence.\n * The default store-backed provider reproduces today's fence behavior; a\n * `by-*` real-time transport is injected via `coordinationStrategy`.\n */\n get coordination(): CoordinationProvider {\n return this.coordinationProvider\n }\n\n /**\n * #693: true when multi-tab coordination is active at all — presence/election\n * alone (`propagateWrites: false`) or full write-propagation — a peer tab can\n * write this instance's shared store out-of-band either way, so per-collection\n * marker-id sets are not authoritative and the re-create gate must fall back to\n * a store read. Live (tab coordination is enable/disable-able at runtime).\n */\n get _tabCoordinationActive(): boolean {\n return this.tabCoordinator !== undefined\n }\n\n /**\n * Soft-lock a single vault: clear its in-memory keyring, DEKs, vault\n * instance, sync engine, policy enforcer, and active-tier entry —\n * WITHOUT destroying the `Noydb` instance.\n *\n * Designed for \"lock screen\" UX: the user taps **Lock** and DEKs are\n * scrubbed from memory immediately, but the same `Noydb` instance can\n * be re-unlocked via {@link unlockViaAuthenticator} (tier 2) or\n * {@link unlockViaPin} (tier 3) without re-running `createNoydb`.\n *\n * **QuickUnlock state is preserved.** That's the whole point — the\n * user can still resume via PIN without a full credential re-prompt.\n * The on-disk `_meta/policy` document is also kept in cache (it\n * survives lock; nothing about it changes when DEKs are scrubbed).\n *\n * No-op when `vault` is not currently in cache (idempotent).\n */\n lockVault(vault: string): void {\n // Sync engine: stop autosync + drop the engine so the next openVault\n // builds a fresh one against the freshly-loaded keyring.\n this.syncEngines.get(vault)?.stopAutoSync()\n this.syncEngines.delete(vault)\n // Policy enforcer: cancels its idle timer and any visibility listener.\n this.policyEnforcers.get(vault)?.destroy()\n this.policyEnforcers.delete(vault)\n // Live caches: scrub DEKs, vault instance, active tier.\n this.vaultCache.get(vault)?._stopFenceCoordination() // stop heartbeat/watcher timers\n this.keyringCache.delete(vault)\n this.vaultCache.delete(vault)\n this.activeTier.delete(vault)\n // Intentionally NOT cleared:\n // - this.quickUnlock — preserves PIN resume.\n // - this.policyCache — vault policy is on-disk data, survives lock.\n // - this.strategies.session — no per-vault revoke; close() handles bulk.\n }\n\n close(): void {\n this.closed = true\n this.snapshots.stop()\n // #897 — stop every scheduler's timers alongside the other timer teardown below.\n for (const engine of this.syncEngines.values()) engine.stopScheduler()\n if (this.sessionTimer) {\n clearTimeout(this.sessionTimer)\n this.sessionTimer = null\n }\n // Destroy all policy enforcers (cancels timers + visibility listeners)\n for (const enforcer of this.policyEnforcers.values()) {\n enforcer.destroy()\n }\n this.policyEnforcers.clear()\n // Revoke all in-memory session keys\n this.strategies.session.revokeAllSessions()\n // Stop all sync engines\n for (const engine of this.syncEngines.values()) {\n engine.stopAutoSync()\n }\n this.syncEngines.clear()\n for (const v of this.vaultCache.values()) v._stopFenceCoordination() // stop heartbeat/watcher timers\n for (const v of this.vaultCache.values()) void v._flushSearchIndexes() // best-effort flush\n this.disableTabCoordination() // stop tab lock/heartbeat timers\n this.keyringCache.clear()\n this.vaultCache.clear()\n this.activeTier.clear()\n this.policyCache.clear()\n this.quickUnlock.clear()\n this.emitter.removeAllListeners()\n // Clear translator state — same lifetime as KEK/DEKs\n this.translatorCache.clear()\n this._translatorAuditLog.length = 0\n }\n\n /**\n * Returns a snapshot of all translator invocations since the last\n * `close()`. Useful for testing and compliance auditing. The log is\n * in-memory only — it is cleared when `db.close()` is called.\n *\n * Entries deliberately omit content hashes. See `TranslatorAuditEntry`\n * and issue for the rationale.\n */\n translatorAuditLog(): readonly TranslatorAuditEntry[] {\n return [...this._translatorAuditLog]\n }\n\n /**\n * Invoke the configured `plaintextTranslator` (or serve from cache).\n * Records one `TranslatorAuditEntry` per call regardless of cache hit.\n * Called by `Vault` during `put()` for `autoTranslate: true` fields.\n *\n * @internal — not part of the public API surface\n */\n async invokeTranslator(\n text: string,\n from: string,\n to: string,\n field: string,\n collection: string,\n ): Promise<string> {\n const cacheKey = `${field}\\x00${collection}\\x00${from}\\x00${to}\\x00${text}`\n const translatorName = this.options.plaintextTranslatorName ?? 'anonymous'\n\n const cached = this.translatorCache.get(cacheKey)\n if (cached !== undefined) {\n this._translatorAuditLog.push({\n type: 'translator-invocation',\n field,\n collection,\n fromLocale: from,\n toLocale: to,\n translatorName,\n timestamp: new Date().toISOString(),\n cached: true,\n })\n return cached\n }\n\n const result = await this.options.plaintextTranslator!({ text, from, to, field, collection })\n this.translatorCache.set(cacheKey, result)\n this._translatorAuditLog.push({\n type: 'translator-invocation',\n field,\n collection,\n fromLocale: from,\n toLocale: to,\n translatorName,\n timestamp: new Date().toISOString(),\n })\n return result\n }\n\n // ─── Policy gates (issue #9) ──────────────────────────────────\n /**\n * Read the active policy for a vault. Loads from `_meta/policy` on\n * first call; subsequent calls hit the in-memory cache. Throws\n * `ValidationError` if the vault has not been opened.\n */\n async getPolicy(vault: string): Promise<VaultPolicy> {\n return this.policyManager.getPolicy(vault)\n }\n\n /**\n * Replace the policy document at `_meta/policy` and update the\n * in-memory cache. Gated by the `enroll-user` policy (a policy\n * change is fundamentally a privilege-management action).\n */\n async updatePolicy(vault: string, override: Partial<VaultPolicy>): Promise<VaultPolicy> {\n return this.policyManager.updatePolicy(vault, override)\n }\n\n /**\n * Read the current vault-level user-directory toggle. Returns\n * the default-on shape (`{ enabled: true }`) when no `_meta/directory`\n * document has been persisted yet.\n *\n * No role gate — anyone who can open the vault can read the toggle.\n */\n async getDirectoryEnabled(vault: string): Promise<boolean> {\n if (this.closed) throw new ValidationError('Instance is closed')\n const persisted = await readDirectoryConfig(this.options.store, vault)\n return persisted?.enabled ?? true\n }\n\n /**\n * Toggle the vault's user-directory listing on or off.\n * Owner-only. When disabled, `listUsersWithEnvelopes()` throws\n * {@link import('./errors.js').DirectoryDisabledError} for callers\n * whose role is neither `owner` nor `admin`.\n *\n * Honest caveat: this is a UX flag, not a privacy guarantee. The\n * keyring file at `_keyring/<userId>` and the envelope ciphertext at\n * `_users/<keyringId>` remain observable to anyone with direct store\n * read access — only the hub-level enumeration is gated. See\n * `https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/user-envelope.md` → \"Directory visibility\".\n */\n async setDirectoryEnabled(vault: string, enabled: boolean): Promise<void> {\n if (this.closed) throw new ValidationError('Instance is closed')\n const keyring = await this._getKeyringInternal(vault)\n if (keyring.role !== 'owner') {\n throw new PermissionDeniedError(\n `setDirectoryEnabled requires owner role; caller has role \"${keyring.role}\"`,\n )\n }\n await persistDirectoryConfig(this.options.store, vault, { enabled })\n }\n\n /**\n * Evaluate a policy gate against the active session tier and the\n * presented factor proofs. Throws {@link PolicyDeniedError} on\n * denial; resolves with `void` on success.\n *\n * @param vault The vault whose policy applies.\n * @param gate Gate name — built-in (e.g. `'rotate-secret'`)\n * or app-defined (`app:*`).\n * @param presented Caller-supplied factor proofs.\n */\n async checkGate(\n vault: string,\n gate: GateName,\n factors?: FactorProofBundle,\n ): Promise<void> {\n const policy = await this.getPolicy(vault)\n const tier = this.activeTier.get(vault) ?? 1\n await this.policyCheckGate(policy, gate, {\n activeTier: tier,\n ...(factors?.factors !== undefined ? { factors: factors.factors } : {}),\n ...(factors?.sharedDevice !== undefined\n ? { sharedDevice: factors.sharedDevice }\n : {}),\n })\n }\n\n /** Read or persist the vault policy at `_meta/policy` on first open. */\n private async bootstrapPolicy(\n vault: string,\n opts?: { skipManagedCheck?: boolean },\n ): Promise<void> {\n return this.policyManager.bootstrapPolicy(vault, opts)\n }\n\n /**\n * Throw {@link RecoveryNotEnrolledError} or\n * {@link ManagedRecoveryNotEnrolledError} when recovery enrollment\n * is missing.\n *\n * Two enforcement modes:\n *\n * 1. **Managed-mode mandatory strong-recovery.** When\n * `secretMode === 'managed'`, the vault MUST have at least\n * one **strong** recovery profile (Shamir today). Paper alone is\n * rejected because under managed mode the user has no memorized\n * secret, so losing the paper sheet = losing every record.\n * This check is unconditional — independent of `requireRecovery`\n * and the `recover-secret` gate.\n *\n * 2. **Opt-in strict mandatory-recovery.** When\n * `requireRecovery: true` is set on createNoydb (and the gate is\n * not explicitly disabled), require ANY recovery profile (paper\n * or shamir). This is the v0.x default-off behavior; v1.0 may\n * flip it default-on.\n *\n * The managed-mode check fires from {@link bootstrapPolicy} unless\n * the `skipManagedCheck` flag is set (used by\n * {@link openVaultAndEnrollRecovery} to allow atomic create-and-enroll).\n */\n private async assertRecoveryEnrolled(\n vault: string,\n policy: VaultPolicy,\n opts?: { skipManagedCheck?: boolean },\n ): Promise<void> {\n const skipManaged = (opts?.skipManagedCheck ?? false) || this._skipNextManagedRecoveryCheck\n if (this.options.secretMode === 'managed' && !skipManaged) {\n const enrolled = await hasStrongRecoveryEnrolled(this.options.store, vault)\n if (!enrolled) {\n throw new ManagedRecoveryNotEnrolledError(vault)\n }\n }\n if (this.options.requireRecovery !== true) return\n const gate = policy.gates['recover-secret']\n if (gate?.enabled === false) return\n const enrolled = await hasRecoveryEnrolled(this.options.store, vault)\n if (enrolled) return\n throw new RecoveryNotEnrolledError()\n }\n\n /**\n * Internal accessor used by tier-2/tier-3 unlock paths\n * to mark the active session tier.\n * @internal\n */\n _setActiveTier(vault: string, tier: ActiveTier): void {\n this.activeTier.set(vault, tier)\n }\n\n // ─── Tier-2 enroll / remove ─────────────────────────────────────\n\n\n\n\n\n\n\n // ─── Cover (https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md) ──────\n /**\n * Set the owner-curated cover for a vault. Throws\n * `ValidationError` if the developer did not opt the hub into\n * `cover` via `NoydbOptions`, or if the input violates\n * the resolved schema (oversized icon, disallowed MIME, oversized\n * string, unknown field).\n *\n * `createdAt` is set on the first write and preserved on every\n * subsequent write. `updatedAt` is refreshed on every write.\n * `version` is monotonic — increments on every successful write.\n *\n * `custom` (opt-in via `fields: [..., 'custom']`) patches at the\n * namespace level — provided namespaces replace their previous\n * value, absent ones are preserved, `null` deletes (#800).\n */\n async setCover(\n vault: string,\n input: SetCoverInput,\n ): Promise<Cover> {\n // `cover` wins over the deprecated `publicEnvelope` key (#799).\n const coverOption = this.options.cover\n if (!coverOption) {\n throw new ValidationError(\n 'setCover: the cover feature is not enabled. ' +\n 'Pass `cover: true` (or a schema object) to `createNoydb`.',\n )\n }\n const { loadCover, saveCover, resolveSchema, validateCoverInput, mergeCustom, validateCoverSize } =\n await import('../with-party/directory/cover/index.js')\n const schema = resolveSchema(coverOption)!\n validateCoverInput(input, schema)\n\n const now = new Date().toISOString()\n const existing = await loadCover(this.options.store, vault)\n const next: Cover = {\n _noydb_public: 1,\n version: (existing?.version ?? 0) + 1,\n ...(existing?.createdAt !== undefined ? { createdAt: existing.createdAt } : { createdAt: now }),\n updatedAt: now,\n ...(input.name !== undefined ? { name: input.name } : (existing?.name !== undefined ? { name: existing.name } : {})),\n ...(input.description !== undefined ? { description: input.description } : (existing?.description !== undefined ? { description: existing.description } : {})),\n ...(input.icon !== undefined ? { icon: input.icon } : (existing?.icon !== undefined ? { icon: existing.icon } : {})),\n ...(input.defaultLocale !== undefined ? { defaultLocale: input.defaultLocale } : (existing?.defaultLocale !== undefined ? { defaultLocale: existing.defaultLocale } : {})),\n // #800: namespace-level patch — provided namespaces replace, absent are preserved, `null` deletes.\n ...mergeCustom(existing?.custom, input.custom),\n }\n // #800: size caps run against the WOULD-BE-PERSISTED (post-merge) document.\n validateCoverSize(next, schema)\n await saveCover(this.options.store, vault, next)\n return next\n }\n\n /**\n * Read the cover for a vault. Returns `undefined` when none has\n * been written. Pass `locale` to resolve any locale-map fields to\n * plain strings; omitting `locale` returns the raw map.\n *\n * Works even when the developer didn't enable\n * `cover` — reads are passive and never throw on a\n * missing schema (the cover is plaintext and exists on disk\n * regardless).\n */\n async getCover(\n vault: string,\n opts: { readonly locale?: string } = {},\n ): Promise<Cover | undefined> {\n const { readCover } = await import('../with-party/directory/cover/index.js')\n return readCover(this.options.store, vault, opts)\n }\n\n // ─── Auth introspection ─────────────────────────────────────────\n\n\n\n\n // ─── Tier-1 change flows ────────────────────────────────────────\n\n\n\n\n\n\n\n\n // ─── Tier-3 enroll / unlock ─────────────────────────────────────\n\n\n\n\n /**\n * Live-reference variant used by the hub's own code paths. Internal\n * mutations on `deks` (e.g. {@link ensureCollectionDEK} adding a\n * collection key) need to land on the cached keyring so subsequent\n * accesses see them. Not exposed publicly — callers outside hub\n * should use {@link getKeyring}, which returns a defensive copy.\n */\n private async _getKeyringInternal(\n vault: string,\n opts: { create: boolean } = { create: true },\n ): Promise<UnlockedKeyring> {\n if (this.options.encrypt === false) {\n return createPlaintextKeyring(this.options.user, this.options.debugPlaintext === true)\n }\n\n const cached = this.keyringCache.get(vault)\n if (cached) return cached\n\n // Custom unlock path (e.g. WebAuthn / OIDC / Shamir): caller-supplied\n // callback owns \"open existing vs create new\" — no automatic NoAccessError\n // fallback because the callback owner has the UI context for that choice.\n if (this.options.getKeyring) {\n const keyring = await this.options.getKeyring(vault)\n this.keyringCache.set(vault, keyring)\n return keyring\n }\n\n // Pre-gate: refuse to self-provision into a vault held by other\n // principals; create-on-open only for a genuinely-new vault. Runs BEFORE\n // resolveManagedSecret (which persists on first open) so a fail-closed open\n // writes nothing. encrypt:false returned a plaintext keyring above, so we're\n // always on the encrypted path here. Logic lives in team/keyring.ts.\n await assertKeyringOpenAllowed(this.options.store, vault, this.options.user, opts.create)\n\n // Managed-secret mode — resolve the effective secret\n // before falling into the normal load/create path. The first call\n // mints + seals + persists; subsequent calls unseal what's there.\n // The returned string takes the place of `options.secret` for the\n // rest of this method (and is NOT persisted on `this.options`).\n let effectiveSecret: string | undefined\n if (this.options.secretMode === 'managed') {\n // sealingKey presence was validated at createNoydb time.\n \n effectiveSecret = await resolveManagedSecret(\n this.options.store,\n vault,\n this.options.sealingKey!,\n )\n } else {\n effectiveSecret = this.options.secret\n }\n\n if (!effectiveSecret) {\n throw new ValidationError('A secret (secret) or getKeyring callback is required when encryption is enabled')\n }\n\n let keyring: UnlockedKeyring\n try {\n keyring = await loadKeyring(this.options.store, vault, { userId: this.options.user, secret: effectiveSecret })\n } catch (err) {\n if (err instanceof NoAccessError) {\n // No keyring on disk — first boot or cleared store.\n keyring = await createOwnerKeyring(this.options.store, vault, {\n userId: this.options.user,\n secret: effectiveSecret,\n // Managed mode generates 256-bit base64 strings that don't satisfy\n // the human-secret strength rules (no spaces, no \"words\").\n // Skip validation in managed mode — the entropy floor is already\n // 256 bits by construction.\n validate: this.options.secretMode === 'managed'\n ? false\n : this.options.validateSecret === true,\n })\n } else if (err instanceof InvalidKeyError && this.options.onInvalidKey === 'reset') {\n // Stale keyring: exists in the store but the current credentials can't\n // decrypt it (e.g. the data records were cleared while the _keyring row\n // survived, or a WebAuthn credential was rotated between sessions).\n // The caller opted into reset — delete the stale row and start fresh.\n await this.options.store.delete(vault, '_keyring', this.options.user)\n keyring = await createOwnerKeyring(this.options.store, vault, {\n userId: this.options.user,\n secret: effectiveSecret,\n validate: this.options.secretMode === 'managed'\n ? false\n : this.options.validateSecret === true,\n })\n } else {\n throw err\n }\n }\n\n this.keyringCache.set(vault, keyring)\n return keyring\n }\n\n /**\n * Take an on-demand checkpoint of the given vault.\n * Requires `snapshotsStrategy: withSnapshots({ store })` in `createNoydb`.\n * @throws ValidationError when the vault is not open\n */\n async snapshot(vault: string, opts?: { label?: string; note?: string }): Promise<SnapshotMeta> {\n return this.snapshots.snapshot(vault, opts)\n }\n\n /**\n * List all snapshots for the given vault, newest first.\n * Reads only the sidecar index — does not download snapshot bytes.\n */\n async listSnapshots(vault: string): Promise<SnapshotMeta[]> {\n return this.snapshots.listSnapshots(vault)\n }\n\n /**\n * Restore the vault to a previously snapshotted state.\n * Runs `verifyBackupIntegrity()` automatically on restore.\n * @throws SnapshotNotFoundError when `version` doesn't exist in the store\n * @throws ValidationError when the vault is not open\n */\n async restoreSnapshot(vault: string, version: string): Promise<void> {\n return this.snapshots.restoreSnapshot(vault, version)\n }\n}\n\n/** Create a new NOYDB instance. */\nexport async function createNoydb(options: NoydbOptions): Promise<Noydb> {\n if (!options.store) options = { ...options, store: memoryStore() }\n const encrypted = options.encrypt !== false\n const managed = options.secretMode === 'managed'\n\n if (options.secret && options.getKeyring) {\n throw new ValidationError('Provide either `secret` or `getKeyring`, not both')\n }\n\n // Managed-secret mode — mutually exclusive with both\n // `secret` (the whole point is hub generates and seals; the user\n // doesn't supply one) and `getKeyring` (a custom unlock path that\n // bypasses the sealing flow entirely). Requires a SealingKeyProvider.\n if (managed) {\n if (options.secret) {\n throw new ValidationError(\n '`secretMode: \"managed\"` is mutually exclusive with `secret` — '\n + 'managed mode generates the secret itself. Drop `secret`.',\n )\n }\n if (options.getKeyring) {\n throw new ValidationError(\n '`secretMode: \"managed\"` is mutually exclusive with `getKeyring` — '\n + 'a custom unlock callback would bypass the sealing flow. Drop `getKeyring`.',\n )\n }\n if (!options.sealingKey) {\n throw new ValidationError(\n '`secretMode: \"managed\"` requires `sealingKey: SealingKeyProvider` '\n + '(see @noy-db/seal-macos-keychain / @noy-db/seal-aws-kms / etc.).',\n )\n }\n }\n\n if (encrypted && !managed && !options.secret && !options.getKeyring) {\n throw new ValidationError('A secret (secret) or getKeyring callback is required when encryption is enabled')\n }\n\n if (!options.coordinationStrategy) options = { ...options, coordinationStrategy: await createDefaultCoordinationProvider(options.store!) }\n if (!options.userApiFactory) options = { ...options, userApiFactory: (await import('../with-party/directory/user-envelope/api.js')).createUserApi }\n if (!options.policyFactory) {\n const policyModule = await import('../with-party/policy/index.js')\n options = { ...options, policyFactory: policyModule.createNoydbPolicy, policyCheckGateFn: policyModule.checkGate }\n }\n\n return new Noydb(options as ResolvedNoydbOptions)\n}\n\n// ─── Internal helpers ─────────────────────────────────────────────────\n\n/**\n * Normalize `NoydbOptions.sync` to a `SyncTarget[]`.\n * Accepts a bare NoydbStore, a SyncTarget, or an array.\n */\nfunction normalizeSyncTargets(\n sync: NoydbOptions['sync'],\n): SyncTarget[] {\n if (!sync) return []\n if (Array.isArray(sync)) return sync\n // SyncTarget has a `role` property; bare NoydbStore does not\n if ('role' in sync && typeof sync.role === 'string') {\n return [sync]\n }\n // Bare NoydbStore — wrap as sync-peer\n return [{ store: sync as NoydbStore, role: 'sync-peer' }]\n}\n"],"mappings":"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","names":["ref","via","via","cached","out","previousEnvelope","record","ref","ref","opts","ref","handle","generateULID","enrolled","keyring"]}
|