@noy-db/hub 0.6.0-pre.9 → 0.7.0-pre.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7127 -0
- package/README.md +1 -1
- package/codemods/0.4.0-pre.json +24 -0
- package/codemods/0.6.0-pre.json +229 -0
- package/codemods/0.7.0-pre.json +258 -0
- package/dist/api-EQYRTZO2.js +20 -0
- package/dist/as/index.js +146 -0
- package/dist/as/index.js.map +1 -0
- package/dist/at/index.js +23 -0
- package/dist/attestation/index.js +19 -19
- package/dist/{backup-KULFZ2T4.js → backup-Z7ZBTAQ6.js} +36 -18
- package/dist/backup-Z7ZBTAQ6.js.map +1 -0
- package/dist/blobs/index.js +22 -20
- package/dist/blobs/index.js.map +1 -1
- package/dist/broker/index.js +12 -12
- package/dist/by/index.js +11 -0
- package/dist/cargo/index.js +40 -36
- package/dist/{chunk-YAWK6AWF.js → chunk-225O5CXQ.js} +2 -2
- package/dist/{chunk-MSWYQLMQ.js → chunk-2GXEQUEX.js} +2 -2
- package/dist/chunk-2GXEQUEX.js.map +1 -0
- package/dist/{chunk-3URQC7EH.js → chunk-2LPVI4PX.js} +355 -132
- package/dist/chunk-2LPVI4PX.js.map +1 -0
- package/dist/{chunk-JJNOLSG5.js → chunk-3L2MVE36.js} +15 -16
- package/dist/chunk-3L2MVE36.js.map +1 -0
- package/dist/{chunk-OF3L2SD6.js → chunk-3QARDAYW.js} +2 -2
- package/dist/{chunk-WLZ47GSL.js → chunk-467SKJ65.js} +12 -10
- package/dist/{chunk-WLZ47GSL.js.map → chunk-467SKJ65.js.map} +1 -1
- package/dist/{chunk-W3TVWF6N.js → chunk-4A4TYISP.js} +2 -2
- package/dist/{chunk-ZJADGNYF.js → chunk-4AOERLTV.js} +1 -1
- package/dist/chunk-4AOERLTV.js.map +1 -0
- package/dist/{chunk-CCZJJ4I2.js → chunk-4G25SDQL.js} +6 -6
- package/dist/{chunk-4I72F5DF.js → chunk-4LPF226H.js} +11 -14
- package/dist/chunk-4LPF226H.js.map +1 -0
- package/dist/{chunk-7F4DBNSP.js → chunk-4ZPE6SKS.js} +135 -18
- package/dist/chunk-4ZPE6SKS.js.map +1 -0
- package/dist/{chunk-7TSYBD3E.js → chunk-5263OEM3.js} +2 -2
- package/dist/{chunk-WFUIE565.js → chunk-57JTHWLQ.js} +17 -14
- package/dist/chunk-57JTHWLQ.js.map +1 -0
- package/dist/{chunk-FNSMZQS4.js → chunk-5ACAVJUI.js} +2 -2
- package/dist/{chunk-PDLLCOGD.js → chunk-5AFMP532.js} +20 -17
- package/dist/chunk-5AFMP532.js.map +1 -0
- package/dist/{chunk-JRKZTEZZ.js → chunk-5W7YXFV5.js} +444 -73
- package/dist/chunk-5W7YXFV5.js.map +1 -0
- package/dist/chunk-6EW2UCVF.js +190 -0
- package/dist/chunk-6EW2UCVF.js.map +1 -0
- package/dist/{chunk-4VUPLMZ6.js → chunk-6FOGTKBY.js} +68 -73
- package/dist/chunk-6FOGTKBY.js.map +1 -0
- package/dist/{chunk-VMCCGUQB.js → chunk-7LYUJNU3.js} +2 -2
- package/dist/{chunk-52JPHN5N.js → chunk-A2YW5EMU.js} +27 -149
- package/dist/chunk-A2YW5EMU.js.map +1 -0
- package/dist/{chunk-WLYIROCJ.js → chunk-AB5P32RE.js} +2 -2
- package/dist/{chunk-PL2GHSCM.js → chunk-ALB64CZM.js} +157 -90
- package/dist/chunk-ALB64CZM.js.map +1 -0
- package/dist/{chunk-SUFG5E73.js → chunk-ALUNQEBY.js} +2 -2
- package/dist/{chunk-CADUYBQD.js → chunk-ATL3ZVXT.js} +2 -2
- package/dist/{chunk-BWVKEOPE.js → chunk-ATV637J7.js} +7 -11
- package/dist/chunk-ATV637J7.js.map +1 -0
- package/dist/{chunk-DG27IUVI.js → chunk-CBRS2NEK.js} +2 -11
- package/dist/chunk-CBRS2NEK.js.map +1 -0
- package/dist/{chunk-7MNBICB5.js → chunk-CN6B5PEN.js} +16 -14
- package/dist/chunk-CN6B5PEN.js.map +1 -0
- package/dist/{chunk-6FJWSWFT.js → chunk-DBNYPLWY.js} +3 -3
- package/dist/{chunk-5JY5TSVY.js → chunk-DFAUMLD7.js} +25 -31
- package/dist/chunk-DFAUMLD7.js.map +1 -0
- package/dist/{chunk-FFDNKRCY.js → chunk-DKWPJOYH.js} +2 -2
- package/dist/chunk-DKWPJOYH.js.map +1 -0
- package/dist/{chunk-VJFMXYKP.js → chunk-E6YA6UAP.js} +2 -2
- package/dist/{chunk-WASHZV34.js → chunk-F23WQK3G.js} +65 -27
- package/dist/chunk-F23WQK3G.js.map +1 -0
- package/dist/{chunk-JIUVJ4M7.js → chunk-F7ZFRPGQ.js} +3 -3
- package/dist/{chunk-HXGUIPQB.js → chunk-FOG7YEJP.js} +3 -3
- package/dist/{chunk-QULVCV3M.js → chunk-GK4DRVUD.js} +6 -6
- package/dist/chunk-GK4DRVUD.js.map +1 -0
- package/dist/{chunk-BRVW2GS5.js → chunk-H36KSN6X.js} +87 -34
- package/dist/chunk-H36KSN6X.js.map +1 -0
- package/dist/{chunk-O2ERS4UJ.js → chunk-H4M7ADXY.js} +81 -52
- package/dist/chunk-H4M7ADXY.js.map +1 -0
- package/dist/{chunk-FZ6NYJ7L.js → chunk-H7HP56F6.js} +11 -8
- package/dist/chunk-H7HP56F6.js.map +1 -0
- package/dist/chunk-HK67PX4J.js +27 -0
- package/dist/chunk-HK67PX4J.js.map +1 -0
- package/dist/{chunk-X56RTUK3.js → chunk-HM4JSXX2.js} +3 -3
- package/dist/{chunk-AHLJSVRL.js → chunk-HTGRQZFB.js} +5 -7
- package/dist/chunk-HTGRQZFB.js.map +1 -0
- package/dist/{chunk-GQ3BX5EA.js → chunk-I3ISCYT7.js} +2 -2
- package/dist/{chunk-Q6TEJXBX.js → chunk-IESNYJXZ.js} +31 -49
- package/dist/chunk-IESNYJXZ.js.map +1 -0
- package/dist/{chunk-FUHKW252.js → chunk-J4MN6XIU.js} +2 -2
- package/dist/{chunk-ADW22QSB.js → chunk-J4UJ5FRV.js} +4 -4
- package/dist/{chunk-HNGSV2YC.js → chunk-JBIV4FLR.js} +67 -10
- package/dist/chunk-JBIV4FLR.js.map +1 -0
- package/dist/{chunk-HVQGCKY4.js → chunk-JVLSU7S2.js} +2 -2
- package/dist/{chunk-AR2JDFAE.js → chunk-KDJGJR7F.js} +2 -2
- package/dist/{chunk-NPP5R7FF.js → chunk-KN4W2OQ4.js} +22 -18
- package/dist/chunk-KN4W2OQ4.js.map +1 -0
- package/dist/{chunk-G6S5VVHP.js → chunk-L6GTLZRK.js} +10 -10
- package/dist/chunk-L6GTLZRK.js.map +1 -0
- package/dist/{chunk-2BMRJ6LQ.js → chunk-LF6DMX4C.js} +8 -11
- package/dist/{chunk-2BMRJ6LQ.js.map → chunk-LF6DMX4C.js.map} +1 -1
- package/dist/chunk-LFUID7OW.js +163 -0
- package/dist/chunk-LFUID7OW.js.map +1 -0
- package/dist/{chunk-747LRSOO.js → chunk-LKFKXS5K.js} +2 -2
- package/dist/{chunk-U5O6GIWZ.js → chunk-LR4Z47QD.js} +3 -3
- package/dist/{chunk-VZ3XFUQ7.js → chunk-MTBXJAS4.js} +16 -22
- package/dist/chunk-MTBXJAS4.js.map +1 -0
- package/dist/chunk-N4CNVSUF.js +66 -0
- package/dist/chunk-N4CNVSUF.js.map +1 -0
- package/dist/{chunk-RTAMLDWP.js → chunk-NLKLXXTO.js} +2 -2
- package/dist/{chunk-IGJCYUT5.js → chunk-NSITFOCJ.js} +1 -1
- package/dist/chunk-NSITFOCJ.js.map +1 -0
- package/dist/{chunk-FDX7OWWI.js → chunk-OPXR4PB2.js} +2 -2
- package/dist/{chunk-4GZ6XOVW.js → chunk-OWLVBOWO.js} +44 -42
- package/dist/chunk-OWLVBOWO.js.map +1 -0
- package/dist/{chunk-Z45YRGFO.js → chunk-P6ASQOZR.js} +2 -2
- package/dist/{chunk-5O5HRRTV.js → chunk-PCQDY6QN.js} +7 -7
- package/dist/{chunk-5O5HRRTV.js.map → chunk-PCQDY6QN.js.map} +1 -1
- package/dist/{chunk-BEFVYAR5.js → chunk-PGFKIOR3.js} +4 -4
- package/dist/chunk-PGFKIOR3.js.map +1 -0
- package/dist/{chunk-3FSX6LDG.js → chunk-POS53FG6.js} +18 -3
- package/dist/{chunk-3FSX6LDG.js.map → chunk-POS53FG6.js.map} +1 -1
- package/dist/{chunk-3IXIU6FP.js → chunk-PQ6Z2TAP.js} +7 -10
- package/dist/chunk-PQ6Z2TAP.js.map +1 -0
- package/dist/{chunk-CEJWMBXO.js → chunk-PUJTKLPL.js} +6 -2
- package/dist/chunk-PUJTKLPL.js.map +1 -0
- package/dist/{chunk-GAG7QOVO.js → chunk-QGJ4XIA7.js} +53 -18
- package/dist/chunk-QGJ4XIA7.js.map +1 -0
- package/dist/{chunk-2DHSSLOD.js → chunk-QHJKK77B.js} +13 -15
- package/dist/chunk-QHJKK77B.js.map +1 -0
- package/dist/{chunk-2Z3NCLNX.js → chunk-QI5NWLVW.js} +7 -7
- package/dist/{chunk-6SAFL5YE.js → chunk-RC4BROYR.js} +3 -3
- package/dist/{chunk-NJDQ4YSV.js → chunk-RDHUZ674.js} +4 -4
- package/dist/{chunk-YPYHVOXP.js → chunk-RK7N4OQ5.js} +2 -2
- package/dist/chunk-RK7N4OQ5.js.map +1 -0
- package/dist/{chunk-3737A6EA.js → chunk-S2VG3ABP.js} +127 -31
- package/dist/chunk-S2VG3ABP.js.map +1 -0
- package/dist/{chunk-3JVXVJ7L.js → chunk-S35S77YU.js} +10 -10
- package/dist/{chunk-KUDZVJKQ.js → chunk-SHILAQH5.js} +2 -2
- package/dist/{chunk-4UVDI4XE.js → chunk-T3PHCEN4.js} +4 -4
- package/dist/{chunk-55LKVALY.js → chunk-T7IR4N2S.js} +1 -3
- package/dist/chunk-T7IR4N2S.js.map +1 -0
- package/dist/{chunk-RXYYFSBB.js → chunk-TOV6VMHF.js} +6 -6
- package/dist/chunk-TOV6VMHF.js.map +1 -0
- package/dist/{chunk-W77KZHCW.js → chunk-TVIFAHZR.js} +16 -17
- package/dist/chunk-TVIFAHZR.js.map +1 -0
- package/dist/chunk-UBSFPGVJ.js +1 -0
- package/dist/{chunk-FAXZQ5UF.js → chunk-UCUALOSM.js} +2 -2
- package/dist/{chunk-4HDYQL3J.js → chunk-VAG47QHV.js} +2 -2
- package/dist/{chunk-35EBKWQU.js → chunk-VFIWDPXZ.js} +4 -4
- package/dist/{chunk-5ZKS6ZE2.js → chunk-VTG7327U.js} +4 -4
- package/dist/chunk-VTG7327U.js.map +1 -0
- package/dist/{chunk-VCETL77O.js → chunk-W5LHQXZU.js} +36 -7
- package/dist/chunk-W5LHQXZU.js.map +1 -0
- package/dist/{chunk-6NVPFKN3.js → chunk-WK5FSW7T.js} +92 -35
- package/dist/chunk-WK5FSW7T.js.map +1 -0
- package/dist/{chunk-HNHCQ556.js → chunk-WLLUM35R.js} +2 -2
- package/dist/{chunk-YJ6IONGA.js → chunk-X62MEF2O.js} +13 -5
- package/dist/chunk-X62MEF2O.js.map +1 -0
- package/dist/{chunk-7G6VDWXB.js → chunk-X67FCULK.js} +5 -5
- package/dist/chunk-X67FCULK.js.map +1 -0
- package/dist/{chunk-UHXCLPGC.js → chunk-XDVVBETV.js} +2 -2
- package/dist/chunk-XDVVBETV.js.map +1 -0
- package/dist/chunk-XJ3FEKEY.js +15 -0
- package/dist/chunk-XJ3FEKEY.js.map +1 -0
- package/dist/{chunk-E6427JU2.js → chunk-XSN63FUS.js} +19 -3
- package/dist/chunk-XSN63FUS.js.map +1 -0
- package/dist/{chunk-JRCYZEHU.js → chunk-XVU7J43V.js} +2 -2
- package/dist/{chunk-2GAJGUNM.js → chunk-Y3YLJORD.js} +408 -260
- package/dist/chunk-Y3YLJORD.js.map +1 -0
- package/dist/{chunk-6BU3L4UE.js → chunk-Y6GZ2P4M.js} +7 -10
- package/dist/chunk-Y6GZ2P4M.js.map +1 -0
- package/dist/{chunk-DMQCLZ4Z.js → chunk-YCSM3GZU.js} +2 -2
- package/dist/{chunk-RV3ARMPN.js → chunk-YKPGQJFU.js} +30 -180
- package/dist/chunk-YKPGQJFU.js.map +1 -0
- package/dist/{chunk-FMQJZH4R.js → chunk-YMLQBZFJ.js} +6 -6
- package/dist/{chunk-6HFM7EIT.js → chunk-YPSOHDNC.js} +2 -2
- package/dist/{chunk-CDB2HVQW.js → chunk-YXA2TCTZ.js} +14 -15
- package/dist/chunk-YXA2TCTZ.js.map +1 -0
- package/dist/{chunk-N35NC4JH.js → chunk-Z2PWOSCJ.js} +2 -2
- package/dist/{chunk-XWX7GL56.js → chunk-Z2WK53N6.js} +47 -23
- package/dist/chunk-Z2WK53N6.js.map +1 -0
- package/dist/{chunk-HPLWFNG4.js → chunk-Z7ZXZL6Y.js} +2 -2
- package/dist/{chunk-PNKHAKQ7.js → chunk-ZO252Q5S.js} +17 -10
- package/dist/chunk-ZO252Q5S.js.map +1 -0
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-2KJAXRRO.js → classified-marker-BSQHU4JT.js} +3 -3
- package/dist/collection-facade-LG3NYZVB.js +45 -0
- package/dist/{computed-6G5M3UPH.js → computed-ASBNTLOK.js} +3 -3
- package/dist/consent/index.js +10 -10
- package/dist/cover/index.js +10 -3
- package/dist/custody/index.js +12 -11
- package/dist/{dead-filter-DCB62VWW.js → dead-filter-QKU56XTQ.js} +2 -2
- package/dist/debug/index.js +1 -1
- package/dist/{delegation-MO7YZYJS.js → delegation-XWRPYODW.js} +24 -23
- package/dist/delegation-XWRPYODW.js.map +1 -0
- package/dist/derivations/index.js +12 -12
- package/dist/derive-CXHCY46K.js +22 -0
- package/dist/directory/index.js +10 -10
- package/dist/{dispatch-MJ6SHB3Y.js → dispatch-4AP4PUZU.js} +18 -18
- package/dist/{dispatch-FZEAWKVM.js → dispatch-VR4LRXZ7.js} +9 -6
- package/dist/dispatch-VR4LRXZ7.js.map +1 -0
- package/dist/{enclave-JU4YIEPB.js → enclave-NYPT7WA7.js} +31 -9
- package/dist/executor-3KFRQETS.js +29 -0
- package/dist/executor-AFHQYRAU.js +9 -0
- package/dist/executor-YYDW6XQI.js +9 -0
- package/dist/export-accessible-BX2ILB4C.js +23 -0
- package/dist/extract-partition-UPOVITFI.js +38 -0
- package/dist/{fanout-sidecar-NNAJQXMX.js → fanout-sidecar-IWP3R4RC.js} +18 -27
- package/dist/fanout-sidecar-IWP3R4RC.js.map +1 -0
- package/dist/{fence-watcher-DHQ775JB.js → fence-watcher-ZVSMLKQD.js} +1 -1
- package/dist/fence-watcher-ZVSMLKQD.js.map +1 -0
- package/dist/find-SZBL2HPB.js +11 -0
- package/dist/forget/index.js +9 -9
- package/dist/guards/index.js +4 -4
- package/dist/history/index.js +23 -20
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +14 -14
- package/dist/index.d.ts +35 -18
- package/dist/index.js +199 -204
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +4 -4
- package/dist/introspection/index.js +12 -11
- package/dist/issue-G53NB6EW.js +19 -0
- package/dist/kernel/collection-config.d.ts +9 -9
- package/dist/kernel/collection.d.ts +9 -3
- package/dist/kernel/constants.d.ts +36 -0
- package/dist/kernel/enclave/crypto.d.ts +52 -4
- package/dist/kernel/enclave/index.d.ts +10 -3
- package/dist/kernel/enclave/record-aad.d.ts +131 -0
- package/dist/kernel/enclave/record-envelope.d.ts +76 -0
- package/dist/kernel/enclave/record-keys/envelope-body.d.ts +34 -2
- package/dist/kernel/enclave/record-keys/lifecycle.d.ts +22 -5
- package/dist/kernel/enclave/record-keys/record-codec.d.ts +47 -14
- package/dist/kernel/enclave/record-keys/rekey-blob.d.ts +88 -0
- package/dist/kernel/enclave/record-keys/rekey.d.ts +91 -0
- package/dist/kernel/enclave/record-keys/tombstone.d.ts +3 -2
- package/dist/kernel/errors.d.ts +134 -14
- package/dist/kernel/merge-authority.d.ts +25 -0
- package/dist/kernel/noydb.d.ts +33 -10
- package/dist/kernel/query/builder.d.ts +51 -4
- package/dist/kernel/query/join.d.ts +27 -0
- package/dist/kernel/query/live.d.ts +31 -9
- package/dist/kernel/query/predicate.d.ts +9 -0
- package/dist/kernel/refs.d.ts +3 -1
- package/dist/kernel/secret-mode.d.ts +1 -1
- package/dist/kernel/sync-policy.d.ts +0 -2
- package/dist/kernel/tier-visibility.d.ts +34 -0
- package/dist/kernel/types.d.ts +145 -28
- package/dist/kernel/vault.d.ts +16 -7
- package/dist/kernel/via/compose.d.ts +3 -3
- package/dist/kernel/via/index.d.ts +15 -6
- package/dist/kernel/via/pipeline.d.ts +6 -6
- package/dist/kernel/via/reconcile.d.ts +14 -2
- package/dist/kernel/via/taint-binding.d.ts +3 -3
- package/dist/{ledger-AETNF4OM.js → ledger-T5K4P2D7.js} +11 -11
- package/dist/liberate-VEOZRESE.js +25 -0
- package/dist/{link-set-E5HNY67I.js → link-set-76JZ6YB4.js} +11 -11
- package/dist/{managed-secret-CWQ6PND5.js → managed-secret-6YC32VXG.js} +13 -5
- package/dist/materialized-views/index.js +27 -27
- package/dist/migrate-cek-LBRKYUZZ.js +19 -0
- package/dist/migrate-cek-LBRKYUZZ.js.map +1 -0
- package/dist/money/index.js +5 -5
- package/dist/noydb-EDJA4JNJ.js +86 -0
- package/dist/on/index.js +1 -0
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +12 -12
- package/dist/pod/index.js +79 -88
- package/dist/pod-handle-P6DPBM5U.js +41 -0
- package/dist/pod-handle-P6DPBM5U.js.map +1 -0
- package/dist/policy/index.js +11 -4
- package/dist/port/as/active.d.ts +10 -0
- package/dist/port/as/index.d.ts +32 -0
- package/dist/port/as/types.d.ts +113 -0
- package/dist/port/at/index.d.ts +37 -0
- package/dist/port/by/default-provider.d.ts +3 -3
- package/dist/port/by/index.d.ts +32 -10
- package/dist/port/by/types.d.ts +29 -11
- package/dist/port/on/index.d.ts +50 -0
- package/dist/port/to/index.d.ts +4 -4
- package/dist/port/to/locator.d.ts +54 -8
- package/dist/port/with/computed-strategy.d.ts +1 -1
- package/dist/port/with/device-seal-strategy.d.ts +2 -2
- package/dist/port/with/formats-strategy.d.ts +76 -0
- package/dist/port/with/i18n-strategy.d.ts +4 -1
- package/dist/port/with/lookup-strategy.d.ts +4 -1
- package/dist/port/with/merge-authority.d.ts +52 -0
- package/dist/port/with/service-bus.d.ts +0 -4
- package/dist/port/with/strategies.d.ts +13 -5
- package/dist/port/with/team-strategy.d.ts +5 -1
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-2XSSMGEQ.js → post-register-53O7AJRZ.js} +6 -6
- package/dist/query/index.js +6 -6
- package/dist/reduce/index.js +6 -6
- package/dist/register-6TCBR6XD.js +32 -0
- package/dist/registry-DH2L4O2V.js +18 -0
- package/dist/registry-IWFMXCHX.js +9 -0
- package/dist/registry-Q3FG3OAX.js +9 -0
- package/dist/registry-YC3IFG3A.js +19 -0
- package/dist/request-withdrawal-NM5VYR6F.js +31 -0
- package/dist/{reveal-BW36KCOQ.js → reveal-XBIMHAXR.js} +6 -6
- package/dist/revoke-MJNYWO72.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/schema-update/index.js +2 -2
- package/dist/sealed-record/index.js +20 -13
- package/dist/sealed-record/index.js.map +1 -1
- package/dist/search/index.js +4 -4
- package/dist/{seed-GDV5PT4R.js → seed-NSNIGYXE.js} +20 -22
- package/dist/seed-NSNIGYXE.js.map +1 -0
- package/dist/sequence/index.js +9 -9
- package/dist/session/index.js +10 -10
- package/dist/shadow/index.js +2 -2
- package/dist/share-link/index.js +1 -1
- package/dist/signer-6XVS2AU3.js +25 -0
- package/dist/snapshots/index.js +10 -10
- package/dist/snapshots/index.js.map +1 -1
- package/dist/{stale-ARHFVL5U.js → stale-MCS46TFO.js} +10 -10
- package/dist/storage-ZXUT476I.js +23 -0
- package/dist/storage-ZXUT476I.js.map +1 -0
- package/dist/{store-coordination-provider-GFCUOBR6.js → store-coordination-provider-6FM26VQM.js} +22 -15
- package/dist/store-coordination-provider-6FM26VQM.js.map +1 -0
- package/dist/sync/index.js +11 -11
- package/dist/team/index.js +17 -16
- package/dist/tiers/index.js +11 -10
- package/dist/to/index.js +17 -9
- package/dist/to/index.js.map +1 -1
- package/dist/transactions/index.js +4 -4
- package/dist/{ulid-PTAIMDG4.js → ulid-VQW6ERQN.js} +2 -2
- package/dist/ulid-VQW6ERQN.js.map +1 -0
- package/dist/util/index.js +1 -1
- package/dist/vault-diff-FE5J35NJ.js +9 -0
- package/dist/vault-diff-FE5J35NJ.js.map +1 -0
- package/dist/vault-head/index.js +115 -0
- package/dist/vault-head/index.js.map +1 -0
- package/dist/{verify-RO5RTZOJ.js → verify-WYOFLSNA.js} +5 -5
- package/dist/via/blob/binding.d.ts +6 -6
- package/dist/via/blob/index.d.ts +3 -0
- package/dist/via/classified/binding.d.ts +9 -9
- package/dist/via/computed/binding.d.ts +2 -2
- package/dist/via/i18n/binding.d.ts +4 -4
- package/dist/via/lookup/binding.d.ts +5 -5
- package/dist/via/lookup/handle.d.ts +4 -1
- package/dist/via/lookup/index.d.ts +1 -1
- package/dist/via/lookup/snapshot.d.ts +1 -1
- package/dist/via/money/binding.d.ts +3 -3
- package/dist/via/money/normalize.d.ts +1 -1
- package/dist/via/money/where.d.ts +3 -3
- package/dist/walk-JNEOYCAU.js +21 -0
- package/dist/walk-JNEOYCAU.js.map +1 -0
- package/dist/with-audit/periods/periods.d.ts +1 -1
- package/dist/with-audit/periods/strategy.d.ts +1 -1
- package/dist/with-audit/sealed-record/index.d.ts +13 -0
- package/dist/with-audit/tiers/index.d.ts +17 -2
- package/dist/with-cargo/adopt-partition.d.ts +7 -7
- package/dist/with-cargo/extract-partition.d.ts +1 -1
- package/dist/with-cargo/floor.d.ts +1 -1
- package/dist/with-cargo/index.d.ts +2 -2
- package/dist/with-commit/history/history.d.ts +26 -0
- package/dist/with-commit/history/index.d.ts +2 -1
- package/dist/with-commit/history/ledger/store.d.ts +7 -1
- package/dist/with-commit/history/strategy.d.ts +11 -1
- package/dist/with-commit/numbering/index.d.ts +0 -5
- package/dist/with-commit/vault-head/active.d.ts +2 -0
- package/dist/with-commit/vault-head/head.d.ts +28 -0
- package/dist/with-commit/vault-head/index.d.ts +10 -0
- package/dist/with-commit/vault-head/strategy.d.ts +127 -0
- package/dist/with-commit/vault-head/verify.d.ts +90 -0
- package/dist/with-formula/materialized-views/dependency-analyzer.d.ts +4 -0
- package/dist/with-formula/materialized-views/projection-legs.d.ts +59 -0
- package/dist/with-formula/materialized-views/registry.d.ts +50 -0
- package/dist/with-formula/materialized-views/types.d.ts +68 -10
- package/dist/with-party/directory/cover/storage.d.ts +0 -8
- package/dist/with-party/directory/storage.d.ts +0 -11
- package/dist/with-party/directory/visibility.d.ts +0 -21
- package/dist/with-party/policy/storage.d.ts +0 -10
- package/dist/with-party/team/deed.d.ts +4 -4
- package/dist/with-party/team/device-seal.d.ts +5 -5
- package/dist/with-party/team/echo-ceremony.d.ts +2 -2
- package/dist/with-party/team/echo-secret.d.ts +4 -4
- package/dist/with-party/team/index.d.ts +3 -3
- package/dist/with-party/team/keyring.d.ts +141 -4
- package/dist/with-party/team/managed-secret.d.ts +21 -11
- package/dist/with-party/team/noydb-facade.d.ts +7 -3
- package/dist/with-party/team/{shamir-recovery-provider.d.ts → noydb-shamir.d.ts} +1 -1
- package/dist/with-party/team/recovery.d.ts +3 -3
- package/dist/with-party/team/roster-tag.d.ts +101 -0
- package/dist/with-party/team/rotate-recover.d.ts +5 -5
- package/dist/with-party/team/tiers.d.ts +2 -1
- package/dist/with-pod/format.d.ts +11 -13
- package/dist/with-pod/index.d.ts +10 -10
- package/dist/with-pod/open.d.ts +2 -2
- package/dist/with-pod/pod-handle.d.ts +19 -0
- package/dist/with-pod/pod-store.d.ts +0 -8
- package/dist/with-pod/{bundle.d.ts → pod.d.ts} +17 -25
- package/dist/with-pod/ulid.d.ts +1 -1
- package/dist/with-shape/blobs/blob-compaction.d.ts +13 -0
- package/dist/with-shape/blobs/blob-set.d.ts +83 -11
- package/dist/with-shape/blobs/orphan-report.d.ts +62 -0
- package/dist/with-shape/introspection/describe.d.ts +2 -2
- package/dist/with-shape/schema-update/fence-controller.d.ts +4 -4
- package/dist/with-shape/schema-update/fence-watcher.d.ts +4 -4
- package/dist/with-shape/schema-update/store-coordination-provider.d.ts +7 -6
- package/dist/with-sync/engine.d.ts +54 -5
- package/dist/with-sync/strategy.d.ts +3 -0
- package/dist/withdraw-accessible-ILTSXTIE.js +28 -0
- package/dist/withdraw-accessible-ILTSXTIE.js.map +1 -0
- package/package.json +29 -5
- package/dist/api-RXUMEKT3.js +0 -20
- package/dist/backup-KULFZ2T4.js.map +0 -1
- package/dist/bundle-handle-GFNHT52M.js +0 -36
- package/dist/bundle-handle-GFNHT52M.js.map +0 -1
- package/dist/chunk-2DHSSLOD.js.map +0 -1
- package/dist/chunk-2GAJGUNM.js.map +0 -1
- package/dist/chunk-3737A6EA.js.map +0 -1
- package/dist/chunk-3IXIU6FP.js.map +0 -1
- package/dist/chunk-3URQC7EH.js.map +0 -1
- package/dist/chunk-4GZ6XOVW.js.map +0 -1
- package/dist/chunk-4I72F5DF.js.map +0 -1
- package/dist/chunk-4VUPLMZ6.js.map +0 -1
- package/dist/chunk-52JPHN5N.js.map +0 -1
- package/dist/chunk-55LKVALY.js.map +0 -1
- package/dist/chunk-5JY5TSVY.js.map +0 -1
- package/dist/chunk-5ZKS6ZE2.js.map +0 -1
- package/dist/chunk-6BU3L4UE.js.map +0 -1
- package/dist/chunk-6NVPFKN3.js.map +0 -1
- package/dist/chunk-7F4DBNSP.js.map +0 -1
- package/dist/chunk-7G6VDWXB.js.map +0 -1
- package/dist/chunk-7H73RIE3.js +0 -45
- package/dist/chunk-7H73RIE3.js.map +0 -1
- package/dist/chunk-7MNBICB5.js.map +0 -1
- package/dist/chunk-AFHQATY4.js +0 -47
- package/dist/chunk-AFHQATY4.js.map +0 -1
- package/dist/chunk-AHLJSVRL.js.map +0 -1
- package/dist/chunk-BEFVYAR5.js.map +0 -1
- package/dist/chunk-BRVW2GS5.js.map +0 -1
- package/dist/chunk-BWVKEOPE.js.map +0 -1
- package/dist/chunk-CDB2HVQW.js.map +0 -1
- package/dist/chunk-CEJWMBXO.js.map +0 -1
- package/dist/chunk-DG27IUVI.js.map +0 -1
- package/dist/chunk-E6427JU2.js.map +0 -1
- package/dist/chunk-FFDNKRCY.js.map +0 -1
- package/dist/chunk-FZ6NYJ7L.js.map +0 -1
- package/dist/chunk-G6S5VVHP.js.map +0 -1
- package/dist/chunk-GAG7QOVO.js.map +0 -1
- package/dist/chunk-HNGSV2YC.js.map +0 -1
- package/dist/chunk-IGJCYUT5.js.map +0 -1
- package/dist/chunk-JJNOLSG5.js.map +0 -1
- package/dist/chunk-JRKZTEZZ.js.map +0 -1
- package/dist/chunk-MSWYQLMQ.js.map +0 -1
- package/dist/chunk-NPP5R7FF.js.map +0 -1
- package/dist/chunk-O2ERS4UJ.js.map +0 -1
- package/dist/chunk-PDLLCOGD.js.map +0 -1
- package/dist/chunk-PL2GHSCM.js.map +0 -1
- package/dist/chunk-PNKHAKQ7.js.map +0 -1
- package/dist/chunk-Q6TEJXBX.js.map +0 -1
- package/dist/chunk-QULVCV3M.js.map +0 -1
- package/dist/chunk-RV3ARMPN.js.map +0 -1
- package/dist/chunk-RXYYFSBB.js.map +0 -1
- package/dist/chunk-UHXCLPGC.js.map +0 -1
- package/dist/chunk-VCETL77O.js.map +0 -1
- package/dist/chunk-VZ3XFUQ7.js.map +0 -1
- package/dist/chunk-W77KZHCW.js.map +0 -1
- package/dist/chunk-WASHZV34.js.map +0 -1
- package/dist/chunk-WFUIE565.js.map +0 -1
- package/dist/chunk-XWX7GL56.js.map +0 -1
- package/dist/chunk-YJ6IONGA.js.map +0 -1
- package/dist/chunk-YPYHVOXP.js.map +0 -1
- package/dist/chunk-ZJADGNYF.js.map +0 -1
- package/dist/collection-facade-QEJIM6BC.js +0 -45
- package/dist/delegation-MO7YZYJS.js.map +0 -1
- package/dist/derive-IUA6JFLB.js +0 -22
- package/dist/dispatch-FZEAWKVM.js.map +0 -1
- package/dist/executor-CYJQLKKI.js +0 -9
- package/dist/executor-S4QIKEHW.js +0 -9
- package/dist/executor-YIQB2S6N.js +0 -29
- package/dist/export-accessible-4S36PQNR.js +0 -23
- package/dist/extract-partition-IO7FDZ2P.js +0 -38
- package/dist/fanout-sidecar-NNAJQXMX.js.map +0 -1
- package/dist/fence-watcher-DHQ775JB.js.map +0 -1
- package/dist/find-RBBYKXI7.js +0 -11
- package/dist/issue-RIVHSY2S.js +0 -19
- package/dist/liberate-GFN4C7RR.js +0 -24
- package/dist/noydb-ASEXNJS6.js +0 -83
- package/dist/register-4EFJCVYD.js +0 -32
- package/dist/registry-4SDHHOJ7.js +0 -18
- package/dist/registry-CZVINVQH.js +0 -9
- package/dist/registry-IKUR2MXD.js +0 -9
- package/dist/registry-OYTFGWVK.js +0 -19
- package/dist/request-withdrawal-KGXGDPVQ.js +0 -31
- package/dist/revoke-JFN773KF.js +0 -24
- package/dist/seed-GDV5PT4R.js.map +0 -1
- package/dist/signer-TA55QB6R.js +0 -25
- package/dist/storage-V7MTFAQJ.js +0 -23
- package/dist/store-coordination-provider-GFCUOBR6.js.map +0 -1
- package/dist/walk-3ZECBFDA.js +0 -21
- package/dist/with-pod/bundle-handle.d.ts +0 -9
- package/dist/withdraw-accessible-7PG4DYQK.js +0 -28
- /package/dist/{api-RXUMEKT3.js.map → api-EQYRTZO2.js.map} +0 -0
- /package/dist/{collection-facade-QEJIM6BC.js.map → at/index.js.map} +0 -0
- /package/dist/{computed-6G5M3UPH.js.map → by/index.js.map} +0 -0
- /package/dist/{chunk-YAWK6AWF.js.map → chunk-225O5CXQ.js.map} +0 -0
- /package/dist/{chunk-OF3L2SD6.js.map → chunk-3QARDAYW.js.map} +0 -0
- /package/dist/{chunk-W3TVWF6N.js.map → chunk-4A4TYISP.js.map} +0 -0
- /package/dist/{chunk-CCZJJ4I2.js.map → chunk-4G25SDQL.js.map} +0 -0
- /package/dist/{chunk-7TSYBD3E.js.map → chunk-5263OEM3.js.map} +0 -0
- /package/dist/{chunk-FNSMZQS4.js.map → chunk-5ACAVJUI.js.map} +0 -0
- /package/dist/{chunk-VMCCGUQB.js.map → chunk-7LYUJNU3.js.map} +0 -0
- /package/dist/{chunk-WLYIROCJ.js.map → chunk-AB5P32RE.js.map} +0 -0
- /package/dist/{chunk-SUFG5E73.js.map → chunk-ALUNQEBY.js.map} +0 -0
- /package/dist/{chunk-CADUYBQD.js.map → chunk-ATL3ZVXT.js.map} +0 -0
- /package/dist/{chunk-6FJWSWFT.js.map → chunk-DBNYPLWY.js.map} +0 -0
- /package/dist/{chunk-VJFMXYKP.js.map → chunk-E6YA6UAP.js.map} +0 -0
- /package/dist/{chunk-JIUVJ4M7.js.map → chunk-F7ZFRPGQ.js.map} +0 -0
- /package/dist/{chunk-HXGUIPQB.js.map → chunk-FOG7YEJP.js.map} +0 -0
- /package/dist/{chunk-X56RTUK3.js.map → chunk-HM4JSXX2.js.map} +0 -0
- /package/dist/{chunk-GQ3BX5EA.js.map → chunk-I3ISCYT7.js.map} +0 -0
- /package/dist/{chunk-FUHKW252.js.map → chunk-J4MN6XIU.js.map} +0 -0
- /package/dist/{chunk-ADW22QSB.js.map → chunk-J4UJ5FRV.js.map} +0 -0
- /package/dist/{chunk-HVQGCKY4.js.map → chunk-JVLSU7S2.js.map} +0 -0
- /package/dist/{chunk-AR2JDFAE.js.map → chunk-KDJGJR7F.js.map} +0 -0
- /package/dist/{chunk-747LRSOO.js.map → chunk-LKFKXS5K.js.map} +0 -0
- /package/dist/{chunk-U5O6GIWZ.js.map → chunk-LR4Z47QD.js.map} +0 -0
- /package/dist/{chunk-RTAMLDWP.js.map → chunk-NLKLXXTO.js.map} +0 -0
- /package/dist/{chunk-FDX7OWWI.js.map → chunk-OPXR4PB2.js.map} +0 -0
- /package/dist/{chunk-Z45YRGFO.js.map → chunk-P6ASQOZR.js.map} +0 -0
- /package/dist/{chunk-2Z3NCLNX.js.map → chunk-QI5NWLVW.js.map} +0 -0
- /package/dist/{chunk-6SAFL5YE.js.map → chunk-RC4BROYR.js.map} +0 -0
- /package/dist/{chunk-NJDQ4YSV.js.map → chunk-RDHUZ674.js.map} +0 -0
- /package/dist/{chunk-3JVXVJ7L.js.map → chunk-S35S77YU.js.map} +0 -0
- /package/dist/{chunk-KUDZVJKQ.js.map → chunk-SHILAQH5.js.map} +0 -0
- /package/dist/{chunk-4UVDI4XE.js.map → chunk-T3PHCEN4.js.map} +0 -0
- /package/dist/{derive-IUA6JFLB.js.map → chunk-UBSFPGVJ.js.map} +0 -0
- /package/dist/{chunk-FAXZQ5UF.js.map → chunk-UCUALOSM.js.map} +0 -0
- /package/dist/{chunk-4HDYQL3J.js.map → chunk-VAG47QHV.js.map} +0 -0
- /package/dist/{chunk-35EBKWQU.js.map → chunk-VFIWDPXZ.js.map} +0 -0
- /package/dist/{chunk-HNHCQ556.js.map → chunk-WLLUM35R.js.map} +0 -0
- /package/dist/{chunk-JRCYZEHU.js.map → chunk-XVU7J43V.js.map} +0 -0
- /package/dist/{chunk-DMQCLZ4Z.js.map → chunk-YCSM3GZU.js.map} +0 -0
- /package/dist/{chunk-FMQJZH4R.js.map → chunk-YMLQBZFJ.js.map} +0 -0
- /package/dist/{chunk-6HFM7EIT.js.map → chunk-YPSOHDNC.js.map} +0 -0
- /package/dist/{chunk-N35NC4JH.js.map → chunk-Z2PWOSCJ.js.map} +0 -0
- /package/dist/{chunk-HPLWFNG4.js.map → chunk-Z7ZXZL6Y.js.map} +0 -0
- /package/dist/{classified-marker-2KJAXRRO.js.map → classified-marker-BSQHU4JT.js.map} +0 -0
- /package/dist/{enclave-JU4YIEPB.js.map → collection-facade-LG3NYZVB.js.map} +0 -0
- /package/dist/{executor-CYJQLKKI.js.map → computed-ASBNTLOK.js.map} +0 -0
- /package/dist/{dead-filter-DCB62VWW.js.map → dead-filter-QKU56XTQ.js.map} +0 -0
- /package/dist/{executor-S4QIKEHW.js.map → derive-CXHCY46K.js.map} +0 -0
- /package/dist/{dispatch-MJ6SHB3Y.js.map → dispatch-4AP4PUZU.js.map} +0 -0
- /package/dist/{executor-YIQB2S6N.js.map → enclave-NYPT7WA7.js.map} +0 -0
- /package/dist/{export-accessible-4S36PQNR.js.map → executor-3KFRQETS.js.map} +0 -0
- /package/dist/{extract-partition-IO7FDZ2P.js.map → executor-AFHQYRAU.js.map} +0 -0
- /package/dist/{find-RBBYKXI7.js.map → executor-YYDW6XQI.js.map} +0 -0
- /package/dist/{issue-RIVHSY2S.js.map → export-accessible-BX2ILB4C.js.map} +0 -0
- /package/dist/{ledger-AETNF4OM.js.map → extract-partition-UPOVITFI.js.map} +0 -0
- /package/dist/{liberate-GFN4C7RR.js.map → find-SZBL2HPB.js.map} +0 -0
- /package/dist/{link-set-E5HNY67I.js.map → issue-G53NB6EW.js.map} +0 -0
- /package/dist/{managed-secret-CWQ6PND5.js.map → ledger-T5K4P2D7.js.map} +0 -0
- /package/dist/{noydb-ASEXNJS6.js.map → liberate-VEOZRESE.js.map} +0 -0
- /package/dist/{register-4EFJCVYD.js.map → link-set-76JZ6YB4.js.map} +0 -0
- /package/dist/{registry-4SDHHOJ7.js.map → managed-secret-6YC32VXG.js.map} +0 -0
- /package/dist/{registry-CZVINVQH.js.map → noydb-EDJA4JNJ.js.map} +0 -0
- /package/dist/{registry-IKUR2MXD.js.map → on/index.js.map} +0 -0
- /package/dist/{post-register-2XSSMGEQ.js.map → post-register-53O7AJRZ.js.map} +0 -0
- /package/dist/{registry-OYTFGWVK.js.map → register-6TCBR6XD.js.map} +0 -0
- /package/dist/{request-withdrawal-KGXGDPVQ.js.map → registry-DH2L4O2V.js.map} +0 -0
- /package/dist/{revoke-JFN773KF.js.map → registry-IWFMXCHX.js.map} +0 -0
- /package/dist/{signer-TA55QB6R.js.map → registry-Q3FG3OAX.js.map} +0 -0
- /package/dist/{stale-ARHFVL5U.js.map → registry-YC3IFG3A.js.map} +0 -0
- /package/dist/{storage-V7MTFAQJ.js.map → request-withdrawal-NM5VYR6F.js.map} +0 -0
- /package/dist/{reveal-BW36KCOQ.js.map → reveal-XBIMHAXR.js.map} +0 -0
- /package/dist/{ulid-PTAIMDG4.js.map → revoke-MJNYWO72.js.map} +0 -0
- /package/dist/{walk-3ZECBFDA.js.map → signer-6XVS2AU3.js.map} +0 -0
- /package/dist/{withdraw-accessible-7PG4DYQK.js.map → stale-MCS46TFO.js.map} +0 -0
- /package/dist/{verify-RO5RTZOJ.js.map → verify-WYOFLSNA.js.map} +0 -0
|
@@ -1,12 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
generateULID
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-4AOERLTV.js";
|
|
4
4
|
import {
|
|
5
|
+
buildRecordAad,
|
|
5
6
|
openEnvelopeJson
|
|
6
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-2LPVI4PX.js";
|
|
8
|
+
import {
|
|
9
|
+
buildRecordEnvelope
|
|
10
|
+
} from "./chunk-N4CNVSUF.js";
|
|
7
11
|
import {
|
|
8
12
|
encrypt
|
|
9
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-W5LHQXZU.js";
|
|
10
14
|
|
|
11
15
|
// src/with-audit/consent/consent.ts
|
|
12
16
|
var CONSENT_AUDIT_COLLECTION = "_consent_audit";
|
|
@@ -26,7 +30,7 @@ async function loadConsentEntries(adapter, vault, encrypted, getDEK, filter = {}
|
|
|
26
30
|
for (const id of ids.sort()) {
|
|
27
31
|
const envelope = await adapter.get(vault, CONSENT_AUDIT_COLLECTION, id);
|
|
28
32
|
if (!envelope) continue;
|
|
29
|
-
const entry = await decryptEntry(envelope, encrypted, getDEK);
|
|
33
|
+
const entry = await decryptEntry(id, envelope, encrypted, getDEK);
|
|
30
34
|
if (!matchesFilter(entry, filter)) continue;
|
|
31
35
|
entries.push(entry);
|
|
32
36
|
}
|
|
@@ -34,28 +38,18 @@ async function loadConsentEntries(adapter, vault, encrypted, getDEK, filter = {}
|
|
|
34
38
|
}
|
|
35
39
|
async function buildEnvelope(entry, encrypted, getDEK) {
|
|
36
40
|
const json = JSON.stringify(entry);
|
|
41
|
+
const identity = { collection: CONSENT_AUDIT_COLLECTION, id: entry.id, version: 1 };
|
|
42
|
+
const body = { ts: entry.timestamp };
|
|
37
43
|
if (!encrypted) {
|
|
38
|
-
return {
|
|
39
|
-
_noydb: 1,
|
|
40
|
-
_v: 1,
|
|
41
|
-
_ts: entry.timestamp,
|
|
42
|
-
_iv: "",
|
|
43
|
-
_data: json
|
|
44
|
-
};
|
|
44
|
+
return buildRecordEnvelope(identity, { ...body, iv: "", data: json });
|
|
45
45
|
}
|
|
46
46
|
const dek = await getDEK(CONSENT_AUDIT_COLLECTION);
|
|
47
|
-
const { iv, data } = await encrypt(json, dek);
|
|
48
|
-
return {
|
|
49
|
-
_noydb: 1,
|
|
50
|
-
_v: 1,
|
|
51
|
-
_ts: entry.timestamp,
|
|
52
|
-
_iv: iv,
|
|
53
|
-
_data: data
|
|
54
|
-
};
|
|
47
|
+
const { iv, data } = await encrypt(json, dek, buildRecordAad(identity));
|
|
48
|
+
return buildRecordEnvelope(identity, { ...body, iv, data });
|
|
55
49
|
}
|
|
56
|
-
async function decryptEntry(envelope, encrypted, getDEK) {
|
|
50
|
+
async function decryptEntry(id, envelope, encrypted, getDEK) {
|
|
57
51
|
if (!encrypted) return JSON.parse(envelope._data);
|
|
58
|
-
const json = await openEnvelopeJson(envelope, await getDEK(CONSENT_AUDIT_COLLECTION));
|
|
52
|
+
const json = await openEnvelopeJson({ collection: CONSENT_AUDIT_COLLECTION, id }, envelope, await getDEK(CONSENT_AUDIT_COLLECTION));
|
|
59
53
|
return JSON.parse(json);
|
|
60
54
|
}
|
|
61
55
|
function matchesFilter(entry, f) {
|
|
@@ -72,4 +66,4 @@ export {
|
|
|
72
66
|
writeConsentEntry,
|
|
73
67
|
loadConsentEntries
|
|
74
68
|
};
|
|
75
|
-
//# sourceMappingURL=chunk-
|
|
69
|
+
//# sourceMappingURL=chunk-MTBXJAS4.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-audit/consent/consent.ts"],"sourcesContent":["/**\n * Consent boundaries — per-access audit log.\n *\n * ```ts\n * const audit = await vault.withConsent(\n * { purpose: 'quarterly-review', consentHash: '7f3a...' },\n * async () => {\n * const invoices = await vault.collection<Invoice>('invoices').list()\n * return invoices\n * },\n * )\n *\n * const log = await vault.consentAudit({ since: '2026-01-01T00:00:00Z' })\n * // → entries: { actor, purpose, consentHash, ts, op, collection, id }\n * ```\n *\n * ## Contract\n *\n * Every `get` / `put` / `delete` that happens inside a `withConsent`\n * callback writes one entry to the reserved `_consent_audit`\n * collection. Entries are encrypted with the vault's consent-audit\n * DEK (separate from per-user-collection DEKs so access-log queries\n * don't require unwrapping individual collection keys). Outside a\n * `withConsent` scope, no entries are written — consent is\n * opt-in by design (GDPR Art. 7: *demonstrable*, *specific*\n * consent).\n *\n * ## Why store the hash, not the consent text?\n *\n * The `consentHash` is the sha256 of whatever consent receipt the\n * actor presented (a signed GDPR banner click, a HIPAA authorisation\n * PDF, an API-level `X-Consent-Hash` header). Storing only the hash:\n *\n * 1. Keeps the audit log small and indexable.\n * 2. Preserves zero-knowledge at the adapter — adapters see\n * ciphertext envelopes of `{ actor, purpose, consentHash, ts,\n * op, collection, id }`, never the consent record itself.\n * 3. Lets the regulator verify a presented consent doc matches\n * the logged hash at audit time without the system ever\n * possessing the doc.\n *\n * ## Concurrency\n *\n * The consent context lives on the {@link Vault} instance. Two\n * concurrent `withConsent` calls on the same Vault would stomp each\n * other — documented limitation; adopters needing per-flight scope\n * should use separate Vault instances or an AsyncLocalStorage shim.\n *\n * @module\n */\nimport type { EncryptedEnvelope, NoydbStore } from '../../kernel/types.js'\nimport { buildRecordAad, buildRecordEnvelope, encrypt, openEnvelopeJson, type EnclaveKey } from '../../kernel/enclave/index.js'\nimport { generateULID } from '../../with-pod/ulid.js'\n\n/** Reserved collection for consent-audit entries. */\nexport const CONSENT_AUDIT_COLLECTION = '_consent_audit'\n\n/**\n * The consent scope active for a block of work. Set via\n * `vault.withConsent()`; observed by the collection's access hooks.\n */\nexport interface ConsentContext {\n /**\n * What this access is for. Used by the audit query (`consentAudit\n * ({ purpose })`) and carried in the stored entry. Free-form; the\n * regulator or compliance tooling decides the vocabulary.\n */\n readonly purpose: string\n /**\n * Hex-encoded sha256 of whatever consent artefact the actor\n * presented. Stored as-is in each entry.\n */\n readonly consentHash: string\n}\n\n/**\n * Access operation recorded in an audit entry.\n *\n * Union-widening checklist (I-2) — these three sites widen together or a\n * downstream exhaustive switch breaks at its next in-range minor:\n * 1. `ConsentOp` here (public, re-exported at `index.ts`).\n * 2. `onAccess` op union on `kernel/collection-config.ts`.\n * 3. classified ctx `onAccess` op union on `port/with/classified-strategy.ts`\n * (the `ClassifiedVerifyCtx` one — the `ClassifiedRevealCtx` one stays `'reveal'`-only).\n */\nexport type ConsentOp = 'get' | 'put' | 'delete' | 'reveal' | 'verify' | 'find'\n\n/** One consent-audit record, as decrypted for the caller. */\nexport interface ConsentAuditEntry {\n /** ULID — stable insertion-order key. */\n readonly id: string\n readonly timestamp: string\n readonly actor: string\n readonly purpose: string\n readonly consentHash: string\n readonly op: ConsentOp\n readonly collection: string\n readonly recordId: string\n}\n\n/** Filter passed to `vault.consentAudit()`. */\nexport interface ConsentAuditFilter {\n /** Only entries at or after this ISO timestamp. */\n readonly since?: string\n /** Only entries at or before this ISO timestamp. */\n readonly until?: string\n /** Match entries targeting this collection. */\n readonly collection?: string\n /** Match entries written by this actor. */\n readonly actor?: string\n /** Match entries with this purpose. */\n readonly purpose?: string\n}\n\n/**\n * Write one audit entry. Called by Vault's onAccess hook when a\n * consent context is active.\n */\nexport async function writeConsentEntry(\n adapter: NoydbStore,\n vault: string,\n encrypted: boolean,\n entry: Omit<ConsentAuditEntry, 'id' | 'timestamp'>,\n getDEK: (collection: string) => Promise<EnclaveKey>,\n): Promise<void> {\n const id = generateULID()\n const full: ConsentAuditEntry = {\n id,\n timestamp: new Date().toISOString(),\n ...entry,\n }\n const envelope = await buildEnvelope(full, encrypted, getDEK)\n await adapter.put(vault, CONSENT_AUDIT_COLLECTION, id, envelope)\n}\n\n/** Load + decrypt + filter all entries. */\nexport async function loadConsentEntries(\n adapter: NoydbStore,\n vault: string,\n encrypted: boolean,\n getDEK: (collection: string) => Promise<EnclaveKey>,\n filter: ConsentAuditFilter = {},\n): Promise<ConsentAuditEntry[]> {\n const ids = await adapter.list(vault, CONSENT_AUDIT_COLLECTION)\n const entries: ConsentAuditEntry[] = []\n\n for (const id of ids.sort()) {\n const envelope = await adapter.get(vault, CONSENT_AUDIT_COLLECTION, id)\n if (!envelope) continue\n const entry = await decryptEntry(id, envelope, encrypted, getDEK)\n if (!matchesFilter(entry, filter)) continue\n entries.push(entry)\n }\n return entries\n}\n\n// ── internals ──────────────────────────────────────────────────────\n\nasync function buildEnvelope(\n entry: ConsentAuditEntry,\n encrypted: boolean,\n getDEK: (collection: string) => Promise<EnclaveKey>,\n): Promise<EncryptedEnvelope> {\n const json = JSON.stringify(entry)\n // `entry.id` IS the record id the caller writes under, so identity needs no\n // threading here (#1051).\n const identity = { collection: CONSENT_AUDIT_COLLECTION, id: entry.id, version: 1 }\n const body = { ts: entry.timestamp }\n if (!encrypted) {\n return buildRecordEnvelope(identity, { ...body, iv: '', data: json })\n }\n const dek = await getDEK(CONSENT_AUDIT_COLLECTION)\n const { iv, data } = await encrypt(json, dek, buildRecordAad(identity))\n return buildRecordEnvelope(identity, { ...body, iv, data })\n}\n\nasync function decryptEntry(\n id: string,\n envelope: EncryptedEnvelope,\n encrypted: boolean,\n getDEK: (collection: string) => Promise<EnclaveKey>,\n): Promise<ConsentAuditEntry> {\n if (!encrypted) return JSON.parse(envelope._data) as ConsentAuditEntry\n const json = await openEnvelopeJson({ collection: CONSENT_AUDIT_COLLECTION, id }, envelope, await getDEK(CONSENT_AUDIT_COLLECTION))\n return JSON.parse(json) as ConsentAuditEntry\n}\n\nfunction matchesFilter(entry: ConsentAuditEntry, f: ConsentAuditFilter): boolean {\n if (f.since && entry.timestamp < f.since) return false\n if (f.until && entry.timestamp > f.until) return false\n if (f.collection && entry.collection !== f.collection) return false\n if (f.actor && entry.actor !== f.actor) return false\n if (f.purpose && entry.purpose !== f.purpose) return false\n return true\n}\n"],"mappings":";;;;;;;;;;;;;;;AAuDO,IAAM,2BAA2B;AA+DxC,eAAsB,kBACpB,SACA,OACA,WACA,OACA,QACe;AACf,QAAM,KAAK,aAAa;AACxB,QAAM,OAA0B;AAAA,IAC9B;AAAA,IACA,YAAW,oBAAI,KAAK,GAAE,YAAY;AAAA,IAClC,GAAG;AAAA,EACL;AACA,QAAM,WAAW,MAAM,cAAc,MAAM,WAAW,MAAM;AAC5D,QAAM,QAAQ,IAAI,OAAO,0BAA0B,IAAI,QAAQ;AACjE;AAGA,eAAsB,mBACpB,SACA,OACA,WACA,QACA,SAA6B,CAAC,GACA;AAC9B,QAAM,MAAM,MAAM,QAAQ,KAAK,OAAO,wBAAwB;AAC9D,QAAM,UAA+B,CAAC;AAEtC,aAAW,MAAM,IAAI,KAAK,GAAG;AAC3B,UAAM,WAAW,MAAM,QAAQ,IAAI,OAAO,0BAA0B,EAAE;AACtE,QAAI,CAAC,SAAU;AACf,UAAM,QAAQ,MAAM,aAAa,IAAI,UAAU,WAAW,MAAM;AAChE,QAAI,CAAC,cAAc,OAAO,MAAM,EAAG;AACnC,YAAQ,KAAK,KAAK;AAAA,EACpB;AACA,SAAO;AACT;AAIA,eAAe,cACb,OACA,WACA,QAC4B;AAC5B,QAAM,OAAO,KAAK,UAAU,KAAK;AAGjC,QAAM,WAAW,EAAE,YAAY,0BAA0B,IAAI,MAAM,IAAI,SAAS,EAAE;AAClF,QAAM,OAAO,EAAE,IAAI,MAAM,UAAU;AACnC,MAAI,CAAC,WAAW;AACd,WAAO,oBAAoB,UAAU,EAAE,GAAG,MAAM,IAAI,IAAI,MAAM,KAAK,CAAC;AAAA,EACtE;AACA,QAAM,MAAM,MAAM,OAAO,wBAAwB;AACjD,QAAM,EAAE,IAAI,KAAK,IAAI,MAAM,QAAQ,MAAM,KAAK,eAAe,QAAQ,CAAC;AACtE,SAAO,oBAAoB,UAAU,EAAE,GAAG,MAAM,IAAI,KAAK,CAAC;AAC5D;AAEA,eAAe,aACb,IACA,UACA,WACA,QAC4B;AAC5B,MAAI,CAAC,UAAW,QAAO,KAAK,MAAM,SAAS,KAAK;AAChD,QAAM,OAAO,MAAM,iBAAiB,EAAE,YAAY,0BAA0B,GAAG,GAAG,UAAU,MAAM,OAAO,wBAAwB,CAAC;AAClI,SAAO,KAAK,MAAM,IAAI;AACxB;AAEA,SAAS,cAAc,OAA0B,GAAgC;AAC/E,MAAI,EAAE,SAAS,MAAM,YAAY,EAAE,MAAO,QAAO;AACjD,MAAI,EAAE,SAAS,MAAM,YAAY,EAAE,MAAO,QAAO;AACjD,MAAI,EAAE,cAAc,MAAM,eAAe,EAAE,WAAY,QAAO;AAC9D,MAAI,EAAE,SAAS,MAAM,UAAU,EAAE,MAAO,QAAO;AAC/C,MAAI,EAAE,WAAW,MAAM,YAAY,EAAE,QAAS,QAAO;AACrD,SAAO;AACT;","names":[]}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {
|
|
2
|
+
NOYDB_FORMAT_VERSION
|
|
3
|
+
} from "./chunk-RK7N4OQ5.js";
|
|
4
|
+
|
|
5
|
+
// src/kernel/enclave/record-envelope.ts
|
|
6
|
+
function buildRecordEnvelope(identity, body) {
|
|
7
|
+
return {
|
|
8
|
+
_noydb: NOYDB_FORMAT_VERSION,
|
|
9
|
+
_v: identity.version,
|
|
10
|
+
_ts: body.ts ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
11
|
+
_iv: body.iv,
|
|
12
|
+
_data: body.data,
|
|
13
|
+
...identity.by !== void 0 ? { _by: identity.by } : {},
|
|
14
|
+
...identity.tier !== void 0 && identity.tier > 0 ? { _tier: identity.tier } : {},
|
|
15
|
+
...body.cek !== void 0 ? { _cek: body.cek } : {},
|
|
16
|
+
...body.provenance !== void 0 ? { _source: body.provenance.source, _sourceTs: body.provenance.sourceTs } : {},
|
|
17
|
+
...body.extra ?? {}
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
async function buildSealedRecordEnvelope(identity, seal, body) {
|
|
21
|
+
const sealed = await seal(identity);
|
|
22
|
+
return buildRecordEnvelope(identity, {
|
|
23
|
+
...body,
|
|
24
|
+
iv: sealed._iv,
|
|
25
|
+
data: sealed._data,
|
|
26
|
+
cek: sealed._cek
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// src/kernel/enclave/record-keys/tombstone.ts
|
|
31
|
+
function isTombstoneShape(envelope) {
|
|
32
|
+
return envelope._data === "" && envelope._cek === void 0 && envelope._del !== true;
|
|
33
|
+
}
|
|
34
|
+
function isTombstone(envelope, encrypted) {
|
|
35
|
+
if (!encrypted) return false;
|
|
36
|
+
return isTombstoneShape(envelope);
|
|
37
|
+
}
|
|
38
|
+
function buildTombstone(ref, version, actor) {
|
|
39
|
+
return buildRecordEnvelope(
|
|
40
|
+
{ ...ref, version, ...actor ? { by: actor } : {} },
|
|
41
|
+
{ iv: "", data: "" }
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
function isDeleteMarker(envelope) {
|
|
45
|
+
return envelope._del === true;
|
|
46
|
+
}
|
|
47
|
+
function buildDeleteMarker(ref, version, actor) {
|
|
48
|
+
return {
|
|
49
|
+
...buildRecordEnvelope(
|
|
50
|
+
{ ...ref, version, ...actor ? { by: actor } : {} },
|
|
51
|
+
{ iv: "", data: "" }
|
|
52
|
+
),
|
|
53
|
+
_del: true
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export {
|
|
58
|
+
buildRecordEnvelope,
|
|
59
|
+
buildSealedRecordEnvelope,
|
|
60
|
+
isTombstoneShape,
|
|
61
|
+
isTombstone,
|
|
62
|
+
buildTombstone,
|
|
63
|
+
isDeleteMarker,
|
|
64
|
+
buildDeleteMarker
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=chunk-N4CNVSUF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/kernel/enclave/record-envelope.ts","../src/kernel/enclave/record-keys/tombstone.ts"],"sourcesContent":["/**\n * The one place an `EncryptedEnvelope` is constructed (#1051).\n *\n * ## Why this exists\n *\n * 49 files built envelopes with an object literal, bypassing\n * `RecordCodec.buildEnvelope` (which had 4 callers). That is **writer\n * fan-out**: N independent places each had to know the envelope contract, and\n * nothing checked that they agreed.\n *\n * It only became load-bearing with #1041. Binding a record's identity into the\n * AEAD requires every writer to supply that identity — and a writer that\n * doesn't produces data the reader rejects. Reader fan-out you fix by threading\n * an argument through call sites; **writer fan-out cannot be migrated\n * incrementally**, because the first migrated writer emits envelopes the\n * unmigrated readers refuse.\n *\n * ## Why adopting it is safe\n *\n * `identity` is **required but not yet used**. Output is byte-identical to the\n * literals it replaces, so every producer can migrate independently and the\n * existing suite verifies each step. The behaviour change happens **once**,\n * when AAD is switched on here — by which point every writer already supplies\n * identity, and the compiler proved it.\n *\n * That ordering is deliberate: a required-but-unused parameter converts \"did\n * we find every writer?\" from a question into a compile error, the same trick\n * that made the `NOYDB_FORMAT_VERSION` single-sourcing safe in #1048.\n *\n * @packageDocumentation\n */\nimport { NOYDB_FORMAT_VERSION } from '../types.js'\nimport type { EncryptedEnvelope } from '../types.js'\nimport type { RecordIdentity } from './record-aad.js'\n\n/** The body an envelope carries, independent of who is writing it. */\nexport interface RecordEnvelopeBody {\n /** AES-GCM IV, base64. Empty string for a plaintext or tombstone envelope. */\n readonly iv: string\n /** Ciphertext (or plaintext JSON when the collection stores plaintext). */\n readonly data: string\n /** ISO timestamp. Defaults to now — pass it when the caller has a real one. */\n readonly ts?: string | undefined\n /** Wrapped per-record CEK, when the record has one. */\n readonly cek?: string | undefined\n readonly provenance?: { readonly source: string; readonly sourceTs: string } | undefined\n /**\n * Slots the envelope may additionally carry.\n *\n * `_tier`, `_by` and `_v` are deliberately NOT here — they come from\n * `identity`, which is the single source for all three. See\n * {@link buildRecordEnvelope}.\n */\n readonly extra?: Partial<Pick<EncryptedEnvelope, '_det' | '_sealed' | '_vdig' | '_bidx'>> | undefined\n}\n\n/**\n * Build an envelope for `identity`.\n *\n * ## `identity` is the SINGLE SOURCE for `_by`, `_tier` and `_v`\n *\n * All three are stamped from it, and `RecordEnvelopeBody` deliberately cannot\n * carry them. That is not tidiness — it is what makes the AAD binding safe.\n *\n * The caller encrypts the body under AAD derived from `{collection, id, tier,\n * by, version}`. A reader recomputes that AAD from the address it fetched from\n * plus `_tier`/`_by`/`_v` read back **off the envelope** (`recordAadFor`). So if the\n * identity a writer *declares* could differ from the fields it *stamps*, the\n * AAD would not reproduce and the record would be undecryptable — silently, at\n * write time, discoverable only on the next read, and invisible to every gate\n * because the envelope is perfectly well-formed.\n *\n * An earlier draft took both and asserted they agreed. The assertion fired 230\n * times on the existing tree, which is the argument against it: a rule that can\n * be violated is a rule someone must remember. Taking one source removes the\n * violation instead of reporting it.\n */\nexport function buildRecordEnvelope(\n identity: RecordIdentity,\n body: RecordEnvelopeBody,\n): EncryptedEnvelope {\n return {\n _noydb: NOYDB_FORMAT_VERSION,\n _v: identity.version,\n _ts: body.ts ?? new Date().toISOString(),\n _iv: body.iv,\n _data: body.data,\n ...(identity.by !== undefined ? { _by: identity.by } : {}),\n ...(identity.tier !== undefined && identity.tier > 0 ? { _tier: identity.tier } : {}),\n ...(body.cek !== undefined ? { _cek: body.cek } : {}),\n ...(body.provenance !== undefined\n ? { _source: body.provenance.source, _sourceTs: body.provenance.sourceTs }\n : {}),\n ...(body.extra ?? {}),\n }\n}\n\n/**\n * Build an envelope from an already-sealed body — the output of\n * `writeEnvelopeBody` — **without the caller ever naming `_iv`/`_data`/`_cek`**.\n *\n * This exists because of a guard, and the guard was right. Migrating\n * `writeEnvelopeBody` callers to {@link buildRecordEnvelope} meant rewriting\n * `...body` (a spread, which names nothing) into `iv: body._iv, data:\n * body._data, cek: body._cek` — and `enclave-body-only` failed it: three new\n * protected-body accesses in files that previously had zero.\n *\n * That is the correct outcome rather than an obstacle. #1051 exists to move\n * knowledge of the envelope's shape *inward*; a migration that spreads the\n * protected field names outward to every caller would have defeated its own\n * purpose while looking like progress. The pairing belongs here.\n *\n * ## It takes a SEALER, not a sealed body — and that is load-bearing (#1041)\n *\n * The obvious shape is `(identity, alreadySealedBody, rest)`. That requires the\n * caller to name the identity TWICE — once for `writeEnvelopeBody` and once\n * here — and the two must agree byte for byte or the record is sealed under\n * AAD no reader can reproduce.\n *\n * They did not agree. `with-party/broker/seed.ts` sealed against\n * `{collection, id}` and stamped `{collection, id, by}`, so every broker seed\n * became unreadable the moment AAD switched on. Taking the sealer means the\n * identity is written once and handed to both — divergence stops being\n * possible rather than being something to remember.\n */\nexport async function buildSealedRecordEnvelope(\n identity: RecordIdentity,\n seal: (identity: RecordIdentity) => Promise<Pick<EncryptedEnvelope, '_iv' | '_data' | '_cek'>>,\n body: Omit<RecordEnvelopeBody, 'iv' | 'data' | 'cek'>,\n): Promise<EncryptedEnvelope> {\n const sealed = await seal(identity)\n return buildRecordEnvelope(identity, {\n ...body,\n iv: sealed._iv,\n data: sealed._data,\n cek: sealed._cek,\n })\n}\n","/**\n * Tombstone shape + predicate for the per-record-key (CEK) layer.\n *\n * A *tombstone* is the residue a GDPR crypto-shred (`vault.forget()`)\n * leaves on disk: the live envelope rewritten to `{ _noydb, _v, _ts, _by,\n * _iv:'', _data:'' }`, dropping `_iv`/`_data`/`_cek`/`_det`. With the wrapped\n * per-record CEK gone, the body — and every history version under the same\n * CEK — is permanently undecryptable, while the record KEY survives so the\n * version counter and \"record existed and was erased\" persist for the audit\n * ledger.\n *\n * These two helpers are the pure, collection-independent core of that\n * contract: {@link buildTombstone} mints the shape, {@link isTombstone}\n * recognises it on the read path. The orchestration that *writes* a tombstone\n * (`_writeTombstone`) and drives `vault.forget()` lives with the collection /\n * vault; it calls into these.\n */\nimport { type EncryptedEnvelope } from '../../types.js'\nimport { buildRecordEnvelope } from '../record-envelope.js'\nimport type { RecordRef } from '../record-aad.js'\n\n/**\n * Shape-only tombstone recognition for layers that have no per-collection\n * context (the sync engine, #590): a tombstone carries an empty `_data` and\n * no wrapped CEK. No live envelope can match — record bodies never serialize\n * to the empty string (the `_sync` meta envelope carries non-empty `_data`,\n * and legacy migration envelopes carry non-empty `_iv`/`_data`).\n */\nexport function isTombstoneShape(envelope: EncryptedEnvelope): boolean {\n return envelope._data === '' && envelope._cek === undefined && envelope._del !== true\n}\n\n/**\n * Is this envelope a crypto-shred tombstone?\n *\n * A tombstone carries no body (`_data` empty) and no wrapped CEK (`_cek`\n * absent) — decrypting it would call `decrypt('', '', dek)` → an AES-GCM\n * throw, so every read choke point must short-circuit to `null` instead.\n *\n * `encrypted` is the collection's encryption flag: on an unencrypted\n * collection there are no envelopes to shred, so nothing is ever a tombstone.\n * (Legacy migration envelopes carry non-empty `_iv`/`_data`, so they are not\n * tombstones and stay readable.)\n */\nexport function isTombstone(envelope: EncryptedEnvelope, encrypted: boolean): boolean {\n if (!encrypted) return false\n return isTombstoneShape(envelope)\n}\n\n/**\n * Mint a tombstone envelope from a record's live version + actor.\n *\n * Keeps `_v` (the displaced version) so the counter is monotonic across the\n * shred, stamps a fresh `_ts`, and records `_by` when an actor is supplied.\n * Deliberately omits `_iv`/`_data`/`_cek`/`_det` — that omission *is* the\n * erasure.\n */\nexport function buildTombstone(\n ref: RecordRef,\n version: number,\n actor: string,\n): EncryptedEnvelope {\n // `actor` rides on the IDENTITY, not the body — it is stamped as `_by` and\n // bound into the AAD from that one source (#1041).\n return buildRecordEnvelope(\n { ...ref, version, ...(actor ? { by: actor } : {}) },\n { iv: '', data: '' },\n )\n}\n\n/** #589: is this envelope an ordinary-delete marker (version-ordered, reads as absent)? */\nexport function isDeleteMarker(envelope: EncryptedEnvelope): boolean {\n return envelope._del === true\n}\n\n/**\n * Mint a delete marker from the deleted record's next version + actor (#589).\n * Minted at the NEXT version (`existing._v + 1`) — unlike `buildTombstone`, which\n * keeps the displaced `_v` — so it wins convergence over the pre-delete copy and a\n * re-create can still win over it at a higher version.\n */\nexport function buildDeleteMarker(\n ref: RecordRef,\n version: number,\n actor: string,\n): EncryptedEnvelope {\n // `_del` is not one of buildRecordEnvelope's declared slots — a delete marker\n // is a distinct envelope class, not a record body — so it is stamped here.\n return {\n ...buildRecordEnvelope(\n { ...ref, version, ...(actor ? { by: actor } : {}) },\n { iv: '', data: '' },\n ),\n _del: true,\n }\n}\n"],"mappings":";;;;;AA6EO,SAAS,oBACd,UACA,MACmB;AACnB,SAAO;AAAA,IACL,QAAQ;AAAA,IACR,IAAI,SAAS;AAAA,IACb,KAAK,KAAK,OAAM,oBAAI,KAAK,GAAE,YAAY;AAAA,IACvC,KAAK,KAAK;AAAA,IACV,OAAO,KAAK;AAAA,IACZ,GAAI,SAAS,OAAO,SAAY,EAAE,KAAK,SAAS,GAAG,IAAI,CAAC;AAAA,IACxD,GAAI,SAAS,SAAS,UAAa,SAAS,OAAO,IAAI,EAAE,OAAO,SAAS,KAAK,IAAI,CAAC;AAAA,IACnF,GAAI,KAAK,QAAQ,SAAY,EAAE,MAAM,KAAK,IAAI,IAAI,CAAC;AAAA,IACnD,GAAI,KAAK,eAAe,SACpB,EAAE,SAAS,KAAK,WAAW,QAAQ,WAAW,KAAK,WAAW,SAAS,IACvE,CAAC;AAAA,IACL,GAAI,KAAK,SAAS,CAAC;AAAA,EACrB;AACF;AA8BA,eAAsB,0BACpB,UACA,MACA,MAC4B;AAC5B,QAAM,SAAS,MAAM,KAAK,QAAQ;AAClC,SAAO,oBAAoB,UAAU;AAAA,IACnC,GAAG;AAAA,IACH,IAAI,OAAO;AAAA,IACX,MAAM,OAAO;AAAA,IACb,KAAK,OAAO;AAAA,EACd,CAAC;AACH;;;AC7GO,SAAS,iBAAiB,UAAsC;AACrE,SAAO,SAAS,UAAU,MAAM,SAAS,SAAS,UAAa,SAAS,SAAS;AACnF;AAcO,SAAS,YAAY,UAA6B,WAA6B;AACpF,MAAI,CAAC,UAAW,QAAO;AACvB,SAAO,iBAAiB,QAAQ;AAClC;AAUO,SAAS,eACd,KACA,SACA,OACmB;AAGnB,SAAO;AAAA,IACL,EAAE,GAAG,KAAK,SAAS,GAAI,QAAQ,EAAE,IAAI,MAAM,IAAI,CAAC,EAAG;AAAA,IACnD,EAAE,IAAI,IAAI,MAAM,GAAG;AAAA,EACrB;AACF;AAGO,SAAS,eAAe,UAAsC;AACnE,SAAO,SAAS,SAAS;AAC3B;AAQO,SAAS,kBACd,KACA,SACA,OACmB;AAGnB,SAAO;AAAA,IACL,GAAG;AAAA,MACD,EAAE,GAAG,KAAK,SAAS,GAAI,QAAQ,EAAE,IAAI,MAAM,IAAI,CAAC,EAAG;AAAA,MACnD,EAAE,IAAI,IAAI,MAAM,GAAG;AAAA,IACrB;AAAA,IACA,MAAM;AAAA,EACR;AACF;","names":[]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
IllegalTransitionError,
|
|
3
3
|
RecordLockedError,
|
|
4
4
|
ValidationError
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-JBIV4FLR.js";
|
|
6
6
|
|
|
7
7
|
// src/with-audit/guards/with-guard.ts
|
|
8
8
|
function withGuard(strategy) {
|
|
@@ -124,4 +124,4 @@ export {
|
|
|
124
124
|
immutableGuard,
|
|
125
125
|
transitionGuard
|
|
126
126
|
};
|
|
127
|
-
//# sourceMappingURL=chunk-
|
|
127
|
+
//# sourceMappingURL=chunk-NLKLXXTO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/kernel/query/predicate.ts"],"sourcesContent":["/**\n * Operator implementations for the query DSL.\n *\n * All predicates run client-side, AFTER decryption — they never see ciphertext.\n * Field clauses over a Via-covered field (e.g. money) carry their own\n * evaluator closure (see {@link FieldClause.via}), so this module has no\n * dependency on any Via feature's implementation — still tree-shakeable.\n */\n\n/** Comparison operators supported by the where() builder. */\nexport type Operator =\n | '=='\n | '!='\n | '<'\n | '<='\n | '>'\n | '>='\n | 'in'\n | 'contains'\n | 'startsWith'\n | 'between'\n\n/**\n * A single field comparison clause inside a query plan.\n * Plans are JSON-serializable, so this type uses primitives only.\n */\nexport interface FieldClause {\n readonly type: 'field'\n readonly field: string\n readonly op: Operator\n readonly value: unknown\n /**\n * Present when `field` is covered by a Via feature binding (e.g. a\n * declared money field): the opaque payload built by the binding's\n * `buildClause` at query BUILD time, plus a closure that evaluates it\n * per record via the binding's `evaluateClause`. Attached by\n * `Query.where()` / `ScanBuilder.where()` when `source.via` covers the\n * field. The closure keeps this module free of any dependency on a\n * Via feature's implementation — clauses are in-memory only, never\n * serialized, so carrying a function here is safe.\n */\n readonly via?: {\n readonly brand: string\n readonly payload: unknown\n readonly evaluate: (actual: unknown, op: string) => boolean\n /**\n * The binding's `indexProbe` result for this clause's op/payload\n * (#625) — the STORED-form operand `candidateRecords()` (`kernel/\n * query/builder.ts`) can hand to `CollectionIndexes.lookupEqual`/\n * `lookupIn` for a fast path. `undefined` (no `indexProbe` hook, or\n * the binding declined to probe this op) means the field must fall\n * back to a linear scan via `evaluate` above.\n */\n readonly indexValue?: unknown\n }\n}\n\n/**\n * A user-supplied predicate function escape hatch. Not serializable.\n *\n * The predicate accepts `unknown` at the type level so the surrounding\n * Clause type can stay non-parametric — this keeps Collection<T> covariant\n * in T at the public API surface. Builder methods cast user predicates\n * (typed `(record: T) => boolean`) into this shape on the way in.\n */\nexport interface FilterClause {\n readonly type: 'filter'\n readonly fn: (record: unknown) => boolean\n}\n\n/**\n * A declared deterministic predicate reference. The query\n * builder produces this via `.wherePredicate(name, ctx?)` when a\n * Query has been augmented with a predicates map (typically by the\n * materialized-view registry).\n *\n * `predicateHash` is the consumer-supplied stable hash for the\n * function body; `ctxHash` is the canonical-JSON SHA-256 of `ctx`.\n * Both fold into the MV's `queryHash` so a function or ctx change\n * forces refresh on next visit.\n *\n * `fn` is resolved at builder time from the predicates map and\n * embedded directly — so `evaluateClause` can fire it without a\n * runtime lookup.\n */\nexport interface WherePredicateClause {\n readonly type: 'wherePredicate'\n readonly name: string\n readonly ctx: unknown\n readonly predicateHash: string\n readonly ctxHash: string\n readonly fn: (record: unknown, ctx?: unknown) => boolean\n}\n\n/** A logical group of clauses combined by AND or OR. */\nexport interface GroupClause {\n readonly type: 'group'\n readonly op: 'and' | 'or'\n readonly clauses: readonly Clause[]\n}\n\n/**\n * Cartesian-product expansion clause. Appended to `QueryPlan.clauses`\n * by `Query.crossJoin()`. Processed in declaration order by\n * `executeClausePipeline` — NOT by `evaluateClause` (which is a\n * per-record predicate and throws on this type).\n */\nexport interface CrossJoinClause {\n readonly type: 'crossJoin'\n /** Target collection name to cross-join against. */\n readonly target: string\n /** Alias under which the right-side record is exposed on each result row. */\n readonly as: string\n /**\n * Lateral filter callback. `undefined` → full cartesian product.\n * Two call shapes:\n * - Subset: `(left) => TTarget[]` — returns the right rows for this left row\n * - Predicate: `(left) => (right) => boolean` — executor materializes then filters\n */\n readonly on?: (left: unknown) => unknown[] | ((right: unknown) => boolean)\n /** When `on:` was supplied as `{ predicate: name }`, the name is stored here for queryHash. */\n readonly onPredicateName?: string\n /** Per-clause row ceiling override. `undefined` → `DEFAULT_CROSS_JOIN_MAX_ROWS`. */\n readonly maxRows?: number\n /**\n * Left-outer mode (#1130). When the `on:` subset for a left row is empty,\n * emit that row once with `null` under `as` instead of dropping it.\n *\n * Applies to both call shapes. With `on:` the empty thing is that left\n * row's subset; without it, an empty TARGET collection is what would\n * otherwise drop every left row.\n */\n readonly outer?: boolean\n}\n\nexport type Clause = FieldClause | FilterClause | WherePredicateClause | GroupClause | CrossJoinClause\n\n/**\n * Read a possibly nested field path like \"address.city\" from a record.\n * Returns undefined if any segment is missing.\n */\nexport function readPath(record: unknown, path: string): unknown {\n if (record === null || record === undefined) return undefined\n if (!path.includes('.')) {\n return (record as Record<string, unknown>)[path]\n }\n const segments = path.split('.')\n let cursor: unknown = record\n for (const segment of segments) {\n if (cursor === null || cursor === undefined) return undefined\n cursor = (cursor as Record<string, unknown>)[segment]\n }\n return cursor\n}\n\n/**\n * Evaluate a single field clause against a record.\n * Returns false on type mismatches rather than throwing — query results\n * exclude non-matching records by definition.\n */\nexport function evaluateFieldClause(record: unknown, clause: FieldClause): boolean {\n const actual = readPath(record, clause.field)\n const { op, value } = clause\n\n // A Via-covered field (e.g. money) may store a transformed\n // representation (money: BigInt-exact in scaled-integer space) that the\n // generic paths below can't compare correctly — the operand was\n // pre-built at query BUILD time and the binding's own evaluator knows\n // how to compare it against the raw stored value.\n if (clause.via) return clause.via.evaluate(actual, op)\n\n switch (op) {\n case '==':\n return actual === value\n case '!=':\n return actual !== value\n case '<':\n return isComparable(actual, value) && (actual as number) < (value as number)\n case '<=':\n return isComparable(actual, value) && (actual as number) <= (value as number)\n case '>':\n return isComparable(actual, value) && (actual as number) > (value as number)\n case '>=':\n return isComparable(actual, value) && (actual as number) >= (value as number)\n case 'in':\n return Array.isArray(value) && value.includes(actual)\n case 'contains':\n if (typeof actual === 'string') return typeof value === 'string' && actual.includes(value)\n if (Array.isArray(actual)) return actual.includes(value)\n return false\n case 'startsWith':\n return typeof actual === 'string' && typeof value === 'string' && actual.startsWith(value)\n case 'between': {\n if (!Array.isArray(value) || value.length !== 2) return false\n const [lo, hi] = value\n if (!isComparable(actual, lo) || !isComparable(actual, hi)) return false\n return (actual as number) >= (lo as number) && (actual as number) <= (hi as number)\n }\n default: {\n // Exhaustiveness — TS will error if a new operator is added without a case.\n const _exhaustive: never = op\n void _exhaustive\n return false\n }\n }\n}\n\n/**\n * Two values are \"comparable\" if they share an order-defined runtime type.\n * Strings compare lexicographically; numbers and Dates numerically; otherwise false.\n */\nfunction isComparable(a: unknown, b: unknown): boolean {\n if (typeof a === 'number' && typeof b === 'number') return true\n if (typeof a === 'string' && typeof b === 'string') return true\n if (a instanceof Date && b instanceof Date) return true\n return false\n}\n\n/**\n * Evaluate any clause (field / filter / group) against a record.\n * The recursion depth is bounded by the user's query expression — no risk of\n * blowing the stack on a 50K-record collection.\n *\n * `fnRecord`, when provided, is the view handed to USER CALLBACK clauses\n * (`filter` / `wherePredicate`) instead of `record` — the executor passes\n * the money-decoded view there so user code never sees the stored\n * scaled-int form, while field clauses keep evaluating against the raw\n * record (their money operands are pre-quantized to that space).\n */\nexport function evaluateClause(record: unknown, clause: Clause, fnRecord?: unknown): boolean {\n switch (clause.type) {\n case 'field':\n return evaluateFieldClause(record, clause)\n case 'filter':\n return clause.fn(fnRecord !== undefined ? fnRecord : record)\n case 'wherePredicate':\n return clause.fn(fnRecord !== undefined ? fnRecord : record, clause.ctx)\n case 'crossJoin':\n throw new Error(\n `evaluateClause: 'crossJoin' clauses are expansion primitives and are not ` +\n `evaluated per-record. This is a query planner routing error — ` +\n `crossJoin clauses must be extracted from the clause list before calling ` +\n `evaluateClause or filterRecords.`,\n )\n case 'group':\n if (clause.op === 'and') {\n for (const child of clause.clauses) {\n if (!evaluateClause(record, child, fnRecord)) return false\n }\n return true\n } else {\n for (const child of clause.clauses) {\n if (evaluateClause(record, child, fnRecord)) return true\n }\n return false\n }\n }\n}\n\n/**\n * Does the clause list contain any user-callback clause (filter /\n * wherePredicate), at any group nesting depth? Used by executors to\n * decide whether the per-record decoded view needs materializing.\n */\nexport function hasFnClause(clauses: readonly Clause[]): boolean {\n for (const c of clauses) {\n if (c.type === 'filter' || c.type === 'wherePredicate') return true\n if (c.type === 'group' && hasFnClause(c.clauses)) return true\n }\n return false\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ValidationError
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JBIV4FLR.js";
|
|
4
4
|
|
|
5
5
|
// src/with-formula/overlay-views/with-overlayed-view.ts
|
|
6
6
|
function withOverlayedView(spec) {
|
|
@@ -33,4 +33,4 @@ function withOverlayedView(spec) {
|
|
|
33
33
|
export {
|
|
34
34
|
withOverlayedView
|
|
35
35
|
};
|
|
36
|
-
//# sourceMappingURL=chunk-
|
|
36
|
+
//# sourceMappingURL=chunk-OPXR4PB2.js.map
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
import {
|
|
2
|
+
SCHEMAS_COLLECTION
|
|
3
|
+
} from "./chunk-YXA2TCTZ.js";
|
|
4
|
+
import {
|
|
5
|
+
assemblePodContainer,
|
|
6
|
+
buildExtractedPartitionWrapper
|
|
7
|
+
} from "./chunk-6FOGTKBY.js";
|
|
1
8
|
import {
|
|
2
9
|
BLOB_CHUNKS_COLLECTION,
|
|
3
10
|
BLOB_COLLECTION,
|
|
@@ -5,17 +12,10 @@ import {
|
|
|
5
12
|
BLOB_INTENT_COLLECTION,
|
|
6
13
|
BLOB_SLOTS_PREFIX,
|
|
7
14
|
BLOB_VERSIONS_PREFIX
|
|
8
|
-
} from "./chunk-
|
|
9
|
-
import {
|
|
10
|
-
SCHEMAS_COLLECTION
|
|
11
|
-
} from "./chunk-CDB2HVQW.js";
|
|
12
|
-
import {
|
|
13
|
-
assembleBundleContainer,
|
|
14
|
-
buildExtractedPartitionWrapper
|
|
15
|
-
} from "./chunk-4VUPLMZ6.js";
|
|
15
|
+
} from "./chunk-ALB64CZM.js";
|
|
16
16
|
import {
|
|
17
17
|
generateULID
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-4AOERLTV.js";
|
|
19
19
|
import {
|
|
20
20
|
LEDGER_COLLECTION
|
|
21
21
|
} from "./chunk-I7FD46FF.js";
|
|
@@ -23,11 +23,16 @@ import {
|
|
|
23
23
|
canonicalJson,
|
|
24
24
|
envelopePayloadHash,
|
|
25
25
|
hashEntry
|
|
26
|
-
} from "./chunk-
|
|
26
|
+
} from "./chunk-RC4BROYR.js";
|
|
27
27
|
import {
|
|
28
|
+
buildRecordAad,
|
|
28
29
|
openEnvelopeJson,
|
|
30
|
+
recordAadFor,
|
|
29
31
|
writeEnvelopeBody
|
|
30
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-2LPVI4PX.js";
|
|
33
|
+
import {
|
|
34
|
+
buildRecordEnvelope
|
|
35
|
+
} from "./chunk-N4CNVSUF.js";
|
|
31
36
|
import {
|
|
32
37
|
bufferToBase64,
|
|
33
38
|
decrypt,
|
|
@@ -37,14 +42,13 @@ import {
|
|
|
37
42
|
generateDEK,
|
|
38
43
|
unwrapCek,
|
|
39
44
|
wrapCek
|
|
40
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-W5LHQXZU.js";
|
|
41
46
|
import {
|
|
42
|
-
NOYDB_BACKUP_VERSION
|
|
43
|
-
|
|
44
|
-
} from "./chunk-YPYHVOXP.js";
|
|
47
|
+
NOYDB_BACKUP_VERSION
|
|
48
|
+
} from "./chunk-RK7N4OQ5.js";
|
|
45
49
|
import {
|
|
46
50
|
PartitionExtractionError
|
|
47
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-JBIV4FLR.js";
|
|
48
52
|
|
|
49
53
|
// src/with-cargo/walk-closure.ts
|
|
50
54
|
async function walkClosure(vault, opts) {
|
|
@@ -185,15 +189,16 @@ async function reKeyClosure(vault, closure, fieldProjection) {
|
|
|
185
189
|
);
|
|
186
190
|
}
|
|
187
191
|
if (env._cek !== void 0) {
|
|
192
|
+
const aad = recordAadFor({ collection: collectionName, id }, env);
|
|
188
193
|
const cek = await unwrapCek(env._cek, srcDek);
|
|
189
|
-
const plaintext2 = await decrypt(env._iv, env._data, cek);
|
|
190
|
-
const { iv: iv2, data: data2 } = await encrypt(project(plaintext2), cek);
|
|
194
|
+
const plaintext2 = await decrypt(env._iv, env._data, cek, aad);
|
|
195
|
+
const { iv: iv2, data: data2 } = await encrypt(project(plaintext2), cek, aad);
|
|
191
196
|
const wrapped = await wrapCek(cek, destDek);
|
|
192
197
|
out[id] = { ...env, _iv: iv2, _data: data2, _cek: wrapped };
|
|
193
198
|
continue;
|
|
194
199
|
}
|
|
195
|
-
const plaintext = await openEnvelopeJson(env, srcDek);
|
|
196
|
-
const { iv, data } = await encrypt(project(plaintext), destDek);
|
|
200
|
+
const plaintext = await openEnvelopeJson({ collection: collectionName, id }, env, srcDek);
|
|
201
|
+
const { iv, data } = await encrypt(project(plaintext), destDek, recordAadFor({ collection: collectionName, id }, env));
|
|
197
202
|
out[id] = { ...env, _iv: iv, _data: data };
|
|
198
203
|
}
|
|
199
204
|
collections[collectionName] = out;
|
|
@@ -210,8 +215,8 @@ async function reKeySchemas(vault, closure, destDeks, fieldProjection) {
|
|
|
210
215
|
const destDek = destDeks.get(collectionName);
|
|
211
216
|
if (!destDek) continue;
|
|
212
217
|
const srcDek = await getDEK(collectionName);
|
|
213
|
-
const plaintext = await openEnvelopeJson(env, srcDek);
|
|
214
|
-
const { iv, data } = await encrypt(plaintext, destDek);
|
|
218
|
+
const plaintext = await openEnvelopeJson({ collection: SCHEMAS_COLLECTION, id: collectionName }, env, srcDek);
|
|
219
|
+
const { iv, data } = await encrypt(plaintext, destDek, recordAadFor({ collection: SCHEMAS_COLLECTION, id: collectionName }, env));
|
|
215
220
|
out[collectionName] = { ...env, _iv: iv, _data: data };
|
|
216
221
|
}
|
|
217
222
|
return out;
|
|
@@ -225,7 +230,7 @@ async function reKeyLedger(vault, closure, reKeyedCollections, ledgerDek) {
|
|
|
225
230
|
for (const id of ids) {
|
|
226
231
|
const env = await adapter.get(vaultName, LEDGER_COLLECTION, id);
|
|
227
232
|
if (!env) continue;
|
|
228
|
-
srcEntries.push(JSON.parse(await openEnvelopeJson(env, srcLedgerDek)));
|
|
233
|
+
srcEntries.push(JSON.parse(await openEnvelopeJson({ collection: LEDGER_COLLECTION, id }, env, srcLedgerDek)));
|
|
229
234
|
}
|
|
230
235
|
const kept = srcEntries.filter(
|
|
231
236
|
(e) => (e.op === "put" || e.op === "delete") && (closure.get(e.collection)?.has(e.id) ?? false)
|
|
@@ -258,15 +263,12 @@ async function reKeyLedger(vault, closure, reKeyedCollections, ledgerDek) {
|
|
|
258
263
|
payloadHash,
|
|
259
264
|
...src.reason !== void 0 ? { reason: src.reason } : {}
|
|
260
265
|
};
|
|
261
|
-
const
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
_data: data,
|
|
268
|
-
_by: entry.actor
|
|
269
|
-
};
|
|
266
|
+
const ledgerIdentity = { collection: LEDGER_COLLECTION, id: paddedIndex(i), version: i + 1 };
|
|
267
|
+
const { iv, data } = await encrypt(canonicalJson(entry), ledgerDek, buildRecordAad(ledgerIdentity));
|
|
268
|
+
entries[paddedIndex(i)] = buildRecordEnvelope(
|
|
269
|
+
ledgerIdentity,
|
|
270
|
+
{ ts: entry.ts, iv, data }
|
|
271
|
+
);
|
|
270
272
|
prevHash = await hashEntry(entry);
|
|
271
273
|
last = entry;
|
|
272
274
|
}
|
|
@@ -305,8 +307,8 @@ async function reKeyBlobs(vault, closure, destDeks, fieldProjection) {
|
|
|
305
307
|
const intentId = `${collectionName}::${id}`;
|
|
306
308
|
const intentEnv = await adapter.get(vaultName, BLOB_INTENT_COLLECTION, intentId);
|
|
307
309
|
if (intentEnv) {
|
|
308
|
-
const intentPlain = await openEnvelopeJson(intentEnv, srcDek);
|
|
309
|
-
const intentBody = await writeEnvelopeBody(intentPlain, destDek);
|
|
310
|
+
const intentPlain = await openEnvelopeJson({ collection: BLOB_INTENT_COLLECTION, id: intentId }, intentEnv, srcDek);
|
|
311
|
+
const intentBody = await writeEnvelopeBody({ collection: BLOB_INTENT_COLLECTION, id: intentId, version: intentEnv._v }, intentPlain, destDek);
|
|
310
312
|
place(BLOB_INTENT_COLLECTION, intentId, { ...intentEnv, ...intentBody });
|
|
311
313
|
}
|
|
312
314
|
const env = await adapter.get(vaultName, slotsCollection, id);
|
|
@@ -316,7 +318,7 @@ async function reKeyBlobs(vault, closure, destDeks, fieldProjection) {
|
|
|
316
318
|
`#748: reKeyBlobs fetched an elevated slot-map envelope (collection="${slotsCollection}" id="${id}" _tier=${env._tier}) \u2014 this is unreachable by construction. Refusing to carry it into a partition.`
|
|
317
319
|
);
|
|
318
320
|
}
|
|
319
|
-
const slots = JSON.parse(await openEnvelopeJson(env, srcDek));
|
|
321
|
+
const slots = JSON.parse(await openEnvelopeJson({ collection: slotsCollection, id }, env, srcDek));
|
|
320
322
|
const kept = {};
|
|
321
323
|
for (const [slotName, slot] of Object.entries(slots)) {
|
|
322
324
|
if (proj && !proj.has(slotName)) continue;
|
|
@@ -326,7 +328,7 @@ async function reKeyBlobs(vault, closure, destDeks, fieldProjection) {
|
|
|
326
328
|
addRef(slot.eTag);
|
|
327
329
|
}
|
|
328
330
|
if (Object.keys(kept).length === 0) continue;
|
|
329
|
-
const { iv, data } = await encrypt(JSON.stringify(kept), destDek);
|
|
331
|
+
const { iv, data } = await encrypt(JSON.stringify(kept), destDek, recordAadFor({ collection: slotsCollection, id }, env));
|
|
330
332
|
place(slotsCollection, id, { ...env, _iv: iv, _data: data });
|
|
331
333
|
}
|
|
332
334
|
const versionsCollection = `${BLOB_VERSIONS_PREFIX}${collectionName}`;
|
|
@@ -342,9 +344,9 @@ async function reKeyBlobs(vault, closure, destDeks, fieldProjection) {
|
|
|
342
344
|
`#748: reKeyBlobs fetched an elevated version-record envelope (collection="${versionsCollection}" key="${key}" _tier=${env._tier}) \u2014 this is unreachable by construction. Refusing to carry it into a partition.`
|
|
343
345
|
);
|
|
344
346
|
}
|
|
345
|
-
const record = JSON.parse(await openEnvelopeJson(env, srcDek));
|
|
347
|
+
const record = JSON.parse(await openEnvelopeJson({ collection: versionsCollection, id: key }, env, srcDek));
|
|
346
348
|
addRef(record.eTag);
|
|
347
|
-
const { iv, data } = await encrypt(JSON.stringify(record), destDek);
|
|
349
|
+
const { iv, data } = await encrypt(JSON.stringify(record), destDek, recordAadFor({ collection: versionsCollection, id: key }, env));
|
|
348
350
|
place(versionsCollection, key, { ...env, _iv: iv, _data: data });
|
|
349
351
|
}
|
|
350
352
|
}
|
|
@@ -354,7 +356,7 @@ async function reKeyBlobs(vault, closure, destDeks, fieldProjection) {
|
|
|
354
356
|
for (const [eTag, refCount] of carriedRefs) {
|
|
355
357
|
const idxEnv = await adapter.get(vaultName, BLOB_INDEX_COLLECTION, eTag);
|
|
356
358
|
if (!idxEnv) continue;
|
|
357
|
-
const blob = JSON.parse(await openEnvelopeJson(idxEnv, srcBlobDek));
|
|
359
|
+
const blob = JSON.parse(await openEnvelopeJson({ collection: BLOB_INDEX_COLLECTION, id: eTag }, idxEnv, srcBlobDek));
|
|
358
360
|
let contentCek;
|
|
359
361
|
let chunksPassthrough;
|
|
360
362
|
if (blob._cek !== void 0) {
|
|
@@ -384,7 +386,7 @@ async function reKeyBlobs(vault, closure, destDeks, fieldProjection) {
|
|
|
384
386
|
const { _cekPending, ...rest } = blob;
|
|
385
387
|
void _cekPending;
|
|
386
388
|
const carried = { ...rest, refCount, _cek: await wrapCek(contentCek, transferBlobDek) };
|
|
387
|
-
const { iv, data } = await encrypt(JSON.stringify(carried), transferBlobDek);
|
|
389
|
+
const { iv, data } = await encrypt(JSON.stringify(carried), transferBlobDek, recordAadFor({ collection: BLOB_INDEX_COLLECTION, id: eTag }, idxEnv));
|
|
388
390
|
place(BLOB_INDEX_COLLECTION, eTag, { ...idxEnv, _iv: iv, _data: data });
|
|
389
391
|
}
|
|
390
392
|
return { internal, blobDek: transferBlobDek };
|
|
@@ -469,7 +471,7 @@ async function extractPartitionCore(vault, opts) {
|
|
|
469
471
|
};
|
|
470
472
|
const bodyJsonStr = JSON.stringify(buildExtractedPartitionWrapper(JSON.stringify(backup), seal));
|
|
471
473
|
const handle = generateULID();
|
|
472
|
-
const bundleBytes = await
|
|
474
|
+
const bundleBytes = await assemblePodContainer({
|
|
473
475
|
handle,
|
|
474
476
|
bodyJsonStr,
|
|
475
477
|
compression: opts.compression,
|
|
@@ -492,4 +494,4 @@ export {
|
|
|
492
494
|
extractPartition,
|
|
493
495
|
extractPartitionCore
|
|
494
496
|
};
|
|
495
|
-
//# sourceMappingURL=chunk-
|
|
497
|
+
//# sourceMappingURL=chunk-OWLVBOWO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-cargo/walk-closure.ts","../src/with-cargo/extract-partition.ts"],"sourcesContent":["/**\n * Transitive-closure FK walker. Computes the set of\n * (collection, id) tuples reachable from seed predicates, so a\n * partition extraction ships a referentially-complete subset.\n *\n * Two-phase, plaintext, read-only (runs inside the unlocked vault\n * session — see foundation §13.4 / spec invariant 7):\n * 1. INBOUND expansion: from selected records, pull every record\n * that references them (children travel with parents), to a\n * fixed point.\n * 2. OUTBOUND completion: pull every VISIBLE parent the selected set\n * references, transitively, WITHOUT re-expanding inbound from those\n * parents (bounds the closure). A tier-elevated (or missing) parent is\n * excluded rather than admitted — see `danglingRefs` on the result.\n *\n * The FK graph is auto-derived from the vault's existing RefRegistry\n * (the `ref('target')` declarations on collections) — no hand-written\n * edge list.\n *\n * @module\n */\nimport type { Vault } from '../kernel/vault.js'\nimport { PartitionExtractionError } from '../kernel/errors.js'\n\n/** Seed predicate per collection. Records that return true become roots. */\nexport interface WalkClosureOptions {\n readonly seeds: Record<\n string,\n (record: Record<string, unknown>) => boolean | Promise<boolean>\n >\n /** Max fixed-point iterations before throwing. Default 16. */\n readonly maxDepth?: number\n}\n\n/**\n * #759: an outbound FK edge whose referenced parent was excluded from the\n * closure — either because it doesn't exist, or because it is tier-elevated\n * and therefore invisible (same \"elevated ≡ missing\" semantics as root\n * selection / inbound expansion). The child keeps its FK value; the parent\n * does not travel. Callers (extract-partition) surface this as a residue\n * notice rather than silently dropping it.\n */\nexport interface DanglingRefNotice {\n /** Collection of the child record that holds the dangling FK. */\n readonly collection: string\n /** Id of the child record. */\n readonly id: string\n /** FK field on the child that references the missing/elevated parent. */\n readonly field: string\n /** Target collection the FK points at. */\n readonly target: string\n /** Id of the missing/elevated parent. */\n readonly targetId: string\n /**\n * #772: distinguishes an intentional tier boundary (`'elevated'` — the\n * parent exists but is above the caller's readable tier) from a genuine\n * data-integrity gap (`'missing'` — no envelope for `targetId` at all).\n */\n readonly reason: 'missing' | 'elevated'\n}\n\nexport interface ClosureResult {\n /** collection → set of record ids that travel together. */\n readonly closure: Map<string, Set<string>>\n readonly graph: {\n /** Fixed-point iterations the walk needed to converge. */\n readonly depth: number\n /** True if an edge pointed back to an already-selected node. */\n readonly cyclesDetected: boolean\n }\n /** #759: outbound FK edges whose parent was excluded (missing or elevated). */\n readonly danglingRefs: ReadonlyArray<DanglingRefNotice>\n}\n\nexport async function walkClosure(\n vault: Vault,\n opts: WalkClosureOptions,\n): Promise<ClosureResult> {\n const closure = new Map<string, Set<string>>()\n\n // Records carry a string `id` by construction (Collection.put(id: string)).\n // A non-string id during the walk means a malformed record — fail loud\n // rather than silently dropping it from the closure (which would leave a\n // dangling FK or a missing child in the extracted bundle).\n const requireStringId = (collection: string, record: Record<string, unknown>): string => {\n const id = record['id']\n if (typeof id !== 'string') {\n throw new PartitionExtractionError(\n `walkClosure: record in collection \"${collection}\" has a non-string ` +\n `id (${typeof id}); cannot include it in the partition closure.`,\n )\n }\n return id\n }\n\n const add = (collection: string, id: string): boolean => {\n let set = closure.get(collection)\n if (!set) {\n set = new Set<string>()\n closure.set(collection, set)\n }\n if (set.has(id)) return false\n set.add(id)\n return true\n }\n\n // Phase 0: evaluate seed predicates.\n for (const [collectionName, predicate] of Object.entries(opts.seeds)) {\n const coll = vault.collection<Record<string, unknown>>(collectionName)\n const records = await coll.list()\n for (const record of records) {\n if (await predicate(record)) {\n add(collectionName, requireStringId(collectionName, record))\n }\n }\n }\n\n const { refRegistry, adapter, name: vaultName } = vault._introspectState()\n const maxDepth = opts.maxDepth ?? 16\n let cyclesDetected = false\n\n // `depth` counts PRODUCTIVE expansion generations (rounds that added at\n // least one new record), taken as the max over the two phases — i.e. the\n // FK hop-distance the closure needed, not the raw loop-iteration count.\n // The terminal draining pass that adds nothing does not count.\n let inboundDepth = 0\n let outboundDepth = 0\n\n // Phase 1 — INBOUND expansion. Worklist of newly-added (collection,id)\n // whose children we still need to pull.\n let frontier: Array<[string, string]> = []\n for (const [c, ids] of closure) for (const id of ids) frontier.push([c, id])\n\n while (frontier.length > 0) {\n const next: Array<[string, string]> = []\n for (const [collectionName, id] of frontier) {\n // Which collections reference THIS collection, and via which field?\n for (const inbound of refRegistry.getInbound(collectionName)) {\n const childColl = vault.collection<Record<string, unknown>>(inbound.collection)\n // TODO(perf): re-scans the full inbound collection on every frontier\n // element. O(frontier · inboundCollections · records) per depth. Fine\n // at consumer-firm scale (foundation §13.4); revisit with an index or\n // pagination if extraction over very large vaults gets slow.\n const childRecords = await childColl.list()\n for (const child of childRecords) {\n const fk = child[inbound.field]\n // Only scalar FK values can match an id; skip null/objects\n // (mirrors checkIntegrity's scalar guard, vault.ts).\n if (typeof fk !== 'string' && typeof fk !== 'number') continue\n if (String(fk) !== id) continue\n const childId = requireStringId(inbound.collection, child)\n if (add(inbound.collection, childId)) {\n next.push([inbound.collection, childId])\n } else {\n cyclesDetected = true\n }\n }\n }\n }\n if (next.length > 0 && ++inboundDepth > maxDepth) {\n throw new PartitionExtractionError(\n `walkClosure exceeded maxDepth=${maxDepth}; the FK graph may be ` +\n `unexpectedly deep or cyclic. Raise maxDepth or narrow the seeds.`,\n )\n }\n frontier = next\n }\n\n // Phase 2 — OUTBOUND completion. Pull referenced parents so no FK\n // dangles. Transitive over outbound edges only; parents are NOT\n // inbound-expanded (that would drag in unrelated siblings).\n let outboundFrontier: Array<[string, string]> = []\n for (const [c, ids] of closure) for (const id of ids) outboundFrontier.push([c, id])\n\n const danglingRefs: DanglingRefNotice[] = []\n\n while (outboundFrontier.length > 0) {\n const next: Array<[string, string]> = []\n for (const [collectionName, id] of outboundFrontier) {\n const outbound = refRegistry.getOutbound(collectionName)\n if (Object.keys(outbound).length === 0) continue\n const coll = vault.collection<Record<string, unknown>>(collectionName)\n const record = await coll.get(id)\n if (!record) continue\n for (const [field, descriptor] of Object.entries(outbound)) {\n const rawId = record[field]\n // Only scalar FK values reference a parent id; skip null/objects.\n if (typeof rawId !== 'string' && typeof rawId !== 'number') continue\n const parentId = String(rawId)\n // #759: verify the referenced parent is visible through the SAME\n // tier-gated primitive root selection / inbound expansion use\n // (`Collection.get()` → `#getRaw`, which returns null for both a\n // missing record and a tier-elevated one). An elevated parent must\n // be excluded exactly like an elevated root or inbound target —\n // \"elevated ≡ invisible\" — rather than admitted into the closure,\n // where `reKeyClosure`'s raw adapter read would later hit it and\n // fail loud (the #748 canary). Record the resulting dangling FK\n // instead of silently dropping it.\n const parentColl = vault.collection<Record<string, unknown>>(descriptor.target)\n const parentRecord = await parentColl.get(parentId)\n if (!parentRecord) {\n // #772: a raw (tier-unaware) read distinguishes the two cases the\n // tier-gated `Collection.get()` above collapses to the same null —\n // an envelope present with `_tier > 0` is an intentional tier\n // boundary; no envelope at all is a genuine data-integrity gap.\n const rawParentEnv = await adapter.get(vaultName, descriptor.target, parentId)\n const reason: 'missing' | 'elevated' =\n rawParentEnv && (rawParentEnv._tier ?? 0) > 0 ? 'elevated' : 'missing'\n danglingRefs.push({\n collection: collectionName, id, field, target: descriptor.target, targetId: parentId, reason,\n })\n continue\n }\n // Reaching an already-selected parent here is normal DAG\n // convergence (a child referencing its in-scope parent), not a\n // cycle — so do NOT flag cyclesDetected in the outbound phase.\n if (add(descriptor.target, parentId)) {\n next.push([descriptor.target, parentId])\n }\n }\n }\n if (next.length > 0 && ++outboundDepth > maxDepth) {\n throw new PartitionExtractionError(\n `walkClosure exceeded maxDepth=${maxDepth} during outbound completion.`,\n )\n }\n outboundFrontier = next\n }\n\n const depth = Math.max(inboundDepth, outboundDepth)\n\n return { closure, graph: { depth, cyclesDetected }, danglingRefs }\n}\n","/**\n * Partition extraction. Walks the FK closure, re-encrypts\n * the selected records under fresh per-collection DEKs, seals those DEKs\n * under a one-time transfer key, and serializes an unowned\n * `extracted-partition` bundle.\n *\n * @module\n */\nimport type { Vault } from '../kernel/vault.js'\nimport type { EncryptedEnvelope, BlobObject, SlotRecord, VersionRecord } from '../kernel/types.js'\nimport { NOYDB_BACKUP_VERSION } from '../kernel/types.js'\nimport { buildRecordAad, recordAadFor,\n decrypt,\n encrypt,\n openEnvelopeJson,\n writeEnvelopeBody,\n generateDEK,\n bufferToBase64,\n encryptBytesWithAAD,\n decryptBytesWithAAD,\n unwrapCek,\n wrapCek,\n type EnclaveKey,\n} from '../kernel/enclave/index.js'\nimport {\n BLOB_COLLECTION,\n BLOB_INDEX_COLLECTION,\n BLOB_CHUNKS_COLLECTION,\n BLOB_SLOTS_PREFIX,\n BLOB_VERSIONS_PREFIX,\n} from '../with-shape/blobs/blob-set.js'\nimport { BLOB_INTENT_COLLECTION } from '../with-shape/blobs/blob-intent.js'\nimport { PartitionExtractionError } from '../kernel/errors.js'\nimport { walkClosure, type WalkClosureOptions, type DanglingRefNotice } from './walk-closure.js'\nimport { generateULID } from '../with-pod/ulid.js'\nimport { SCHEMAS_COLLECTION } from '../with-shape/persisted-schemas/storage.js'\nimport { LEDGER_COLLECTION } from '../with-commit/history/ledger/constants.js'\nimport { canonicalJson, hashEntry } from '../with-commit/history/ledger/entry.js'\nimport type { LedgerEntry } from '../with-commit/history/ledger/entry.js'\nimport { envelopePayloadHash } from '../with-commit/history/ledger/hash.js'\nimport { buildRecordEnvelope } from '../kernel/enclave/index.js'\nimport {\n assemblePodContainer,\n buildExtractedPartitionWrapper,\n type TransferSealPayload,\n} from '../with-pod/pod.js'\n\n/** Re-keyed collections snapshot + the fresh DEKs used. */\nexport interface ReKeyResult {\n readonly collections: Record<string, Record<string, EncryptedEnvelope>>\n readonly deks: Map<string, EnclaveKey>\n}\n\n/**\n * Re-encrypt every record in `closure` under a fresh per-collection DEK.\n * Reads raw source envelopes, decrypts under the source DEK, re-encrypts\n * under the new DEK. Plaintext-pipeline: requires an unlocked vault.\n */\nexport async function reKeyClosure(\n vault: Vault,\n closure: Map<string, Set<string>>,\n fieldProjection?: Record<string, readonly string[]>,\n): Promise<ReKeyResult> {\n const { name: vaultName, adapter, getDEK } = vault._introspectState()\n const collections: Record<string, Record<string, EncryptedEnvelope>> = {}\n const deks = new Map<string, EnclaveKey>()\n\n for (const [collectionName, ids] of closure) {\n const srcDek = await getDEK(collectionName)\n const destDek = await generateDEK()\n deks.set(collectionName, destDek)\n const out: Record<string, EncryptedEnvelope> = {}\n // FR-7 structural field projection: when this collection has a projection,\n // narrow the plaintext body to `id` (always) + the listed fields BEFORE\n // re-encryption, so excluded fields never travel in the bundle. Applied\n // identically in both re-key branches; only the body changes — the `_cek`\n // re-wrap order is untouched. Absent/empty projection → byte-identical to\n // the un-projected path (`proj` is undefined and `project` is a no-op).\n const projList = fieldProjection?.[collectionName]\n const proj = projList ? new Set(projList) : undefined\n const project = (plaintext: string): string => {\n if (!proj) return plaintext\n const rec = JSON.parse(plaintext) as Record<string, unknown>\n const kept: Record<string, unknown> = {}\n if ('id' in rec) kept['id'] = rec['id'] // id ALWAYS preserved\n for (const f of proj) if (f in rec) kept[f] = rec[f]\n return JSON.stringify(kept)\n }\n\n for (const id of ids) {\n const env = await adapter.get(vaultName, collectionName, id)\n if (!env) continue\n // #748 defense-in-depth canary: `closure` is built exclusively through\n // tier-gated `Collection.list()`/`get()` (collection.ts `ensureHydrated`\n // / `#getRaw` both skip `_tier > 0` envelopes), so an elevated record\n // can never reach this raw `adapter.get` fetch — this should be\n // unreachable by construction. Not a user-facing guard; a cheap tripwire\n // in case that invariant ever regresses.\n if ((env._tier ?? 0) > 0) {\n throw new PartitionExtractionError(\n `#748: reKeyClosure fetched an elevated envelope (collection=\"${collectionName}\" id=\"${id}\" `\n + `_tier=${env._tier}) — this is unreachable by construction (walkClosure only ever adds ids `\n + `reachable through tier-gated Collection reads). Refusing to carry it into a partition.`,\n )\n }\n if (env._cek !== undefined) {\n // Per-record CEK: a naive `{ ...env }` spread would carry a\n // SOURCE-DEK-wrapped CEK into a bundle re-keyed under a different\n // destination DEK — silently undecryptable for the recipient.\n // Re-wrap: unwrap the CEK under the source DEK, re-encrypt the body\n // under the SAME CEK (decision 2 — CEK reused on re-key, preserving\n // the history-chain identity), then wrap the CEK under the fresh\n // destination DEK. The recipient gains access transitively once they\n // re-wrap the collection DEK under their KEK on adopt.\n // Identity is UNCHANGED by extraction — collection/id/_tier/_by all\n // travel with the record, and `vault` is deliberately unbound (the ADR's\n // constraint (c) exists precisely so adoption can re-home a partition).\n // So the same AAD opens the source and seals the destination (#1041).\n const aad = recordAadFor({ collection: collectionName, id }, env)\n const cek = await unwrapCek(env._cek, srcDek)\n const plaintext = await decrypt(env._iv, env._data, cek, aad)\n const { iv, data } = await encrypt(project(plaintext), cek, aad)\n const wrapped = await wrapCek(cek, destDek)\n out[id] = { ...env, _iv: iv, _data: data, _cek: wrapped }\n continue\n }\n const plaintext = await openEnvelopeJson({ collection: collectionName, id }, env, srcDek)\n const { iv, data } = await encrypt(project(plaintext), destDek, recordAadFor({ collection: collectionName, id }, env))\n out[id] = { ...env, _iv: iv, _data: data }\n }\n collections[collectionName] = out\n }\n\n return { collections, deks }\n}\n\n/**\n * Re-key the persisted JSON Schemas (`_schemas/<collection>`) for the\n * closure collections under the destination DEKs. Returns a\n * `{ collection: envelope }` map for the carried collections that actually\n * have a schema; collections without one are omitted.\n */\nexport async function reKeySchemas(\n vault: Vault,\n closure: Map<string, Set<string>>,\n destDeks: Map<string, EnclaveKey>,\n fieldProjection?: Record<string, readonly string[]>,\n): Promise<Record<string, EncryptedEnvelope>> {\n const { name: vaultName, adapter, getDEK } = vault._introspectState()\n const out: Record<string, EncryptedEnvelope> = {}\n\n for (const collectionName of closure.keys()) {\n // FR-7: skip a projected collection's schema — the narrowed shape no\n // longer matches the stored JSON Schema, so carrying it would assert a\n // contract the projected records violate (missing required fields).\n if (fieldProjection?.[collectionName]) continue\n const env = await adapter.get(vaultName, SCHEMAS_COLLECTION, collectionName)\n if (!env) continue // collection has no persisted schema — skip\n const destDek = destDeks.get(collectionName)\n if (!destDek) continue\n const srcDek = await getDEK(collectionName)\n const plaintext = await openEnvelopeJson({ collection: SCHEMAS_COLLECTION, id: collectionName }, env, srcDek)\n const { iv, data } = await encrypt(plaintext, destDek, recordAadFor({ collection: SCHEMAS_COLLECTION, id: collectionName }, env))\n out[collectionName] = { ...env, _iv: iv, _data: data }\n }\n return out\n}\n\nconst paddedIndex = (n: number): string => String(n).padStart(10, '0')\n\nexport interface ReKeyLedgerResult {\n /** { paddedIndex: re-encrypted entry envelope } for backup._internal._ledger. */\n readonly entries: Record<string, EncryptedEnvelope>\n /** Recomputed ledgerHead for the carried chain (index -1 when empty). */\n readonly head: { hash: string; index: number; ts: string }\n}\n\n/**\n * Build the carried `_ledger` chain for an extracted partition.\n * Filters source entries to the closure, RE-CHAINS them (fresh index + prevHash),\n * and re-encrypts under `ledgerDek`. The `payloadHash` is recomputed against the\n * re-keyed envelope ONLY for the latest `put` per (collection,id) — the entry\n * `verifyBackupIntegrity` cross-checks; earlier puts + deletes keep their source\n * `payloadHash` verbatim (recomputing an intermediate put would assert a false\n * hash for an older version). Amendments + out-of-closure entries are dropped;\n * `_ledger_deltas`/`_history` are deferred to slice 2.\n */\nexport async function reKeyLedger(\n vault: Vault,\n closure: Map<string, Set<string>>,\n reKeyedCollections: Record<string, Record<string, EncryptedEnvelope>>,\n ledgerDek: EnclaveKey,\n): Promise<ReKeyLedgerResult> {\n const { name: vaultName, adapter, getDEK } = vault._introspectState()\n const srcLedgerDek = await getDEK(LEDGER_COLLECTION)\n\n // 1. Load + decrypt source entries in index order.\n const ids = (await adapter.list(vaultName, LEDGER_COLLECTION)).sort()\n const srcEntries: LedgerEntry[] = []\n for (const id of ids) {\n const env = await adapter.get(vaultName, LEDGER_COLLECTION, id)\n if (!env) continue\n srcEntries.push(JSON.parse(await openEnvelopeJson({ collection: LEDGER_COLLECTION, id }, env, srcLedgerDek)) as LedgerEntry)\n }\n\n // 2. Keep closure put/delete entries (drop amendments + out-of-closure).\n const kept = srcEntries.filter(\n (e) => (e.op === 'put' || e.op === 'delete') && (closure.get(e.collection)?.has(e.id) ?? false),\n )\n\n // 3a. Reverse pass: index of the LATEST put per (collection,id).\n const latestPutIndex = new Map<string, number>()\n for (let i = kept.length - 1; i >= 0; i--) {\n const e = kept[i]!\n if (e.op !== 'put') continue\n const key = `${e.collection}/${e.id}`\n if (!latestPutIndex.has(key)) latestPutIndex.set(key, i)\n }\n\n // 3b. Forward re-chain + re-encrypt.\n const entries: Record<string, EncryptedEnvelope> = {}\n let prevHash = ''\n let last: LedgerEntry | undefined\n for (let i = 0; i < kept.length; i++) {\n const src = kept[i]!\n const key = `${src.collection}/${src.id}`\n const isLatestPut = src.op === 'put' && latestPutIndex.get(key) === i\n const reKeyedEnv = reKeyedCollections[src.collection]?.[src.id]\n const payloadHash = isLatestPut && reKeyedEnv\n ? await envelopePayloadHash(reKeyedEnv)\n : src.payloadHash\n const entry: LedgerEntry = {\n index: i,\n prevHash,\n op: src.op,\n collection: src.collection,\n id: src.id,\n version: src.version,\n ts: src.ts,\n actor: src.actor,\n payloadHash,\n ...(src.reason !== undefined ? { reason: src.reason } : {}),\n }\n const ledgerIdentity = { collection: LEDGER_COLLECTION, id: paddedIndex(i), version: i + 1 }\n const { iv, data } = await encrypt(canonicalJson(entry), ledgerDek, buildRecordAad(ledgerIdentity))\n entries[paddedIndex(i)] = buildRecordEnvelope(\n ledgerIdentity,\n { ts: entry.ts, iv, data},\n )\n prevHash = await hashEntry(entry)\n last = entry\n }\n\n return {\n entries,\n head: last ? { hash: prevHash, index: last.index, ts: last.ts } : { hash: '', index: -1, ts: '' },\n }\n}\n\n/** Build the AAD binding for chunk integrity: \"{eTag}:{chunkIndex}:{chunkCount}\".\n * Mirrors `chunkAAD` in blob-set.ts — the eTag is preserved verbatim across\n * the transfer (see `reKeyBlobs`), so the same AAD that bound a chunk in the\n * source keeps binding it in the bundle. */\nfunction chunkAAD(eTag: string, chunkIndex: number, chunkCount: number): Uint8Array {\n return new TextEncoder().encode(`${eTag}:${chunkIndex}:${chunkCount}`)\n}\n\n/** Carried blob internals + the fresh transfer `_blob` DEK (present only when\n * the closure references at least one chunk-based blob). */\nexport interface ReKeyBlobsResult {\n /** `_blob_slots_<C>` / `_blob_versions_<C>` / `_blob_index` / `_blob_chunks`\n * envelopes for the bundle's `_internal` map. */\n readonly internal: Record<string, Record<string, EncryptedEnvelope>>\n /** Fresh transfer `_blob` DEK — seal it so owner-creation wraps it under the\n * recipient KEK. Undefined when no blob travels (source keyring untouched). */\n readonly blobDek?: EnclaveKey\n}\n\n/**\n * Carry the FK-closed slice's blobs — HARDENED key handling (no master-key leak).\n *\n * The source vault's shared `_blob` DEK decrypts (or unwraps the content CEK of)\n * EVERY blob in the source. Sealing it into the transfer would hand the recipient\n * a key to blobs far outside their slice. Instead we mint a **fresh transfer\n * `_blob` DEK** and arrange every carried blob into per-blob-CEK mode under it:\n *\n * - **erasable blob** (`_cek` present): unwrap the per-blob content CEK under the\n * SOURCE `_blob` DEK, re-wrap it under the FRESH transfer DEK. Chunks travel\n * **verbatim** (still ciphertext under that same content CEK — passthrough).\n * - **legacy blob** (no `_cek`, chunks under the shared `_blob` DEK): promote it\n * IN-BUNDLE — mint a fresh content CEK, decrypt each chunk under the source\n * `_blob` DEK and re-encrypt under the content CEK (same AAD, so the eTag-bound\n * integrity holds), then wrap the content CEK under the transfer DEK. The\n * SOURCE is never mutated (non-destructive), and the bundle never holds\n * plaintext blob bytes (zero-knowledge preserved).\n *\n * **eTag identity is preserved** (not re-HMAC'd). eTags are HMAC-keyed off the\n * `_blob` DEK, but they are stored as OPAQUE keys (`_blob_index/<eTag>`,\n * `_blob_chunks/<eTag>_<i>`) and never recomputed on read — only on a `put()`\n * for dedup. Keeping them verbatim keeps every slot/version/index/chunk key and\n * the chunk AAD coherent with zero chunk-key churn. The only consequence: a\n * future `put()` of identical bytes in the adopted vault computes a different\n * eTag (HMAC under the fresh DEK) and will NOT dedup against the carried blob —\n * an accepted, documented trade for hardened key isolation.\n *\n * Slots/versions are re-keyed under their parent collection's destination DEK\n * (honoring `fieldProjection` — projected-out blob fields' slots never travel);\n * `BlobObject.refCount` is recomputed from carried references only.\n *\n * `external` slots reference an unencrypted shared-bucket object that is not in\n * the bundle — their slot metadata travels (so the catalog entry survives) but\n * the bytes do not (a documented v1 limitation; their eTag is `''`).\n */\nexport async function reKeyBlobs(\n vault: Vault,\n closure: Map<string, Set<string>>,\n destDeks: Map<string, EnclaveKey>,\n fieldProjection?: Record<string, readonly string[]>,\n): Promise<ReKeyBlobsResult> {\n const { name: vaultName, adapter, getDEK } = vault._introspectState()\n const internal: Record<string, Record<string, EncryptedEnvelope>> = {}\n\n // travel set: eTag → number of carried references (slots + versions) within\n // the closure. Recomputed refCount, NOT the source's (which may count\n // out-of-slice referrers, leaving the adopted blob un-GC-able).\n const carriedRefs = new Map<string, number>()\n const addRef = (eTag: string): void => {\n if (!eTag) return // external slot — no chunk-based blob to carry\n carriedRefs.set(eTag, (carriedRefs.get(eTag) ?? 0) + 1)\n }\n\n const place = (collection: string, id: string, env: EncryptedEnvelope): void => {\n let bucket = internal[collection]\n if (!bucket) { bucket = {}; internal[collection] = bucket }\n bucket[id] = env\n }\n\n // ── Slots + versions (parent-collection-DEK keyed) ─────────────────\n for (const [collectionName, ids] of closure) {\n const destDek = destDeks.get(collectionName)\n if (!destDek) continue\n const srcDek = await getDEK(collectionName)\n const projList = fieldProjection?.[collectionName]\n const proj = projList ? new Set(projList) : undefined\n\n // Slots: one envelope per record, a `{ slotName: SlotRecord }` map.\n const slotsCollection = `${BLOB_SLOTS_PREFIX}${collectionName}`\n for (const id of ids) {\n // #767: carry any in-flight `_blob_intent` marker for this record,\n // re-keyed under the SAME destination DEK as its owning collection\n // (mirrors `dumpVault`'s backup allowlist, which carries `_blob_intent`\n // for the identical crash-recovery reason — a partition extracted\n // mid-shred/mid-rehome must carry the marker so resume-on-touch heals\n // it post-restore). Checked independently of the slot-map fetch below:\n // a marker can be present even when the slot map has already been\n // touched or removed by the in-flight operation.\n const intentId = `${collectionName}::${id}`\n const intentEnv = await adapter.get(vaultName, BLOB_INTENT_COLLECTION, intentId)\n if (intentEnv) {\n const intentPlain = await openEnvelopeJson({ collection: BLOB_INTENT_COLLECTION, id: intentId }, intentEnv, srcDek)\n const intentBody = await writeEnvelopeBody({ collection: BLOB_INTENT_COLLECTION, id: intentId, version: intentEnv._v }, intentPlain, destDek)\n place(BLOB_INTENT_COLLECTION, intentId, { ...intentEnv, ...intentBody })\n }\n\n const env = await adapter.get(vaultName, slotsCollection, id)\n if (!env) continue\n // #748 defense-in-depth canary — see the matching one in `reKeyClosure`:\n // `ids` comes from the same tier-gated `closure`, so an elevated\n // record's slot map should never be reachable here. Unreachable by\n // construction; a cheap tripwire, not a user-facing guard.\n if ((env._tier ?? 0) > 0) {\n throw new PartitionExtractionError(\n `#748: reKeyBlobs fetched an elevated slot-map envelope (collection=\"${slotsCollection}\" `\n + `id=\"${id}\" _tier=${env._tier}) — this is unreachable by construction. Refusing to carry it into a partition.`,\n )\n }\n const slots = JSON.parse(await openEnvelopeJson({ collection: slotsCollection, id }, env, srcDek)) as Record<string, SlotRecord>\n // FR-7: drop projected-out blob fields' slots (slot names are blob field\n // names) — their eTags then never enter the travel set.\n const kept: Record<string, SlotRecord> = {}\n for (const [slotName, slot] of Object.entries(slots)) {\n if (proj && !proj.has(slotName)) continue\n // #769: strip the internal `pendingRelease` resume breadcrumb before\n // it travels. It is a SOURCE-VAULT-LOCAL rehome marker (see\n // `SlotRecord.pendingRelease`'s doc comment) pointing at an old eTag\n // awaiting release — meaningless, and potentially misleading, once\n // detached from the source vault (the eTag it names may be absent\n // from the destination). Unlike `_blob_intent` above (carried, so\n // resume-on-touch heals it post-restore), this breadcrumb must NOT\n // travel into a cross-vault partition.\n const { pendingRelease, ...strippedSlot } = slot\n void pendingRelease\n kept[slotName] = strippedSlot\n addRef(slot.eTag)\n }\n if (Object.keys(kept).length === 0) continue\n const { iv, data } = await encrypt(JSON.stringify(kept), destDek, recordAadFor({ collection: slotsCollection, id }, env))\n place(slotsCollection, id, { ...env, _iv: iv, _data: data })\n }\n\n // Versions: key = `${recordId}::${slotName}::${label}`; each an independent\n // refCount hold on its eTag.\n const versionsCollection = `${BLOB_VERSIONS_PREFIX}${collectionName}`\n const versionKeys = await adapter.list(vaultName, versionsCollection)\n for (const key of versionKeys) {\n const [recordId, slotName] = key.split('::')\n if (recordId === undefined || !ids.has(recordId)) continue\n if (proj && slotName !== undefined && !proj.has(slotName)) continue\n const env = await adapter.get(vaultName, versionsCollection, key)\n if (!env) continue\n // #748 defense-in-depth canary — see `reKeyClosure`'s. Unreachable by\n // construction; a cheap tripwire, not a user-facing guard.\n if ((env._tier ?? 0) > 0) {\n throw new PartitionExtractionError(\n `#748: reKeyBlobs fetched an elevated version-record envelope (collection=\"${versionsCollection}\" `\n + `key=\"${key}\" _tier=${env._tier}) — this is unreachable by construction. Refusing to carry it into a partition.`,\n )\n }\n const record = JSON.parse(await openEnvelopeJson({ collection: versionsCollection, id: key }, env, srcDek)) as VersionRecord\n addRef(record.eTag)\n const { iv, data } = await encrypt(JSON.stringify(record), destDek, recordAadFor({ collection: versionsCollection, id: key }, env))\n place(versionsCollection, key, { ...env, _iv: iv, _data: data })\n }\n }\n\n // No chunk-based blob in the closure → carry nothing, mint nothing. Guarded\n // so `getDEK('_blob')` does not auto-mint + persist a phantom DEK on the\n // source keyring (mirrors the carryLedger non-destructive guard).\n if (carriedRefs.size === 0) return { internal }\n\n // ── Index + chunks (re-keyed under a FRESH transfer `_blob` DEK) ────\n const srcBlobDek = await getDEK(BLOB_COLLECTION)\n const transferBlobDek = await generateDEK()\n\n for (const [eTag, refCount] of carriedRefs) {\n const idxEnv = await adapter.get(vaultName, BLOB_INDEX_COLLECTION, eTag)\n if (!idxEnv) continue // dangling slot reference — nothing to carry\n const blob = JSON.parse(await openEnvelopeJson({ collection: BLOB_INDEX_COLLECTION, id: eTag }, idxEnv, srcBlobDek)) as BlobObject\n\n // Resolve the per-blob content CEK; passthrough vs. in-bundle promotion.\n let contentCek: EnclaveKey\n let chunksPassthrough: boolean\n if (blob._cek !== undefined) {\n contentCek = await unwrapCek(blob._cek, srcBlobDek)\n chunksPassthrough = true\n } else {\n // Legacy: promote to per-blob-CEK for the bundle (source untouched).\n contentCek = await generateDEK()\n chunksPassthrough = false\n }\n\n // Chunks: verbatim for an already-erasable blob; decrypt-then-re-encrypt\n // under the fresh content CEK for a legacy blob (same eTag-bound AAD).\n for (let i = 0; i < blob.chunkCount; i++) {\n const chunkId = `${eTag}_${i}`\n const chunkEnv = await adapter.get(vaultName, BLOB_CHUNKS_COLLECTION, chunkId)\n if (!chunkEnv) {\n throw new PartitionExtractionError(\n `reKeyBlobs: blob chunk ${i}/${blob.chunkCount} missing for eTag \"${eTag}\"; `\n + `cannot carry an incomplete blob into the partition.`,\n )\n }\n if (chunksPassthrough) {\n place(BLOB_CHUNKS_COLLECTION, chunkId, chunkEnv)\n } else {\n const aad = chunkAAD(eTag, i, blob.chunkCount)\n const plain = await decryptBytesWithAAD(chunkEnv._iv, chunkEnv._data, srcBlobDek, aad)\n const { iv, data } = await encryptBytesWithAAD(plain, contentCek, aad)\n place(BLOB_CHUNKS_COLLECTION, chunkId, { ...chunkEnv, _iv: iv, _data: data })\n }\n }\n\n // Index: per-blob-CEK mode under the transfer DEK, refCount corrected.\n // Drop any transient `_cekPending` (never set on a settled blob — possible\n // only if the source is mid-migration; we set a fresh settled `_cek`).\n const { _cekPending, ...rest } = blob\n void _cekPending\n const carried: BlobObject = { ...rest, refCount, _cek: await wrapCek(contentCek, transferBlobDek) }\n const { iv, data } = await encrypt(JSON.stringify(carried), transferBlobDek, recordAadFor({ collection: BLOB_INDEX_COLLECTION, id: eTag }, idxEnv))\n place(BLOB_INDEX_COLLECTION, eTag, { ...idxEnv, _iv: iv, _data: data })\n }\n\n return { internal, blobDek: transferBlobDek }\n}\n\n/** A minted transfer key (raw 32 bytes) + the seal carrying the DEK set. */\nexport interface SealResult {\n readonly seal: TransferSealPayload\n readonly transferKey: Uint8Array\n}\n\n/**\n * Mint a random 32-byte transfer key, export each DEK to raw bytes, and\n * AES-256-GCM-seal the `{ collection: base64(rawDEK) }` map under the\n * transfer key. The transfer key is returned to the caller out-of-band;\n * only the sealed bytes travel in the bundle. Layout: iv(12) ‖ ct ‖ tag.\n */\nexport async function sealDeks(deks: Map<string, EnclaveKey>): Promise<SealResult> {\n const dekMap: Record<string, string> = {}\n for (const [collection, dek] of deks) {\n const raw = await crypto.subtle.exportKey('raw', dek)\n dekMap[collection] = bufferToBase64(raw)\n }\n\n const transferKey = crypto.getRandomValues(new Uint8Array(32))\n const key = await crypto.subtle.importKey('raw', transferKey, 'AES-GCM', false, ['encrypt'])\n const iv = crypto.getRandomValues(new Uint8Array(12))\n const plaintext = new TextEncoder().encode(JSON.stringify(dekMap))\n const ct = await crypto.subtle.encrypt({ name: 'AES-GCM', iv }, key, plaintext)\n\n const combined = new Uint8Array(iv.byteLength + ct.byteLength)\n combined.set(iv, 0)\n combined.set(new Uint8Array(ct), iv.byteLength)\n\n const sealId = bufferToBase64(crypto.getRandomValues(new Uint8Array(12)))\n return {\n seal: { v: 1, alg: 'aes-256-gcm-pre-shared', sealId, payload: bufferToBase64(combined) },\n transferKey,\n }\n}\n\nexport interface ExtractPartitionResult {\n readonly bundleBytes: Uint8Array\n /** Raw 32-byte transfer key — deliver out-of-band; required to adopt. */\n readonly transferKey: Uint8Array\n readonly sealId: string\n /**\n * #759: outbound FK edges whose referenced parent was excluded from the\n * partition (missing, or tier-elevated and therefore invisible). The\n * child record still carries its FK value; the parent did not travel —\n * callers should surface this to the operator rather than assume\n * referential completeness.\n */\n readonly danglingRefs: ReadonlyArray<DanglingRefNotice>\n}\n\n/**\n * Extract a re-keyed, transfer-sealed partition. Owner-only\n * (invariant 5): producing a standalone re-keyed vault is an\n * ownership operation. Non-destructive on the source.\n */\nexport type ExtractPartitionOptions = WalkClosureOptions & {\n readonly compression?: 'auto' | 'brotli' | 'gzip' | 'none'\n readonly carrySchemas?: boolean\n readonly carryLedger?: boolean\n /**\n * FR-7 structural field projection: per-collection allow-list of fields\n * to keep. Non-listed fields are dropped from each record BEFORE\n * re-encryption (so they never travel in the bundle); `id` is always\n * preserved. A projected collection's persisted schema is NOT carried.\n * Absent/empty → un-projected behavior (byte-identical to today).\n */\n readonly fieldProjection?: Record<string, readonly string[]>\n}\n\n/**\n * Public extract-partition entry — gated behind `cargoStrategy: withCargo()`\n * (S4). Routes through the source vault's cargo strategy so an un-opted-in\n * caller hits `NO_CARGO`'s throw; `withCargo()` dynamically imports and runs\n * {@link extractPartitionCore} (the crypto engine, kept out of the floor).\n */\nexport async function extractPartition(\n vault: Vault,\n opts: ExtractPartitionOptions,\n): Promise<ExtractPartitionResult> {\n return vault.cargoStrategy.extractPartition(vault, opts)\n}\n\n/**\n * The extract-partition crypto engine — reached only when `withCargo()` is\n * opted in (via the lazy `with-cargo/active.ts` chunk). Body unchanged from the\n * hardened implementation; only the public gate wraps it.\n */\nexport async function extractPartitionCore(\n vault: Vault,\n opts: ExtractPartitionOptions,\n): Promise<ExtractPartitionResult> {\n // FR-6: extract-and-sever is the inalienability-floor half — owner-only. A\n // custodian operates fully but must NEVER produce a standalone re-keyed\n // partition (that would let it sever a copy out from under the sealed owner).\n // Explicit assertion so the security boundary is auditable at this site.\n if (vault.role === 'custodian') {\n throw new PartitionExtractionError(\n 'extractPartition is owner-only; a custodian cannot extract-and-sever '\n + '(FR-6: producing a re-keyed standalone partition is an ownership operation; use the Deed owner).',\n )\n }\n if (vault.role !== 'owner') {\n throw new PartitionExtractionError(\n `extractPartition requires the 'owner' role on the source vault; caller is '${vault.role}'. `\n + `Producing a re-keyed standalone partition is an ownership operation.`,\n )\n }\n\n // Persisted-schema writes (collection({ persistJsonSchema: true })) are fire-\n // and-forget queued onto vault._pendingSchemaWrites — a caller that does\n // `collection() → put() → extractPartition({ carrySchemas: true })` in quick\n // succession can hit a window where _schemas/<col> is not yet on disk and\n // reKeySchemas silently drops the row. Drain BEFORE reKeySchemas reads.\n if (opts.carrySchemas) await vault._drainPendingSchemaWrites()\n\n const { closure, danglingRefs } = await walkClosure(vault, opts)\n const { collections, deks } = await reKeyClosure(vault, closure, opts.fieldProjection)\n\n // carryLedger: mint a fresh _ledger DEK, build the carried chain, and\n // SEAL the ledger DEK alongside the data DEKs so owner-creation wraps it into the\n // recipient keyring (lets them decrypt + verify the chain). Must run BEFORE\n // sealDeks.\n let ledgerHead: { hash: string; index: number; ts: string } | undefined\n let ledgerEntries: Record<string, EncryptedEnvelope> | undefined\n if (opts.carryLedger && vault._getLedgerOrNull() !== null) {\n // Skip when the source vault has no history strategy: reKeyLedger's first\n // `getDEK(LEDGER_COLLECTION)` would auto-mint and persist a phantom\n // _ledger DEK on the source keyring (contradicting \"non-destructive on\n // the source\"), and there's nothing to carry anyway. Mirrors the same\n // null-guard the source audit-append uses below.\n const ledgerDek = await generateDEK()\n const built = await reKeyLedger(vault, closure, collections, ledgerDek)\n if (built.head.index >= 0) {\n ledgerEntries = built.entries\n ledgerHead = built.head\n deks.set(LEDGER_COLLECTION, ledgerDek)\n }\n }\n\n // Carry the slice's blobs — re-keyed under a FRESH transfer `_blob` DEK\n // (HARDENED: never carries the source's shared blob DEK). Runs BEFORE\n // sealDeks so the fresh DEK is sealed alongside the data DEKs; non-destructive\n // on the source (mints + reads `_blob` only when the closure has blobs).\n const blobs = await reKeyBlobs(vault, closure, deks, opts.fieldProjection)\n if (blobs.blobDek) deks.set(BLOB_COLLECTION, blobs.blobDek)\n\n // Build _internal (schemas + ledger + blobs). reKeySchemas reads data-\n // collection DEKs only, so it is unaffected by the _ledger DEK added above.\n const internalSchemas = opts.carrySchemas ? await reKeySchemas(vault, closure, deks, opts.fieldProjection) : {}\n const internal: Record<string, Record<string, EncryptedEnvelope>> = {}\n if (Object.keys(internalSchemas).length > 0) internal[SCHEMAS_COLLECTION] = internalSchemas\n if (ledgerEntries) internal[LEDGER_COLLECTION] = ledgerEntries\n for (const [collection, records] of Object.entries(blobs.internal)) internal[collection] = records\n const hasInternal = Object.keys(internal).length > 0\n\n const { seal, transferKey } = await sealDeks(deks)\n\n // Source-side audit: record that a partition\n // was handed over. Non-destructive — an audit append, no record touched.\n // No-op when the source vault has no history strategy. append() fills\n // index/prevHash/ts and (since actor is '') the ledger's configured actor.\n await vault._getLedgerOrNull()?.append({\n op: 'lifecycle',\n collection: '',\n id: '',\n version: 0,\n actor: '',\n payloadHash: '',\n reason: `partition-handed-over:${seal.sealId}`,\n })\n\n // Build the dump JSON: unowned (empty keyrings), empty ledger (default),\n // re-keyed collections only.\n const { name: vaultName } = vault._introspectState()\n const backup = {\n _noydb_backup: NOYDB_BACKUP_VERSION,\n _compartment: vaultName,\n _exported_at: new Date().toISOString(),\n _exported_by: '', // unowned — no source user travels\n keyrings: {},\n collections,\n ...(hasInternal ? { _internal: internal } : {}),\n ...(ledgerHead ? { ledgerHead: { hash: ledgerHead.hash, index: ledgerHead.index, ts: ledgerHead.ts } } : {}),\n }\n const bodyJsonStr = JSON.stringify(buildExtractedPartitionWrapper(JSON.stringify(backup), seal))\n\n // An extracted partition is a NEW vault, not a re-export of the source —\n // mint a fresh handle rather than reusing the source's stable ULID\n // (which would collide if a recipient imports both source + partition).\n const handle = generateULID()\n const bundleBytes = await assemblePodContainer({\n handle,\n bodyJsonStr,\n compression: opts.compression,\n headerExtras: {\n bundleKind: 'extracted-partition',\n transferSeal: { v: seal.v, alg: seal.alg, sealId: seal.sealId }, // indicator only\n },\n })\n\n return { bundleBytes, transferKey, sealId: seal.sealId, danglingRefs }\n}\n"],"mappings":"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","names":["plaintext","iv","data"]}
|
|
@@ -3,7 +3,7 @@ import {
|
|
|
3
3
|
} from "./chunk-Y2NBBT6K.js";
|
|
4
4
|
import {
|
|
5
5
|
sha256Hex
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-W5LHQXZU.js";
|
|
7
7
|
|
|
8
8
|
// src/with-shape/persisted-schemas/derive.ts
|
|
9
9
|
function isZodSchema(value) {
|
|
@@ -79,4 +79,4 @@ export {
|
|
|
79
79
|
isZod4Schema,
|
|
80
80
|
derivePersistedSchema
|
|
81
81
|
};
|
|
82
|
-
//# sourceMappingURL=chunk-
|
|
82
|
+
//# sourceMappingURL=chunk-P6ASQOZR.js.map
|