@noy-db/hub 0.3.0-pre.2 → 0.3.0-pre.4
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/adapter/index.d.ts +2 -2
- package/dist/adapter/index.js +1 -1
- package/dist/aggregate/index.d.ts +3 -3
- package/dist/aggregate/index.js +4 -4
- package/dist/api-JOXUNSKP.js +20 -0
- package/dist/as/index.d.ts +4 -4
- package/dist/as/index.js +12 -6
- package/dist/at/index.d.ts +2 -2
- package/dist/attestation/index.d.ts +3 -3
- package/dist/attestation/index.js +19 -13
- package/dist/attestation/index.js.map +1 -1
- package/dist/{backup-KMJQ66MF.js → backup-MOB27UUN.js} +12 -6
- package/dist/{backup-KMJQ66MF.js.map → backup-MOB27UUN.js.map} +1 -1
- package/dist/blobs/index.d.ts +4 -4
- package/dist/blobs/index.js +11 -5
- package/dist/blobs/index.js.map +1 -1
- package/dist/bundle/index.d.ts +5 -5
- package/dist/bundle/index.js +21 -15
- package/dist/bundle/index.js.map +1 -1
- package/dist/{bundle-PwBGkhpe.d.ts → bundle-Bs13EZtX.d.ts} +1 -1
- package/dist/by/index.js +2 -2
- package/dist/cargo/index.d.ts +4 -4
- package/dist/cargo/index.js +23 -17
- package/dist/{chunk-SMXWYP24.js → chunk-3QRQOBS7.js} +3 -3
- package/dist/{chunk-QHJW5EXU.js → chunk-3Y4QLJ6K.js} +2 -2
- package/dist/{chunk-NF5JWERG.js → chunk-43ISXURO.js} +2 -2
- package/dist/{chunk-5LUY7UTV.js → chunk-4K3MQ5S3.js} +2 -2
- package/dist/{chunk-QZISFCVG.js → chunk-5CY35H55.js} +11 -9
- package/dist/{chunk-QZISFCVG.js.map → chunk-5CY35H55.js.map} +1 -1
- package/dist/chunk-5EWYUR5P.js +37 -0
- package/dist/chunk-5EWYUR5P.js.map +1 -0
- package/dist/{chunk-Y22T3KQE.js → chunk-5MRE3C4Q.js} +5 -5
- package/dist/{chunk-M6OST55S.js → chunk-5W7AOFWA.js} +2 -2
- package/dist/{chunk-AXRXJTE2.js → chunk-6HNKCKFZ.js} +7 -7
- package/dist/{chunk-UAG5KWVA.js → chunk-6RXPSMKR.js} +3 -3
- package/dist/{chunk-TJYQIGAP.js → chunk-7J7JRYXW.js} +9 -5
- package/dist/chunk-7J7JRYXW.js.map +1 -0
- package/dist/{chunk-UDRIWL7A.js → chunk-A5DYVMDR.js} +3 -3
- package/dist/chunk-AF5ZRTZ4.js +108 -0
- package/dist/chunk-AF5ZRTZ4.js.map +1 -0
- package/dist/{chunk-I3TIKTJO.js → chunk-BKGIWGCX.js} +2 -2
- package/dist/{chunk-IO6GRPT6.js → chunk-BMQOH7MM.js} +2 -2
- package/dist/{chunk-26LGBE4T.js → chunk-CPXPHQGX.js} +6 -4
- package/dist/{chunk-26LGBE4T.js.map → chunk-CPXPHQGX.js.map} +1 -1
- package/dist/{chunk-FISN7WE4.js → chunk-EWR7HL3K.js} +4 -4
- package/dist/{chunk-AQTBSL7R.js → chunk-FH52CDEW.js} +5 -5
- package/dist/chunk-G4MGYGSS.js +130 -0
- package/dist/chunk-G4MGYGSS.js.map +1 -0
- package/dist/{chunk-UV5MFVO3.js → chunk-G7RDYYTE.js} +2 -2
- package/dist/{chunk-UIU2THRG.js → chunk-GBTUANXF.js} +16 -297
- package/dist/chunk-GBTUANXF.js.map +1 -0
- package/dist/{chunk-TEILUWOI.js → chunk-GOUNIHFA.js} +10 -10
- package/dist/{chunk-LXQT4WMP.js → chunk-GQOT6QJR.js} +8 -6
- package/dist/{chunk-LXQT4WMP.js.map → chunk-GQOT6QJR.js.map} +1 -1
- package/dist/{chunk-RUEKROOS.js → chunk-GXGK22QU.js} +2 -2
- package/dist/{chunk-IELYAOGG.js → chunk-GZZL5R73.js} +4 -4
- package/dist/{chunk-JNUWZ6D3.js → chunk-H5XRIJX3.js} +7 -5
- package/dist/{chunk-JNUWZ6D3.js.map → chunk-H5XRIJX3.js.map} +1 -1
- package/dist/{chunk-CWPPNPOH.js → chunk-H7RYPVMJ.js} +2 -2
- package/dist/{chunk-5N6CZTCY.js → chunk-HBKDR7R3.js} +3 -3
- package/dist/{chunk-KXGNJJXB.js → chunk-HLUKZ36Q.js} +9 -9
- package/dist/{chunk-LMTH2RM6.js → chunk-HMXLN43G.js} +2 -2
- package/dist/{chunk-BG3SPSR4.js → chunk-HY6ZGGEC.js} +2 -2
- package/dist/{chunk-UPJNJGGA.js → chunk-K5P46KB3.js} +27 -10
- package/dist/chunk-K5P46KB3.js.map +1 -0
- package/dist/chunk-KYY7L72M.js +106 -0
- package/dist/chunk-KYY7L72M.js.map +1 -0
- package/dist/{chunk-62QYRORB.js → chunk-LIP6JWYK.js} +3 -3
- package/dist/{chunk-5TDJ56JE.js → chunk-LN22XH4B.js} +1 -1
- package/dist/chunk-LN22XH4B.js.map +1 -0
- package/dist/chunk-LP7BEXCT.js +32 -0
- package/dist/chunk-LP7BEXCT.js.map +1 -0
- package/dist/{chunk-IGUYVGGI.js → chunk-LPRPVCNY.js} +5 -5
- package/dist/{chunk-AIWULCUO.js → chunk-M66NAZA4.js} +5 -3
- package/dist/{chunk-AIWULCUO.js.map → chunk-M66NAZA4.js.map} +1 -1
- package/dist/{chunk-KVOXU4T5.js → chunk-N5YVZHCB.js} +2 -2
- package/dist/{chunk-76722EBH.js → chunk-NB47TXGP.js} +14 -12
- package/dist/{chunk-76722EBH.js.map → chunk-NB47TXGP.js.map} +1 -1
- package/dist/chunk-NO272T7Q.js +194 -0
- package/dist/chunk-NO272T7Q.js.map +1 -0
- package/dist/{chunk-SRB2XEWB.js → chunk-O2DB4C3M.js} +8 -6
- package/dist/{chunk-SRB2XEWB.js.map → chunk-O2DB4C3M.js.map} +1 -1
- package/dist/{chunk-IUEN57TV.js → chunk-OFBFAVLI.js} +6 -6
- package/dist/{chunk-MTMJVJ5W.js → chunk-OPTFANOX.js} +5 -3
- package/dist/chunk-OPTFANOX.js.map +1 -0
- package/dist/{chunk-5O3AOPDT.js → chunk-OVO2RZAE.js} +212 -439
- package/dist/chunk-OVO2RZAE.js.map +1 -0
- package/dist/{chunk-GYGWYIOZ.js → chunk-P27Z66EB.js} +7 -5
- package/dist/{chunk-GYGWYIOZ.js.map → chunk-P27Z66EB.js.map} +1 -1
- package/dist/{chunk-HCIPRAGS.js → chunk-P2LDXRGP.js} +2 -2
- package/dist/chunk-P3NGV5RV.js +41 -0
- package/dist/chunk-P3NGV5RV.js.map +1 -0
- package/dist/{chunk-5R3ERCDH.js → chunk-P3V7JTB6.js} +25 -9
- package/dist/{chunk-5R3ERCDH.js.map → chunk-P3V7JTB6.js.map} +1 -1
- package/dist/{chunk-LV7M27WM.js → chunk-P5WXDYMD.js} +8 -197
- package/dist/chunk-P5WXDYMD.js.map +1 -0
- package/dist/chunk-PGFY7IRW.js +95 -0
- package/dist/chunk-PGFY7IRW.js.map +1 -0
- package/dist/chunk-QKVILR7N.js +25 -0
- package/dist/chunk-QKVILR7N.js.map +1 -0
- package/dist/{chunk-V7RWQRG7.js → chunk-QNTEDPWP.js} +3 -3
- package/dist/{chunk-Q7SS3IME.js → chunk-RDHAGBEB.js} +3 -3
- package/dist/{chunk-EIZUR2XW.js → chunk-RTS23VIJ.js} +2 -2
- package/dist/{chunk-LFLXAY2W.js → chunk-SEQ2JI3Y.js} +9 -7
- package/dist/{chunk-LFLXAY2W.js.map → chunk-SEQ2JI3Y.js.map} +1 -1
- package/dist/{chunk-AZAOEIKW.js → chunk-SW56GSYC.js} +2 -2
- package/dist/{chunk-TA66UMI4.js → chunk-T2EGAXPM.js} +2 -2
- package/dist/{chunk-SM3AVUHC.js → chunk-T45LAT2Y.js} +2 -2
- package/dist/{chunk-SKF73JOP.js → chunk-T65UZXR6.js} +3 -3
- package/dist/{chunk-ITNUCOXM.js → chunk-TB5RNNJ4.js} +7 -5
- package/dist/{chunk-ITNUCOXM.js.map → chunk-TB5RNNJ4.js.map} +1 -1
- package/dist/chunk-TCIUO62Z.js +29 -0
- package/dist/chunk-TCIUO62Z.js.map +1 -0
- package/dist/chunk-THNJ3IKU.js +17 -0
- package/dist/chunk-THNJ3IKU.js.map +1 -0
- package/dist/chunk-TLJOJBZD.js +404 -0
- package/dist/chunk-TLJOJBZD.js.map +1 -0
- package/dist/chunk-TQ3REHVF.js +95 -0
- package/dist/chunk-TQ3REHVF.js.map +1 -0
- package/dist/{chunk-DGDI2D4M.js → chunk-TVRQ3RYH.js} +28 -7
- package/dist/chunk-TVRQ3RYH.js.map +1 -0
- package/dist/{chunk-PSMV73A5.js → chunk-TYGW5TOR.js} +7 -7
- package/dist/{chunk-ZYUC53LT.js → chunk-U23JUUPX.js} +58 -2
- package/dist/{chunk-ZYUC53LT.js.map → chunk-U23JUUPX.js.map} +1 -1
- package/dist/{chunk-3YFXJ3ZP.js → chunk-U24XHXNK.js} +2 -2
- package/dist/chunk-ULIHDPKL.js +94 -0
- package/dist/chunk-ULIHDPKL.js.map +1 -0
- package/dist/chunk-UOEWDCUX.js +69 -0
- package/dist/chunk-UOEWDCUX.js.map +1 -0
- package/dist/{chunk-WWGT2MDV.js → chunk-VAWY44JW.js} +8 -8
- package/dist/{chunk-WWGT2MDV.js.map → chunk-VAWY44JW.js.map} +1 -1
- package/dist/chunk-VFRNWE5P.js +239 -0
- package/dist/chunk-VFRNWE5P.js.map +1 -0
- package/dist/{chunk-IPB7FTQX.js → chunk-VMJ5URU7.js} +10 -8
- package/dist/chunk-VMJ5URU7.js.map +1 -0
- package/dist/{chunk-VFQGRQIH.js → chunk-VPCMJ5Z4.js} +7 -5
- package/dist/{chunk-VFQGRQIH.js.map → chunk-VPCMJ5Z4.js.map} +1 -1
- package/dist/{chunk-VCTFO5CO.js → chunk-VRPBEOWU.js} +2 -2
- package/dist/{chunk-ZCGAHGUS.js → chunk-VWGCJUTV.js} +2 -2
- package/dist/{chunk-XXYIOFUB.js → chunk-XJR3COJO.js} +5 -5
- package/dist/{chunk-PKHL44ER.js → chunk-XYYW64LB.js} +2 -2
- package/dist/{chunk-IAGBDSCS.js → chunk-YFF2RP3X.js} +2 -2
- package/dist/{chunk-MD3Y6J3L.js → chunk-Z3FZC5GV.js} +7 -5
- package/dist/{chunk-MD3Y6J3L.js.map → chunk-Z3FZC5GV.js.map} +1 -1
- package/dist/{chunk-DFEMTNPJ.js → chunk-Z5PIUYNB.js} +10 -8
- package/dist/{chunk-DFEMTNPJ.js.map → chunk-Z5PIUYNB.js.map} +1 -1
- package/dist/{chunk-WYSO2NIH.js → chunk-Z7KI4WHR.js} +2 -2
- package/dist/chunk-ZKF6HH7V.js +120 -0
- package/dist/chunk-ZKF6HH7V.js.map +1 -0
- package/dist/{chunk-I2NOIW44.js → chunk-ZKYMKF2S.js} +8 -6
- package/dist/{chunk-I2NOIW44.js.map → chunk-ZKYMKF2S.js.map} +1 -1
- package/dist/{chunk-PSHOXR6C.js → chunk-ZPHDGUZZ.js} +737 -1082
- package/dist/chunk-ZPHDGUZZ.js.map +1 -0
- package/dist/{chunk-CMGR4ZEW.js → chunk-ZROMNP7Q.js} +2 -2
- package/dist/classified/index.d.ts +17 -0
- package/dist/classified/index.js +38 -0
- package/dist/collection-facade-MKEBZDWW.js +39 -0
- package/dist/computed-BMMEFRFJ.js +11 -0
- package/dist/config-drift-KGM7ZRW4.js +24 -0
- package/dist/config-drift-KGM7ZRW4.js.map +1 -0
- package/dist/consent/index.d.ts +3 -3
- package/dist/consent/index.js +10 -4
- package/dist/consent/index.js.map +1 -1
- package/dist/crdt/index.d.ts +3 -3
- package/dist/delegation-BQNIEHZE.js +25 -0
- package/dist/derivations/index.d.ts +4 -4
- package/dist/derivations/index.js +12 -6
- package/dist/describe/index.d.ts +1 -1
- package/dist/{describe-Ccd1hS7a.d.ts → describe-C6iHNlqJ.d.ts} +19 -0
- package/dist/{dev-unlock-h0K-UZTk.d.ts → dev-unlock-Cqd5Xv5J.d.ts} +1 -1
- package/dist/{enclave-UL5LW66V.js → enclave-YN6223OG.js} +47 -18
- package/dist/executor-CBTNU5VZ.js +9 -0
- package/dist/executor-DJHNSTIR.js +9 -0
- package/dist/executor-FGISLQIN.js +21 -0
- package/dist/export-accessible-P7SLRLK3.js +23 -0
- package/dist/extract-partition-RNVSFHAB.js +36 -0
- package/dist/{fanout-sidecar-GF3DJ6KR.js → fanout-sidecar-WS22Q5WH.js} +17 -14
- package/dist/fanout-sidecar-WS22Q5WH.js.map +1 -0
- package/dist/fence-watcher-DHQ775JB.js +69 -0
- package/dist/fence-watcher-DHQ775JB.js.map +1 -0
- package/dist/find-RNBG7LBY.js +11 -0
- package/dist/forget/index.js +10 -4
- package/dist/forget/index.js.map +1 -1
- package/dist/guards/index.d.ts +4 -4
- package/dist/guards/index.js +3 -3
- package/dist/{hash-CdSr06sm.d.ts → hash-D8Q5MJLA.d.ts} +7 -2
- package/dist/history/index.d.ts +4 -4
- package/dist/history/index.js +12 -6
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.d.ts +3 -3
- package/dist/i18n/index.js +14 -8
- package/dist/i18n/index.js.map +1 -1
- package/dist/in/index.d.ts +2 -2
- package/dist/{index-_6At2_9_.d.ts → index-D4GQe1Rx.d.ts} +1058 -49
- package/dist/{index-CGLLRtFc.d.ts → index-DRxk8q_7.d.ts} +3 -3
- package/dist/index.d.ts +60 -15
- package/dist/index.js +1081 -121
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.d.ts +3 -3
- package/dist/indexing/index.js +4 -4
- package/dist/issue-W5QG53B5.js +19 -0
- package/dist/json-schema-I22JCYCG.js +44 -0
- package/dist/json-schema-I22JCYCG.js.map +1 -0
- package/dist/kernel/index.d.ts +3 -3
- package/dist/kernel/index.js +13 -7
- package/dist/lazy/index.d.ts +21 -0
- package/dist/lazy/index.js +12 -0
- package/dist/{ledger-RYI35CDS.js → ledger-KZWBKAG5.js} +12 -6
- package/dist/liberate-GMGCHIND.js +24 -0
- package/dist/link-set-UQEIYQAM.js +31 -0
- package/dist/materialized-views/index.d.ts +4 -4
- package/dist/materialized-views/index.js +16 -10
- package/dist/{mime-magic-B4RoFj3B.d.ts → mime-magic-DmwT7OzZ.d.ts} +1 -1
- package/dist/noydb-KS2O2MRI.js +60 -0
- package/dist/on/index.d.ts +2 -2
- package/dist/on/index.js +10 -4
- package/dist/overlay-views/index.d.ts +4 -4
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.d.ts +3 -3
- package/dist/periods/index.js +13 -7
- package/dist/pod/index.d.ts +3 -3
- package/dist/pod/index.js +12 -6
- package/dist/{policy-IXK4FVXP.js → policy-YIKUH4AD.js} +5 -5
- package/dist/portability/index.d.ts +3 -3
- package/dist/portability/index.js +8 -8
- package/dist/{public-envelope-JHDQCPSX.js → public-envelope-MRN5YYZZ.js} +4 -4
- package/dist/query/index.d.ts +2 -2
- package/dist/query/index.js +6 -6
- package/dist/register-K6DDSIXN.js +21 -0
- package/dist/registry-IMNMHWTM.js +17 -0
- package/dist/registry-K6VUQXKV.js +19 -0
- package/dist/registry-ZVO3T4M5.js +9 -0
- package/dist/registry-ZVO3T4M5.js.map +1 -0
- package/dist/request-withdrawal-EHALV66Y.js +31 -0
- package/dist/request-withdrawal-EHALV66Y.js.map +1 -0
- package/dist/reveal-TBLTFWQ2.js +38 -0
- package/dist/reveal-TBLTFWQ2.js.map +1 -0
- package/dist/revoke-MHAUAESM.js +24 -0
- package/dist/revoke-MHAUAESM.js.map +1 -0
- package/dist/sealed-record/index.d.ts +3 -3
- package/dist/sealed-record/index.js +13 -7
- package/dist/sealed-record/index.js.map +1 -1
- package/dist/session/index.d.ts +4 -4
- package/dist/session/index.js +10 -4
- package/dist/session/index.js.map +1 -1
- package/dist/shadow/index.d.ts +3 -3
- package/dist/shadow/index.js +2 -2
- package/dist/signer-PQ74YXRY.js +25 -0
- package/dist/signer-PQ74YXRY.js.map +1 -0
- package/dist/snapshots/index.d.ts +3 -3
- package/dist/snapshots/index.js +11 -5
- package/dist/snapshots/index.js.map +1 -1
- package/dist/{stale-3JWHNDIY.js → stale-7Q62KVI3.js} +2 -2
- package/dist/stale-7Q62KVI3.js.map +1 -0
- package/dist/storage-5E6YB2JY.js +21 -0
- package/dist/storage-5E6YB2JY.js.map +1 -0
- package/dist/{store-coordination-provider-3I7XWZZK.js → store-coordination-provider-JJCEMTAE.js} +3 -3
- package/dist/sync/index.d.ts +2 -2
- package/dist/sync/index.js +10 -4
- package/dist/sync/index.js.map +1 -1
- package/dist/team/index.d.ts +18 -4
- package/dist/team/index.js +24 -11
- package/dist/tiers/index.d.ts +2 -2
- package/dist/tiers/index.js +11 -5
- package/dist/to/index.d.ts +2 -2
- package/dist/to/index.js +1 -1
- package/dist/{transition-guard-DqodPNKw.d.ts → transition-guard-C4hvR-Ac.d.ts} +1 -1
- package/dist/tx/index.d.ts +3 -3
- package/dist/tx/index.js +3 -3
- package/dist/ui/index.d.ts +1 -1
- package/dist/util/index.js +1 -1
- package/dist/validators-Ctgkj5qd.d.ts +101 -0
- package/dist/{vault-diff-BtpiBvic.d.ts → vault-diff-B1Ir6EGs.d.ts} +1 -1
- package/dist/verify-YB5LQHNA.js +139 -0
- package/dist/verify-YB5LQHNA.js.map +1 -0
- package/dist/walk-5C3GPKT2.js +241 -0
- package/dist/walk-5C3GPKT2.js.map +1 -0
- package/dist/with/index.d.ts +3 -3
- package/dist/with/index.js +12 -6
- package/dist/{with-materialized-view-DMmWtYfJ.d.ts → with-materialized-view-Bp65kKdQ.d.ts} +1 -1
- package/dist/{with-overlayed-view-D_IB2nkM.d.ts → with-overlayed-view-BRhdQNrK.d.ts} +1 -1
- package/dist/{with-rollup-em2wxoHP.d.ts → with-rollup-bQRPc3y1.d.ts} +1 -1
- package/dist/withdraw-accessible-JMX2TCPX.js +28 -0
- package/dist/withdraw-accessible-JMX2TCPX.js.map +1 -0
- package/package.json +11 -3
- package/dist/api-RW3KP7WU.js +0 -14
- package/dist/chunk-5O3AOPDT.js.map +0 -1
- package/dist/chunk-5TDJ56JE.js.map +0 -1
- package/dist/chunk-DGDI2D4M.js.map +0 -1
- package/dist/chunk-IPB7FTQX.js.map +0 -1
- package/dist/chunk-LV7M27WM.js.map +0 -1
- package/dist/chunk-M2YKN37S.js +0 -524
- package/dist/chunk-M2YKN37S.js.map +0 -1
- package/dist/chunk-MTMJVJ5W.js.map +0 -1
- package/dist/chunk-PSHOXR6C.js.map +0 -1
- package/dist/chunk-TJYQIGAP.js.map +0 -1
- package/dist/chunk-UIU2THRG.js.map +0 -1
- package/dist/chunk-UPJNJGGA.js.map +0 -1
- package/dist/collection-facade-GQAOGJP2.js +0 -33
- package/dist/delegation-UL5HKLER.js +0 -19
- package/dist/executor-2FWQRLMG.js +0 -15
- package/dist/executor-QZ7BXICW.js +0 -9
- package/dist/executor-Z5ZLJVTV.js +0 -9
- package/dist/export-accessible-KRV5W4GH.js +0 -17
- package/dist/extract-partition-GLKBOXFQ.js +0 -30
- package/dist/fanout-sidecar-GF3DJ6KR.js.map +0 -1
- package/dist/issue-Y6UVIR43.js +0 -13
- package/dist/liberate-CRPZEV7O.js +0 -18
- package/dist/noydb-LDEBLNHY.js +0 -50
- package/dist/registry-45RJNWGU.js +0 -9
- package/dist/registry-5GRV5VXI.js +0 -13
- package/dist/registry-WEUCHBO4.js +0 -11
- package/dist/request-withdrawal-GBPH2FDY.js +0 -25
- package/dist/revoke-TUFRGI6S.js +0 -18
- package/dist/signer-PNKTBVF7.js +0 -19
- package/dist/withdraw-accessible-FFS46EOD.js +0 -22
- /package/dist/{api-RW3KP7WU.js.map → api-JOXUNSKP.js.map} +0 -0
- /package/dist/{chunk-SMXWYP24.js.map → chunk-3QRQOBS7.js.map} +0 -0
- /package/dist/{chunk-QHJW5EXU.js.map → chunk-3Y4QLJ6K.js.map} +0 -0
- /package/dist/{chunk-NF5JWERG.js.map → chunk-43ISXURO.js.map} +0 -0
- /package/dist/{chunk-5LUY7UTV.js.map → chunk-4K3MQ5S3.js.map} +0 -0
- /package/dist/{chunk-Y22T3KQE.js.map → chunk-5MRE3C4Q.js.map} +0 -0
- /package/dist/{chunk-M6OST55S.js.map → chunk-5W7AOFWA.js.map} +0 -0
- /package/dist/{chunk-AXRXJTE2.js.map → chunk-6HNKCKFZ.js.map} +0 -0
- /package/dist/{chunk-UAG5KWVA.js.map → chunk-6RXPSMKR.js.map} +0 -0
- /package/dist/{chunk-UDRIWL7A.js.map → chunk-A5DYVMDR.js.map} +0 -0
- /package/dist/{chunk-I3TIKTJO.js.map → chunk-BKGIWGCX.js.map} +0 -0
- /package/dist/{chunk-IO6GRPT6.js.map → chunk-BMQOH7MM.js.map} +0 -0
- /package/dist/{chunk-FISN7WE4.js.map → chunk-EWR7HL3K.js.map} +0 -0
- /package/dist/{chunk-AQTBSL7R.js.map → chunk-FH52CDEW.js.map} +0 -0
- /package/dist/{chunk-UV5MFVO3.js.map → chunk-G7RDYYTE.js.map} +0 -0
- /package/dist/{chunk-TEILUWOI.js.map → chunk-GOUNIHFA.js.map} +0 -0
- /package/dist/{chunk-RUEKROOS.js.map → chunk-GXGK22QU.js.map} +0 -0
- /package/dist/{chunk-IELYAOGG.js.map → chunk-GZZL5R73.js.map} +0 -0
- /package/dist/{chunk-CWPPNPOH.js.map → chunk-H7RYPVMJ.js.map} +0 -0
- /package/dist/{chunk-5N6CZTCY.js.map → chunk-HBKDR7R3.js.map} +0 -0
- /package/dist/{chunk-KXGNJJXB.js.map → chunk-HLUKZ36Q.js.map} +0 -0
- /package/dist/{chunk-LMTH2RM6.js.map → chunk-HMXLN43G.js.map} +0 -0
- /package/dist/{chunk-BG3SPSR4.js.map → chunk-HY6ZGGEC.js.map} +0 -0
- /package/dist/{chunk-62QYRORB.js.map → chunk-LIP6JWYK.js.map} +0 -0
- /package/dist/{chunk-IGUYVGGI.js.map → chunk-LPRPVCNY.js.map} +0 -0
- /package/dist/{chunk-KVOXU4T5.js.map → chunk-N5YVZHCB.js.map} +0 -0
- /package/dist/{chunk-IUEN57TV.js.map → chunk-OFBFAVLI.js.map} +0 -0
- /package/dist/{chunk-HCIPRAGS.js.map → chunk-P2LDXRGP.js.map} +0 -0
- /package/dist/{chunk-V7RWQRG7.js.map → chunk-QNTEDPWP.js.map} +0 -0
- /package/dist/{chunk-Q7SS3IME.js.map → chunk-RDHAGBEB.js.map} +0 -0
- /package/dist/{chunk-EIZUR2XW.js.map → chunk-RTS23VIJ.js.map} +0 -0
- /package/dist/{chunk-AZAOEIKW.js.map → chunk-SW56GSYC.js.map} +0 -0
- /package/dist/{chunk-TA66UMI4.js.map → chunk-T2EGAXPM.js.map} +0 -0
- /package/dist/{chunk-SM3AVUHC.js.map → chunk-T45LAT2Y.js.map} +0 -0
- /package/dist/{chunk-SKF73JOP.js.map → chunk-T65UZXR6.js.map} +0 -0
- /package/dist/{chunk-PSMV73A5.js.map → chunk-TYGW5TOR.js.map} +0 -0
- /package/dist/{chunk-3YFXJ3ZP.js.map → chunk-U24XHXNK.js.map} +0 -0
- /package/dist/{chunk-VCTFO5CO.js.map → chunk-VRPBEOWU.js.map} +0 -0
- /package/dist/{chunk-ZCGAHGUS.js.map → chunk-VWGCJUTV.js.map} +0 -0
- /package/dist/{chunk-XXYIOFUB.js.map → chunk-XJR3COJO.js.map} +0 -0
- /package/dist/{chunk-PKHL44ER.js.map → chunk-XYYW64LB.js.map} +0 -0
- /package/dist/{chunk-IAGBDSCS.js.map → chunk-YFF2RP3X.js.map} +0 -0
- /package/dist/{chunk-WYSO2NIH.js.map → chunk-Z7KI4WHR.js.map} +0 -0
- /package/dist/{chunk-CMGR4ZEW.js.map → chunk-ZROMNP7Q.js.map} +0 -0
- /package/dist/{collection-facade-GQAOGJP2.js.map → classified/index.js.map} +0 -0
- /package/dist/{delegation-UL5HKLER.js.map → collection-facade-MKEBZDWW.js.map} +0 -0
- /package/dist/{enclave-UL5LW66V.js.map → computed-BMMEFRFJ.js.map} +0 -0
- /package/dist/{executor-2FWQRLMG.js.map → delegation-BQNIEHZE.js.map} +0 -0
- /package/dist/{executor-QZ7BXICW.js.map → enclave-YN6223OG.js.map} +0 -0
- /package/dist/{executor-Z5ZLJVTV.js.map → executor-CBTNU5VZ.js.map} +0 -0
- /package/dist/{export-accessible-KRV5W4GH.js.map → executor-DJHNSTIR.js.map} +0 -0
- /package/dist/{extract-partition-GLKBOXFQ.js.map → executor-FGISLQIN.js.map} +0 -0
- /package/dist/{issue-Y6UVIR43.js.map → export-accessible-P7SLRLK3.js.map} +0 -0
- /package/dist/{ledger-RYI35CDS.js.map → extract-partition-RNVSFHAB.js.map} +0 -0
- /package/dist/{liberate-CRPZEV7O.js.map → find-RNBG7LBY.js.map} +0 -0
- /package/dist/{noydb-LDEBLNHY.js.map → issue-W5QG53B5.js.map} +0 -0
- /package/dist/{policy-IXK4FVXP.js.map → lazy/index.js.map} +0 -0
- /package/dist/{public-envelope-JHDQCPSX.js.map → ledger-KZWBKAG5.js.map} +0 -0
- /package/dist/{registry-45RJNWGU.js.map → liberate-GMGCHIND.js.map} +0 -0
- /package/dist/{registry-5GRV5VXI.js.map → link-set-UQEIYQAM.js.map} +0 -0
- /package/dist/{registry-WEUCHBO4.js.map → noydb-KS2O2MRI.js.map} +0 -0
- /package/dist/{request-withdrawal-GBPH2FDY.js.map → policy-YIKUH4AD.js.map} +0 -0
- /package/dist/{revoke-TUFRGI6S.js.map → public-envelope-MRN5YYZZ.js.map} +0 -0
- /package/dist/{signer-PNKTBVF7.js.map → register-K6DDSIXN.js.map} +0 -0
- /package/dist/{stale-3JWHNDIY.js.map → registry-IMNMHWTM.js.map} +0 -0
- /package/dist/{withdraw-accessible-FFS46EOD.js.map → registry-K6VUQXKV.js.map} +0 -0
- /package/dist/{store-coordination-provider-3I7XWZZK.js.map → store-coordination-provider-JJCEMTAE.js.map} +0 -0
|
@@ -1,22 +1,35 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
jsonSchemaToFields
|
|
3
|
+
} from "./chunk-TQ3REHVF.js";
|
|
4
4
|
import {
|
|
5
5
|
NO_SEQUENCE,
|
|
6
6
|
SEQUENCE_COLLECTION,
|
|
7
7
|
compileSequenceFormat,
|
|
8
8
|
resolveSequenceKey
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-P27Z66EB.js";
|
|
10
|
+
import {
|
|
11
|
+
loadVaultPolicy
|
|
12
|
+
} from "./chunk-T45LAT2Y.js";
|
|
13
|
+
import {
|
|
14
|
+
LinkIntegrityError,
|
|
15
|
+
isLinkCollectionName,
|
|
16
|
+
linkCollectionName,
|
|
17
|
+
linkRowKey
|
|
18
|
+
} from "./chunk-P3NGV5RV.js";
|
|
19
|
+
import {
|
|
20
|
+
derivePersistedSchema,
|
|
21
|
+
isZod4Schema
|
|
22
|
+
} from "./chunk-ULIHDPKL.js";
|
|
10
23
|
import {
|
|
11
24
|
loadFence
|
|
12
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-YFF2RP3X.js";
|
|
13
26
|
import {
|
|
14
27
|
InvertedIndex,
|
|
15
28
|
MemoryIndexStore,
|
|
16
29
|
NO_SEARCH,
|
|
17
30
|
VectorSet,
|
|
18
31
|
buildPersistedIndexCallbacks
|
|
19
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-GOUNIHFA.js";
|
|
20
33
|
import {
|
|
21
34
|
ServiceBus,
|
|
22
35
|
WriteHookRegistry,
|
|
@@ -24,58 +37,65 @@ import {
|
|
|
24
37
|
assertCanImport,
|
|
25
38
|
canExport,
|
|
26
39
|
canImport
|
|
27
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-P3V7JTB6.js";
|
|
28
41
|
import {
|
|
29
42
|
NO_ATTESTATION
|
|
30
|
-
} from "./chunk-
|
|
43
|
+
} from "./chunk-Z7KI4WHR.js";
|
|
44
|
+
import {
|
|
45
|
+
NO_CLASSIFIED,
|
|
46
|
+
enforceClassifiedWrite,
|
|
47
|
+
resolveClassifiedFields
|
|
48
|
+
} from "./chunk-AF5ZRTZ4.js";
|
|
31
49
|
import {
|
|
32
50
|
NO_TIERS,
|
|
33
51
|
classifySealedShred
|
|
34
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-VMJ5URU7.js";
|
|
35
53
|
import {
|
|
36
54
|
NO_PORTABILITY
|
|
37
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-N5YVZHCB.js";
|
|
38
56
|
import {
|
|
39
57
|
CustodyApi,
|
|
40
58
|
NO_CARGO,
|
|
41
59
|
NO_CUSTODY
|
|
42
|
-
} from "./chunk-
|
|
60
|
+
} from "./chunk-7J7JRYXW.js";
|
|
43
61
|
import {
|
|
44
62
|
runDrainBarrier
|
|
45
|
-
} from "./chunk-
|
|
63
|
+
} from "./chunk-3Y4QLJ6K.js";
|
|
64
|
+
import {
|
|
65
|
+
PERIODS_COLLECTION
|
|
66
|
+
} from "./chunk-GZZL5R73.js";
|
|
46
67
|
import {
|
|
47
68
|
TxContext,
|
|
48
69
|
revertExecuted
|
|
49
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-T65UZXR6.js";
|
|
50
71
|
import {
|
|
51
72
|
OverlayedCollection
|
|
52
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-ZROMNP7Q.js";
|
|
53
74
|
import {
|
|
54
75
|
EXPORT_AUDIT_COLLECTION,
|
|
55
76
|
createExportBlobsHandle,
|
|
56
77
|
runCompaction
|
|
57
|
-
} from "./chunk-
|
|
78
|
+
} from "./chunk-5MRE3C4Q.js";
|
|
58
79
|
import {
|
|
59
80
|
LazyQuery,
|
|
60
81
|
decodeIdxId,
|
|
61
82
|
encodeIdxId
|
|
62
|
-
} from "./chunk-
|
|
83
|
+
} from "./chunk-QNTEDPWP.js";
|
|
63
84
|
import {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
85
|
+
IMPLICIT_LAZY,
|
|
86
|
+
Lru,
|
|
87
|
+
estimateRecordBytes
|
|
88
|
+
} from "./chunk-NO272T7Q.js";
|
|
67
89
|
import {
|
|
68
90
|
resolveManagedSecret,
|
|
69
91
|
saveSealedPassphrase
|
|
70
|
-
} from "./chunk-
|
|
71
|
-
import {
|
|
72
|
-
PERIODS_COLLECTION
|
|
73
|
-
} from "./chunk-IELYAOGG.js";
|
|
92
|
+
} from "./chunk-VWGCJUTV.js";
|
|
74
93
|
import {
|
|
75
94
|
isDictCollectionName,
|
|
76
95
|
isStaticDictDescriptor
|
|
77
|
-
} from "./chunk-
|
|
96
|
+
} from "./chunk-SEQ2JI3Y.js";
|
|
78
97
|
import {
|
|
98
|
+
NO_TEAM,
|
|
79
99
|
enrollAuthenticator,
|
|
80
100
|
findAuthenticator,
|
|
81
101
|
recoverPassphrase,
|
|
@@ -84,7 +104,7 @@ import {
|
|
|
84
104
|
rotatePassphrase,
|
|
85
105
|
updateAuthenticator,
|
|
86
106
|
writeMagicLinkGrant
|
|
87
|
-
} from "./chunk-
|
|
107
|
+
} from "./chunk-K5P46KB3.js";
|
|
88
108
|
import {
|
|
89
109
|
hasRecoveryEnrolled,
|
|
90
110
|
hasStrongRecoveryEnrolled,
|
|
@@ -94,7 +114,7 @@ import {
|
|
|
94
114
|
mintShamirRecoveryEntry,
|
|
95
115
|
savePaperRecoveryEntries,
|
|
96
116
|
saveShamirRecoveryEntries
|
|
97
|
-
} from "./chunk-
|
|
117
|
+
} from "./chunk-LPRPVCNY.js";
|
|
98
118
|
import {
|
|
99
119
|
INDEXED_STORE_POLICY
|
|
100
120
|
} from "./chunk-VQNJ7UZL.js";
|
|
@@ -104,25 +124,22 @@ import {
|
|
|
104
124
|
changeSecret,
|
|
105
125
|
createOwnerKeyring,
|
|
106
126
|
ensureCollectionDEK,
|
|
107
|
-
grant,
|
|
108
127
|
hasAccess,
|
|
109
128
|
hasWritePermission,
|
|
110
129
|
listUsers,
|
|
111
130
|
loadKeyring,
|
|
112
|
-
revoke,
|
|
113
|
-
rotateKeys,
|
|
114
131
|
updateKeyringIdentity
|
|
115
|
-
} from "./chunk-
|
|
132
|
+
} from "./chunk-VAWY44JW.js";
|
|
116
133
|
import {
|
|
117
134
|
persistDirectoryConfig,
|
|
118
135
|
readDirectoryConfig
|
|
119
|
-
} from "./chunk-
|
|
136
|
+
} from "./chunk-TB5RNNJ4.js";
|
|
120
137
|
import {
|
|
121
138
|
generateULID
|
|
122
139
|
} from "./chunk-ZJADGNYF.js";
|
|
123
140
|
import {
|
|
124
|
-
sha256Hex
|
|
125
|
-
} from "./chunk-
|
|
141
|
+
sha256Hex
|
|
142
|
+
} from "./chunk-M66NAZA4.js";
|
|
126
143
|
import {
|
|
127
144
|
NO_FORGET,
|
|
128
145
|
addSubjectRef,
|
|
@@ -131,52 +148,54 @@ import {
|
|
|
131
148
|
readDottedPath,
|
|
132
149
|
rebuildSubjectIndex,
|
|
133
150
|
removeSubjectRef
|
|
134
|
-
} from "./chunk-
|
|
151
|
+
} from "./chunk-O2DB4C3M.js";
|
|
135
152
|
import {
|
|
136
153
|
NO_SEALED_RECORD
|
|
137
|
-
} from "./chunk-
|
|
154
|
+
} from "./chunk-G7RDYYTE.js";
|
|
138
155
|
import {
|
|
139
156
|
RecordCodec,
|
|
140
157
|
SEALED_CEK_NS,
|
|
141
|
-
buildTombstone,
|
|
142
|
-
encrypt,
|
|
143
158
|
findByDet,
|
|
144
159
|
hasPerRecordKey,
|
|
145
|
-
isTombstone,
|
|
146
160
|
openEnvelopeJson,
|
|
147
161
|
queryByDet,
|
|
148
162
|
resolveStableCek,
|
|
149
|
-
sha256Hex,
|
|
150
163
|
validateSchemaInput
|
|
151
|
-
} from "./chunk-
|
|
164
|
+
} from "./chunk-OVO2RZAE.js";
|
|
165
|
+
import {
|
|
166
|
+
buildTombstone,
|
|
167
|
+
isTombstone
|
|
168
|
+
} from "./chunk-QKVILR7N.js";
|
|
152
169
|
import {
|
|
153
170
|
NOYDB_FORMAT_VERSION
|
|
154
|
-
} from "./chunk-
|
|
171
|
+
} from "./chunk-LN22XH4B.js";
|
|
172
|
+
import {
|
|
173
|
+
encrypt
|
|
174
|
+
} from "./chunk-TLJOJBZD.js";
|
|
155
175
|
import {
|
|
156
176
|
NO_AGGREGATE,
|
|
157
177
|
Query,
|
|
158
|
-
ScanBuilder
|
|
159
|
-
|
|
160
|
-
canonicalizeStoredMoney,
|
|
161
|
-
decodeMoneyFields,
|
|
162
|
-
quantizeMoneyFields,
|
|
163
|
-
validateMoneyFieldPaths
|
|
164
|
-
} from "./chunk-UIU2THRG.js";
|
|
178
|
+
ScanBuilder
|
|
179
|
+
} from "./chunk-GBTUANXF.js";
|
|
165
180
|
import {
|
|
166
181
|
canonicalGroupKey
|
|
167
|
-
} from "./chunk-
|
|
182
|
+
} from "./chunk-P5WXDYMD.js";
|
|
168
183
|
import {
|
|
184
|
+
moneyRuntime,
|
|
169
185
|
readPath
|
|
170
|
-
} from "./chunk-
|
|
186
|
+
} from "./chunk-ZKF6HH7V.js";
|
|
171
187
|
import {
|
|
172
188
|
getAtPath,
|
|
173
189
|
resolvePolicy,
|
|
174
190
|
setAtPathInPlace,
|
|
175
191
|
stripI18nFilled
|
|
176
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-4K3MQ5S3.js";
|
|
177
193
|
import {
|
|
178
194
|
AlreadyElevatedError,
|
|
179
195
|
AttestationError,
|
|
196
|
+
ClassifiedConfigError,
|
|
197
|
+
ClassifiedRevealError,
|
|
198
|
+
ClassifiedVerifyError,
|
|
180
199
|
ConflictError,
|
|
181
200
|
DebugPlaintextError,
|
|
182
201
|
DerivationCapExceededError,
|
|
@@ -207,40 +226,79 @@ import {
|
|
|
207
226
|
UnknownDictCodeError,
|
|
208
227
|
UnsupportedIndexOptionError,
|
|
209
228
|
ValidationError
|
|
210
|
-
} from "./chunk-
|
|
229
|
+
} from "./chunk-U23JUUPX.js";
|
|
211
230
|
|
|
212
231
|
// src/port/by/default-provider.ts
|
|
213
232
|
async function createDefaultCoordinationProvider(store) {
|
|
214
|
-
const { StoreCoordinationProvider } = await import("./store-coordination-provider-
|
|
233
|
+
const { StoreCoordinationProvider } = await import("./store-coordination-provider-JJCEMTAE.js");
|
|
215
234
|
return new StoreCoordinationProvider(store);
|
|
216
235
|
}
|
|
217
236
|
|
|
218
|
-
// src/with-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
237
|
+
// src/with-shape/classified/guards.ts
|
|
238
|
+
function guardClassifiedCompat(collection, byField, ctx) {
|
|
239
|
+
const digestOnly = Object.entries(byField).filter(([, s]) => s.storage === "digest-only");
|
|
240
|
+
const protectedForms = Object.values(byField).filter((s) => s.storage === "digest-only" || s.storage === "recoverable");
|
|
241
|
+
if (protectedForms.length > 0 && (ctx.crdt || ctx.hasConflictPolicy)) {
|
|
242
|
+
throw new ClassifiedConfigError(
|
|
243
|
+
collection,
|
|
244
|
+
"digest-only/recoverable classified fields cannot combine with a crdt mode or a conflictPolicy resolver \u2014 merge paths bypass write enforcement (R2)"
|
|
224
245
|
);
|
|
225
|
-
this.field = field;
|
|
226
|
-
this.id = id;
|
|
227
|
-
this.cause = cause;
|
|
228
|
-
this.name = "ComputedFieldError";
|
|
229
246
|
}
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
247
|
+
for (const [f, spec] of Object.entries(byField)) {
|
|
248
|
+
if (spec.equatable === true && spec.storage !== "digest-only") {
|
|
249
|
+
throw new ClassifiedConfigError(
|
|
250
|
+
collection,
|
|
251
|
+
`field "${f}" declares equatable but storage is '${spec.storage}' \u2014 equatable is a digest-only knob; recoverable equality is _det's job (R7)`
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
const hasEquatable = Object.values(byField).some((s) => s.equatable === true);
|
|
256
|
+
if (hasEquatable && ctx.acknowledgeEquatableRisk !== true) {
|
|
257
|
+
throw new ClassifiedConfigError(
|
|
258
|
+
collection,
|
|
259
|
+
`classified equatable fields require \`acknowledgeEquatableRisk: true\` \u2014 equal values produce equal store-visible index tags (a partition leak a DEK holder can offline-dictionary at the PBKDF2 floor); the door is the real control for low-entropy fields (R8)`
|
|
260
|
+
);
|
|
261
|
+
}
|
|
262
|
+
if (digestOnly.length === 0) return;
|
|
263
|
+
if (!ctx.storeCiphertext) {
|
|
264
|
+
throw new ClassifiedConfigError(
|
|
265
|
+
collection,
|
|
266
|
+
`storage:'digest-only' requires an encrypted collection \u2014 with encrypt: false the write path skips the digest slot entirely and the secret would persist as raw plaintext`
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
if (!ctx.perRecordKeys) {
|
|
270
|
+
throw new ClassifiedConfigError(
|
|
271
|
+
collection,
|
|
272
|
+
`storage:'digest-only' requires perRecordKeys: true \u2014 vdig keys derive from the per-record CEK so forget() shreds them (R1)`
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
for (const [f, spec] of digestOnly) {
|
|
276
|
+
const n = spec.notLastN ?? 0;
|
|
277
|
+
if (!Number.isInteger(n) || n < 0 || n > 8) {
|
|
278
|
+
throw new ClassifiedConfigError(
|
|
279
|
+
collection,
|
|
280
|
+
`digest-only field "${f}" declares notLastN ${n} \u2014 must be an integer 0..8 (write cost is n \xD7 600K PBKDF2; ring blast radius is documented)`
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
if (ctx.bareSensitiveFields.has(f)) {
|
|
284
|
+
throw new ClassifiedConfigError(
|
|
285
|
+
collection,
|
|
286
|
+
`field "${f}" is digest-only AND listed in sensitive[] \u2014 storage forms are mutually exclusive per field (R5)`
|
|
287
|
+
);
|
|
288
|
+
}
|
|
289
|
+
if (ctx.deterministicFields?.has(f)) {
|
|
290
|
+
throw new ClassifiedConfigError(
|
|
291
|
+
collection,
|
|
292
|
+
`digest-only field "${f}" cannot be deterministic \u2014 equality-correlatable ciphertext defeats per-write salts (R3)`
|
|
293
|
+
);
|
|
294
|
+
}
|
|
295
|
+
if (ctx.indexedFields.has(f) || ctx.textIndexFields.has(f) || ctx.vectorSourceFields.has(f) || ctx.subjectKeyField === f) {
|
|
296
|
+
throw new ClassifiedConfigError(
|
|
297
|
+
collection,
|
|
298
|
+
`digest-only field "${f}" cannot be indexed, text-indexed, embedded, or a forget-subject key (R4)`
|
|
299
|
+
);
|
|
241
300
|
}
|
|
242
301
|
}
|
|
243
|
-
return out;
|
|
244
302
|
}
|
|
245
303
|
|
|
246
304
|
// src/with-lookup/indexing/collection-facade.ts
|
|
@@ -497,89 +555,6 @@ async function purgePersistedIndexes(ctx, id) {
|
|
|
497
555
|
return { purged, residue };
|
|
498
556
|
}
|
|
499
557
|
|
|
500
|
-
// src/with-shape/persisted-schemas/canonicalize.ts
|
|
501
|
-
function canonicalize(value) {
|
|
502
|
-
if (value === null || typeof value !== "object") {
|
|
503
|
-
return JSON.stringify(value);
|
|
504
|
-
}
|
|
505
|
-
if (Array.isArray(value)) {
|
|
506
|
-
return "[" + value.map(canonicalize).join(",") + "]";
|
|
507
|
-
}
|
|
508
|
-
const obj = value;
|
|
509
|
-
const keys = Object.keys(obj).sort();
|
|
510
|
-
const parts = keys.map((k) => JSON.stringify(k) + ":" + canonicalize(obj[k]));
|
|
511
|
-
return "{" + parts.join(",") + "}";
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
// src/with-shape/persisted-schemas/derive.ts
|
|
515
|
-
function isZodSchema(value) {
|
|
516
|
-
if (value === null || typeof value !== "object") return false;
|
|
517
|
-
const std = value["~standard"];
|
|
518
|
-
if (std && typeof std === "object" && std.vendor === "zod") return true;
|
|
519
|
-
const def = value._def;
|
|
520
|
-
if (!def || typeof def !== "object") return false;
|
|
521
|
-
return typeof def.typeName === "string" && def.typeName.startsWith("Zod");
|
|
522
|
-
}
|
|
523
|
-
function detectKind(validator) {
|
|
524
|
-
if (isZodSchema(validator)) return "Zod";
|
|
525
|
-
return "Unknown";
|
|
526
|
-
}
|
|
527
|
-
function isZod4Schema(value) {
|
|
528
|
-
if (value === null || typeof value !== "object") return false;
|
|
529
|
-
return "_zod" in value;
|
|
530
|
-
}
|
|
531
|
-
async function loadZodToJsonSchemaConverter() {
|
|
532
|
-
try {
|
|
533
|
-
const mod = await import("zod-to-json-schema");
|
|
534
|
-
if (!mod.zodToJsonSchema) {
|
|
535
|
-
throw new Error("zod-to-json-schema export missing");
|
|
536
|
-
}
|
|
537
|
-
return mod.zodToJsonSchema;
|
|
538
|
-
} catch (err) {
|
|
539
|
-
throw new Error(
|
|
540
|
-
`persistJsonSchema requires the optional peer-dep \`zod-to-json-schema\`. Install it: \`pnpm add zod-to-json-schema\` (or npm/yarn equivalent). Original error: ${err instanceof Error ? err.message : String(err)}`
|
|
541
|
-
);
|
|
542
|
-
}
|
|
543
|
-
}
|
|
544
|
-
async function loadZodV4Converter() {
|
|
545
|
-
try {
|
|
546
|
-
const mod = await import("./zod-HAJM7LMS.js");
|
|
547
|
-
if (typeof mod.toJSONSchema !== "function") {
|
|
548
|
-
throw new Error("zod.toJSONSchema not available (zod v4 required)");
|
|
549
|
-
}
|
|
550
|
-
return mod.toJSONSchema;
|
|
551
|
-
} catch (err) {
|
|
552
|
-
throw new Error(
|
|
553
|
-
`persistJsonSchema with a Zod v4 schema requires zod@4 with toJSONSchema. Original error: ${err instanceof Error ? err.message : String(err)}`
|
|
554
|
-
);
|
|
555
|
-
}
|
|
556
|
-
}
|
|
557
|
-
async function derivePersistedSchema(validator) {
|
|
558
|
-
const kind = detectKind(validator);
|
|
559
|
-
const derivedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
560
|
-
if (kind === "Zod") {
|
|
561
|
-
let jsonSchema;
|
|
562
|
-
if (isZod4Schema(validator)) {
|
|
563
|
-
const convert = await loadZodV4Converter();
|
|
564
|
-
jsonSchema = convert(validator);
|
|
565
|
-
} else {
|
|
566
|
-
const convert = await loadZodToJsonSchemaConverter();
|
|
567
|
-
jsonSchema = convert(validator);
|
|
568
|
-
}
|
|
569
|
-
const canonical = canonicalize(jsonSchema);
|
|
570
|
-
const hash = await sha256Hex(new TextEncoder().encode(canonical));
|
|
571
|
-
return { _noydb_schema: 1, kind, jsonSchema, hash, derivedAt };
|
|
572
|
-
}
|
|
573
|
-
return {
|
|
574
|
-
_noydb_schema: 1,
|
|
575
|
-
kind,
|
|
576
|
-
jsonSchema: null,
|
|
577
|
-
hash: null,
|
|
578
|
-
reason: `derivation not yet supported for kind=${kind} (v0 supports Zod only)`,
|
|
579
|
-
derivedAt
|
|
580
|
-
};
|
|
581
|
-
}
|
|
582
|
-
|
|
583
558
|
// src/with-lookup/indexing/strategy.ts
|
|
584
559
|
var NO_INDEXING = {
|
|
585
560
|
createState() {
|
|
@@ -825,97 +800,6 @@ function resolveFieldMeta(key, inputs) {
|
|
|
825
800
|
};
|
|
826
801
|
}
|
|
827
802
|
|
|
828
|
-
// src/with-shape/introspection/fields.ts
|
|
829
|
-
function jsonSchemaType(node) {
|
|
830
|
-
if (Array.isArray(node.type)) {
|
|
831
|
-
const non = node.type.filter((t) => t !== "null");
|
|
832
|
-
return non[0] ?? "opaque";
|
|
833
|
-
}
|
|
834
|
-
if (node.enum && Array.isArray(node.enum)) return "enum";
|
|
835
|
-
if (node.const !== void 0) return "enum";
|
|
836
|
-
if (typeof node.type === "string") return node.type;
|
|
837
|
-
return "opaque";
|
|
838
|
-
}
|
|
839
|
-
function constraintsFor(node) {
|
|
840
|
-
const out = {};
|
|
841
|
-
if (node.enum) out.values = node.enum;
|
|
842
|
-
if (node.const !== void 0) out.values = [node.const];
|
|
843
|
-
if (node.minLength !== void 0) out.minLength = node.minLength;
|
|
844
|
-
if (node.maxLength !== void 0) out.maxLength = node.maxLength;
|
|
845
|
-
if (node.pattern !== void 0) out.pattern = node.pattern;
|
|
846
|
-
if (node.format !== void 0) out.format = node.format;
|
|
847
|
-
if (node.minimum !== void 0) out.minimum = node.minimum;
|
|
848
|
-
if (node.maximum !== void 0) out.maximum = node.maximum;
|
|
849
|
-
if (node.exclusiveMinimum !== void 0) out.gt = node.exclusiveMinimum;
|
|
850
|
-
if (node.exclusiveMaximum !== void 0) out.lt = node.exclusiveMaximum;
|
|
851
|
-
return Object.keys(out).length === 0 ? void 0 : out;
|
|
852
|
-
}
|
|
853
|
-
function extractObjectFields(obj, source, refs) {
|
|
854
|
-
const required = new Set(Array.isArray(obj.required) ? obj.required : []);
|
|
855
|
-
const fields = {};
|
|
856
|
-
if (!obj.properties || typeof obj.properties !== "object") return { fields, required };
|
|
857
|
-
for (const [name, node] of Object.entries(obj.properties)) {
|
|
858
|
-
const descriptor = {
|
|
859
|
-
type: jsonSchemaType(node),
|
|
860
|
-
source,
|
|
861
|
-
...required.has(name) ? {} : { optional: true },
|
|
862
|
-
...refs?.[name] ? { references: `${refs[name].target}.id` } : {}
|
|
863
|
-
};
|
|
864
|
-
const constraints = constraintsFor(node);
|
|
865
|
-
if (constraints) descriptor.constraints = constraints;
|
|
866
|
-
fields[name] = descriptor;
|
|
867
|
-
}
|
|
868
|
-
return { fields, required };
|
|
869
|
-
}
|
|
870
|
-
function mergeUnionMembers(members, source, refs) {
|
|
871
|
-
if (members.length === 0) return {};
|
|
872
|
-
const extracted = members.filter((m) => m.properties && typeof m.properties === "object").map((m) => extractObjectFields(m, source, refs));
|
|
873
|
-
if (extracted.length === 0) return {};
|
|
874
|
-
const allNames = /* @__PURE__ */ new Set();
|
|
875
|
-
for (const { fields } of extracted) {
|
|
876
|
-
for (const name of Object.keys(fields)) allNames.add(name);
|
|
877
|
-
}
|
|
878
|
-
const memberCount = extracted.length;
|
|
879
|
-
const out = {};
|
|
880
|
-
for (const name of allNames) {
|
|
881
|
-
const presentIn = extracted.filter(({ fields }) => name in fields);
|
|
882
|
-
const requiredInAll = presentIn.length === memberCount && presentIn.every(({ required }) => required.has(name));
|
|
883
|
-
const base = presentIn[0].fields[name];
|
|
884
|
-
const allValues = [];
|
|
885
|
-
for (const { fields } of presentIn) {
|
|
886
|
-
const fd = fields[name];
|
|
887
|
-
if (fd?.constraints?.values && Array.isArray(fd.constraints.values)) {
|
|
888
|
-
for (const v of fd.constraints.values) {
|
|
889
|
-
if (!allValues.includes(v)) allValues.push(v);
|
|
890
|
-
}
|
|
891
|
-
}
|
|
892
|
-
}
|
|
893
|
-
const mergedConstraints = allValues.length > 0 ? { ...base.constraints ?? {}, values: allValues } : base.constraints;
|
|
894
|
-
const descriptor = {
|
|
895
|
-
type: base.type,
|
|
896
|
-
source,
|
|
897
|
-
...requiredInAll ? {} : { optional: true },
|
|
898
|
-
...base.references ? { references: base.references } : {}
|
|
899
|
-
};
|
|
900
|
-
if (mergedConstraints) {
|
|
901
|
-
descriptor.constraints = mergedConstraints;
|
|
902
|
-
}
|
|
903
|
-
out[name] = descriptor;
|
|
904
|
-
}
|
|
905
|
-
return out;
|
|
906
|
-
}
|
|
907
|
-
function jsonSchemaToFields(jsonSchema, source, refs) {
|
|
908
|
-
if (!jsonSchema || typeof jsonSchema !== "object") return {};
|
|
909
|
-
const root = jsonSchema;
|
|
910
|
-
const unionMembers = root.anyOf ?? root.oneOf;
|
|
911
|
-
if (Array.isArray(unionMembers) && unionMembers.length > 0) {
|
|
912
|
-
return mergeUnionMembers(unionMembers, source, refs);
|
|
913
|
-
}
|
|
914
|
-
if (!root.properties || typeof root.properties !== "object") return {};
|
|
915
|
-
const { fields } = extractObjectFields(root, source, refs);
|
|
916
|
-
return fields;
|
|
917
|
-
}
|
|
918
|
-
|
|
919
803
|
// src/with-shape/introspection/describe.ts
|
|
920
804
|
var ZOD_META_KEYS = /* @__PURE__ */ new Set([
|
|
921
805
|
"label",
|
|
@@ -985,7 +869,7 @@ function deriveWidget(opts) {
|
|
|
985
869
|
return "text";
|
|
986
870
|
}
|
|
987
871
|
function buildDescription(input) {
|
|
988
|
-
const { collection, fieldMeta, moneyFields, dictKeyFields, computed, refs, zodFields, dictLabels, meta, i18nFields } = input;
|
|
872
|
+
const { collection, fieldMeta, moneyFields, dictKeyFields, computed, refs, zodFields, dictLabels, meta, i18nFields, classified } = input;
|
|
989
873
|
if (zodFields !== void 0 && Object.keys(zodFields).length > 0 && fieldMeta !== void 0) {
|
|
990
874
|
const knownFields = /* @__PURE__ */ new Set([
|
|
991
875
|
...Object.keys(moneyFields ?? {}),
|
|
@@ -1004,7 +888,8 @@ function buildDescription(input) {
|
|
|
1004
888
|
...Object.keys(computed ?? {}),
|
|
1005
889
|
...Object.keys(fieldMeta ?? {}),
|
|
1006
890
|
...Object.keys(zodFields ?? {}),
|
|
1007
|
-
...Object.keys(i18nFields ?? {})
|
|
891
|
+
...Object.keys(i18nFields ?? {}),
|
|
892
|
+
...Object.keys(classified ?? {})
|
|
1008
893
|
]);
|
|
1009
894
|
const fields = [];
|
|
1010
895
|
for (const key of [...allKeys].sort()) {
|
|
@@ -1014,6 +899,7 @@ function buildDescription(input) {
|
|
|
1014
899
|
const refDesc = refs[key];
|
|
1015
900
|
const isComputed = computed !== void 0 && key in computed;
|
|
1016
901
|
const i18nDesc = i18nFields?.[key];
|
|
902
|
+
const cls = classified?.[key];
|
|
1017
903
|
let type = zod?.type ?? "unknown";
|
|
1018
904
|
const inferred = {};
|
|
1019
905
|
let moneyBlock;
|
|
@@ -1069,6 +955,7 @@ function buildDescription(input) {
|
|
|
1069
955
|
type = "string";
|
|
1070
956
|
} else if (isComputed) {
|
|
1071
957
|
}
|
|
958
|
+
if (cls !== void 0) inferred.sensitivity = cls.sensitivity;
|
|
1072
959
|
const channelEntry = fieldMeta?.[key];
|
|
1073
960
|
const zodMeta = zod?.meta;
|
|
1074
961
|
const resolved = resolveFieldMeta(key, {
|
|
@@ -1096,6 +983,7 @@ function buildDescription(input) {
|
|
|
1096
983
|
key,
|
|
1097
984
|
type,
|
|
1098
985
|
optional: zod?.optional ?? false,
|
|
986
|
+
...zod?.constraints !== void 0 ? { constraints: zod.constraints } : {},
|
|
1099
987
|
label: resolved.label,
|
|
1100
988
|
...resolved.description !== void 0 ? { description: resolved.description } : {},
|
|
1101
989
|
...resolved.group !== void 0 ? { group: resolved.group } : {},
|
|
@@ -1112,7 +1000,15 @@ function buildDescription(input) {
|
|
|
1112
1000
|
...isComputed ? { computed: true } : {},
|
|
1113
1001
|
...i18nBlock !== void 0 ? { i18n: i18nBlock } : {},
|
|
1114
1002
|
widget,
|
|
1115
|
-
editable
|
|
1003
|
+
editable,
|
|
1004
|
+
...cls !== void 0 ? {
|
|
1005
|
+
classified: {
|
|
1006
|
+
preset: cls.preset,
|
|
1007
|
+
storage: cls.storage,
|
|
1008
|
+
list: cls.list.kind === "omit" ? "omit" : cls.list.kind === "mask" ? { mask: cls.list.pattern } : { rider: cls.list.rider },
|
|
1009
|
+
...cls.equatable === true ? { equatable: true } : {}
|
|
1010
|
+
}
|
|
1011
|
+
} : {}
|
|
1116
1012
|
};
|
|
1117
1013
|
fields.push(field);
|
|
1118
1014
|
}
|
|
@@ -1127,203 +1023,6 @@ function buildDescription(input) {
|
|
|
1127
1023
|
};
|
|
1128
1024
|
}
|
|
1129
1025
|
|
|
1130
|
-
// src/with-shape/introspection/json-schema.ts
|
|
1131
|
-
function jsonType(t) {
|
|
1132
|
-
switch (t) {
|
|
1133
|
-
case "number":
|
|
1134
|
-
return "number";
|
|
1135
|
-
case "boolean":
|
|
1136
|
-
return "boolean";
|
|
1137
|
-
case "array":
|
|
1138
|
-
return "array";
|
|
1139
|
-
case "object":
|
|
1140
|
-
return "object";
|
|
1141
|
-
default:
|
|
1142
|
-
return "string";
|
|
1143
|
-
}
|
|
1144
|
-
}
|
|
1145
|
-
function buildJsonSchema(desc, base) {
|
|
1146
|
-
const baseProps = base?.["properties"] ?? {};
|
|
1147
|
-
const properties = {};
|
|
1148
|
-
for (const f of desc.fields) {
|
|
1149
|
-
const prop = { ...baseProps[f.key] ?? { type: jsonType(f.type) } };
|
|
1150
|
-
prop["x-label"] = f.label;
|
|
1151
|
-
if (f.unit !== void 0) prop["x-unit"] = f.unit;
|
|
1152
|
-
if (f.semanticType !== void 0) prop["x-semanticType"] = f.semanticType;
|
|
1153
|
-
if (f.sensitivity !== void 0) prop["x-sensitivity"] = f.sensitivity;
|
|
1154
|
-
if (f.widget !== void 0) prop["x-widget"] = f.widget;
|
|
1155
|
-
if (f.editable === false) prop["x-readonly"] = true;
|
|
1156
|
-
if (f.money !== void 0) prop["x-money"] = f.money;
|
|
1157
|
-
if (f.ref !== void 0) prop["x-ref"] = f.ref.target;
|
|
1158
|
-
if (f.dict?.values) {
|
|
1159
|
-
const labels = {};
|
|
1160
|
-
for (const v of f.dict.values) if (v.label !== void 0) labels[v.value] = v.label;
|
|
1161
|
-
if (Object.keys(labels).length) prop["x-enumLabels"] = labels;
|
|
1162
|
-
}
|
|
1163
|
-
properties[f.key] = prop;
|
|
1164
|
-
}
|
|
1165
|
-
return base != null && typeof base === "object" ? { ...base, properties } : { type: "object", properties };
|
|
1166
|
-
}
|
|
1167
|
-
|
|
1168
|
-
// src/kernel/cache/lru.ts
|
|
1169
|
-
var Lru = class {
|
|
1170
|
-
entries = /* @__PURE__ */ new Map();
|
|
1171
|
-
maxRecords;
|
|
1172
|
-
maxBytes;
|
|
1173
|
-
currentBytes = 0;
|
|
1174
|
-
hits = 0;
|
|
1175
|
-
misses = 0;
|
|
1176
|
-
evictions = 0;
|
|
1177
|
-
constructor(options) {
|
|
1178
|
-
if (options.maxRecords === void 0 && options.maxBytes === void 0) {
|
|
1179
|
-
throw new Error("Lru: must specify maxRecords, maxBytes, or both");
|
|
1180
|
-
}
|
|
1181
|
-
this.maxRecords = options.maxRecords;
|
|
1182
|
-
this.maxBytes = options.maxBytes;
|
|
1183
|
-
}
|
|
1184
|
-
/**
|
|
1185
|
-
* Look up a key. Hits promote the entry to most-recently-used; misses
|
|
1186
|
-
* return undefined. Both update the running stats counters.
|
|
1187
|
-
*/
|
|
1188
|
-
get(key) {
|
|
1189
|
-
const entry = this.entries.get(key);
|
|
1190
|
-
if (!entry) {
|
|
1191
|
-
this.misses++;
|
|
1192
|
-
return void 0;
|
|
1193
|
-
}
|
|
1194
|
-
this.entries.delete(key);
|
|
1195
|
-
this.entries.set(key, entry);
|
|
1196
|
-
this.hits++;
|
|
1197
|
-
return entry.value;
|
|
1198
|
-
}
|
|
1199
|
-
/**
|
|
1200
|
-
* Insert or update a key. If the key already exists, its size is
|
|
1201
|
-
* accounted for and the entry is promoted to MRU. After insertion,
|
|
1202
|
-
* eviction runs to maintain both budgets.
|
|
1203
|
-
*/
|
|
1204
|
-
set(key, value, size) {
|
|
1205
|
-
const existing = this.entries.get(key);
|
|
1206
|
-
if (existing) {
|
|
1207
|
-
this.currentBytes -= existing.size;
|
|
1208
|
-
this.entries.delete(key);
|
|
1209
|
-
}
|
|
1210
|
-
this.entries.set(key, { value, size });
|
|
1211
|
-
this.currentBytes += size;
|
|
1212
|
-
this.evictUntilUnderBudget();
|
|
1213
|
-
}
|
|
1214
|
-
/**
|
|
1215
|
-
* Remove a key without affecting hit/miss stats. Used by `Collection.delete()`.
|
|
1216
|
-
* Returns true if the key was present.
|
|
1217
|
-
*/
|
|
1218
|
-
remove(key) {
|
|
1219
|
-
const existing = this.entries.get(key);
|
|
1220
|
-
if (!existing) return false;
|
|
1221
|
-
this.currentBytes -= existing.size;
|
|
1222
|
-
this.entries.delete(key);
|
|
1223
|
-
return true;
|
|
1224
|
-
}
|
|
1225
|
-
/** True if the cache currently holds an entry for the given key. */
|
|
1226
|
-
has(key) {
|
|
1227
|
-
return this.entries.has(key);
|
|
1228
|
-
}
|
|
1229
|
-
/**
|
|
1230
|
-
* Drop every entry. Stats counters survive — call `resetStats()` if you
|
|
1231
|
-
* want a clean slate. Used by `Collection.invalidate()` on key rotation.
|
|
1232
|
-
*/
|
|
1233
|
-
clear() {
|
|
1234
|
-
this.entries.clear();
|
|
1235
|
-
this.currentBytes = 0;
|
|
1236
|
-
}
|
|
1237
|
-
/** Reset hit/miss/eviction counters to zero. Does NOT touch entries. */
|
|
1238
|
-
resetStats() {
|
|
1239
|
-
this.hits = 0;
|
|
1240
|
-
this.misses = 0;
|
|
1241
|
-
this.evictions = 0;
|
|
1242
|
-
}
|
|
1243
|
-
/** Snapshot of current cache statistics. Cheap — no copying. */
|
|
1244
|
-
stats() {
|
|
1245
|
-
return {
|
|
1246
|
-
hits: this.hits,
|
|
1247
|
-
misses: this.misses,
|
|
1248
|
-
evictions: this.evictions,
|
|
1249
|
-
size: this.entries.size,
|
|
1250
|
-
bytes: this.currentBytes
|
|
1251
|
-
};
|
|
1252
|
-
}
|
|
1253
|
-
/**
|
|
1254
|
-
* Iterate over all currently-cached values. Order is least-recently-used
|
|
1255
|
-
* first. Used by tests and devtools — production callers should use
|
|
1256
|
-
* `Collection.scan()` instead.
|
|
1257
|
-
*/
|
|
1258
|
-
*values() {
|
|
1259
|
-
for (const entry of this.entries.values()) yield entry.value;
|
|
1260
|
-
}
|
|
1261
|
-
/**
|
|
1262
|
-
* Walk the cache from the LRU end and drop entries until both budgets
|
|
1263
|
-
* are satisfied. Called after every `set()`. Single pass — entries are
|
|
1264
|
-
* never re-promoted during eviction.
|
|
1265
|
-
*/
|
|
1266
|
-
evictUntilUnderBudget() {
|
|
1267
|
-
while (this.overBudget()) {
|
|
1268
|
-
const oldest = this.entries.keys().next();
|
|
1269
|
-
if (oldest.done) return;
|
|
1270
|
-
const key = oldest.value;
|
|
1271
|
-
const entry = this.entries.get(key);
|
|
1272
|
-
if (entry) this.currentBytes -= entry.size;
|
|
1273
|
-
this.entries.delete(key);
|
|
1274
|
-
this.evictions++;
|
|
1275
|
-
}
|
|
1276
|
-
}
|
|
1277
|
-
overBudget() {
|
|
1278
|
-
if (this.maxRecords !== void 0 && this.entries.size > this.maxRecords) return true;
|
|
1279
|
-
if (this.maxBytes !== void 0 && this.currentBytes > this.maxBytes) return true;
|
|
1280
|
-
return false;
|
|
1281
|
-
}
|
|
1282
|
-
};
|
|
1283
|
-
|
|
1284
|
-
// src/kernel/cache/policy.ts
|
|
1285
|
-
var UNITS = {
|
|
1286
|
-
"": 1,
|
|
1287
|
-
"B": 1,
|
|
1288
|
-
"KB": 1024,
|
|
1289
|
-
"MB": 1024 * 1024,
|
|
1290
|
-
"GB": 1024 * 1024 * 1024
|
|
1291
|
-
// 'TB' deliberately not supported — if you need it, you're not using NOYDB.
|
|
1292
|
-
};
|
|
1293
|
-
function parseBytes(input) {
|
|
1294
|
-
if (typeof input === "number") {
|
|
1295
|
-
if (!Number.isFinite(input) || input <= 0) {
|
|
1296
|
-
throw new Error(`parseBytes: numeric input must be a positive finite number, got ${String(input)}`);
|
|
1297
|
-
}
|
|
1298
|
-
return Math.floor(input);
|
|
1299
|
-
}
|
|
1300
|
-
const trimmed = input.trim();
|
|
1301
|
-
if (trimmed === "") {
|
|
1302
|
-
throw new Error("parseBytes: empty string is not a valid byte budget");
|
|
1303
|
-
}
|
|
1304
|
-
const match = /^([0-9]+(?:\.[0-9]+)?)\s*([A-Za-z]*)$/.exec(trimmed);
|
|
1305
|
-
if (!match) {
|
|
1306
|
-
throw new Error(`parseBytes: invalid byte budget "${input}". Expected format: "1024", "50KB", "50MB", "1GB"`);
|
|
1307
|
-
}
|
|
1308
|
-
const value = parseFloat(match[1]);
|
|
1309
|
-
const unit = (match[2] ?? "").toUpperCase();
|
|
1310
|
-
if (!(unit in UNITS)) {
|
|
1311
|
-
throw new Error(`parseBytes: unknown unit "${match[2]}" in "${input}". Supported: B, KB, MB, GB`);
|
|
1312
|
-
}
|
|
1313
|
-
const bytes = Math.floor(value * UNITS[unit]);
|
|
1314
|
-
if (bytes <= 0) {
|
|
1315
|
-
throw new Error(`parseBytes: byte budget must be > 0, got ${bytes} from "${input}"`);
|
|
1316
|
-
}
|
|
1317
|
-
return bytes;
|
|
1318
|
-
}
|
|
1319
|
-
function estimateRecordBytes(record) {
|
|
1320
|
-
try {
|
|
1321
|
-
return JSON.stringify(record).length;
|
|
1322
|
-
} catch {
|
|
1323
|
-
return 0;
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
|
|
1327
1026
|
// src/with-formula/derivations/stale.ts
|
|
1328
1027
|
var _staleByRegistry = /* @__PURE__ */ new WeakMap();
|
|
1329
1028
|
var keyFor = (source, sourceId) => `${source}/${sourceId}`;
|
|
@@ -1360,7 +1059,7 @@ async function resolveStaleOnRead(accessor, outputCollection, id) {
|
|
|
1360
1059
|
}
|
|
1361
1060
|
const sourceWithId = { ...source, id };
|
|
1362
1061
|
if (DerivationExecutor === null) {
|
|
1363
|
-
({ DerivationExecutor } = await import("./executor-
|
|
1062
|
+
({ DerivationExecutor } = await import("./executor-CBTNU5VZ.js"));
|
|
1364
1063
|
}
|
|
1365
1064
|
const ctx = { vault: accessor.getReadOnlyFacade() };
|
|
1366
1065
|
const result = await DerivationExecutor.run(spec, sourceWithId, 0, strategyHash, ctx);
|
|
@@ -1517,7 +1216,17 @@ function resolveCollectionConfig(opts) {
|
|
|
1517
1216
|
`Collection "${opts.name}": embeddings are not supported on CRDT collections (L2). Use a non-CRDT collection for semantic search.`
|
|
1518
1217
|
);
|
|
1519
1218
|
}
|
|
1520
|
-
if (opts.moneyFields) validateMoneyFieldPaths(opts.moneyFields);
|
|
1219
|
+
if (opts.moneyFields) moneyRuntime().validateMoneyFieldPaths(opts.moneyFields);
|
|
1220
|
+
const resolvedClassified = opts.classifiedFields !== void 0 ? resolveClassifiedFields(opts.name, opts.classifiedFields) : void 0;
|
|
1221
|
+
let mergedComputed = opts.computed;
|
|
1222
|
+
if (resolvedClassified !== void 0) {
|
|
1223
|
+
for (const key of Object.keys(opts.computed ?? {})) {
|
|
1224
|
+
if (resolvedClassified.riderComputed[key] !== void 0) {
|
|
1225
|
+
throw new ClassifiedConfigError(opts.name, `computed field "${key}" collides with a rider companion`);
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
mergedComputed = { ...resolvedClassified.riderComputed, ...opts.computed ?? {} };
|
|
1229
|
+
}
|
|
1521
1230
|
let deterministicFields;
|
|
1522
1231
|
if (opts.deterministicFields && opts.deterministicFields.length > 0) {
|
|
1523
1232
|
if (opts.acknowledgeDeterministicRisk !== true) {
|
|
@@ -1533,7 +1242,39 @@ function resolveCollectionConfig(opts) {
|
|
|
1533
1242
|
Object.entries(opts.i18nFields).filter(([, d]) => d.options.densifyOnWrite === true)
|
|
1534
1243
|
) : {};
|
|
1535
1244
|
const i18nDensifyFields = Object.keys(densifyFields).length > 0 ? densifyFields : void 0;
|
|
1536
|
-
const
|
|
1245
|
+
const guardIndexedFields = /* @__PURE__ */ new Set();
|
|
1246
|
+
for (const ix of opts.indexes ?? []) {
|
|
1247
|
+
if (typeof ix === "string") guardIndexedFields.add(ix);
|
|
1248
|
+
else if (Array.isArray(ix)) for (const f of ix) guardIndexedFields.add(f);
|
|
1249
|
+
else for (const f of ix.fields) guardIndexedFields.add(f);
|
|
1250
|
+
}
|
|
1251
|
+
const embeddingSources = opts.embeddings === void 0 ? [] : typeof opts.embeddings.source === "string" ? [opts.embeddings.source] : [...opts.embeddings.source];
|
|
1252
|
+
const classifiedGuardCtx = {
|
|
1253
|
+
perRecordKeys: opts.perRecordKeys === true,
|
|
1254
|
+
crdt: opts.crdt !== void 0,
|
|
1255
|
+
hasConflictPolicy: opts.conflictPolicy !== void 0,
|
|
1256
|
+
storeCiphertext: opts.encrypted,
|
|
1257
|
+
deterministicFields,
|
|
1258
|
+
indexedFields: guardIndexedFields,
|
|
1259
|
+
textIndexFields: new Set(opts.textIndexes ?? []),
|
|
1260
|
+
vectorSourceFields: new Set(embeddingSources),
|
|
1261
|
+
subjectKeyField: opts.subjectKeyField,
|
|
1262
|
+
bareSensitiveFields: new Set(opts.sensitive ?? []),
|
|
1263
|
+
acknowledgeEquatableRisk: opts.acknowledgeEquatableRisk === true
|
|
1264
|
+
};
|
|
1265
|
+
if (resolvedClassified !== void 0) {
|
|
1266
|
+
guardClassifiedCompat(opts.name, resolvedClassified.byField, classifiedGuardCtx);
|
|
1267
|
+
}
|
|
1268
|
+
const classifiedSensitive = resolvedClassified === void 0 ? [] : Object.entries(resolvedClassified.byField).filter(([, s]) => s.storage === "recoverable").map(([f]) => f);
|
|
1269
|
+
const sensitiveList = [...opts.sensitive ?? [], ...classifiedSensitive];
|
|
1270
|
+
const sensitiveFields = sensitiveList.length > 0 ? Object.freeze(new Set(sensitiveList)) : Object.freeze(/* @__PURE__ */ new Set());
|
|
1271
|
+
const vdigEntries = resolvedClassified === void 0 ? [] : Object.entries(resolvedClassified.byField).filter(([, s]) => s.storage === "digest-only").map(([f, s]) => [f, {
|
|
1272
|
+
normalize: s.verifyNormalize ?? "password",
|
|
1273
|
+
notLastN: s.notLastN ?? 0,
|
|
1274
|
+
equatable: s.equatable === true,
|
|
1275
|
+
...s.rotateDays !== void 0 ? { rotateDays: s.rotateDays } : {}
|
|
1276
|
+
}]);
|
|
1277
|
+
const vdigFields = vdigEntries.length > 0 ? new Map(vdigEntries) : null;
|
|
1537
1278
|
const perRecordCek = opts.perRecordKeys === true;
|
|
1538
1279
|
const cekCache = perRecordCek ? new Lru({ maxRecords: 4096 }) : null;
|
|
1539
1280
|
return {
|
|
@@ -1577,7 +1318,10 @@ function resolveCollectionConfig(opts) {
|
|
|
1577
1318
|
meta: opts.meta,
|
|
1578
1319
|
_refs: opts.declaredRefs ?? {},
|
|
1579
1320
|
moneyFields: opts.moneyFields,
|
|
1580
|
-
|
|
1321
|
+
classified: resolvedClassified,
|
|
1322
|
+
classifiedGuardCtx,
|
|
1323
|
+
classifiedStrategy: opts.classifiedStrategy ?? NO_CLASSIFIED,
|
|
1324
|
+
computed: mergedComputed,
|
|
1581
1325
|
dictLabelResolver: opts.dictLabelResolver,
|
|
1582
1326
|
getDictionary: opts.getDictionary,
|
|
1583
1327
|
i18nPutValidator: opts.i18nPutValidator,
|
|
@@ -1595,12 +1339,20 @@ function resolveCollectionConfig(opts) {
|
|
|
1595
1339
|
onCrossTierAccess: opts.onCrossTierAccess,
|
|
1596
1340
|
deterministicFields,
|
|
1597
1341
|
sensitiveFields,
|
|
1342
|
+
vdigFields,
|
|
1598
1343
|
perRecordCek,
|
|
1599
1344
|
cekCache,
|
|
1600
1345
|
provenance: opts.provenance === true
|
|
1601
1346
|
};
|
|
1602
1347
|
}
|
|
1603
1348
|
|
|
1349
|
+
// src/with-formula/computed/lazy.ts
|
|
1350
|
+
var fn = null;
|
|
1351
|
+
async function loadEvalComputedFields() {
|
|
1352
|
+
fn ??= (await import("./computed-BMMEFRFJ.js")).evalComputedFields;
|
|
1353
|
+
return fn;
|
|
1354
|
+
}
|
|
1355
|
+
|
|
1604
1356
|
// src/kernel/collection.ts
|
|
1605
1357
|
function selfWriteFieldEqual(a, b) {
|
|
1606
1358
|
if (a === b) return true;
|
|
@@ -1827,6 +1579,35 @@ var Collection = class {
|
|
|
1827
1579
|
* the same MV-pre-creation reconcile as {@link moneyFields}.
|
|
1828
1580
|
*/
|
|
1829
1581
|
computed;
|
|
1582
|
+
/**
|
|
1583
|
+
* Resolved classified() sensitive-field descriptors, declared via the
|
|
1584
|
+
* `classifiedFields` collection option. Mutable so {@link _applyClassifiedFields}
|
|
1585
|
+
* can attach a declaration to a collection MV-analysis pre-created.
|
|
1586
|
+
*/
|
|
1587
|
+
classified;
|
|
1588
|
+
/**
|
|
1589
|
+
* Frozen construction-time facts the refusal matrix (R1-R5) checks against.
|
|
1590
|
+
* Stored so {@link _applyClassifiedFields} — door 2, the reconcile seam —
|
|
1591
|
+
* can re-run the SAME guard the config resolver ran at door 1 (C5's lesson:
|
|
1592
|
+
* crdt/conflictPolicy/perRecordKeys are construction-only but
|
|
1593
|
+
* classifiedFields can attach later).
|
|
1594
|
+
*/
|
|
1595
|
+
classifiedGuardCtx;
|
|
1596
|
+
/**
|
|
1597
|
+
* Digest-only classified fields (`storage: 'digest-only'`), keyed by field
|
|
1598
|
+
* name — the enclave-consumable policy map the codec's write path carries
|
|
1599
|
+
* `_vdig` forward under (C6). `null` when the collection declares none.
|
|
1600
|
+
*/
|
|
1601
|
+
vdigFields;
|
|
1602
|
+
/** C-A/R10 memoization: marker declared-set lookup (undefined=unresolved) + classified-handle persist-once flag. */
|
|
1603
|
+
_markerDigestOnlyCache = void 0;
|
|
1604
|
+
_markerPersisted = false;
|
|
1605
|
+
/**
|
|
1606
|
+
* Tree-shake seam for `reveal()` — defaults to `NO_CLASSIFIED`, which
|
|
1607
|
+
* throws `ClassifiedNotEnabledError`. Set via the `classifiedStrategy`
|
|
1608
|
+
* `createNoydb()` option (opt in with `withClassified()`).
|
|
1609
|
+
*/
|
|
1610
|
+
classifiedStrategy;
|
|
1830
1611
|
/**
|
|
1831
1612
|
* Async callback provided by the Vault that resolves a dict key
|
|
1832
1613
|
* to its label for a given locale. Used by the locale-read path for
|
|
@@ -2031,6 +1812,10 @@ var Collection = class {
|
|
|
2031
1812
|
this.meta = cfg.meta;
|
|
2032
1813
|
this._refs = cfg._refs;
|
|
2033
1814
|
this.moneyFields = cfg.moneyFields;
|
|
1815
|
+
this.classified = cfg.classified;
|
|
1816
|
+
this.classifiedGuardCtx = cfg.classifiedGuardCtx;
|
|
1817
|
+
this.vdigFields = cfg.vdigFields;
|
|
1818
|
+
this.classifiedStrategy = cfg.classifiedStrategy;
|
|
2034
1819
|
this.computed = cfg.computed;
|
|
2035
1820
|
this.dictLabelResolver = cfg.dictLabelResolver;
|
|
2036
1821
|
this.getDictionary = cfg.getDictionary;
|
|
@@ -2077,11 +1862,13 @@ var Collection = class {
|
|
|
2077
1862
|
provenance: this.provenance,
|
|
2078
1863
|
sensitiveFields: this.sensitiveFields,
|
|
2079
1864
|
deterministicFields: this.deterministicFields,
|
|
1865
|
+
vdigFields: this.vdigFields,
|
|
2080
1866
|
crdtMode: this.crdtMode,
|
|
2081
1867
|
crdtStrategy: this.crdtStrategy,
|
|
2082
1868
|
schema: this.schema,
|
|
2083
1869
|
getDEK: () => this.getDEK(this.name),
|
|
2084
|
-
cekCache: this.cekCache
|
|
1870
|
+
cekCache: this.cekCache,
|
|
1871
|
+
classifiedMarkerDigestOnly: () => this._classifiedMarkerDigestOnly()
|
|
2085
1872
|
});
|
|
2086
1873
|
if (opts.crdt && opts.onRegisterConflictResolver) {
|
|
2087
1874
|
const crdtMode = opts.crdt;
|
|
@@ -2153,15 +1940,7 @@ var Collection = class {
|
|
|
2153
1940
|
}
|
|
2154
1941
|
this.lazy = opts.prefetch === false;
|
|
2155
1942
|
if (this.lazy) {
|
|
2156
|
-
|
|
2157
|
-
throw new Error(
|
|
2158
|
-
`Collection "${this.name}": lazy mode (prefetch: false) requires a cache option with maxRecords and/or maxBytes. An unbounded lazy cache defeats the purpose.`
|
|
2159
|
-
);
|
|
2160
|
-
}
|
|
2161
|
-
const lruOptions = {};
|
|
2162
|
-
if (opts.cache.maxRecords !== void 0) lruOptions.maxRecords = opts.cache.maxRecords;
|
|
2163
|
-
if (opts.cache.maxBytes !== void 0) lruOptions.maxBytes = parseBytes(opts.cache.maxBytes);
|
|
2164
|
-
this.lru = new Lru(lruOptions);
|
|
1943
|
+
this.lru = (opts.lazyStrategy ?? IMPLICIT_LAZY).createCache(this.name, opts.cache);
|
|
2165
1944
|
this.hydrated = true;
|
|
2166
1945
|
} else {
|
|
2167
1946
|
this.lru = null;
|
|
@@ -2248,7 +2027,8 @@ var Collection = class {
|
|
|
2248
2027
|
refs: this._refs,
|
|
2249
2028
|
zodFields: void 0,
|
|
2250
2029
|
...this.meta !== void 0 ? { meta: this.meta } : {},
|
|
2251
|
-
...this.i18nFields !== void 0 ? { i18nFields: this.i18nFields } : {}
|
|
2030
|
+
...this.i18nFields !== void 0 ? { i18nFields: this.i18nFields } : {},
|
|
2031
|
+
...this.classified !== void 0 ? { classified: this.classified.byField } : {}
|
|
2252
2032
|
});
|
|
2253
2033
|
}
|
|
2254
2034
|
/**
|
|
@@ -2285,11 +2065,13 @@ var Collection = class {
|
|
|
2285
2065
|
zodFields,
|
|
2286
2066
|
...dictLabels !== void 0 ? { dictLabels } : {},
|
|
2287
2067
|
...this.meta !== void 0 ? { meta: this.meta } : {},
|
|
2288
|
-
...this.i18nFields !== void 0 ? { i18nFields: this.i18nFields } : {}
|
|
2068
|
+
...this.i18nFields !== void 0 ? { i18nFields: this.i18nFields } : {},
|
|
2069
|
+
...this.classified !== void 0 ? { classified: this.classified.byField } : {}
|
|
2289
2070
|
});
|
|
2290
2071
|
}
|
|
2291
2072
|
/** JSON Schema for this collection with describe() metadata as x- extensions. */
|
|
2292
2073
|
async toJSONSchema() {
|
|
2074
|
+
const { buildJsonSchema } = await import("./json-schema-I22JCYCG.js");
|
|
2293
2075
|
const desc = await this.describe({});
|
|
2294
2076
|
let base = null;
|
|
2295
2077
|
if (this.schema !== void 0) {
|
|
@@ -2298,6 +2080,195 @@ var Collection = class {
|
|
|
2298
2080
|
}
|
|
2299
2081
|
return buildJsonSchema(desc, base);
|
|
2300
2082
|
}
|
|
2083
|
+
/** Single-point audited reveal of one classified field. Requires withClassified(). */
|
|
2084
|
+
async reveal(id, field) {
|
|
2085
|
+
const spec = this.classified?.byField[field];
|
|
2086
|
+
if (spec === void 0) throw new ClassifiedRevealError(this.name, field, "field is not classified");
|
|
2087
|
+
if (spec.storage === "never") {
|
|
2088
|
+
throw new ClassifiedRevealError(this.name, field, `storage:'never' \u2014 nothing is stored to reveal`);
|
|
2089
|
+
}
|
|
2090
|
+
if (spec.storage === "digest-only") {
|
|
2091
|
+
throw new ClassifiedRevealError(this.name, field, `storage:'digest-only' \u2014 verify-only; nothing recoverable to reveal`);
|
|
2092
|
+
}
|
|
2093
|
+
return this.classifiedStrategy.reveal({
|
|
2094
|
+
collection: this.name,
|
|
2095
|
+
spec,
|
|
2096
|
+
encrypted: this.storeCiphertext,
|
|
2097
|
+
getEnvelope: (rid) => this.adapter.get(this.vault, this.name, rid),
|
|
2098
|
+
resolveCek: (env) => this.codec.resolveEnvelopeCek(env),
|
|
2099
|
+
getDEK: () => this.getDEK(this.name),
|
|
2100
|
+
...this.onAccess !== void 0 ? { onAccess: async (_op, rid) => {
|
|
2101
|
+
await this.onAccess("reveal", rid);
|
|
2102
|
+
} } : {}
|
|
2103
|
+
}, id, field);
|
|
2104
|
+
}
|
|
2105
|
+
/** Verify-without-reveal: verdict-only oracle for one classified field. Requires withClassified(). */
|
|
2106
|
+
async verify(id, field, candidate) {
|
|
2107
|
+
const spec = this.classified?.byField[field];
|
|
2108
|
+
if (spec === void 0) throw new ClassifiedVerifyError(this.name, field, "field is not classified");
|
|
2109
|
+
if (spec.storage === "never") {
|
|
2110
|
+
throw new ClassifiedVerifyError(this.name, field, `storage:'never' \u2014 nothing is stored to verify against`);
|
|
2111
|
+
}
|
|
2112
|
+
const ctx = this._classifiedVerifyCtx(spec);
|
|
2113
|
+
return spec.storage === "digest-only" ? this.classifiedStrategy.verify(ctx, id, field, candidate) : this.classifiedStrategy.verifyText(ctx, id, field, candidate);
|
|
2114
|
+
}
|
|
2115
|
+
/** k-of-n challenge over the collection's secretAnswer members. Requires withClassified(). */
|
|
2116
|
+
async verifyGroup(id, answers, opts) {
|
|
2117
|
+
const members = Object.entries(this.classified?.byField ?? {}).filter(([, s]) => s.storage === "digest-only" && s.verifyGroupMember === true).map(([field, spec]) => ({ field, spec }));
|
|
2118
|
+
if (members.length === 0) {
|
|
2119
|
+
throw new ClassifiedVerifyError(this.name, "*", "no groupable digest-only (secretAnswer) fields declared");
|
|
2120
|
+
}
|
|
2121
|
+
const ctx = { ...this._classifiedVerifyCtx(members[0].spec), groupMembers: members };
|
|
2122
|
+
return this.classifiedStrategy.matchGroup(ctx, id, answers, opts);
|
|
2123
|
+
}
|
|
2124
|
+
_classifiedVerifyCtx(spec) {
|
|
2125
|
+
return {
|
|
2126
|
+
collection: this.name,
|
|
2127
|
+
spec,
|
|
2128
|
+
getEnvelope: (rid) => this.adapter.get(this.vault, this.name, rid),
|
|
2129
|
+
resolveCek: (env) => this.codec.resolveEnvelopeCek(env),
|
|
2130
|
+
getDEK: () => this.getDEK(this.name),
|
|
2131
|
+
now: () => Date.now(),
|
|
2132
|
+
// Q7: injected here; engine tests inject their own
|
|
2133
|
+
...this.onAccess !== void 0 ? { onAccess: async (_op, rid) => {
|
|
2134
|
+
await this.onAccess("verify", rid);
|
|
2135
|
+
} } : {}
|
|
2136
|
+
};
|
|
2137
|
+
}
|
|
2138
|
+
/**
|
|
2139
|
+
* Equatable blind-index lookup: the ids whose classified digest-only
|
|
2140
|
+
* `equatable` field carries a `_bidx` tag matching `candidate` AND whose
|
|
2141
|
+
* `_vdig` payload confirms it. Requires the field to be declared
|
|
2142
|
+
* `classified.password({ equatable: true })` (or `secretAnswer`) and the
|
|
2143
|
+
* collection to have opened its `acknowledgeEquatableRisk` door.
|
|
2144
|
+
*
|
|
2145
|
+
* The algorithm order is load-bearing (spec §3):
|
|
2146
|
+
* 1. Caller-bug refusals thrown at ~0 elapsed, BEFORE any PBKDF2 (R9 /
|
|
2147
|
+
* Oracle #6): the three field mis-declarations share ONE constant,
|
|
2148
|
+
* field-name-free message so the refusal text cannot enumerate which
|
|
2149
|
+
* fields are classified / digest-only / equatable.
|
|
2150
|
+
* 2. Derive the ONE blind-index target UNCONDITIONALLY (I-1 / F1): an empty
|
|
2151
|
+
* collection still pays exactly one 600K PBKDF2, so wall-time can never
|
|
2152
|
+
* distinguish "no records" from "no match". No early return may precede
|
|
2153
|
+
* this line.
|
|
2154
|
+
* 3. Scan `list + one get` per id, string-comparing the stored `_bidx` tag —
|
|
2155
|
+
* decrypting NOTHING — and retain each hit's already-fetched envelope.
|
|
2156
|
+
* 4. Emit the single sweep consent op (`onAccess('find', '*')`) now — after
|
|
2157
|
+
* the scan, before confirm (Oracle #5) — fixing its store-write timestamp
|
|
2158
|
+
* independent of hit count.
|
|
2159
|
+
* 5. Confirm-by-verify against the ALREADY-FETCHED envelope (C-B): run the
|
|
2160
|
+
* enclave `verifyDigestField` on an in-memory `getEnvelope` closure so the
|
|
2161
|
+
* confirm reads ZERO additional envelopes. A tag-hit whose `_vdig` fails
|
|
2162
|
+
* to confirm is dropped silently (a splice is indistinguishable from a
|
|
2163
|
+
* stale tag). Store-shape law: the only store calls are `list + N get`.
|
|
2164
|
+
*/
|
|
2165
|
+
async findByDigest(field, candidate) {
|
|
2166
|
+
const spec = this.classified?.byField[field];
|
|
2167
|
+
if (spec === void 0 || spec.storage !== "digest-only" || spec.equatable !== true) {
|
|
2168
|
+
throw new ClassifiedVerifyError(
|
|
2169
|
+
this.name,
|
|
2170
|
+
"*",
|
|
2171
|
+
"not a declared equatable digest-only classified field"
|
|
2172
|
+
);
|
|
2173
|
+
}
|
|
2174
|
+
if (typeof candidate !== "string") {
|
|
2175
|
+
throw new ClassifiedVerifyError(this.name, "*", "candidate must be a string");
|
|
2176
|
+
}
|
|
2177
|
+
const target = await this.classifiedStrategy.computeTarget(this._classifiedVerifyCtx(spec), field, candidate);
|
|
2178
|
+
const ids = await this.adapter.list(this.vault, this.name);
|
|
2179
|
+
const hits = [];
|
|
2180
|
+
const hitMap = /* @__PURE__ */ new Map();
|
|
2181
|
+
for (const id of ids) {
|
|
2182
|
+
const env = await this.adapter.get(this.vault, this.name, id);
|
|
2183
|
+
if (target !== null && env?._bidx?.[field] === target) {
|
|
2184
|
+
hits.push(id);
|
|
2185
|
+
hitMap.set(id, env);
|
|
2186
|
+
}
|
|
2187
|
+
}
|
|
2188
|
+
await this.onAccess?.("find", "*");
|
|
2189
|
+
if (hits.length === 0) return [];
|
|
2190
|
+
const { verifyDigestField } = await import("./verify-YB5LQHNA.js");
|
|
2191
|
+
const policy = {
|
|
2192
|
+
normalize: spec.verifyNormalize ?? "password",
|
|
2193
|
+
notLastN: spec.notLastN ?? 0,
|
|
2194
|
+
equatable: true,
|
|
2195
|
+
...spec.rotateDays !== void 0 ? { rotateDays: spec.rotateDays } : {}
|
|
2196
|
+
};
|
|
2197
|
+
const confirmCtx = {
|
|
2198
|
+
collection: this.name,
|
|
2199
|
+
getEnvelope: async (rid) => hitMap.get(rid) ?? null,
|
|
2200
|
+
// in-memory: zero extra store.get
|
|
2201
|
+
resolveCek: (env) => this.codec.resolveEnvelopeCek(env),
|
|
2202
|
+
getDEK: () => this.getDEK(this.name),
|
|
2203
|
+
now: () => Date.now()
|
|
2204
|
+
};
|
|
2205
|
+
const confirmed = [];
|
|
2206
|
+
for (const id of hits) {
|
|
2207
|
+
const verdict = await verifyDigestField(confirmCtx, id, field, candidate, policy);
|
|
2208
|
+
if (verdict.ok === true) confirmed.push(id);
|
|
2209
|
+
}
|
|
2210
|
+
return confirmed;
|
|
2211
|
+
}
|
|
2212
|
+
/**
|
|
2213
|
+
* Retire a field's equatable blind-index (`_bidx`) coverage across every
|
|
2214
|
+
* live record — the SOLE lazy-write-independent drop-path for a still-live
|
|
2215
|
+
* record's tag (besides clear / `forget()` / DEK-rotation). For each envelope
|
|
2216
|
+
* carrying `_bidx[field]`, rewrite it WITHOUT that slot (dropping the whole
|
|
2217
|
+
* `_bidx` map when it becomes empty), leaving `_vdig[field]` and everything
|
|
2218
|
+
* else INTACT — the field stays `digest-only`, only the index coverage is
|
|
2219
|
+
* retired. NO crypto, NO re-mint, NO re-encrypt: a targeted envelope rewrite.
|
|
2220
|
+
* Returns the count of records scrubbed.
|
|
2221
|
+
*
|
|
2222
|
+
* This is a maintenance write, not a read-egress: it emits NO `'find'` op and
|
|
2223
|
+
* no consent. The field is validated to a declared equatable digest-only
|
|
2224
|
+
* classified field (only such a field ever carries `_bidx`).
|
|
2225
|
+
*
|
|
2226
|
+
* **Ledger consistency**: dropping `_bidx[field]` changes the envelope's
|
|
2227
|
+
* payload hash (`_bidx` is bound into `envelopeBodyForHash`), so a raw
|
|
2228
|
+
* `adapter.put` of the scrubbed envelope WITHOUT a matching ledger entry would
|
|
2229
|
+
* desync the chain and make a future integrity cross-check flag false
|
|
2230
|
+
* tampering. After each rewrite we therefore append an `op:'migration'` entry
|
|
2231
|
+
* recording the NEW payloadHash at the SAME version — this is index retirement,
|
|
2232
|
+
* not a new record version, so `_v` is NOT bumped; the migration op is
|
|
2233
|
+
* reverse-delta-inert (`ledger.reconstruct` skips non-put/delete ops) yet
|
|
2234
|
+
* keeps the hash chain and the record's latest recorded payloadHash correct.
|
|
2235
|
+
*/
|
|
2236
|
+
async scrubEquatableTags(field) {
|
|
2237
|
+
const spec = this.classified?.byField[field];
|
|
2238
|
+
if (spec === void 0 || spec.storage !== "digest-only" || spec.equatable !== true) {
|
|
2239
|
+
throw new ClassifiedVerifyError(
|
|
2240
|
+
this.name,
|
|
2241
|
+
"*",
|
|
2242
|
+
"not a declared equatable digest-only classified field"
|
|
2243
|
+
);
|
|
2244
|
+
}
|
|
2245
|
+
const ids = await this.adapter.list(this.vault, this.name);
|
|
2246
|
+
let count = 0;
|
|
2247
|
+
for (const id of ids) {
|
|
2248
|
+
const env = await this.adapter.get(this.vault, this.name, id);
|
|
2249
|
+
if (env?._bidx?.[field] === void 0) continue;
|
|
2250
|
+
const nextBidx = { ...env._bidx };
|
|
2251
|
+
delete nextBidx[field];
|
|
2252
|
+
const scrubbedRaw = { ...env };
|
|
2253
|
+
delete scrubbedRaw._bidx;
|
|
2254
|
+
if (Object.keys(nextBidx).length > 0) scrubbedRaw._bidx = nextBidx;
|
|
2255
|
+
const scrubbed = scrubbedRaw;
|
|
2256
|
+
await this.adapter.put(this.vault, this.name, id, scrubbed);
|
|
2257
|
+
if (this.ledger) {
|
|
2258
|
+
await this.ledger.append({
|
|
2259
|
+
op: "migration",
|
|
2260
|
+
collection: this.name,
|
|
2261
|
+
id,
|
|
2262
|
+
version: scrubbed._v,
|
|
2263
|
+
actor: this.keyring.userId,
|
|
2264
|
+
payloadHash: await this.historyStrategy.envelopePayloadHash(scrubbed),
|
|
2265
|
+
reason: "classified:scrub-equatable-tags"
|
|
2266
|
+
});
|
|
2267
|
+
}
|
|
2268
|
+
count++;
|
|
2269
|
+
}
|
|
2270
|
+
return count;
|
|
2271
|
+
}
|
|
2301
2272
|
/**
|
|
2302
2273
|
* @internal — attach money descriptors post-construction. MV dependency
|
|
2303
2274
|
* analysis auto-creates a source collection (without options) during
|
|
@@ -2306,7 +2277,7 @@ var Collection = class {
|
|
|
2306
2277
|
*/
|
|
2307
2278
|
_applyMoneyFields(moneyFields) {
|
|
2308
2279
|
if (this.moneyFields !== void 0) return;
|
|
2309
|
-
validateMoneyFieldPaths(moneyFields);
|
|
2280
|
+
moneyRuntime().validateMoneyFieldPaths(moneyFields);
|
|
2310
2281
|
this.moneyFields = moneyFields;
|
|
2311
2282
|
}
|
|
2312
2283
|
/** @internal — attach computed fields post-construction. See {@link _applyMoneyFields}. */
|
|
@@ -2321,6 +2292,52 @@ var Collection = class {
|
|
|
2321
2292
|
_applyMeta(meta) {
|
|
2322
2293
|
if (this.meta === void 0) this.meta = meta;
|
|
2323
2294
|
}
|
|
2295
|
+
/**
|
|
2296
|
+
* @internal — attach classified fields post-construction. See {@link _applyMoneyFields}.
|
|
2297
|
+
* First-wins. Note: unlike money/computed/meta, this cannot retro-seal a
|
|
2298
|
+
* collection that was already auto-created — `sensitiveFields` is frozen at
|
|
2299
|
+
* construction time. A reconciled declaration is only accepted when none of
|
|
2300
|
+
* its members are `storage: 'recoverable'` (those require sealing at first
|
|
2301
|
+
* open); otherwise this throws rather than silently persisting the value as
|
|
2302
|
+
* inline plaintext while `describe()` advertises protection.
|
|
2303
|
+
*/
|
|
2304
|
+
_applyClassifiedFields(classifiedFields) {
|
|
2305
|
+
const resolved = resolveClassifiedFields(this.name, classifiedFields);
|
|
2306
|
+
if (this.classified !== void 0) {
|
|
2307
|
+
for (const [field, spec] of Object.entries(resolved.byField)) {
|
|
2308
|
+
const prior = this.classified.byField[field];
|
|
2309
|
+
if (prior !== void 0 && prior.storage !== spec.storage) {
|
|
2310
|
+
throw new ClassifiedConfigError(
|
|
2311
|
+
this.name,
|
|
2312
|
+
`field "${field}" was already declared storage:'${prior.storage}' \u2014 storage-form transitions are refused (R6); migrate explicitly`
|
|
2313
|
+
);
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
return;
|
|
2317
|
+
}
|
|
2318
|
+
guardClassifiedCompat(this.name, resolved.byField, this.classifiedGuardCtx);
|
|
2319
|
+
for (const key of Object.keys(resolved.riderComputed)) {
|
|
2320
|
+
if (this.computed?.[key] !== void 0) {
|
|
2321
|
+
throw new ClassifiedConfigError(this.name, `rider companion "${key}" collides with a declared field`);
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
const retroDigest = Object.entries(resolved.byField).filter(([, spec]) => spec.storage === "digest-only").map(([field]) => field);
|
|
2325
|
+
if (retroDigest.length > 0) {
|
|
2326
|
+
throw new ClassifiedConfigError(
|
|
2327
|
+
this.name,
|
|
2328
|
+
`digest-only classified field(s) ${retroDigest.map((f) => `"${f}"`).join(", ")} were declared after the collection was first opened without them \u2014 the digest write path is fixed at first open, so these values would persist recoverably in _data. Declare classifiedFields at the collection's first vault.collection() call.`
|
|
2329
|
+
);
|
|
2330
|
+
}
|
|
2331
|
+
const unsealable = Object.entries(resolved.byField).filter(([field, spec]) => spec.storage === "recoverable" && !this.sensitiveFields.has(field)).map(([field]) => field);
|
|
2332
|
+
if (unsealable.length > 0) {
|
|
2333
|
+
throw new ClassifiedConfigError(
|
|
2334
|
+
this.name,
|
|
2335
|
+
`recoverable classified field(s) ${unsealable.map((f) => `"${f}"`).join(", ")} were declared after the collection was first opened without them \u2014 sealing is fixed at first open, so these values would persist as inline plaintext. Declare classifiedFields at the collection's first vault.collection() call (for materialized-view sources this means recoverable classified fields are not supported in stage 1).`
|
|
2336
|
+
);
|
|
2337
|
+
}
|
|
2338
|
+
this.classified = resolved;
|
|
2339
|
+
this.computed = { ...resolved.riderComputed, ...this.computed ?? {} };
|
|
2340
|
+
}
|
|
2324
2341
|
/** @internal — used only in tests; do not read in production code. */
|
|
2325
2342
|
get _ramCiphertext() {
|
|
2326
2343
|
return this.ramCiphertext;
|
|
@@ -2346,7 +2363,7 @@ var Collection = class {
|
|
|
2346
2363
|
}
|
|
2347
2364
|
}
|
|
2348
2365
|
if (this.materializedViewSource !== void 0) {
|
|
2349
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
2366
|
+
const { resolveStaleMVOnRead } = await import("./stale-7Q62KVI3.js");
|
|
2350
2367
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name);
|
|
2351
2368
|
}
|
|
2352
2369
|
let record;
|
|
@@ -2578,29 +2595,47 @@ var Collection = class {
|
|
|
2578
2595
|
const cached = this.cache.get(id);
|
|
2579
2596
|
return cached ? { record: cached.record, version: cached.version } : void 0;
|
|
2580
2597
|
}
|
|
2598
|
+
/** 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). */
|
|
2599
|
+
async resolveGatePrior(point, id) {
|
|
2600
|
+
if (!this.subsystemBus.gateNeedsPrior(point)) return { env: null, record: null, elided: true };
|
|
2601
|
+
const env = await this.adapter.get(this.vault, this.name, id);
|
|
2602
|
+
if (!env) return { env: null, record: null, elided: false };
|
|
2603
|
+
try {
|
|
2604
|
+
return { env, record: await this.codec.decryptRecord(env, { skipValidation: true }), elided: false };
|
|
2605
|
+
} catch {
|
|
2606
|
+
return { env, record: null, elided: false };
|
|
2607
|
+
}
|
|
2608
|
+
}
|
|
2609
|
+
/**
|
|
2610
|
+
* Wraps {@link RecordCodec.toCacheRecord} with an additional strip for
|
|
2611
|
+
* digest-only classified fields: the codec already omits them from `_data`
|
|
2612
|
+
* on write, but the write path caches the pre-encrypt `record` object
|
|
2613
|
+
* directly (to skip a redundant decrypt) — without this, a vdig field's
|
|
2614
|
+
* plaintext would sit in the working-set cache and `get()` would leak it
|
|
2615
|
+
* right back out, defeating C6.
|
|
2616
|
+
*/
|
|
2617
|
+
async _toCacheableRecord(record, envelope, id) {
|
|
2618
|
+
const base = await this.codec.toCacheRecord(record, envelope, id);
|
|
2619
|
+
if (this.vdigFields === null) return base;
|
|
2620
|
+
const clone = { ...base };
|
|
2621
|
+
for (const field of this.vdigFields.keys()) delete clone[field];
|
|
2622
|
+
return clone;
|
|
2623
|
+
}
|
|
2581
2624
|
/** @internal Untracked put body — call {@link put}, not this. */
|
|
2582
2625
|
async _putInternal(id, record, options) {
|
|
2583
2626
|
if (!hasWritePermission(this.keyring, this.name)) {
|
|
2584
2627
|
throw new ReadOnlyError();
|
|
2585
2628
|
}
|
|
2586
|
-
record = canonicalizeIncomingMoney(record, this.moneyFields);
|
|
2629
|
+
if (this.moneyFields) record = moneyRuntime().canonicalizeIncomingMoney(record, this.moneyFields);
|
|
2587
2630
|
if (this.subsystemBus?.hasGateHandlers("beforePut")) {
|
|
2588
|
-
const existingEnv = await this.
|
|
2589
|
-
let existingRecord = null;
|
|
2590
|
-
if (existingEnv) {
|
|
2591
|
-
try {
|
|
2592
|
-
existingRecord = await this.codec.decryptRecord(existingEnv, { skipValidation: true });
|
|
2593
|
-
} catch {
|
|
2594
|
-
existingRecord = null;
|
|
2595
|
-
}
|
|
2596
|
-
}
|
|
2631
|
+
const { env: existingEnv, record: existingRecord } = await this.resolveGatePrior("beforePut", id);
|
|
2597
2632
|
const gateEvent = {
|
|
2598
2633
|
op: existingEnv ? "update" : "create",
|
|
2599
2634
|
vault: this.vault,
|
|
2600
2635
|
collection: this.name,
|
|
2601
2636
|
docId: id,
|
|
2602
2637
|
incoming: record,
|
|
2603
|
-
existing: canonicalizeStoredMoney(existingRecord, this.moneyFields),
|
|
2638
|
+
existing: this.moneyFields ? moneyRuntime().canonicalizeStoredMoney(existingRecord, this.moneyFields) : existingRecord,
|
|
2604
2639
|
existingVersion: existingEnv?._v ?? 0,
|
|
2605
2640
|
existingTs: existingEnv?._ts,
|
|
2606
2641
|
userId: this.keyring.userId,
|
|
@@ -2609,14 +2644,17 @@ var Collection = class {
|
|
|
2609
2644
|
};
|
|
2610
2645
|
await this.subsystemBus.dispatchGate("beforePut", gateEvent);
|
|
2611
2646
|
}
|
|
2647
|
+
if (this.classified !== void 0) {
|
|
2648
|
+
enforceClassifiedWrite(record, this.classified.byField, this.name);
|
|
2649
|
+
}
|
|
2612
2650
|
if (this.computed !== void 0) {
|
|
2613
|
-
record =
|
|
2651
|
+
record = (await loadEvalComputedFields())(record, this.computed, id);
|
|
2614
2652
|
}
|
|
2615
2653
|
if (this.schema !== void 0) {
|
|
2616
2654
|
record = await validateSchemaInput(this.schema, record, `put(${id})`);
|
|
2617
2655
|
}
|
|
2618
2656
|
if (this.moneyFields) {
|
|
2619
|
-
record = quantizeMoneyFields(record, this.moneyFields);
|
|
2657
|
+
record = moneyRuntime().quantizeMoneyFields(record, this.moneyFields);
|
|
2620
2658
|
}
|
|
2621
2659
|
if (this.i18nFields) {
|
|
2622
2660
|
const obj = record;
|
|
@@ -2744,7 +2782,8 @@ var Collection = class {
|
|
|
2744
2782
|
const existingResolvedRecord = existingEnvelope ? await this.codec.decryptRecord(existingEnvelope, { skipValidation: true }) : null;
|
|
2745
2783
|
const existingResolved = existingResolvedRecord !== null ? { record: existingResolvedRecord, version: existingVersion } : void 0;
|
|
2746
2784
|
if (existingResolved && this.historyConfig.enabled !== false) {
|
|
2747
|
-
const
|
|
2785
|
+
const vdigCtx2 = this.vdigFields !== null ? { id, prev: existingEnvelope } : void 0;
|
|
2786
|
+
const histEnvelope = await this.codec.encryptRecord(existingResolved.record, existingResolved.version, cek2, void 0, void 0, vdigCtx2);
|
|
2748
2787
|
await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, histEnvelope);
|
|
2749
2788
|
this.emitter.emit("history:save", { vault: this.vault, collection: this.name, id, version: existingResolved.version });
|
|
2750
2789
|
if (this.historyConfig.maxVersions) {
|
|
@@ -2803,8 +2842,9 @@ var Collection = class {
|
|
|
2803
2842
|
const version = existing ? existing.version + 1 : 1;
|
|
2804
2843
|
this.uniqueConstraints?.check(id, record);
|
|
2805
2844
|
const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
2845
|
+
const vdigCtx = this.vdigFields !== null ? { id, prev: await this.adapter.get(this.vault, this.name, id) } : void 0;
|
|
2806
2846
|
if (existing && this.historyConfig.enabled !== false) {
|
|
2807
|
-
const historyEnvelope = await this.codec.encryptRecord(existing.record, existing.version, cek);
|
|
2847
|
+
const historyEnvelope = await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, vdigCtx);
|
|
2808
2848
|
await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, historyEnvelope);
|
|
2809
2849
|
this.emitter.emit("history:save", {
|
|
2810
2850
|
vault: this.vault,
|
|
@@ -2818,8 +2858,9 @@ var Collection = class {
|
|
|
2818
2858
|
});
|
|
2819
2859
|
}
|
|
2820
2860
|
}
|
|
2821
|
-
const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs);
|
|
2861
|
+
const envelope = await this.codec.encryptRecord(record, version, cek, options?.source, options?.sourceTs, vdigCtx);
|
|
2822
2862
|
await this.adapter.put(this.vault, this.name, id, envelope);
|
|
2863
|
+
await this._ensureClassifiedMarker();
|
|
2823
2864
|
if (this.embeddings) {
|
|
2824
2865
|
await this.searchStrategy.embedOnWrite(this.searchContext(), id, record, version);
|
|
2825
2866
|
}
|
|
@@ -2839,10 +2880,10 @@ var Collection = class {
|
|
|
2839
2880
|
await this.ledger.append(appendInput);
|
|
2840
2881
|
}
|
|
2841
2882
|
if (this.lazy && this.lru) {
|
|
2842
|
-
this.lru.set(id, { record: await this.
|
|
2883
|
+
this.lru.set(id, { record: await this._toCacheableRecord(record, envelope, id), version }, estimateRecordBytes(record));
|
|
2843
2884
|
await this.maintainPersistedIndexesOnPut(id, record, existing ? existing.record : null, version);
|
|
2844
2885
|
} else {
|
|
2845
|
-
this.cache.set(id, { record: await this.
|
|
2886
|
+
this.cache.set(id, { record: await this._toCacheableRecord(record, envelope, id), version });
|
|
2846
2887
|
this.indexes?.upsert(id, record, existing ? existing.record : null);
|
|
2847
2888
|
this.uniqueConstraints?.upsert(id, record, existing?.record);
|
|
2848
2889
|
}
|
|
@@ -2885,7 +2926,7 @@ var Collection = class {
|
|
|
2885
2926
|
if (mode === "eager") {
|
|
2886
2927
|
if (executor === null) {
|
|
2887
2928
|
;
|
|
2888
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-
|
|
2929
|
+
({ MaterializedViewExecutor: executor } = await import("./executor-FGISLQIN.js"));
|
|
2889
2930
|
}
|
|
2890
2931
|
await executor.refresh(reg, {
|
|
2891
2932
|
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
@@ -2894,7 +2935,7 @@ var Collection = class {
|
|
|
2894
2935
|
});
|
|
2895
2936
|
} else if (mode === "lazy") {
|
|
2896
2937
|
if (staleHelpers === null) {
|
|
2897
|
-
staleHelpers = await import("./stale-
|
|
2938
|
+
staleHelpers = await import("./stale-7Q62KVI3.js");
|
|
2898
2939
|
}
|
|
2899
2940
|
staleHelpers.markMVStale(registry, reg.spec.name);
|
|
2900
2941
|
}
|
|
@@ -2946,7 +2987,7 @@ var Collection = class {
|
|
|
2946
2987
|
raw = (await this.resolvePriorValues(id))?.record ?? null;
|
|
2947
2988
|
}
|
|
2948
2989
|
if (raw === null) return null;
|
|
2949
|
-
return canonicalizeStoredMoney(raw, this.moneyFields);
|
|
2990
|
+
return this.moneyFields ? moneyRuntime().canonicalizeStoredMoney(raw, this.moneyFields) : raw;
|
|
2950
2991
|
}
|
|
2951
2992
|
/**
|
|
2952
2993
|
* @internal Ids of records whose top-level `field` equals `value`.
|
|
@@ -3029,7 +3070,7 @@ var Collection = class {
|
|
|
3029
3070
|
}
|
|
3030
3071
|
async dispatchDerivations(id, record, version) {
|
|
3031
3072
|
if (this.derivationSource === void 0) return;
|
|
3032
|
-
const incoming = canonicalizeStoredMoney(record, this.moneyFields);
|
|
3073
|
+
const incoming = this.moneyFields ? moneyRuntime().canonicalizeStoredMoney(record, this.moneyFields) : record;
|
|
3033
3074
|
if (incoming && typeof incoming === "object" && "_derivedFrom" in incoming) return;
|
|
3034
3075
|
const registry = this.derivationSource.registry();
|
|
3035
3076
|
const strategies = registry.strategiesForSource(this.name);
|
|
@@ -3079,7 +3120,7 @@ var Collection = class {
|
|
|
3079
3120
|
continue;
|
|
3080
3121
|
}
|
|
3081
3122
|
if (DerivationExecutor === null) {
|
|
3082
|
-
({ DerivationExecutor } = await import("./executor-
|
|
3123
|
+
({ DerivationExecutor } = await import("./executor-CBTNU5VZ.js"));
|
|
3083
3124
|
}
|
|
3084
3125
|
for (const run of runs) {
|
|
3085
3126
|
const ctx = { vault: this.derivationSource.getReadOnlyFacade() };
|
|
@@ -3098,7 +3139,7 @@ var Collection = class {
|
|
|
3098
3139
|
const outputCollection = this.derivationSource.getCollection(outSpec.collection);
|
|
3099
3140
|
const txCtx = this.derivationSource.getActiveTxContext();
|
|
3100
3141
|
if (out.kind === "array") {
|
|
3101
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-
|
|
3142
|
+
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-WS22Q5WH.js");
|
|
3102
3143
|
const prior = await loadFanoutSidecar(this.adapter, this.vault, spec.source, run.runId, key, this.getDEK, this.storeCiphertext);
|
|
3103
3144
|
const prevKeys = new Set(prior?.keys ?? []);
|
|
3104
3145
|
const newKeysList = out.entries.map((e) => e.key);
|
|
@@ -3225,7 +3266,7 @@ var Collection = class {
|
|
|
3225
3266
|
const next = transform(record);
|
|
3226
3267
|
const nextVersion = (env._v ?? 0) + 1;
|
|
3227
3268
|
const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
3228
|
-
const newEnv = await this.codec.encryptRecord(next, nextVersion, cek);
|
|
3269
|
+
const newEnv = await this.codec.encryptRecord(next, nextVersion, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: env } : void 0);
|
|
3229
3270
|
await this.adapter.put(this.vault, this.name, id, newEnv);
|
|
3230
3271
|
await this._invalidateCacheEntry(id);
|
|
3231
3272
|
if (this.ledger) {
|
|
@@ -3306,21 +3347,15 @@ var Collection = class {
|
|
|
3306
3347
|
throw new ReadOnlyError();
|
|
3307
3348
|
}
|
|
3308
3349
|
if (this.subsystemBus?.hasGateHandlers("beforeDelete")) {
|
|
3309
|
-
const existingEnv = await this.
|
|
3310
|
-
if (existingEnv) {
|
|
3311
|
-
let existingRecord = null;
|
|
3312
|
-
try {
|
|
3313
|
-
existingRecord = await this.codec.decryptRecord(existingEnv, { skipValidation: true });
|
|
3314
|
-
} catch {
|
|
3315
|
-
existingRecord = null;
|
|
3316
|
-
}
|
|
3350
|
+
const { env: existingEnv, record: existingRecord, elided } = await this.resolveGatePrior("beforeDelete", id);
|
|
3351
|
+
if (existingEnv || elided) {
|
|
3317
3352
|
await this.subsystemBus.dispatchGate("beforeDelete", {
|
|
3318
3353
|
vault: this.vault,
|
|
3319
3354
|
collection: this.name,
|
|
3320
3355
|
docId: id,
|
|
3321
|
-
existing: canonicalizeStoredMoney(existingRecord, this.moneyFields),
|
|
3322
|
-
existingVersion: existingEnv
|
|
3323
|
-
existingTs: existingEnv
|
|
3356
|
+
existing: this.moneyFields ? moneyRuntime().canonicalizeStoredMoney(existingRecord, this.moneyFields) : existingRecord,
|
|
3357
|
+
existingVersion: existingEnv?._v ?? 0,
|
|
3358
|
+
existingTs: existingEnv?._ts,
|
|
3324
3359
|
internal,
|
|
3325
3360
|
userId: this.keyring.userId,
|
|
3326
3361
|
role: this.keyring.role
|
|
@@ -3347,7 +3382,8 @@ var Collection = class {
|
|
|
3347
3382
|
}
|
|
3348
3383
|
if (existing && this.historyConfig.enabled !== false) {
|
|
3349
3384
|
const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
3350
|
-
const
|
|
3385
|
+
const prevForVdig = this.vdigFields !== null ? await this.adapter.get(this.vault, this.name, id) : null;
|
|
3386
|
+
const historyEnvelope = await this.codec.encryptRecord(existing.record, existing.version, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: prevForVdig } : void 0);
|
|
3351
3387
|
await this.historyStrategy.saveHistory(this.adapter, this.vault, this.name, id, historyEnvelope);
|
|
3352
3388
|
}
|
|
3353
3389
|
const previousEnvelope = await this.adapter.get(this.vault, this.name, id);
|
|
@@ -3456,7 +3492,7 @@ var Collection = class {
|
|
|
3456
3492
|
for (const [outputKey, outSpec] of Object.entries(spec.outputs)) {
|
|
3457
3493
|
if (outSpec.shape !== "array") continue;
|
|
3458
3494
|
if (helpers === null) {
|
|
3459
|
-
helpers = await import("./fanout-sidecar-
|
|
3495
|
+
helpers = await import("./fanout-sidecar-WS22Q5WH.js");
|
|
3460
3496
|
}
|
|
3461
3497
|
const sidecar = await helpers.loadFanoutSidecar(this.adapter, this.vault, spec.source, id, outputKey, this.getDEK, this.storeCiphertext);
|
|
3462
3498
|
if (!sidecar) continue;
|
|
@@ -3490,7 +3526,7 @@ var Collection = class {
|
|
|
3490
3526
|
if (mode === "eager") {
|
|
3491
3527
|
if (executor === null) {
|
|
3492
3528
|
;
|
|
3493
|
-
({ MaterializedViewExecutor: executor } = await import("./executor-
|
|
3529
|
+
({ MaterializedViewExecutor: executor } = await import("./executor-FGISLQIN.js"));
|
|
3494
3530
|
}
|
|
3495
3531
|
await executor.refresh(reg, {
|
|
3496
3532
|
getCollection: (name) => this.materializedViewSource.getCollection(name),
|
|
@@ -3499,7 +3535,7 @@ var Collection = class {
|
|
|
3499
3535
|
});
|
|
3500
3536
|
} else if (mode === "lazy") {
|
|
3501
3537
|
if (staleHelpers === null) {
|
|
3502
|
-
staleHelpers = await import("./stale-
|
|
3538
|
+
staleHelpers = await import("./stale-7Q62KVI3.js");
|
|
3503
3539
|
}
|
|
3504
3540
|
staleHelpers.markMVStale(registry, reg.spec.name);
|
|
3505
3541
|
}
|
|
@@ -3522,7 +3558,7 @@ var Collection = class {
|
|
|
3522
3558
|
);
|
|
3523
3559
|
}
|
|
3524
3560
|
if (this.materializedViewSource !== void 0) {
|
|
3525
|
-
const { resolveStaleMVOnRead } = await import("./stale-
|
|
3561
|
+
const { resolveStaleMVOnRead } = await import("./stale-7Q62KVI3.js");
|
|
3526
3562
|
await resolveStaleMVOnRead(this.materializedViewSource, this.name);
|
|
3527
3563
|
}
|
|
3528
3564
|
await this.ensureHydrated();
|
|
@@ -4351,7 +4387,8 @@ var Collection = class {
|
|
|
4351
4387
|
const result = {};
|
|
4352
4388
|
for (const [id, entry] of this.cache) {
|
|
4353
4389
|
const cek = this.perRecordCek ? await this.resolveRecordCek(id) : void 0;
|
|
4354
|
-
|
|
4390
|
+
const prevForVdig = this.vdigFields !== null ? await this.adapter.get(this.vault, this.name, id) : null;
|
|
4391
|
+
result[id] = await this.codec.encryptRecord(entry.record, entry.version, cek, void 0, void 0, this.vdigFields !== null ? { id, prev: prevForVdig } : void 0);
|
|
4355
4392
|
}
|
|
4356
4393
|
return result;
|
|
4357
4394
|
}
|
|
@@ -4377,7 +4414,7 @@ var Collection = class {
|
|
|
4377
4414
|
const locale = localeOpts?.locale ?? this.defaultLocale;
|
|
4378
4415
|
let result = record;
|
|
4379
4416
|
if (hasMoney && this.moneyFields) {
|
|
4380
|
-
result = decodeMoneyFields(result, this.moneyFields, typeof locale === "string" ? locale : void 0);
|
|
4417
|
+
result = moneyRuntime().decodeMoneyFields(result, this.moneyFields, typeof locale === "string" ? locale : void 0);
|
|
4381
4418
|
}
|
|
4382
4419
|
const hasStaticDisplay = hasDict && this.dictKeyFields !== void 0 && Object.values(this.dictKeyFields).some(
|
|
4383
4420
|
(d) => isStaticDictDescriptor(d) && d.displayLocale !== void 0
|
|
@@ -4663,6 +4700,20 @@ var Collection = class {
|
|
|
4663
4700
|
id
|
|
4664
4701
|
);
|
|
4665
4702
|
}
|
|
4703
|
+
/** C-A/R10: persist the classified marker once per classified handle (store I/O in config-drift.ts). */
|
|
4704
|
+
async _ensureClassifiedMarker() {
|
|
4705
|
+
if (this._markerPersisted || this.vdigFields === null) return;
|
|
4706
|
+
const { persistClassifiedMarkerForFields } = await import("./config-drift-KGM7ZRW4.js");
|
|
4707
|
+
await persistClassifiedMarkerForFields(this.adapter, this.vault, this.name, this.vdigFields, await this.getDEK(this.name));
|
|
4708
|
+
this._markerPersisted = true;
|
|
4709
|
+
}
|
|
4710
|
+
/** C-A/R10 drift signal — the marker's declared digest-only set, memoized to one store read per handle (see config-drift.ts). */
|
|
4711
|
+
async _classifiedMarkerDigestOnly() {
|
|
4712
|
+
if (this._markerDigestOnlyCache !== void 0) return this._markerDigestOnlyCache;
|
|
4713
|
+
const { readClassifiedMarkerDigestOnly } = await import("./config-drift-KGM7ZRW4.js");
|
|
4714
|
+
this._markerDigestOnlyCache = await readClassifiedMarkerDigestOnly(this.adapter, this.vault, this.name, await this.getDEK(this.name));
|
|
4715
|
+
return this._markerDigestOnlyCache;
|
|
4716
|
+
}
|
|
4666
4717
|
/**
|
|
4667
4718
|
* find the first record whose deterministic field matches
|
|
4668
4719
|
* the given plaintext. Returns `null` when no match exists.
|
|
@@ -5384,141 +5435,6 @@ var RefRegistry = class {
|
|
|
5384
5435
|
}
|
|
5385
5436
|
};
|
|
5386
5437
|
|
|
5387
|
-
// src/with-shape/links/link-set.ts
|
|
5388
|
-
var LINK_COLLECTION_PREFIX = "_links_";
|
|
5389
|
-
function linkCollectionName(name) {
|
|
5390
|
-
return `${LINK_COLLECTION_PREFIX}${name}`;
|
|
5391
|
-
}
|
|
5392
|
-
function isLinkCollectionName(name) {
|
|
5393
|
-
return name.startsWith(LINK_COLLECTION_PREFIX);
|
|
5394
|
-
}
|
|
5395
|
-
function linkRowKey(aId, bId) {
|
|
5396
|
-
return `${encodeURIComponent(aId)}|${encodeURIComponent(bId)}`;
|
|
5397
|
-
}
|
|
5398
|
-
var LinkSet = class {
|
|
5399
|
-
constructor(adapter, vault, name, spec, encrypted, getDEK, actor, emitter, endpointExists) {
|
|
5400
|
-
this.adapter = adapter;
|
|
5401
|
-
this.vault = vault;
|
|
5402
|
-
this.name = name;
|
|
5403
|
-
this.spec = spec;
|
|
5404
|
-
this.encrypted = encrypted;
|
|
5405
|
-
this.getDEK = getDEK;
|
|
5406
|
-
this.actor = actor;
|
|
5407
|
-
this.emitter = emitter;
|
|
5408
|
-
this.endpointExists = endpointExists;
|
|
5409
|
-
this.collName = linkCollectionName(name);
|
|
5410
|
-
}
|
|
5411
|
-
adapter;
|
|
5412
|
-
vault;
|
|
5413
|
-
name;
|
|
5414
|
-
spec;
|
|
5415
|
-
encrypted;
|
|
5416
|
-
getDEK;
|
|
5417
|
-
actor;
|
|
5418
|
-
emitter;
|
|
5419
|
-
endpointExists;
|
|
5420
|
-
collName;
|
|
5421
|
-
dekPromise = null;
|
|
5422
|
-
dek() {
|
|
5423
|
-
if (!this.dekPromise) this.dekPromise = this.getDEK(this.collName);
|
|
5424
|
-
return this.dekPromise;
|
|
5425
|
-
}
|
|
5426
|
-
async encryptEntry(entry, version) {
|
|
5427
|
-
const json = JSON.stringify(entry);
|
|
5428
|
-
const base = { _noydb: NOYDB_FORMAT_VERSION, _v: version, _ts: (/* @__PURE__ */ new Date()).toISOString(), _by: this.actor };
|
|
5429
|
-
if (!this.encrypted) return { ...base, _iv: "", _data: json };
|
|
5430
|
-
const { iv, data } = await encrypt(json, await this.dek());
|
|
5431
|
-
return { ...base, _iv: iv, _data: data };
|
|
5432
|
-
}
|
|
5433
|
-
async decryptEntry(env) {
|
|
5434
|
-
const json = this.encrypted ? await openEnvelopeJson(env, await this.dek()) : env._data;
|
|
5435
|
-
return JSON.parse(json);
|
|
5436
|
-
}
|
|
5437
|
-
async connect(aId, bId, meta) {
|
|
5438
|
-
if (!await this.endpointExists(this.spec.a, aId)) {
|
|
5439
|
-
throw new LinkEndpointError(this.name, this.spec.a, aId);
|
|
5440
|
-
}
|
|
5441
|
-
if (!await this.endpointExists(this.spec.b, bId)) {
|
|
5442
|
-
throw new LinkEndpointError(this.name, this.spec.b, bId);
|
|
5443
|
-
}
|
|
5444
|
-
const key = linkRowKey(aId, bId);
|
|
5445
|
-
const entry = meta !== void 0 ? { a: aId, b: bId, meta } : { a: aId, b: bId };
|
|
5446
|
-
const existing = await this.adapter.get(this.vault, this.collName, key);
|
|
5447
|
-
const env = await this.encryptEntry(entry, (existing?._v ?? 0) + 1);
|
|
5448
|
-
await this.adapter.put(this.vault, this.collName, key, env, existing?._v);
|
|
5449
|
-
this.emitter.emit("change", { vault: this.vault, collection: this.collName, id: key, action: "put" });
|
|
5450
|
-
}
|
|
5451
|
-
async disconnect(aId, bId) {
|
|
5452
|
-
const key = linkRowKey(aId, bId);
|
|
5453
|
-
const existing = await this.adapter.get(this.vault, this.collName, key);
|
|
5454
|
-
if (!existing) return;
|
|
5455
|
-
await this.adapter.delete(this.vault, this.collName, key);
|
|
5456
|
-
this.emitter.emit("change", { vault: this.vault, collection: this.collName, id: key, action: "delete" });
|
|
5457
|
-
}
|
|
5458
|
-
async has(aId, bId) {
|
|
5459
|
-
return await this.adapter.get(this.vault, this.collName, linkRowKey(aId, bId)) !== null;
|
|
5460
|
-
}
|
|
5461
|
-
async of(id) {
|
|
5462
|
-
const rows = await this.list();
|
|
5463
|
-
return rows.filter((r) => r.a === id || r.b === id);
|
|
5464
|
-
}
|
|
5465
|
-
async list() {
|
|
5466
|
-
const keys = await this.adapter.list(this.vault, this.collName);
|
|
5467
|
-
const out = [];
|
|
5468
|
-
for (const key of keys) {
|
|
5469
|
-
const env = await this.adapter.get(this.vault, this.collName, key);
|
|
5470
|
-
if (!env) continue;
|
|
5471
|
-
const e = await this.decryptEntry(env);
|
|
5472
|
-
out.push(e.meta !== void 0 ? { a: e.a, b: e.b, meta: e.meta } : { a: e.a, b: e.b });
|
|
5473
|
-
}
|
|
5474
|
-
return out;
|
|
5475
|
-
}
|
|
5476
|
-
// ── Vault-internal cascade helpers ──────────────────────────────────
|
|
5477
|
-
/** @internal — rows where the deleted endpoint id matches the relevant slot. */
|
|
5478
|
-
async _rowsTouchingEndpoint(collection, id) {
|
|
5479
|
-
const rows = await this.list();
|
|
5480
|
-
return rows.filter(
|
|
5481
|
-
(r) => this.spec.a === collection && r.a === id || this.spec.b === collection && r.b === id
|
|
5482
|
-
);
|
|
5483
|
-
}
|
|
5484
|
-
/** @internal — the storage collection name (for tx pre-image capture). */
|
|
5485
|
-
get _collectionName() {
|
|
5486
|
-
return this.collName;
|
|
5487
|
-
}
|
|
5488
|
-
};
|
|
5489
|
-
var LinkEndpointError = class extends NoydbError {
|
|
5490
|
-
link;
|
|
5491
|
-
endpoint;
|
|
5492
|
-
missingId;
|
|
5493
|
-
constructor(link, endpoint, missingId) {
|
|
5494
|
-
super(
|
|
5495
|
-
"LINK_ENDPOINT",
|
|
5496
|
-
`link("${link}").connect: endpoint "${endpoint}" has no record "${missingId}".`
|
|
5497
|
-
);
|
|
5498
|
-
this.name = "LinkEndpointError";
|
|
5499
|
-
this.link = link;
|
|
5500
|
-
this.endpoint = endpoint;
|
|
5501
|
-
this.missingId = missingId;
|
|
5502
|
-
}
|
|
5503
|
-
};
|
|
5504
|
-
var LinkIntegrityError = class extends NoydbError {
|
|
5505
|
-
link;
|
|
5506
|
-
endpoint;
|
|
5507
|
-
id;
|
|
5508
|
-
count;
|
|
5509
|
-
constructor(link, endpoint, id, count) {
|
|
5510
|
-
super(
|
|
5511
|
-
"LINK_INTEGRITY",
|
|
5512
|
-
`Cannot delete "${endpoint}"/"${id}": ${count} link(s) in "${link}" still reference it (onDelete: 'strict').`
|
|
5513
|
-
);
|
|
5514
|
-
this.name = "LinkIntegrityError";
|
|
5515
|
-
this.link = link;
|
|
5516
|
-
this.endpoint = endpoint;
|
|
5517
|
-
this.id = id;
|
|
5518
|
-
this.count = count;
|
|
5519
|
-
}
|
|
5520
|
-
};
|
|
5521
|
-
|
|
5522
5438
|
// src/with-shape/links/vault-facade.ts
|
|
5523
5439
|
var VaultLinks = class {
|
|
5524
5440
|
constructor(deps) {
|
|
@@ -5838,74 +5754,21 @@ var VaultLinks = class {
|
|
|
5838
5754
|
}
|
|
5839
5755
|
};
|
|
5840
5756
|
|
|
5841
|
-
// src/with-shape/
|
|
5842
|
-
function
|
|
5843
|
-
|
|
5844
|
-
const
|
|
5845
|
-
|
|
5846
|
-
|
|
5847
|
-
|
|
5848
|
-
|
|
5849
|
-
|
|
5850
|
-
|
|
5851
|
-
|
|
5852
|
-
|
|
5853
|
-
|
|
5854
|
-
|
|
5855
|
-
|
|
5856
|
-
const shapeChanged = canonicalize(aProps[k]) !== canonicalize(bProps[k]);
|
|
5857
|
-
const requiredChanged = aReq.has(k) !== bReq.has(k);
|
|
5858
|
-
if (shapeChanged || requiredChanged) {
|
|
5859
|
-
changed.push({ field: k, requiredChanged, shapeChanged });
|
|
5860
|
-
}
|
|
5861
|
-
}
|
|
5862
|
-
let kind;
|
|
5863
|
-
if (added.length === 0 && removed.length === 0 && changed.length === 0) {
|
|
5864
|
-
kind = "none";
|
|
5865
|
-
} else if (removed.length === 0 && changed.length === 0 && added.every((k) => !bReq.has(k))) {
|
|
5866
|
-
kind = "additive";
|
|
5867
|
-
} else {
|
|
5868
|
-
kind = "non-additive";
|
|
5869
|
-
}
|
|
5870
|
-
return { collection, kind, added, removed, changed };
|
|
5871
|
-
}
|
|
5872
|
-
|
|
5873
|
-
// src/with-shape/schema-update/dispatch.ts
|
|
5874
|
-
async function evaluateStrategies(delta, strategies, ctx) {
|
|
5875
|
-
for (const strategy of strategies) {
|
|
5876
|
-
const decision = await strategy.onSchemaDelta(delta, ctx);
|
|
5877
|
-
if (decision.action !== "allow") return decision;
|
|
5878
|
-
}
|
|
5879
|
-
return { action: "allow" };
|
|
5880
|
-
}
|
|
5881
|
-
|
|
5882
|
-
// src/with-shape/persisted-schemas/register.ts
|
|
5883
|
-
async function persistSchemaIfNeeded(opts) {
|
|
5884
|
-
const fresh = await derivePersistedSchema(opts.validator);
|
|
5885
|
-
const stored = await loadPersistedSchema(opts.store, opts.vault, opts.collectionName, opts.dek);
|
|
5886
|
-
if (stored && isEquivalent(stored, fresh)) {
|
|
5887
|
-
return { written: false, skipped: true, envelope: stored, decision: { action: "allow" } };
|
|
5888
|
-
}
|
|
5889
|
-
let decision = { action: "allow" };
|
|
5890
|
-
const strategies = opts.strategies ?? [];
|
|
5891
|
-
if (stored && strategies.length > 0 && stored.kind === fresh.kind && isPlainObject(stored.jsonSchema) && isPlainObject(fresh.jsonSchema)) {
|
|
5892
|
-
const delta = computeSchemaDelta(stored.jsonSchema, fresh.jsonSchema, opts.collectionName);
|
|
5893
|
-
decision = await evaluateStrategies(delta, strategies, { collection: opts.collectionName });
|
|
5894
|
-
}
|
|
5895
|
-
if (decision.action !== "allow") {
|
|
5896
|
-
return { written: false, skipped: false, envelope: stored ?? fresh, decision };
|
|
5897
|
-
}
|
|
5898
|
-
await savePersistedSchema(opts.store, opts.vault, opts.collectionName, opts.dek, fresh);
|
|
5899
|
-
return { written: true, skipped: false, envelope: fresh, decision };
|
|
5900
|
-
}
|
|
5901
|
-
function isPlainObject(v) {
|
|
5902
|
-
return typeof v === "object" && v !== null && !Array.isArray(v);
|
|
5903
|
-
}
|
|
5904
|
-
function isEquivalent(a, b) {
|
|
5905
|
-
if (a.kind !== b.kind) return false;
|
|
5906
|
-
if (a.hash && b.hash) return a.hash === b.hash;
|
|
5907
|
-
if (a.hash === null && b.hash === null) return true;
|
|
5908
|
-
return false;
|
|
5757
|
+
// src/with-shape/links/lazy-handle.ts
|
|
5758
|
+
function makeLazyLinkSetHandle(d) {
|
|
5759
|
+
let engine = null;
|
|
5760
|
+
const load = () => engine ??= import("./link-set-UQEIYQAM.js").then(
|
|
5761
|
+
({ LinkSet }) => new LinkSet(d.adapter, d.vault, d.name, d.spec, d.encrypted, d.getDEK, d.actor, d.emitter, d.endpointExists)
|
|
5762
|
+
);
|
|
5763
|
+
return {
|
|
5764
|
+
_collectionName: linkCollectionName(d.name),
|
|
5765
|
+
connect: async (aId, bId, meta) => (await load()).connect(aId, bId, meta),
|
|
5766
|
+
disconnect: async (aId, bId) => (await load()).disconnect(aId, bId),
|
|
5767
|
+
has: async (aId, bId) => (await load()).has(aId, bId),
|
|
5768
|
+
of: async (id) => (await load()).of(id),
|
|
5769
|
+
list: async () => (await load()).list(),
|
|
5770
|
+
_rowsTouchingEndpoint: async (collection, id) => (await load())._rowsTouchingEndpoint(collection, id)
|
|
5771
|
+
};
|
|
5909
5772
|
}
|
|
5910
5773
|
|
|
5911
5774
|
// src/with-shape/schema-update/gate.ts
|
|
@@ -6021,70 +5884,6 @@ var SchemaFenceController = class {
|
|
|
6021
5884
|
}
|
|
6022
5885
|
};
|
|
6023
5886
|
|
|
6024
|
-
// src/with-shape/schema-update/fence-watcher.ts
|
|
6025
|
-
var FenceWatcher = class {
|
|
6026
|
-
#coordination;
|
|
6027
|
-
#vault;
|
|
6028
|
-
#writerId;
|
|
6029
|
-
#sessionId;
|
|
6030
|
-
#onFlush;
|
|
6031
|
-
#now;
|
|
6032
|
-
#emit;
|
|
6033
|
-
#lastState = null;
|
|
6034
|
-
#quiescedAtVersion = null;
|
|
6035
|
-
#timer;
|
|
6036
|
-
constructor(opts) {
|
|
6037
|
-
this.#coordination = opts.coordination;
|
|
6038
|
-
this.#vault = opts.vault;
|
|
6039
|
-
this.#writerId = opts.clientId;
|
|
6040
|
-
this.#sessionId = opts.sessionId ?? opts.clientId;
|
|
6041
|
-
this.#onFlush = opts.onFlush;
|
|
6042
|
-
this.#now = opts.now ?? (() => Date.now());
|
|
6043
|
-
this.#emit = opts.emit ?? (() => {
|
|
6044
|
-
});
|
|
6045
|
-
}
|
|
6046
|
-
/** Publish liveness (and the current ack) without changing quiesce state. */
|
|
6047
|
-
async beat() {
|
|
6048
|
-
await this.#coordination.reportPresence(this.#vault, {
|
|
6049
|
-
writerId: this.#writerId,
|
|
6050
|
-
sessionId: this.#sessionId,
|
|
6051
|
-
lastSeen: this.#now(),
|
|
6052
|
-
quiescedAtVersion: this.#quiescedAtVersion
|
|
6053
|
-
});
|
|
6054
|
-
}
|
|
6055
|
-
/** Poll the fence; quiesce on draining; emit on transitions. */
|
|
6056
|
-
async check() {
|
|
6057
|
-
const fence = await this.#coordination.readFence(this.#vault);
|
|
6058
|
-
if (fence.fenceState !== this.#lastState) {
|
|
6059
|
-
this.#lastState = fence.fenceState;
|
|
6060
|
-
this.#emit({ currentSchemaVersion: fence.currentSchemaVersion, fenceState: fence.fenceState });
|
|
6061
|
-
}
|
|
6062
|
-
if (fence.fenceState === "draining" && this.#quiescedAtVersion !== fence.currentSchemaVersion) {
|
|
6063
|
-
await this.#onFlush();
|
|
6064
|
-
this.#quiescedAtVersion = fence.currentSchemaVersion;
|
|
6065
|
-
await this.beat();
|
|
6066
|
-
}
|
|
6067
|
-
if (fence.fenceState === "normal") {
|
|
6068
|
-
this.#quiescedAtVersion = null;
|
|
6069
|
-
}
|
|
6070
|
-
}
|
|
6071
|
-
start(intervalMs) {
|
|
6072
|
-
if (this.#timer) return;
|
|
6073
|
-
this.#timer = setInterval(() => {
|
|
6074
|
-
void this.beat();
|
|
6075
|
-
void this.check();
|
|
6076
|
-
}, intervalMs);
|
|
6077
|
-
const timer = this.#timer;
|
|
6078
|
-
if (typeof timer.unref === "function") timer.unref();
|
|
6079
|
-
}
|
|
6080
|
-
stop() {
|
|
6081
|
-
if (this.#timer) {
|
|
6082
|
-
clearInterval(this.#timer);
|
|
6083
|
-
this.#timer = void 0;
|
|
6084
|
-
}
|
|
6085
|
-
}
|
|
6086
|
-
};
|
|
6087
|
-
|
|
6088
5887
|
// src/with-audit/attestation/vault-facade.ts
|
|
6089
5888
|
var VaultAttestation = class {
|
|
6090
5889
|
constructor(deps, strategy) {
|
|
@@ -6157,224 +5956,6 @@ var VaultAttestation = class {
|
|
|
6157
5956
|
}
|
|
6158
5957
|
};
|
|
6159
5958
|
|
|
6160
|
-
// src/with-shape/introspection/walk.ts
|
|
6161
|
-
var INTERNAL_PREFIX = "_";
|
|
6162
|
-
var KNOWN_INTERNAL_NAMES = ["_keyring", "_ledger", "_meta", "_schemas", "_deltas"];
|
|
6163
|
-
async function dumpVaultSchema(vault, opts) {
|
|
6164
|
-
const state = vault._introspectState();
|
|
6165
|
-
const sampleSize = opts.sampleSize ?? 50;
|
|
6166
|
-
const withStats = opts.withStats === true;
|
|
6167
|
-
const cacheNames = [...state.collectionCache.keys()];
|
|
6168
|
-
const storageNames = (await safeListAllCollections(state.adapter, state.name)).filter((n) => !n.startsWith(INTERNAL_PREFIX));
|
|
6169
|
-
const allNames = Array.from(/* @__PURE__ */ new Set([...cacheNames, ...storageNames])).sort();
|
|
6170
|
-
const collections = {};
|
|
6171
|
-
for (const name of allNames) {
|
|
6172
|
-
collections[name] = await describeCollection(state, name, sampleSize, withStats);
|
|
6173
|
-
}
|
|
6174
|
-
const materializedViews = describeMVs(state.mvRegistry);
|
|
6175
|
-
const overlayViews = describeOverlays(state.overlayRegistry);
|
|
6176
|
-
const derivations = describeDerivations(state.derivationRegistry);
|
|
6177
|
-
let internal;
|
|
6178
|
-
if (withStats) {
|
|
6179
|
-
internal = {};
|
|
6180
|
-
for (const name of KNOWN_INTERNAL_NAMES) {
|
|
6181
|
-
const stats = await statsForCollection(state.adapter, state.name, name);
|
|
6182
|
-
if (stats.records > 0) {
|
|
6183
|
-
internal[name] = { records: stats.records, bytes: stats.bytes };
|
|
6184
|
-
}
|
|
6185
|
-
}
|
|
6186
|
-
}
|
|
6187
|
-
const snap = {
|
|
6188
|
-
_noydb_snapshot: 1,
|
|
6189
|
-
vault: state.name,
|
|
6190
|
-
emittedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
6191
|
-
subsystems: state.subsystems,
|
|
6192
|
-
...state.vaultMeta !== void 0 ? { meta: state.vaultMeta } : {},
|
|
6193
|
-
collections,
|
|
6194
|
-
materializedViews,
|
|
6195
|
-
overlayViews,
|
|
6196
|
-
derivations,
|
|
6197
|
-
...internal !== void 0 ? { internal } : {}
|
|
6198
|
-
};
|
|
6199
|
-
return snap;
|
|
6200
|
-
}
|
|
6201
|
-
async function safeListAllCollections(adapter, vault) {
|
|
6202
|
-
try {
|
|
6203
|
-
const snap = await adapter.loadAll(vault);
|
|
6204
|
-
return Object.keys(snap);
|
|
6205
|
-
} catch {
|
|
6206
|
-
return [];
|
|
6207
|
-
}
|
|
6208
|
-
}
|
|
6209
|
-
async function describeCollection(state, collectionName, sampleSize, withStats) {
|
|
6210
|
-
let fields = {};
|
|
6211
|
-
let validator;
|
|
6212
|
-
const refsRaw = state.refRegistry.getOutbound(collectionName);
|
|
6213
|
-
const refs = {};
|
|
6214
|
-
for (const [name, desc] of Object.entries(refsRaw)) {
|
|
6215
|
-
refs[name] = { target: desc.target, mode: desc.mode };
|
|
6216
|
-
}
|
|
6217
|
-
try {
|
|
6218
|
-
const dek = await state.getDEK(collectionName);
|
|
6219
|
-
const persisted = await loadPersistedSchema(state.adapter, state.name, collectionName, dek);
|
|
6220
|
-
if (persisted) {
|
|
6221
|
-
validator = { kind: persisted.kind, source: "persisted" };
|
|
6222
|
-
if (persisted.jsonSchema) {
|
|
6223
|
-
fields = jsonSchemaToFields(persisted.jsonSchema, "persisted", refsRaw);
|
|
6224
|
-
}
|
|
6225
|
-
}
|
|
6226
|
-
} catch {
|
|
6227
|
-
}
|
|
6228
|
-
const liveColl = state.collectionCache.get(collectionName);
|
|
6229
|
-
if (!validator) {
|
|
6230
|
-
const schema = liveColl?.getSchema();
|
|
6231
|
-
if (schema) {
|
|
6232
|
-
try {
|
|
6233
|
-
const derived = await derivePersistedSchema(schema);
|
|
6234
|
-
validator = { kind: derived.kind, source: "live-validator" };
|
|
6235
|
-
if (derived.jsonSchema) {
|
|
6236
|
-
fields = jsonSchemaToFields(derived.jsonSchema, "live-validator", refsRaw);
|
|
6237
|
-
}
|
|
6238
|
-
} catch {
|
|
6239
|
-
}
|
|
6240
|
-
}
|
|
6241
|
-
}
|
|
6242
|
-
if (Object.keys(fields).length === 0 && sampleSize > 0) {
|
|
6243
|
-
}
|
|
6244
|
-
const collMeta = liveColl?.getMeta();
|
|
6245
|
-
const collConfig = liveColl?.getConfig();
|
|
6246
|
-
const archivePresent = state.hasCollectionArchive?.(collectionName) === true;
|
|
6247
|
-
const schemaUpdateNames = state.getCollectionSchemaUpdateNames?.(collectionName);
|
|
6248
|
-
const hasSchemaUpdate = schemaUpdateNames !== void 0 && schemaUpdateNames.length > 0;
|
|
6249
|
-
let mergedConfig;
|
|
6250
|
-
if (collConfig !== void 0 || archivePresent || hasSchemaUpdate) {
|
|
6251
|
-
mergedConfig = {
|
|
6252
|
-
...collConfig ?? {},
|
|
6253
|
-
...archivePresent ? { archive: true } : {},
|
|
6254
|
-
...hasSchemaUpdate ? { schemaUpdate: schemaUpdateNames } : {}
|
|
6255
|
-
};
|
|
6256
|
-
}
|
|
6257
|
-
const descriptor = {
|
|
6258
|
-
fields,
|
|
6259
|
-
indexes: [],
|
|
6260
|
-
refs,
|
|
6261
|
-
...validator ? { validator } : {},
|
|
6262
|
-
...collMeta !== void 0 ? { meta: collMeta } : {},
|
|
6263
|
-
...mergedConfig !== void 0 ? { config: mergedConfig } : {}
|
|
6264
|
-
};
|
|
6265
|
-
if (withStats) {
|
|
6266
|
-
const stats = await statsForCollection(state.adapter, state.name, collectionName);
|
|
6267
|
-
descriptor.stats = stats;
|
|
6268
|
-
}
|
|
6269
|
-
return descriptor;
|
|
6270
|
-
}
|
|
6271
|
-
async function statsForCollection(adapter, vault, collection) {
|
|
6272
|
-
const ids = await adapter.list(vault, collection);
|
|
6273
|
-
if (ids.length === 0) {
|
|
6274
|
-
return { records: 0, bytes: 0, bytesAvg: 0, bytesMin: 0, bytesMax: 0, oldest: "", newest: "" };
|
|
6275
|
-
}
|
|
6276
|
-
let total = 0;
|
|
6277
|
-
let min = Number.POSITIVE_INFINITY;
|
|
6278
|
-
let max = 0;
|
|
6279
|
-
let oldest = "\uFFFF";
|
|
6280
|
-
let newest = "";
|
|
6281
|
-
for (const id of ids) {
|
|
6282
|
-
const env = await adapter.get(vault, collection, id);
|
|
6283
|
-
if (!env) continue;
|
|
6284
|
-
const size = env._data.length;
|
|
6285
|
-
total += size;
|
|
6286
|
-
if (size < min) min = size;
|
|
6287
|
-
if (size > max) max = size;
|
|
6288
|
-
if (env._ts < oldest) oldest = env._ts;
|
|
6289
|
-
if (env._ts > newest) newest = env._ts;
|
|
6290
|
-
}
|
|
6291
|
-
return {
|
|
6292
|
-
records: ids.length,
|
|
6293
|
-
bytes: total,
|
|
6294
|
-
bytesAvg: Math.round(total / ids.length),
|
|
6295
|
-
bytesMin: min === Number.POSITIVE_INFINITY ? 0 : min,
|
|
6296
|
-
bytesMax: max,
|
|
6297
|
-
oldest: oldest === "\uFFFF" ? "" : oldest,
|
|
6298
|
-
newest
|
|
6299
|
-
};
|
|
6300
|
-
}
|
|
6301
|
-
function describeMVs(registry) {
|
|
6302
|
-
if (!registry || typeof registry !== "object") return {};
|
|
6303
|
-
const items = listFromRegistry(registry);
|
|
6304
|
-
const out = {};
|
|
6305
|
-
for (const item of items) {
|
|
6306
|
-
const reg = item;
|
|
6307
|
-
const spec = reg.spec;
|
|
6308
|
-
if (!spec?.name) continue;
|
|
6309
|
-
const sources = spec.unionSources ? spec.unionSources.map((u) => u.collection) : reg.dependencies ? [...reg.dependencies].sort() : [];
|
|
6310
|
-
const groupBy = spec.groupBy ? Array.isArray(spec.groupBy) ? [...spec.groupBy] : [spec.groupBy] : void 0;
|
|
6311
|
-
const aggregate = spec.aggregate ? Object.fromEntries(
|
|
6312
|
-
Object.entries(spec.aggregate).map(([k, v]) => [k, summariseAggregateOp(v)])
|
|
6313
|
-
) : void 0;
|
|
6314
|
-
out[spec.name] = {
|
|
6315
|
-
sources,
|
|
6316
|
-
...groupBy ? { groupBy } : {},
|
|
6317
|
-
...aggregate ? { aggregate } : {},
|
|
6318
|
-
refresh: spec.refresh ?? "eager"
|
|
6319
|
-
};
|
|
6320
|
-
}
|
|
6321
|
-
return out;
|
|
6322
|
-
}
|
|
6323
|
-
function describeOverlays(registry) {
|
|
6324
|
-
if (!registry || typeof registry !== "object") return {};
|
|
6325
|
-
const specs = listFromRegistry(registry);
|
|
6326
|
-
const out = {};
|
|
6327
|
-
for (const spec of specs) {
|
|
6328
|
-
const s = spec;
|
|
6329
|
-
if (!s.name || !s.base || !s.overlay) continue;
|
|
6330
|
-
out[s.name] = { base: s.base, overlay: s.overlay };
|
|
6331
|
-
}
|
|
6332
|
-
return out;
|
|
6333
|
-
}
|
|
6334
|
-
function describeDerivations(registry) {
|
|
6335
|
-
if (!registry || typeof registry !== "object") return {};
|
|
6336
|
-
const items = listFromRegistry(registry);
|
|
6337
|
-
const out = {};
|
|
6338
|
-
for (const item of items) {
|
|
6339
|
-
const reg = item;
|
|
6340
|
-
const s = reg.spec ?? reg;
|
|
6341
|
-
if (!s.source) continue;
|
|
6342
|
-
const outputCollections = s.outputs ? Object.values(s.outputs).map((o) => o.collection) : [];
|
|
6343
|
-
const key = outputCollections.length > 0 ? [...outputCollections].sort().join("+") : s.source;
|
|
6344
|
-
out[key] = {
|
|
6345
|
-
source: s.source,
|
|
6346
|
-
outputs: outputCollections
|
|
6347
|
-
};
|
|
6348
|
-
}
|
|
6349
|
-
return out;
|
|
6350
|
-
}
|
|
6351
|
-
function listFromRegistry(reg) {
|
|
6352
|
-
for (const method of ["all", "list", "specs", "values"]) {
|
|
6353
|
-
const fn = reg[method];
|
|
6354
|
-
if (typeof fn === "function") {
|
|
6355
|
-
try {
|
|
6356
|
-
const out = fn.call(reg);
|
|
6357
|
-
if (Array.isArray(out)) return out;
|
|
6358
|
-
if (out && typeof out.values === "function") {
|
|
6359
|
-
return [...out.values()];
|
|
6360
|
-
}
|
|
6361
|
-
} catch {
|
|
6362
|
-
continue;
|
|
6363
|
-
}
|
|
6364
|
-
}
|
|
6365
|
-
}
|
|
6366
|
-
return [];
|
|
6367
|
-
}
|
|
6368
|
-
function summariseAggregateOp(value) {
|
|
6369
|
-
if (value && typeof value === "object") {
|
|
6370
|
-
const op = value.op ?? value.kind;
|
|
6371
|
-
const field = value.field;
|
|
6372
|
-
if (op && field) return `${op}(${field})`;
|
|
6373
|
-
if (op) return op;
|
|
6374
|
-
}
|
|
6375
|
-
return String(value);
|
|
6376
|
-
}
|
|
6377
|
-
|
|
6378
5959
|
// src/kernel/vault.ts
|
|
6379
5960
|
function resolveLabelFromMap(labels, locale, fallback) {
|
|
6380
5961
|
if (labels[locale] !== void 0) return labels[locale];
|
|
@@ -6427,6 +6008,7 @@ var Vault = class {
|
|
|
6427
6008
|
/** Per-collection record archival policies. Indexed by collection name. */
|
|
6428
6009
|
archiveRegistry = /* @__PURE__ */ new Map();
|
|
6429
6010
|
indexStrategy;
|
|
6011
|
+
lazyStrategy;
|
|
6430
6012
|
aggregateStrategy;
|
|
6431
6013
|
crdtStrategy;
|
|
6432
6014
|
tiersStrategy;
|
|
@@ -6448,6 +6030,7 @@ var Vault = class {
|
|
|
6448
6030
|
forgetStrategy;
|
|
6449
6031
|
i18nStrategy;
|
|
6450
6032
|
syncStrategy;
|
|
6033
|
+
classifiedStrategy;
|
|
6451
6034
|
/**
|
|
6452
6035
|
* Per-vault guard registry. `null` until `_initGuards()` runs; stays
|
|
6453
6036
|
* `null` for vaults that never register any guard strategy. The
|
|
@@ -6645,7 +6228,7 @@ var Vault = class {
|
|
|
6645
6228
|
dictionaryCache = /* @__PURE__ */ new Map();
|
|
6646
6229
|
/** Registered link specs, keyed by link name; set by `vault.link()`. */
|
|
6647
6230
|
linkRegistry = /* @__PURE__ */ new Map();
|
|
6648
|
-
/** Cache of
|
|
6231
|
+
/** Cache of link-set handles, one per link name (lazy -- see links()). */
|
|
6649
6232
|
linkSetCache = /* @__PURE__ */ new Map();
|
|
6650
6233
|
/** — subscribers for cross-tier access events. */
|
|
6651
6234
|
crossTierSubs = /* @__PURE__ */ new Set();
|
|
@@ -6679,6 +6262,7 @@ var Vault = class {
|
|
|
6679
6262
|
this.objectStore = opts.objectStore;
|
|
6680
6263
|
this.archiveStrategy = opts.archiveStrategy;
|
|
6681
6264
|
this.indexStrategy = opts.indexStrategy;
|
|
6265
|
+
this.lazyStrategy = opts.lazyStrategy;
|
|
6682
6266
|
this.aggregateStrategy = opts.aggregateStrategy;
|
|
6683
6267
|
this.crdtStrategy = opts.crdtStrategy;
|
|
6684
6268
|
this.tiersStrategy = opts.tiersStrategy;
|
|
@@ -6713,6 +6297,7 @@ var Vault = class {
|
|
|
6713
6297
|
this.forgetStrategy = opts.forgetStrategy ?? NO_FORGET;
|
|
6714
6298
|
this.i18nStrategy = opts.i18nStrategy ?? NO_I18N;
|
|
6715
6299
|
this.syncStrategy = opts.syncStrategy ?? NO_SYNC;
|
|
6300
|
+
this.classifiedStrategy = opts.classifiedStrategy ?? NO_CLASSIFIED;
|
|
6716
6301
|
void opts.guardStrategies;
|
|
6717
6302
|
this.historyConfig = opts.historyConfig ?? { enabled: true };
|
|
6718
6303
|
this.reloadKeyring = opts.reloadKeyring;
|
|
@@ -6825,6 +6410,9 @@ var Vault = class {
|
|
|
6825
6410
|
if (coll && options?.meta) {
|
|
6826
6411
|
coll._applyMeta(options.meta);
|
|
6827
6412
|
}
|
|
6413
|
+
if (coll && options?.classifiedFields) {
|
|
6414
|
+
coll._applyClassifiedFields(options.classifiedFields);
|
|
6415
|
+
}
|
|
6828
6416
|
if (!coll) {
|
|
6829
6417
|
if (options?.refs) {
|
|
6830
6418
|
this.refRegistry.register(collectionName, options.refs);
|
|
@@ -6869,6 +6457,7 @@ var Vault = class {
|
|
|
6869
6457
|
const strategies = options.schemaUpdate ?? [];
|
|
6870
6458
|
const work = (async () => {
|
|
6871
6459
|
const dek = await this.getDEK(collectionName);
|
|
6460
|
+
const { persistSchemaIfNeeded } = await import("./register-K6DDSIXN.js");
|
|
6872
6461
|
const result = await persistSchemaIfNeeded({
|
|
6873
6462
|
store: this.adapter,
|
|
6874
6463
|
vault: this.name,
|
|
@@ -6880,7 +6469,7 @@ var Vault = class {
|
|
|
6880
6469
|
const decision = result.decision ?? { action: "allow" };
|
|
6881
6470
|
if (decision.action === "cutover") {
|
|
6882
6471
|
this.schemaFence.registerPendingCutover(collectionName, decision.transform);
|
|
6883
|
-
this._ensureFenceCoordination();
|
|
6472
|
+
await this._ensureFenceCoordination();
|
|
6884
6473
|
}
|
|
6885
6474
|
return decision;
|
|
6886
6475
|
})();
|
|
@@ -6914,6 +6503,7 @@ var Vault = class {
|
|
|
6914
6503
|
...this.objectStore !== void 0 ? { objectStore: this.objectStore } : {},
|
|
6915
6504
|
...options?.blobFields !== void 0 ? { blobFields: options.blobFields } : {},
|
|
6916
6505
|
...this.indexStrategy !== void 0 ? { indexStrategy: this.indexStrategy } : {},
|
|
6506
|
+
...this.lazyStrategy !== void 0 ? { lazyStrategy: this.lazyStrategy } : {},
|
|
6917
6507
|
...this.aggregateStrategy !== void 0 ? { aggregateStrategy: this.aggregateStrategy } : {},
|
|
6918
6508
|
...this.crdtStrategy !== void 0 ? { crdtStrategy: this.crdtStrategy } : {},
|
|
6919
6509
|
...this.tiersStrategy !== void 0 ? { tiersStrategy: this.tiersStrategy } : {},
|
|
@@ -6921,6 +6511,7 @@ var Vault = class {
|
|
|
6921
6511
|
historyStrategy: this.historyStrategy,
|
|
6922
6512
|
i18nStrategy: this.i18nStrategy,
|
|
6923
6513
|
syncStrategy: this.syncStrategy,
|
|
6514
|
+
classifiedStrategy: this.classifiedStrategy,
|
|
6924
6515
|
// Per-collection ledger opt-out: when this collection sets
|
|
6925
6516
|
// `historyConfig.ledger: false`, withhold the ledger reference so all
|
|
6926
6517
|
// four `if (this.ledger)` append sites in Collection no-op. The chain
|
|
@@ -6970,19 +6561,24 @@ var Vault = class {
|
|
|
6970
6561
|
if (options?.acknowledgeDeterministicRisk !== void 0) {
|
|
6971
6562
|
collOpts.acknowledgeDeterministicRisk = options.acknowledgeDeterministicRisk;
|
|
6972
6563
|
}
|
|
6564
|
+
if (options?.acknowledgeEquatableRisk !== void 0) {
|
|
6565
|
+
collOpts.acknowledgeEquatableRisk = options.acknowledgeEquatableRisk;
|
|
6566
|
+
}
|
|
6973
6567
|
if (options?.sensitive !== void 0) {
|
|
6974
6568
|
collOpts.sensitive = options.sensitive;
|
|
6975
6569
|
}
|
|
6976
6570
|
if (options?.perRecordKeys !== void 0) {
|
|
6977
6571
|
collOpts.perRecordKeys = options.perRecordKeys;
|
|
6978
6572
|
}
|
|
6979
|
-
|
|
6573
|
+
const subjectKey = this.forgetStrategy.subjects[collectionName];
|
|
6574
|
+
if (subjectKey !== void 0) {
|
|
6980
6575
|
if (options?.perRecordKeys === false) {
|
|
6981
6576
|
console.warn(
|
|
6982
6577
|
`[noy-db] Collection "${collectionName}" is declared in withForgetCascade but opened with perRecordKeys: false. Forcing perRecordKeys: true \u2014 GDPR crypto-shred requires per-record CEKs.`
|
|
6983
6578
|
);
|
|
6984
6579
|
}
|
|
6985
6580
|
collOpts.perRecordKeys = true;
|
|
6581
|
+
collOpts.subjectKeyField = subjectKey;
|
|
6986
6582
|
}
|
|
6987
6583
|
if (options?.provenance !== void 0) collOpts.provenance = options.provenance;
|
|
6988
6584
|
if (options?.ramCiphertext !== void 0) collOpts.ramCiphertext = options.ramCiphertext;
|
|
@@ -6997,6 +6593,7 @@ var Vault = class {
|
|
|
6997
6593
|
if (options?.textIndexPersist !== void 0) collOpts.textIndexPersist = options.textIndexPersist;
|
|
6998
6594
|
if (options?.moneyFields !== void 0) collOpts.moneyFields = options.moneyFields;
|
|
6999
6595
|
if (options?.computed !== void 0) collOpts.computed = options.computed;
|
|
6596
|
+
if (options?.classifiedFields !== void 0) collOpts.classifiedFields = options.classifiedFields;
|
|
7000
6597
|
if (options?.dictKeyFields !== void 0) {
|
|
7001
6598
|
collOpts.dictLabelResolver = async (dictName, key, locale, fallback) => {
|
|
7002
6599
|
const stat = this.staticByName.get(dictName);
|
|
@@ -7039,7 +6636,7 @@ var Vault = class {
|
|
|
7039
6636
|
const work = (async () => {
|
|
7040
6637
|
try {
|
|
7041
6638
|
const dek = await this.getDEK(collectionName);
|
|
7042
|
-
await persistSchemaIfNeeded({
|
|
6639
|
+
await (await import("./register-K6DDSIXN.js")).persistSchemaIfNeeded({
|
|
7043
6640
|
store: this.adapter,
|
|
7044
6641
|
vault: this.name,
|
|
7045
6642
|
collectionName,
|
|
@@ -7123,10 +6720,12 @@ var Vault = class {
|
|
|
7123
6720
|
async schemaFenceState() {
|
|
7124
6721
|
return loadFence(this.adapter, this.name);
|
|
7125
6722
|
}
|
|
7126
|
-
/** @internal Start
|
|
7127
|
-
_ensureFenceCoordination() {
|
|
6723
|
+
/** @internal Start heartbeat + fence watcher once a cutover is registered. Async since #553: FenceWatcher dynamic-imports on demand. */
|
|
6724
|
+
async _ensureFenceCoordination() {
|
|
7128
6725
|
if (this.#fenceCoordinationStarted) return;
|
|
7129
6726
|
this.#fenceCoordinationStarted = true;
|
|
6727
|
+
const { FenceWatcher } = await import("./fence-watcher-DHQ775JB.js");
|
|
6728
|
+
if (!this.#fenceCoordinationStarted) return;
|
|
7130
6729
|
this.#fenceWatcher = new FenceWatcher({
|
|
7131
6730
|
coordination: this.noydb.coordination,
|
|
7132
6731
|
vault: this.name,
|
|
@@ -7155,7 +6754,7 @@ var Vault = class {
|
|
|
7155
6754
|
}
|
|
7156
6755
|
/** @internal Drive one heartbeat + watch cycle deterministically (tests). */
|
|
7157
6756
|
async _fenceTick() {
|
|
7158
|
-
this._ensureFenceCoordination();
|
|
6757
|
+
await this._ensureFenceCoordination();
|
|
7159
6758
|
await this.#fenceWatcher.beat();
|
|
7160
6759
|
await this.#fenceWatcher.check();
|
|
7161
6760
|
}
|
|
@@ -7367,17 +6966,17 @@ var Vault = class {
|
|
|
7367
6966
|
if (!spec) {
|
|
7368
6967
|
throw new ValidationError(`vault.links("${name}"): not declared. Call vault.link("${name}", { a, b }) first.`);
|
|
7369
6968
|
}
|
|
7370
|
-
handle =
|
|
7371
|
-
this.adapter,
|
|
7372
|
-
this.name,
|
|
6969
|
+
handle = makeLazyLinkSetHandle({
|
|
6970
|
+
adapter: this.adapter,
|
|
6971
|
+
vault: this.name,
|
|
7373
6972
|
name,
|
|
7374
6973
|
spec,
|
|
7375
|
-
this.encrypted,
|
|
7376
|
-
this.getDEK,
|
|
7377
|
-
this.keyring.userId,
|
|
7378
|
-
this.emitter,
|
|
7379
|
-
async (collection, id) => await this.collection(collection).get(id) !== null
|
|
7380
|
-
);
|
|
6974
|
+
encrypted: this.encrypted,
|
|
6975
|
+
getDEK: this.getDEK,
|
|
6976
|
+
actor: this.keyring.userId,
|
|
6977
|
+
emitter: this.emitter,
|
|
6978
|
+
endpointExists: async (collection, id) => await this.collection(collection).get(id) !== null
|
|
6979
|
+
});
|
|
7381
6980
|
this.linkSetCache.set(name, handle);
|
|
7382
6981
|
}
|
|
7383
6982
|
return handle;
|
|
@@ -7886,8 +7485,14 @@ var Vault = class {
|
|
|
7886
7485
|
if (live?._sealed !== void 0) {
|
|
7887
7486
|
try {
|
|
7888
7487
|
const cls = await coll._classifySealedShred(live);
|
|
7889
|
-
|
|
7890
|
-
|
|
7488
|
+
for (const slot of cls.slots) {
|
|
7489
|
+
if (slot.class === "shreddable" || slot.class === "live-shreddable+dekResidue-in-backups") {
|
|
7490
|
+
sealedFieldsShredded += 1;
|
|
7491
|
+
}
|
|
7492
|
+
if (slot.class === "dekResidue" || slot.class === "live-shreddable+dekResidue-in-backups") {
|
|
7493
|
+
sealedResidue.push(`${ref2.collection}:${ref2.id}:${slot.field}`);
|
|
7494
|
+
}
|
|
7495
|
+
}
|
|
7891
7496
|
} catch {
|
|
7892
7497
|
for (const field of Object.keys(live._sealed)) sealedResidue.push(`${ref2.collection}:${ref2.id}:${field}`);
|
|
7893
7498
|
}
|
|
@@ -7946,7 +7551,7 @@ var Vault = class {
|
|
|
7946
7551
|
indexResidue.push(`${collName}:_ftindex`);
|
|
7947
7552
|
}
|
|
7948
7553
|
}
|
|
7949
|
-
const subjectHash = await
|
|
7554
|
+
const subjectHash = await sha256Hex(subjectId);
|
|
7950
7555
|
const ledger = this.getLedgerOrNull();
|
|
7951
7556
|
if (!ledger) {
|
|
7952
7557
|
throw new Error(
|
|
@@ -8114,7 +7719,7 @@ var Vault = class {
|
|
|
8114
7719
|
async _initDerivations(handles) {
|
|
8115
7720
|
if (handles.length === 0) return;
|
|
8116
7721
|
const [{ DerivationRegistry }, { ReadOnlyVaultFacade }] = await Promise.all([
|
|
8117
|
-
import("./registry-
|
|
7722
|
+
import("./registry-IMNMHWTM.js"),
|
|
8118
7723
|
import("./read-only-facade-5ADRJVTM.js")
|
|
8119
7724
|
]);
|
|
8120
7725
|
const registry = new DerivationRegistry();
|
|
@@ -8145,7 +7750,7 @@ var Vault = class {
|
|
|
8145
7750
|
*/
|
|
8146
7751
|
async _initMaterializedViews(handles) {
|
|
8147
7752
|
if (handles.length === 0) return;
|
|
8148
|
-
const { MaterializedViewRegistry } = await import("./registry-
|
|
7753
|
+
const { MaterializedViewRegistry } = await import("./registry-K6VUQXKV.js");
|
|
8149
7754
|
const registry = new MaterializedViewRegistry();
|
|
8150
7755
|
this.materializedViewRegistry = registry;
|
|
8151
7756
|
const db = this;
|
|
@@ -8169,7 +7774,7 @@ var Vault = class {
|
|
|
8169
7774
|
*/
|
|
8170
7775
|
async _initOverlayedViews(handles) {
|
|
8171
7776
|
if (handles.length === 0) return;
|
|
8172
|
-
const { OverlayedViewRegistry } = await import("./registry-
|
|
7777
|
+
const { OverlayedViewRegistry } = await import("./registry-ZVO3T4M5.js");
|
|
8173
7778
|
const registry = new OverlayedViewRegistry();
|
|
8174
7779
|
const mvRegistry = this.materializedViewRegistry;
|
|
8175
7780
|
const overlayNames = /* @__PURE__ */ new Set();
|
|
@@ -8216,13 +7821,13 @@ var Vault = class {
|
|
|
8216
7821
|
if (!reg) {
|
|
8217
7822
|
throw new Error(`refreshView: no MV registered with name "${name}"`);
|
|
8218
7823
|
}
|
|
8219
|
-
const { MaterializedViewExecutor } = await import("./executor-
|
|
7824
|
+
const { MaterializedViewExecutor } = await import("./executor-FGISLQIN.js");
|
|
8220
7825
|
const result = await MaterializedViewExecutor.refresh(reg, {
|
|
8221
7826
|
getCollection: (n) => this.collection(n),
|
|
8222
7827
|
getActiveTxContext: () => this.noydb._activeTxContextOrNull,
|
|
8223
7828
|
getQueryContext: () => this
|
|
8224
7829
|
});
|
|
8225
|
-
const { clearMVStale } = await import("./stale-
|
|
7830
|
+
const { clearMVStale } = await import("./stale-7Q62KVI3.js");
|
|
8226
7831
|
clearMVStale(registry, name);
|
|
8227
7832
|
return result;
|
|
8228
7833
|
}
|
|
@@ -8238,7 +7843,7 @@ var Vault = class {
|
|
|
8238
7843
|
if (registry === null) return { derived: 0, failed: 0 };
|
|
8239
7844
|
const strategies = registry.strategiesForSource(sourceCollection);
|
|
8240
7845
|
if (strategies.length === 0) return { derived: 0, failed: 0 };
|
|
8241
|
-
const { DerivationExecutor } = await import("./executor-
|
|
7846
|
+
const { DerivationExecutor } = await import("./executor-CBTNU5VZ.js");
|
|
8242
7847
|
const sourceColl = this.collection(sourceCollection);
|
|
8243
7848
|
const records = await sourceColl.list();
|
|
8244
7849
|
const ctx = { vault: this.derivationFacade ?? new (await import("./read-only-facade-5ADRJVTM.js")).ReadOnlyVaultFacade(this, "derivation") };
|
|
@@ -8263,7 +7868,7 @@ var Vault = class {
|
|
|
8263
7868
|
if (!outSpec) continue;
|
|
8264
7869
|
const outputColl = this.collection(outSpec.collection);
|
|
8265
7870
|
if (out.kind === "array") {
|
|
8266
|
-
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-
|
|
7871
|
+
const { loadFanoutSidecar, saveFanoutSidecar } = await import("./fanout-sidecar-WS22Q5WH.js");
|
|
8267
7872
|
const prior = await loadFanoutSidecar(this.adapter, this.name, spec.source, id, key, this.getDEK, this.encrypted);
|
|
8268
7873
|
const prevKeys = new Set(prior?.keys ?? []);
|
|
8269
7874
|
const newKeysList = out.entries.map((e) => e.key);
|
|
@@ -8413,11 +8018,11 @@ var Vault = class {
|
|
|
8413
8018
|
*
|
|
8414
8019
|
*.
|
|
8415
8020
|
*/
|
|
8416
|
-
async withConsent(ctx,
|
|
8021
|
+
async withConsent(ctx, fn2) {
|
|
8417
8022
|
const prior = this.consentContext;
|
|
8418
8023
|
this.consentContext = ctx;
|
|
8419
8024
|
try {
|
|
8420
|
-
return await
|
|
8025
|
+
return await fn2();
|
|
8421
8026
|
} finally {
|
|
8422
8027
|
this.consentContext = prior;
|
|
8423
8028
|
}
|
|
@@ -8485,7 +8090,7 @@ var Vault = class {
|
|
|
8485
8090
|
* collection.
|
|
8486
8091
|
*/
|
|
8487
8092
|
async delegate(opts) {
|
|
8488
|
-
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
8093
|
+
const { issueDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-BQNIEHZE.js");
|
|
8489
8094
|
if (!this.keyring.kek) {
|
|
8490
8095
|
throw new ValidationError(
|
|
8491
8096
|
"issueDelegation: keyring.kek is null \u2014 issuing a delegation requires a tier-1 unlock. Re-authenticate at tier 1 (passphrase) first."
|
|
@@ -8507,7 +8112,7 @@ var Vault = class {
|
|
|
8507
8112
|
* if the id does not exist.
|
|
8508
8113
|
*/
|
|
8509
8114
|
async revokeDelegation(id) {
|
|
8510
|
-
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-
|
|
8115
|
+
const { revokeDelegation, DELEGATIONS_COLLECTION } = await import("./delegation-BQNIEHZE.js");
|
|
8511
8116
|
await revokeDelegation(this.adapter, this.name, id);
|
|
8512
8117
|
void DELEGATIONS_COLLECTION;
|
|
8513
8118
|
}
|
|
@@ -8723,6 +8328,7 @@ var Vault = class {
|
|
|
8723
8328
|
* @see docs/superpowers/specs/2026-05-22-schema-dump-design.md
|
|
8724
8329
|
*/
|
|
8725
8330
|
async dumpSchema(opts = {}) {
|
|
8331
|
+
const { dumpVaultSchema } = await import("./walk-5C3GPKT2.js");
|
|
8726
8332
|
return dumpVaultSchema(this, opts);
|
|
8727
8333
|
}
|
|
8728
8334
|
/**
|
|
@@ -8857,7 +8463,7 @@ var Vault = class {
|
|
|
8857
8463
|
* @see https://github.com/vLannaAi/noy-db-docs/blob/main/content/docs/services/public-envelope.md
|
|
8858
8464
|
*/
|
|
8859
8465
|
async getPublicEnvelope(opts = {}) {
|
|
8860
|
-
const { readPublicEnvelope } = await import("./public-envelope-
|
|
8466
|
+
const { readPublicEnvelope } = await import("./public-envelope-MRN5YYZZ.js");
|
|
8861
8467
|
return readPublicEnvelope(this.adapter, this.name, opts);
|
|
8862
8468
|
}
|
|
8863
8469
|
/**
|
|
@@ -8872,7 +8478,7 @@ var Vault = class {
|
|
|
8872
8478
|
* both modes round-trip cleanly.
|
|
8873
8479
|
*/
|
|
8874
8480
|
async dump() {
|
|
8875
|
-
const { dumpVault } = await import("./backup-
|
|
8481
|
+
const { dumpVault } = await import("./backup-MOB27UUN.js");
|
|
8876
8482
|
return dumpVault(this.backupContext());
|
|
8877
8483
|
}
|
|
8878
8484
|
/**
|
|
@@ -8924,7 +8530,7 @@ var Vault = class {
|
|
|
8924
8530
|
* — there's no chain to verify against.
|
|
8925
8531
|
*/
|
|
8926
8532
|
async load(backupJson) {
|
|
8927
|
-
const { loadVault } = await import("./backup-
|
|
8533
|
+
const { loadVault } = await import("./backup-MOB27UUN.js");
|
|
8928
8534
|
return loadVault(this.backupContext(), backupJson);
|
|
8929
8535
|
}
|
|
8930
8536
|
/**
|
|
@@ -8956,7 +8562,7 @@ var Vault = class {
|
|
|
8956
8562
|
* way to detect tampering of an in-place vault.
|
|
8957
8563
|
*/
|
|
8958
8564
|
async verifyBackupIntegrity() {
|
|
8959
|
-
const { verifyBackupIntegrity } = await import("./backup-
|
|
8565
|
+
const { verifyBackupIntegrity } = await import("./backup-MOB27UUN.js");
|
|
8960
8566
|
return verifyBackupIntegrity(this.backupContext());
|
|
8961
8567
|
}
|
|
8962
8568
|
/**
|
|
@@ -9174,7 +8780,7 @@ var Vault = class {
|
|
|
9174
8780
|
* is the live validator object, not a serialization of it).
|
|
9175
8781
|
*/
|
|
9176
8782
|
async exportJSON(opts = {}) {
|
|
9177
|
-
const { exportVaultJSON } = await import("./backup-
|
|
8783
|
+
const { exportVaultJSON } = await import("./backup-MOB27UUN.js");
|
|
9178
8784
|
return exportVaultJSON(this.backupContext(), opts);
|
|
9179
8785
|
}
|
|
9180
8786
|
};
|
|
@@ -9251,10 +8857,10 @@ var WriteQueueTracker = class {
|
|
|
9251
8857
|
* (success or failure). The fn's resolved value is returned; a thrown
|
|
9252
8858
|
* error is re-thrown after the queue is decremented.
|
|
9253
8859
|
*/
|
|
9254
|
-
async track(
|
|
8860
|
+
async track(fn2) {
|
|
9255
8861
|
this.begin();
|
|
9256
8862
|
try {
|
|
9257
|
-
const value = await
|
|
8863
|
+
const value = await fn2();
|
|
9258
8864
|
this.settle();
|
|
9259
8865
|
return value;
|
|
9260
8866
|
} catch (error) {
|
|
@@ -9339,13 +8945,13 @@ var TabCoordinator = class {
|
|
|
9339
8945
|
const out = [self, ...[...this.#peers.values()].filter((p) => p.lastSeen >= cutoff)];
|
|
9340
8946
|
return out.sort((a, b) => a.tabId.localeCompare(b.tabId));
|
|
9341
8947
|
}
|
|
9342
|
-
onTabRoleChange(
|
|
9343
|
-
this.#roleHandlers.add(
|
|
9344
|
-
return () => this.#roleHandlers.delete(
|
|
8948
|
+
onTabRoleChange(fn2) {
|
|
8949
|
+
this.#roleHandlers.add(fn2);
|
|
8950
|
+
return () => this.#roleHandlers.delete(fn2);
|
|
9345
8951
|
}
|
|
9346
|
-
onActiveTabsChange(
|
|
9347
|
-
this.#tabsHandlers.add(
|
|
9348
|
-
return () => this.#tabsHandlers.delete(
|
|
8952
|
+
onActiveTabsChange(fn2) {
|
|
8953
|
+
this.#tabsHandlers.add(fn2);
|
|
8954
|
+
return () => this.#tabsHandlers.delete(fn2);
|
|
9349
8955
|
}
|
|
9350
8956
|
dispose() {
|
|
9351
8957
|
if (this.#disposed) return;
|
|
@@ -10042,6 +9648,35 @@ var TeamFacade = class {
|
|
|
10042
9648
|
}
|
|
10043
9649
|
return p;
|
|
10044
9650
|
}
|
|
9651
|
+
// ─── Multi-user grant / revoke / rotate runners (#267 team split) ──
|
|
9652
|
+
//
|
|
9653
|
+
// The kernel's `db.grant` / `db.revoke` / `db.rotate` route through the
|
|
9654
|
+
// TeamStrategy seam, which calls back here with the keyring ENGINE as an
|
|
9655
|
+
// argument (statically linked in `active.ts`, i.e. only in the
|
|
9656
|
+
// `@noy-db/hub/team` subpath bundle). These runners own the policy-gate +
|
|
9657
|
+
// keyring plumbing so the kernel keeps single-line delegators and the
|
|
9658
|
+
// engines stay off the single-user floor.
|
|
9659
|
+
/** Gate + run a `grant` engine. See `Noydb.grant` for the public contract. */
|
|
9660
|
+
async runGrant(engine, vault, options, factors) {
|
|
9661
|
+
this.deps.checkPolicyOperation(vault, "grant");
|
|
9662
|
+
await this.deps.checkGate(vault, "enroll-user", factors);
|
|
9663
|
+
const keyring = await this.deps.getKeyringInternal(vault);
|
|
9664
|
+
await engine(this.deps.options.store, vault, keyring, options);
|
|
9665
|
+
}
|
|
9666
|
+
/** Gate + run a `revoke` engine. See `Noydb.revoke` for the public contract. */
|
|
9667
|
+
async runRevoke(engine, vault, options, factors) {
|
|
9668
|
+
this.deps.checkPolicyOperation(vault, "revoke");
|
|
9669
|
+
await this.deps.checkGate(vault, "revoke-user", factors);
|
|
9670
|
+
const keyring = await this.deps.getKeyringInternal(vault);
|
|
9671
|
+
await engine(this.deps.options.store, vault, keyring, options);
|
|
9672
|
+
}
|
|
9673
|
+
/** Gate + run a `rotateKeys` engine. See `Noydb.rotate` for the public contract. */
|
|
9674
|
+
async runRotate(engine, vault, collections) {
|
|
9675
|
+
this.deps.checkPolicyOperation(vault, "rotate");
|
|
9676
|
+
const keyring = await this.deps.getKeyringInternal(vault);
|
|
9677
|
+
await engine(this.deps.options.store, vault, keyring, collections);
|
|
9678
|
+
this.deps.keyringCache.set(vault, keyring);
|
|
9679
|
+
}
|
|
10045
9680
|
// ─── Tier-2 enroll / remove ─────────────────────────────────────
|
|
10046
9681
|
/**
|
|
10047
9682
|
* Add a tier-2 authenticator slot to the calling user's keyring.
|
|
@@ -10787,6 +10422,15 @@ var Noydb = class {
|
|
|
10787
10422
|
/** Pre-resolved `vault.user` API factory (mirrors `coordinationProvider` above). Public so `Vault` can call it. */
|
|
10788
10423
|
userApiFactory;
|
|
10789
10424
|
vaultCache = /* @__PURE__ */ new Map();
|
|
10425
|
+
/**
|
|
10426
|
+
* In-flight `openVault` promise per name — concurrent opens of the same
|
|
10427
|
+
* vault must converge on ONE Vault instance. Without this, two callers
|
|
10428
|
+
* racing past the `vaultCache` miss each construct a Vault (and later two
|
|
10429
|
+
* Collections with independent DEKs for the same store slice), so a record
|
|
10430
|
+
* written through one fails decryption through the other with a spurious
|
|
10431
|
+
* `TamperedError` (#564).
|
|
10432
|
+
*/
|
|
10433
|
+
vaultOpening = /* @__PURE__ */ new Map();
|
|
10790
10434
|
keyringCache = /* @__PURE__ */ new Map();
|
|
10791
10435
|
syncEngines = /* @__PURE__ */ new Map();
|
|
10792
10436
|
/**
|
|
@@ -10826,6 +10470,11 @@ var Noydb = class {
|
|
|
10826
10470
|
* through it; grant/revoke route through it from this class. @internal
|
|
10827
10471
|
*/
|
|
10828
10472
|
custodyStrategy;
|
|
10473
|
+
/**
|
|
10474
|
+
* Opt-in multi-user team strategy (#267 keyring-grant → team split) —
|
|
10475
|
+
* `NO_TEAM` (throwing) unless `withTeam()` was passed; the keyring
|
|
10476
|
+
* engines are linked only by the active strategy, not by this file. */
|
|
10477
|
+
teamStrategy;
|
|
10829
10478
|
sessionStrategy;
|
|
10830
10479
|
syncStrategy;
|
|
10831
10480
|
snapshots;
|
|
@@ -10876,6 +10525,7 @@ var Noydb = class {
|
|
|
10876
10525
|
this.txStrategy = options.txStrategy ?? NO_TX;
|
|
10877
10526
|
this.forgetStrategy = options.forgetStrategy ?? NO_FORGET;
|
|
10878
10527
|
this.custodyStrategy = options.custodyStrategy ?? NO_CUSTODY;
|
|
10528
|
+
this.teamStrategy = options.teamStrategy ?? NO_TEAM;
|
|
10879
10529
|
this.sessionStrategy = options.sessionStrategy ?? NO_SESSION;
|
|
10880
10530
|
this.syncStrategy = options.syncStrategy ?? NO_SYNC;
|
|
10881
10531
|
this.snapshots = new NoydbSnapshots({
|
|
@@ -10907,6 +10557,7 @@ var Noydb = class {
|
|
|
10907
10557
|
quickUnlock: this.quickUnlock,
|
|
10908
10558
|
policyCache: this.policyCache,
|
|
10909
10559
|
checkGate: (vault, gate, factors) => this.checkGate(vault, gate, factors),
|
|
10560
|
+
checkPolicyOperation: (vault, op) => this.checkPolicyOperation(vault, op),
|
|
10910
10561
|
getKeyringInternal: (vault, opts) => this._getKeyringInternal(vault, opts),
|
|
10911
10562
|
assertRecoveryEnrolled: (vault, policy, opts) => this.assertRecoveryEnrolled(vault, policy, opts),
|
|
10912
10563
|
openVault: (vault, opts) => this.openVault(vault, opts),
|
|
@@ -11001,7 +10652,7 @@ var Noydb = class {
|
|
|
11001
10652
|
if (!facade) return;
|
|
11002
10653
|
const ctx = { existing, vault: facade, userId: e.userId, role: e.role };
|
|
11003
10654
|
await registry.runChecks(e.collection, incoming, ctx);
|
|
11004
|
-
const { GuardExecutor } = await import("./executor-
|
|
10655
|
+
const { GuardExecutor } = await import("./executor-DJHNSTIR.js");
|
|
11005
10656
|
for (const g of guards) {
|
|
11006
10657
|
await GuardExecutor.checkFrozenFields(g, e.docId, existing, incoming, e.computedFieldNames);
|
|
11007
10658
|
}
|
|
@@ -11096,12 +10747,26 @@ var Noydb = class {
|
|
|
11096
10747
|
if (this.closed) throw new ValidationError("Instance is closed");
|
|
11097
10748
|
this.touchPolicy(name);
|
|
11098
10749
|
let comp = this.vaultCache.get(name);
|
|
10750
|
+
if (!comp) {
|
|
10751
|
+
const pending = this.vaultOpening.get(name);
|
|
10752
|
+
if (pending) comp = await pending;
|
|
10753
|
+
}
|
|
11099
10754
|
if (comp) {
|
|
11100
10755
|
if (opts?.locale !== void 0) {
|
|
11101
10756
|
comp.setLocale(opts.locale);
|
|
11102
10757
|
}
|
|
11103
10758
|
return comp;
|
|
11104
10759
|
}
|
|
10760
|
+
const opening = this.#openVaultFresh(name, opts);
|
|
10761
|
+
this.vaultOpening.set(name, opening);
|
|
10762
|
+
try {
|
|
10763
|
+
return await opening;
|
|
10764
|
+
} finally {
|
|
10765
|
+
this.vaultOpening.delete(name);
|
|
10766
|
+
}
|
|
10767
|
+
}
|
|
10768
|
+
/** Uncached single-flight body of {@link openVault} — see `vaultOpening`. */
|
|
10769
|
+
async #openVaultFresh(name, opts) {
|
|
11105
10770
|
const keyring = await this._getKeyringInternal(name, { create: opts?.create !== false });
|
|
11106
10771
|
if (!this.activeTier.has(name)) {
|
|
11107
10772
|
this.activeTier.set(name, 1);
|
|
@@ -11142,7 +10807,7 @@ var Noydb = class {
|
|
|
11142
10807
|
this.syncEngines.set(key, engine);
|
|
11143
10808
|
}
|
|
11144
10809
|
}
|
|
11145
|
-
comp = new Vault({
|
|
10810
|
+
const comp = new Vault({
|
|
11146
10811
|
adapter: this.options.store,
|
|
11147
10812
|
name,
|
|
11148
10813
|
noydb: this,
|
|
@@ -11163,6 +10828,7 @@ var Noydb = class {
|
|
|
11163
10828
|
...this.options.objectStore !== void 0 ? { objectStore: this.options.objectStore } : {},
|
|
11164
10829
|
...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
|
|
11165
10830
|
...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
|
|
10831
|
+
...this.options.lazyStrategy !== void 0 ? { lazyStrategy: this.options.lazyStrategy } : {},
|
|
11166
10832
|
...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
|
|
11167
10833
|
...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
|
|
11168
10834
|
...this.options.tiersStrategy !== void 0 ? { tiersStrategy: this.options.tiersStrategy } : {},
|
|
@@ -11178,6 +10844,7 @@ var Noydb = class {
|
|
|
11178
10844
|
...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
|
|
11179
10845
|
forgetStrategy: this.forgetStrategy,
|
|
11180
10846
|
...this.options.attestationStrategy !== void 0 ? { attestationStrategy: this.options.attestationStrategy } : {},
|
|
10847
|
+
...this.options.classifiedStrategy !== void 0 ? { classifiedStrategy: this.options.classifiedStrategy } : {},
|
|
11181
10848
|
...this.options.sealedRecordStrategy !== void 0 ? { sealedRecordStrategy: this.options.sealedRecordStrategy } : {},
|
|
11182
10849
|
...this.options.portabilityStrategy !== void 0 ? { portabilityStrategy: this.options.portabilityStrategy } : {},
|
|
11183
10850
|
...this.options.sequenceStrategy !== void 0 ? { sequenceStrategy: this.options.sequenceStrategy } : {},
|
|
@@ -11228,6 +10895,7 @@ var Noydb = class {
|
|
|
11228
10895
|
...this.options.objectStore !== void 0 ? { objectStore: this.options.objectStore } : {},
|
|
11229
10896
|
...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
|
|
11230
10897
|
...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
|
|
10898
|
+
...this.options.lazyStrategy !== void 0 ? { lazyStrategy: this.options.lazyStrategy } : {},
|
|
11231
10899
|
...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
|
|
11232
10900
|
...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
|
|
11233
10901
|
...this.options.tiersStrategy !== void 0 ? { tiersStrategy: this.options.tiersStrategy } : {},
|
|
@@ -11243,6 +10911,7 @@ var Noydb = class {
|
|
|
11243
10911
|
...this.options.numbering !== void 0 ? { numberingConfigs: this.options.numbering } : {},
|
|
11244
10912
|
forgetStrategy: this.forgetStrategy,
|
|
11245
10913
|
...this.options.attestationStrategy !== void 0 ? { attestationStrategy: this.options.attestationStrategy } : {},
|
|
10914
|
+
...this.options.classifiedStrategy !== void 0 ? { classifiedStrategy: this.options.classifiedStrategy } : {},
|
|
11246
10915
|
...this.options.sealedRecordStrategy !== void 0 ? { sealedRecordStrategy: this.options.sealedRecordStrategy } : {},
|
|
11247
10916
|
...this.options.portabilityStrategy !== void 0 ? { portabilityStrategy: this.options.portabilityStrategy } : {},
|
|
11248
10917
|
...this.options.sequenceStrategy !== void 0 ? { sequenceStrategy: this.options.sequenceStrategy } : {}
|
|
@@ -11267,6 +10936,7 @@ var Noydb = class {
|
|
|
11267
10936
|
...this.options.objectStore !== void 0 ? { objectStore: this.options.objectStore } : {},
|
|
11268
10937
|
...this.options.archiveStrategy !== void 0 ? { archiveStrategy: this.options.archiveStrategy } : {},
|
|
11269
10938
|
...this.options.indexStrategy !== void 0 ? { indexStrategy: this.options.indexStrategy } : {},
|
|
10939
|
+
...this.options.lazyStrategy !== void 0 ? { lazyStrategy: this.options.lazyStrategy } : {},
|
|
11270
10940
|
...this.options.aggregateStrategy !== void 0 ? { aggregateStrategy: this.options.aggregateStrategy } : {},
|
|
11271
10941
|
...this.options.crdtStrategy !== void 0 ? { crdtStrategy: this.options.crdtStrategy } : {},
|
|
11272
10942
|
...this.options.tiersStrategy !== void 0 ? { tiersStrategy: this.options.tiersStrategy } : {},
|
|
@@ -11294,12 +10964,10 @@ var Noydb = class {
|
|
|
11294
10964
|
*
|
|
11295
10965
|
* The legacy `requireReAuthFor: ['grant']` session-policy check still
|
|
11296
10966
|
* fires on top — both are independent opt-ins.
|
|
10967
|
+
* Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
|
|
11297
10968
|
*/
|
|
11298
10969
|
async grant(vault, options, factors) {
|
|
11299
|
-
this.
|
|
11300
|
-
await this.checkGate(vault, "enroll-user", factors);
|
|
11301
|
-
const keyring = await this._getKeyringInternal(vault);
|
|
11302
|
-
await grant(this.options.store, vault, keyring, options);
|
|
10970
|
+
return this.teamStrategy.grant(this.team, vault, options, factors);
|
|
11303
10971
|
}
|
|
11304
10972
|
/**
|
|
11305
10973
|
* Revoke a user's access to a vault.
|
|
@@ -11309,12 +10977,10 @@ var Noydb = class {
|
|
|
11309
10977
|
*
|
|
11310
10978
|
* The legacy `requireReAuthFor: ['revoke']` session-policy check still
|
|
11311
10979
|
* fires on top — both are independent opt-ins.
|
|
10980
|
+
* Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
|
|
11312
10981
|
*/
|
|
11313
10982
|
async revoke(vault, options, factors) {
|
|
11314
|
-
this.
|
|
11315
|
-
await this.checkGate(vault, "revoke-user", factors);
|
|
11316
|
-
const keyring = await this._getKeyringInternal(vault);
|
|
11317
|
-
await revoke(this.options.store, vault, keyring, options);
|
|
10983
|
+
return this.teamStrategy.revoke(this.team, vault, options, factors);
|
|
11318
10984
|
}
|
|
11319
10985
|
/**
|
|
11320
10986
|
* Grant the FR-6 `custodian` role to a user (owner-only custody API).
|
|
@@ -11329,13 +10995,14 @@ var Noydb = class {
|
|
|
11329
10995
|
async grantCustodian(vault, options, factors) {
|
|
11330
10996
|
return this.custodyStrategy.grantCustodian(this, vault, options, factors);
|
|
11331
10997
|
}
|
|
11332
|
-
/** @internal —
|
|
11333
|
-
|
|
10998
|
+
/** @internal — grant-custodian engine, reached only via withCustody(); the
|
|
10999
|
+
* keyring engine arrives as an argument so the floor never carries it (#267). */
|
|
11000
|
+
async _grantCustodianImpl(engine, vault, options, factors) {
|
|
11334
11001
|
this.checkPolicyOperation(vault, "grant");
|
|
11335
11002
|
await this.checkGate(vault, "grant-custodian", factors);
|
|
11336
11003
|
const keyring = await this._getKeyringInternal(vault);
|
|
11337
11004
|
if (keyring.role !== "owner") throw new PermissionDeniedError("only the Deed owner can grant a custodian");
|
|
11338
|
-
await
|
|
11005
|
+
await engine(this.options.store, vault, keyring, { ...options, role: "custodian" });
|
|
11339
11006
|
}
|
|
11340
11007
|
/**
|
|
11341
11008
|
* Revoke a custodian (owner-only custody API).
|
|
@@ -11347,13 +11014,14 @@ var Noydb = class {
|
|
|
11347
11014
|
async revokeCustodian(vault, options, factors) {
|
|
11348
11015
|
return this.custodyStrategy.revokeCustodian(this, vault, options, factors);
|
|
11349
11016
|
}
|
|
11350
|
-
/** @internal —
|
|
11351
|
-
|
|
11017
|
+
/** @internal — revoke-custodian engine, reached only via withCustody().
|
|
11018
|
+
* Mirrors `_grantCustodianImpl` (#267: engine passed in). */
|
|
11019
|
+
async _revokeCustodianImpl(engine, vault, options, factors) {
|
|
11352
11020
|
this.checkPolicyOperation(vault, "revoke");
|
|
11353
11021
|
await this.checkGate(vault, "revoke-user", factors);
|
|
11354
11022
|
const keyring = await this._getKeyringInternal(vault);
|
|
11355
11023
|
if (keyring.role !== "owner") throw new PermissionDeniedError("only the Deed owner can revoke a custodian");
|
|
11356
|
-
await
|
|
11024
|
+
await engine(this.options.store, vault, keyring, options);
|
|
11357
11025
|
}
|
|
11358
11026
|
/**
|
|
11359
11027
|
* Mutate post-grant identity fields on an existing keyring — `role`,
|
|
@@ -11420,12 +11088,10 @@ var Noydb = class {
|
|
|
11420
11088
|
* Exposed on Noydb (rather than only on the lower-level keyring
|
|
11421
11089
|
* module) so CLI and admin tooling can trigger rotation without
|
|
11422
11090
|
* reaching into internals. See `noy-db rotate` for the CLI wrapper.
|
|
11091
|
+
* Opt-in (#267): throws {@link TeamNotEnabledError} without `withTeam()`.
|
|
11423
11092
|
*/
|
|
11424
11093
|
async rotate(vault, collections) {
|
|
11425
|
-
this.
|
|
11426
|
-
const keyring = await this._getKeyringInternal(vault);
|
|
11427
|
-
await rotateKeys(this.options.store, vault, keyring, collections);
|
|
11428
|
-
this.keyringCache.set(vault, keyring);
|
|
11094
|
+
return this.teamStrategy.rotate(this.team, vault, collections);
|
|
11429
11095
|
}
|
|
11430
11096
|
/** List all users with access to a vault. */
|
|
11431
11097
|
async listUsers(vault) {
|
|
@@ -11585,7 +11251,7 @@ var Noydb = class {
|
|
|
11585
11251
|
* })
|
|
11586
11252
|
* ```
|
|
11587
11253
|
*/
|
|
11588
|
-
async queryAcross(vaultIds,
|
|
11254
|
+
async queryAcross(vaultIds, fn2, options = {}) {
|
|
11589
11255
|
if (this.closed) throw new ValidationError("Instance is closed");
|
|
11590
11256
|
this.resetSessionTimer();
|
|
11591
11257
|
const concurrency = Math.max(1, options.concurrency ?? 1);
|
|
@@ -11599,7 +11265,7 @@ var Noydb = class {
|
|
|
11599
11265
|
const task = (async () => {
|
|
11600
11266
|
try {
|
|
11601
11267
|
const comp = await this.openVault(vaultId, { create: options.create !== false });
|
|
11602
|
-
const result = await
|
|
11268
|
+
const result = await fn2(comp);
|
|
11603
11269
|
results[idx] = { vault: vaultId, result };
|
|
11604
11270
|
} catch (err) {
|
|
11605
11271
|
results[idx] = {
|
|
@@ -11859,9 +11525,9 @@ var Noydb = class {
|
|
|
11859
11525
|
return this.writeHooks.onAfterWrite(handler);
|
|
11860
11526
|
}
|
|
11861
11527
|
/** Subscribe to cross-tab write conflicts. Returns an unsubscribe. */
|
|
11862
|
-
onWriteConflict(
|
|
11863
|
-
this.on("write:conflict",
|
|
11864
|
-
return () => this.off("write:conflict",
|
|
11528
|
+
onWriteConflict(fn2) {
|
|
11529
|
+
this.on("write:conflict", fn2);
|
|
11530
|
+
return () => this.off("write:conflict", fn2);
|
|
11865
11531
|
}
|
|
11866
11532
|
/**
|
|
11867
11533
|
* Enable same-device multi-tab coordination: primary/secondary
|
|
@@ -11935,12 +11601,12 @@ var Noydb = class {
|
|
|
11935
11601
|
activeTabs() {
|
|
11936
11602
|
return this.tabCoordinator?.activeTabs() ?? [];
|
|
11937
11603
|
}
|
|
11938
|
-
onTabRoleChange(
|
|
11939
|
-
return this.tabCoordinator?.onTabRoleChange(
|
|
11604
|
+
onTabRoleChange(fn2) {
|
|
11605
|
+
return this.tabCoordinator?.onTabRoleChange(fn2) ?? (() => {
|
|
11940
11606
|
});
|
|
11941
11607
|
}
|
|
11942
|
-
onActiveTabsChange(
|
|
11943
|
-
return this.tabCoordinator?.onActiveTabsChange(
|
|
11608
|
+
onActiveTabsChange(fn2) {
|
|
11609
|
+
return this.tabCoordinator?.onActiveTabsChange(fn2) ?? (() => {
|
|
11944
11610
|
});
|
|
11945
11611
|
}
|
|
11946
11612
|
/** @internal The write-hook registry, threaded into each Collection. */
|
|
@@ -12239,7 +11905,7 @@ var Noydb = class {
|
|
|
12239
11905
|
"setPublicEnvelope: the public-envelope feature is not enabled. Pass `publicEnvelope: true` (or a schema object) to `createNoydb`."
|
|
12240
11906
|
);
|
|
12241
11907
|
}
|
|
12242
|
-
const { loadPublicEnvelope, savePublicEnvelope, resolveSchema, validatePublicEnvelopeInput } = await import("./public-envelope-
|
|
11908
|
+
const { loadPublicEnvelope, savePublicEnvelope, resolveSchema, validatePublicEnvelopeInput } = await import("./public-envelope-MRN5YYZZ.js");
|
|
12243
11909
|
const schema = resolveSchema(this.options.publicEnvelope);
|
|
12244
11910
|
validatePublicEnvelopeInput(input, schema);
|
|
12245
11911
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -12268,7 +11934,7 @@ var Noydb = class {
|
|
|
12268
11934
|
* regardless).
|
|
12269
11935
|
*/
|
|
12270
11936
|
async getPublicEnvelope(vault, opts = {}) {
|
|
12271
|
-
const { readPublicEnvelope } = await import("./public-envelope-
|
|
11937
|
+
const { readPublicEnvelope } = await import("./public-envelope-MRN5YYZZ.js");
|
|
12272
11938
|
return readPublicEnvelope(this.options.store, vault, opts);
|
|
12273
11939
|
}
|
|
12274
11940
|
// ─── Auth introspection ─────────────────────────────────────────
|
|
@@ -12459,9 +12125,9 @@ async function createNoydb(options) {
|
|
|
12459
12125
|
throw new ValidationError("A secret (passphrase) or getKeyring callback is required when encryption is enabled");
|
|
12460
12126
|
}
|
|
12461
12127
|
if (!options.coordinationStrategy) options = { ...options, coordinationStrategy: await createDefaultCoordinationProvider(options.store) };
|
|
12462
|
-
if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-
|
|
12128
|
+
if (!options.userApiFactory) options = { ...options, userApiFactory: (await import("./api-JOXUNSKP.js")).createUserApi };
|
|
12463
12129
|
if (!options.policyFactory) {
|
|
12464
|
-
const policyModule = await import("./policy-
|
|
12130
|
+
const policyModule = await import("./policy-YIKUH4AD.js");
|
|
12465
12131
|
options = { ...options, policyFactory: policyModule.createNoydbPolicy, policyCheckGateFn: policyModule.checkGate };
|
|
12466
12132
|
}
|
|
12467
12133
|
return new Noydb(options);
|
|
@@ -12478,13 +12144,6 @@ function normalizeSyncTargets(sync) {
|
|
|
12478
12144
|
export {
|
|
12479
12145
|
memoryStore,
|
|
12480
12146
|
withArchive,
|
|
12481
|
-
ComputedFieldError,
|
|
12482
|
-
evalComputedFields,
|
|
12483
|
-
isZodSchema,
|
|
12484
|
-
derivePersistedSchema,
|
|
12485
|
-
Lru,
|
|
12486
|
-
parseBytes,
|
|
12487
|
-
estimateRecordBytes,
|
|
12488
12147
|
Collection,
|
|
12489
12148
|
ELEVATION_AUDIT_COLLECTION,
|
|
12490
12149
|
ElevatedHandle,
|
|
@@ -12494,10 +12153,6 @@ export {
|
|
|
12494
12153
|
ref,
|
|
12495
12154
|
refArray,
|
|
12496
12155
|
RefRegistry,
|
|
12497
|
-
isLinkCollectionName,
|
|
12498
|
-
LinkEndpointError,
|
|
12499
|
-
LinkIntegrityError,
|
|
12500
|
-
persistSchemaIfNeeded,
|
|
12501
12156
|
Vault,
|
|
12502
12157
|
QuickUnlockStore,
|
|
12503
12158
|
describeAuthConfig,
|
|
@@ -12507,4 +12162,4 @@ export {
|
|
|
12507
12162
|
Noydb,
|
|
12508
12163
|
createNoydb
|
|
12509
12164
|
};
|
|
12510
|
-
//# sourceMappingURL=chunk-
|
|
12165
|
+
//# sourceMappingURL=chunk-ZPHDGUZZ.js.map
|