@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
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isRewrappedUnder,
|
|
3
|
+
rewrapEnvelope
|
|
4
|
+
} from "./chunk-2LPVI4PX.js";
|
|
5
|
+
import {
|
|
6
|
+
buildRecordEnvelope,
|
|
7
|
+
isTombstone,
|
|
8
|
+
isTombstoneShape
|
|
9
|
+
} from "./chunk-N4CNVSUF.js";
|
|
10
|
+
|
|
11
|
+
// src/with-commit/history/history.ts
|
|
12
|
+
var HISTORY_COLLECTION = "_history";
|
|
13
|
+
var VERSION_PAD = 10;
|
|
14
|
+
function historyId(collection, recordId, version) {
|
|
15
|
+
return `${collection}:${recordId}:${String(version).padStart(VERSION_PAD, "0")}`;
|
|
16
|
+
}
|
|
17
|
+
function historyIdentity(collection, recordId, version) {
|
|
18
|
+
return { collection: HISTORY_COLLECTION, id: historyId(collection, recordId, version), version };
|
|
19
|
+
}
|
|
20
|
+
function matchesPrefix(id, collection, recordId) {
|
|
21
|
+
if (recordId) {
|
|
22
|
+
return id.startsWith(`${collection}:${recordId}:`);
|
|
23
|
+
}
|
|
24
|
+
return id.startsWith(`${collection}:`);
|
|
25
|
+
}
|
|
26
|
+
async function saveHistory(adapter, vault, collection, recordId, envelope) {
|
|
27
|
+
const { id } = historyIdentity(collection, recordId, envelope._v);
|
|
28
|
+
await adapter.put(vault, HISTORY_COLLECTION, id, envelope);
|
|
29
|
+
}
|
|
30
|
+
async function getHistory(adapter, vault, collection, recordId, options) {
|
|
31
|
+
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
32
|
+
const matchingIds = allIds.filter((id) => matchesPrefix(id, collection, recordId)).sort().reverse();
|
|
33
|
+
const entries = [];
|
|
34
|
+
for (const id of matchingIds) {
|
|
35
|
+
const envelope = await adapter.get(vault, HISTORY_COLLECTION, id);
|
|
36
|
+
if (!envelope) continue;
|
|
37
|
+
if (options?.from && envelope._ts < options.from) continue;
|
|
38
|
+
if (options?.to && envelope._ts > options.to) continue;
|
|
39
|
+
entries.push(envelope);
|
|
40
|
+
if (options?.limit && entries.length >= options.limit) break;
|
|
41
|
+
}
|
|
42
|
+
return entries;
|
|
43
|
+
}
|
|
44
|
+
async function getVersionEnvelope(adapter, vault, collection, recordId, version) {
|
|
45
|
+
const id = historyId(collection, recordId, version);
|
|
46
|
+
return adapter.get(vault, HISTORY_COLLECTION, id);
|
|
47
|
+
}
|
|
48
|
+
async function pruneHistory(adapter, vault, collection, recordId, options) {
|
|
49
|
+
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
50
|
+
const matchingIds = allIds.filter((id) => recordId ? matchesPrefix(id, collection, recordId) : matchesPrefix(id, collection)).sort();
|
|
51
|
+
let toDelete = [];
|
|
52
|
+
if (options.keepVersions !== void 0) {
|
|
53
|
+
const keep = options.keepVersions;
|
|
54
|
+
if (matchingIds.length > keep) {
|
|
55
|
+
toDelete = matchingIds.slice(0, matchingIds.length - keep);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (options.beforeDate) {
|
|
59
|
+
for (const id of matchingIds) {
|
|
60
|
+
if (toDelete.includes(id)) continue;
|
|
61
|
+
const envelope = await adapter.get(vault, HISTORY_COLLECTION, id);
|
|
62
|
+
if (envelope && envelope._ts < options.beforeDate) {
|
|
63
|
+
toDelete.push(id);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const uniqueDeletes = [...new Set(toDelete)];
|
|
68
|
+
for (const id of uniqueDeletes) {
|
|
69
|
+
await adapter.delete(vault, HISTORY_COLLECTION, id);
|
|
70
|
+
}
|
|
71
|
+
return uniqueDeletes.length;
|
|
72
|
+
}
|
|
73
|
+
async function clearHistory(adapter, vault, collection, recordId) {
|
|
74
|
+
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
75
|
+
let toDelete;
|
|
76
|
+
if (collection && recordId) {
|
|
77
|
+
toDelete = allIds.filter((id) => matchesPrefix(id, collection, recordId));
|
|
78
|
+
} else if (collection) {
|
|
79
|
+
toDelete = allIds.filter((id) => matchesPrefix(id, collection));
|
|
80
|
+
} else {
|
|
81
|
+
toDelete = allIds;
|
|
82
|
+
}
|
|
83
|
+
for (const id of toDelete) {
|
|
84
|
+
await adapter.delete(vault, HISTORY_COLLECTION, id);
|
|
85
|
+
}
|
|
86
|
+
return toDelete.length;
|
|
87
|
+
}
|
|
88
|
+
async function tombstoneHistory(adapter, vault, collection, recordId, actor, encrypted) {
|
|
89
|
+
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
90
|
+
const matchingIds = allIds.filter((id) => matchesPrefix(id, collection, recordId));
|
|
91
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
92
|
+
let count = 0;
|
|
93
|
+
for (const id of matchingIds) {
|
|
94
|
+
const env = await adapter.get(vault, HISTORY_COLLECTION, id);
|
|
95
|
+
if (!env) continue;
|
|
96
|
+
if (isTombstone(env, encrypted)) continue;
|
|
97
|
+
const tombstone = buildRecordEnvelope(
|
|
98
|
+
{ collection: HISTORY_COLLECTION, id, ...actor ? { by: actor } : {}, version: env._v },
|
|
99
|
+
{ ts: now, iv: "", data: "" }
|
|
100
|
+
);
|
|
101
|
+
await adapter.put(vault, HISTORY_COLLECTION, id, tombstone);
|
|
102
|
+
count++;
|
|
103
|
+
}
|
|
104
|
+
return count;
|
|
105
|
+
}
|
|
106
|
+
async function rewrapHistory(adapter, vault, collection, recordId, fromDek, toDek, tier0Dek) {
|
|
107
|
+
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
108
|
+
const matchingIds = allIds.filter((id) => matchesPrefix(id, collection, recordId));
|
|
109
|
+
for (const id of matchingIds) {
|
|
110
|
+
const env = await adapter.get(vault, HISTORY_COLLECTION, id);
|
|
111
|
+
if (!env) continue;
|
|
112
|
+
if (isTombstoneShape(env)) continue;
|
|
113
|
+
const identity = {
|
|
114
|
+
collection: HISTORY_COLLECTION,
|
|
115
|
+
id,
|
|
116
|
+
version: env._v,
|
|
117
|
+
...env._tier !== void 0 ? { tier: env._tier } : {},
|
|
118
|
+
...env._by !== void 0 ? { by: env._by } : {}
|
|
119
|
+
};
|
|
120
|
+
if (await isRewrappedUnder(identity, env, toDek)) continue;
|
|
121
|
+
let next;
|
|
122
|
+
try {
|
|
123
|
+
next = await rewrapEnvelope(identity, env, fromDek, toDek);
|
|
124
|
+
} catch (err) {
|
|
125
|
+
if (!tier0Dek) throw err;
|
|
126
|
+
next = await rewrapEnvelope(identity, env, tier0Dek, toDek);
|
|
127
|
+
}
|
|
128
|
+
await adapter.put(vault, HISTORY_COLLECTION, id, next);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// src/with-commit/history/strategy.ts
|
|
133
|
+
function notEnabled(op) {
|
|
134
|
+
return new Error(
|
|
135
|
+
`${op} requires the history strategy. Import \`{ withHistory }\` from "@noy-db/hub/history" and pass it to \`createNoydb({ historyStrategy: withHistory() })\`.`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
var NO_HISTORY = {
|
|
139
|
+
async saveHistory() {
|
|
140
|
+
},
|
|
141
|
+
// Unreachable in practice — `saveHistory` above is a no-op, so nothing is
|
|
142
|
+
// ever sealed. Returns the real layout rather than a sentinel so a future
|
|
143
|
+
// caller that reads it without writing cannot be misled.
|
|
144
|
+
historyIdentity: (collection, recordId, version) => historyIdentity(collection, recordId, version),
|
|
145
|
+
async getHistoryEntries() {
|
|
146
|
+
throw notEnabled("collection.history()");
|
|
147
|
+
},
|
|
148
|
+
async getVersionEnvelope() {
|
|
149
|
+
throw notEnabled("collection.getVersion()");
|
|
150
|
+
},
|
|
151
|
+
async pruneHistory() {
|
|
152
|
+
return 0;
|
|
153
|
+
},
|
|
154
|
+
async clearHistory() {
|
|
155
|
+
return 0;
|
|
156
|
+
},
|
|
157
|
+
async tombstoneHistory() {
|
|
158
|
+
return 0;
|
|
159
|
+
},
|
|
160
|
+
async rewrapHistory() {
|
|
161
|
+
},
|
|
162
|
+
async envelopePayloadHash() {
|
|
163
|
+
return "";
|
|
164
|
+
},
|
|
165
|
+
computePatch() {
|
|
166
|
+
return [];
|
|
167
|
+
},
|
|
168
|
+
diff() {
|
|
169
|
+
throw notEnabled("collection.diff()");
|
|
170
|
+
},
|
|
171
|
+
buildLedger() {
|
|
172
|
+
return null;
|
|
173
|
+
},
|
|
174
|
+
buildVaultInstant() {
|
|
175
|
+
throw notEnabled("vault.at() / vault.timeMachine()");
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export {
|
|
180
|
+
historyIdentity,
|
|
181
|
+
saveHistory,
|
|
182
|
+
getHistory,
|
|
183
|
+
getVersionEnvelope,
|
|
184
|
+
pruneHistory,
|
|
185
|
+
clearHistory,
|
|
186
|
+
tombstoneHistory,
|
|
187
|
+
rewrapHistory,
|
|
188
|
+
NO_HISTORY
|
|
189
|
+
};
|
|
190
|
+
//# sourceMappingURL=chunk-6EW2UCVF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-commit/history/history.ts","../src/with-commit/history/strategy.ts"],"sourcesContent":["import { buildRecordEnvelope } from '../../kernel/enclave/index.js'\nimport type { RecordIdentity } from '../../kernel/enclave/index.js'\nimport type { NoydbStore, EncryptedEnvelope, HistoryOptions, PruneOptions } from '../../kernel/types.js'\nimport { isTombstone, isTombstoneShape, rewrapEnvelope, isRewrappedUnder, type EnclaveKey } from '../../kernel/enclave/index.js'\n\n/**\n * History storage convention:\n * Collection: `_history`\n * ID format: `{collection}:{recordId}:{paddedVersion}`\n * Version is zero-padded to 10 digits for lexicographic sorting.\n */\n\nconst HISTORY_COLLECTION = '_history'\nconst VERSION_PAD = 10\n\nfunction historyId(collection: string, recordId: string, version: number): string {\n return `${collection}:${recordId}:${String(version).padStart(VERSION_PAD, '0')}`\n}\n\n/**\n * The identity a history snapshot is **sealed against** — its STORAGE location,\n * not the live record it is a copy of (#1041).\n *\n * ## Why storage, and why this is a decision rather than a detail\n *\n * A snapshot is a copy, so two identities are available: the live record\n * (`collection`/`recordId`) or where the bytes actually land\n * (`_history`/`historyId(...)`). They are not equivalent under attack.\n *\n * Binding the LIVE identity makes a snapshot's AAD **indistinguishable from the\n * live record's at the same version** — so an untrusted store could serve a\n * history entry *as the current record* and the client would accept it. It also\n * leaves entries relocatable within `_history`.\n *\n * Binding STORAGE identity closes both. The cost is that the id must be known\n * *before* the envelope is sealed, where `saveHistory` previously derived it\n * *after* (from `envelope._v`) — which is precisely the restructure this\n * function exists to make possible.\n *\n * `saveHistory` uses this too, so the sealed identity and the put location have\n * **one definition** and cannot drift apart. Changing the layout here changes\n * both at once, by construction.\n */\nexport function historyIdentity(collection: string, recordId: string, version: number): RecordIdentity {\n // The snapshot's own `_v` IS the version it preserves — the same number that\n // appears in its id. One argument feeds both, so they cannot disagree (#1093).\n return { collection: HISTORY_COLLECTION, id: historyId(collection, recordId, version), version }\n}\n\n// Unused today, kept for future history-id parsing utilities.\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\nfunction parseHistoryId(id: string): { collection: string; recordId: string; version: number } | null {\n const lastColon = id.lastIndexOf(':')\n if (lastColon < 0) return null\n const versionStr = id.slice(lastColon + 1)\n const rest = id.slice(0, lastColon)\n const firstColon = rest.indexOf(':')\n if (firstColon < 0) return null\n return {\n collection: rest.slice(0, firstColon),\n recordId: rest.slice(firstColon + 1),\n version: parseInt(versionStr, 10),\n }\n}\n\nfunction matchesPrefix(id: string, collection: string, recordId?: string): boolean {\n if (recordId) {\n return id.startsWith(`${collection}:${recordId}:`)\n }\n return id.startsWith(`${collection}:`)\n}\n\n/** Save a history entry (a complete encrypted envelope snapshot). */\nexport async function saveHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n envelope: EncryptedEnvelope,\n): Promise<void> {\n // Same derivation the caller sealed against — one definition, so the sealed\n // identity and the put location cannot drift (#1041).\n const { id } = historyIdentity(collection, recordId, envelope._v)\n await adapter.put(vault, HISTORY_COLLECTION, id, envelope)\n}\n\n/** Get history entries for a record, sorted newest-first. */\nexport async function getHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n options?: HistoryOptions,\n): Promise<EncryptedEnvelope[]> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds\n .filter(id => matchesPrefix(id, collection, recordId))\n .sort()\n .reverse() // newest first\n\n const entries: EncryptedEnvelope[] = []\n\n for (const id of matchingIds) {\n const envelope = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (!envelope) continue\n\n // Apply time filters\n if (options?.from && envelope._ts < options.from) continue\n if (options?.to && envelope._ts > options.to) continue\n\n entries.push(envelope)\n\n if (options?.limit && entries.length >= options.limit) break\n }\n\n return entries\n}\n\n/** Get a specific version's envelope from history. */\nexport async function getVersionEnvelope(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n version: number,\n): Promise<EncryptedEnvelope | null> {\n const id = historyId(collection, recordId, version)\n return adapter.get(vault, HISTORY_COLLECTION, id)\n}\n\n/** Prune history entries. Returns the number of entries deleted. */\nexport async function pruneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string | undefined,\n options: PruneOptions,\n): Promise<number> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds\n .filter(id => recordId ? matchesPrefix(id, collection, recordId) : matchesPrefix(id, collection))\n .sort()\n\n let toDelete: string[] = []\n\n if (options.keepVersions !== undefined) {\n // Keep only the N most recent, delete the rest\n const keep = options.keepVersions\n if (matchingIds.length > keep) {\n toDelete = matchingIds.slice(0, matchingIds.length - keep)\n }\n }\n\n if (options.beforeDate) {\n // Delete entries older than the specified date\n for (const id of matchingIds) {\n if (toDelete.includes(id)) continue\n const envelope = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (envelope && envelope._ts < options.beforeDate) {\n toDelete.push(id)\n }\n }\n }\n\n // Deduplicate\n const uniqueDeletes = [...new Set(toDelete)]\n\n for (const id of uniqueDeletes) {\n await adapter.delete(vault, HISTORY_COLLECTION, id)\n }\n\n return uniqueDeletes.length\n}\n\n/** Clear all history for a vault, optionally scoped to a collection or record. */\nexport async function clearHistory(\n adapter: NoydbStore,\n vault: string,\n collection?: string,\n recordId?: string,\n): Promise<number> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n let toDelete: string[]\n\n if (collection && recordId) {\n toDelete = allIds.filter(id => matchesPrefix(id, collection, recordId))\n } else if (collection) {\n toDelete = allIds.filter(id => matchesPrefix(id, collection))\n } else {\n toDelete = allIds\n }\n\n for (const id of toDelete) {\n await adapter.delete(vault, HISTORY_COLLECTION, id)\n }\n\n return toDelete.length\n}\n\n/**\n * Crypto-shred every `_history` version of a record. Each non-tombstone\n * history envelope is OVERWRITTEN in place with a tombstone\n * `{ _noydb, _v, _ts: now, _by: actor, _iv: '', _data: '' }` — dropping\n * `_iv`/`_data`/`_cek`/`_det`, so the prior ciphertext (and the wrapped CEK\n * that could decrypt it) is gone everywhere this store reaches. The version\n * counter (`_v`) is preserved so the audit trail still shows \"N versions\n * existed and were erased.\"\n *\n * Overwrite — NOT delete — so the history key itself survives as proof the\n * version existed. Already-tombstoned versions (re-run / idempotent forget)\n * are left untouched and not counted.\n *\n * Returns the number of history versions newly tombstoned.\n */\nexport async function tombstoneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n actor: string,\n encrypted: boolean,\n): Promise<number> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds.filter(id => matchesPrefix(id, collection, recordId))\n\n const now = new Date().toISOString()\n let count = 0\n for (const id of matchingIds) {\n const env = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (!env) continue\n // Already a tombstone (no body and no wrapped CEK)? Skip — idempotent.\n if (isTombstone(env, encrypted)) continue\n // `by` rides on the IDENTITY — passing it in the body went through a\n // conditional spread, which TypeScript does not excess-property-check, so\n // it was silently dropped once `_by` moved to the identity (#1041).\n const tombstone: EncryptedEnvelope = buildRecordEnvelope(\n { collection: HISTORY_COLLECTION, id, ...(actor ? { by: actor } : {}), version: env._v },\n { ts: now, iv: '', data: '' },\n )\n await adapter.put(vault, HISTORY_COLLECTION, id, tombstone)\n count++\n }\n return count\n}\n\n/**\n * Re-key every `_history` snapshot of a record from `fromDek` to `toDek`.\n * Mirrors what `rewrapBodyToDek` already does for a record's LIVE body on a\n * tier move (elevate/demote/putAtTier) — each `_history` envelope also\n * carries its own `_cek`, wrapped under the collection's tier-0 DEK at write\n * time (`record-codec.ts`), so a tier move that rewraps only the live\n * envelope leaves prior versions decryptable at rest under the tier the\n * record left. This is defense-in-depth *beneath* the read-gate\n * (`history()`/`getVersion()` already return empty for an elevated record;\n * this protects the ciphertext even if that gate is bypassed).\n *\n * Rewraps content in place — unlike `tombstoneHistory`, it does NOT blank\n * `_iv`/`_data`/`_cek` — so a subsequent `demote()` restores tier-0\n * readability. Tombstone-shaped entries (a forgotten/shredded version —\n * blanked `_data`, no `_cek`) are skipped: there is no key material left to\n * rewrap.\n *\n * **Legacy fallback.** A snapshot written before this fix stays wrapped\n * under the tier-0 DEK even after its live record has since moved tiers, so\n * a rewrap attempted with a tier-N `fromDek` fails to unwrap/decrypt. When\n * the caller supplies `tier0Dek`, a failed rewrap is retried once with\n * `tier0Dek` as `fromDek` (the only other key a pre-fix snapshot can be\n * wrapped under — history is written only by tier-0 `put()`). The output is\n * always wrapped under `toDek` regardless of which `fromDek` succeeded. A\n * rewrap that fails under BOTH keys re-throws — that is real corruption, not\n * a tier mismatch, and must not be swallowed.\n *\n * **Crash-atomicity / idempotency (#712 whole-branch-fix-3).** This loop has\n * no transaction around it: a crash after some entries have been rewritten\n * under `toDek` but before the loop finishes leaves the record's history\n * split across two keys. A retry of the SAME call must not re-fail on the\n * entries that already made it — so each entry is probed with\n * `isRewrappedUnder(env, toDek)` FIRST; a match means it's already at the\n * target key and is skipped (put nothing). This makes same-target retries\n * and demote-after-crash fully self-healing. It does NOT close every crash\n * window: a crash that lands SOME entries under `toDek` while the record's\n * NEXT move target differs from this call's `toDek` (an intermediate-tier\n * crash — e.g. elevate 0→1 crashes mid-loop, then the record is moved 1→2)\n * still finds those entries unreadable under either `fromDek` or the\n * tier-0 fallback, since `toDek` is a third key the next call never probes\n * for. That residual window is an accepted, fail-closed limitation (see\n * `.changeset/history-at-rest.md` and the design doc) — availability is\n * lost, never confidentiality.\n */\nexport async function rewrapHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n fromDek: EnclaveKey,\n toDek: EnclaveKey,\n tier0Dek?: EnclaveKey,\n): Promise<void> {\n const allIds = await adapter.list(vault, HISTORY_COLLECTION)\n const matchingIds = allIds.filter(id => matchesPrefix(id, collection, recordId))\n\n for (const id of matchingIds) {\n const env = await adapter.get(vault, HISTORY_COLLECTION, id)\n if (!env) continue\n // Already a tombstone (forgotten/shredded version)? Nothing to rewrap.\n if (isTombstoneShape(env)) continue\n // #712/whole-branch-fix-3: toDek-first idempotency skip — already at the\n // target key (a same-target retry, or demote-after-crash landing back on\n // a key it already reached)? Nothing to do; put nothing.\n // In-place re-key of a `_history` entry: the address does not move, so the\n // same identity opens and re-seals it (#1041). Built from the entry itself,\n // exactly as a reader would via `recordAadFor`.\n const identity = {\n collection: HISTORY_COLLECTION, id, version: env._v,\n ...(env._tier !== undefined ? { tier: env._tier } : {}),\n ...(env._by !== undefined ? { by: env._by } : {}),\n }\n if (await isRewrappedUnder(identity, env, toDek)) continue\n\n let next: EncryptedEnvelope\n try {\n next = await rewrapEnvelope(identity, env, fromDek, toDek)\n } catch (err) {\n if (!tier0Dek) throw err\n // Legacy fallback: retry once under the tier-0 DEK. A failure here is\n // real corruption, not a tier mismatch — let it propagate.\n next = await rewrapEnvelope(identity, env, tier0Dek, toDek)\n }\n\n await adapter.put(vault, HISTORY_COLLECTION, id, next)\n }\n}\n","/**\n * Strategy seam for the optional history + ledger + time-machine\n * service. Core imports `HistoryStrategy` type-only + `NO_HISTORY`\n * stub; real implementations of `saveHistory`, `LedgerStore`,\n * `VaultInstant`, `computePatch`, `diff` etc. are only reachable via\n * `withHistory()` in `./active.ts`.\n *\n * Applications that don't track per-record versioning, don't need the\n * hash-chained audit ledger, and don't restore to past instants ship\n * none of the ~1,880 LOC behind this seam.\n *\n * Strategy contract:\n *\n * - **saveHistory / pruneHistory / clearHistory** — no-ops under\n * NO_HISTORY. Writes still succeed; no snapshot is captured.\n * - **getHistoryEntries / getVersionEnvelope / diff** — throw under\n * NO_HISTORY. These are read APIs the consumer would only call\n * after explicitly asking for history; the throw guides them to\n * `@noy-db/hub/history`.\n * - **envelopePayloadHash / computePatch** — return empty / `[]`\n * under NO_HISTORY. These are only used inside the\n * `if (this.ledger)` branch, which is itself gated by\n * `buildLedger()` returning null.\n * - **buildLedger** — returns `null` under NO_HISTORY. The Vault's\n * public `vault.ledger()` accessor throws when null.\n * - **buildVaultInstant** — throws under NO_HISTORY. `vault.at()`\n * propagates the throw.\n *\n * @internal\n */\n\nimport type {\n EncryptedEnvelope,\n NoydbStore,\n HistoryOptions,\n PruneOptions,\n} from '../../kernel/types.js'\nimport type { LedgerStore } from './ledger/store.js'\nimport type { JsonPatch } from './ledger/patch.js'\nimport type { DiffEntry } from './diff.js'\nimport type { VaultInstant, VaultEngine } from './time-machine.js'\nimport type { EnclaveKey, RecordIdentity } from '../../kernel/enclave/index.js'\nimport { historyIdentity } from './history.js'\n\n/**\n * Options accepted by `HistoryStrategy.buildLedger`. Mirrors the\n * `LedgerStore` constructor verbatim — kept in this file so `core`\n * code never imports the LedgerStore module at runtime.\n *\n * @internal\n */\nexport interface BuildLedgerOptions {\n adapter: NoydbStore\n vault: string\n encrypted: boolean\n getDEK: (collectionName: string) => Promise<EnclaveKey>\n actor: string\n}\n\n/**\n * @internal\n */\nexport interface HistoryStrategy {\n /**\n * Persist a full encrypted envelope snapshot of the prior version\n * under `_history/{collection}:{id}:{paddedVersion}`. No-op under\n * `NO_HISTORY`.\n */\n saveHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n envelope: EncryptedEnvelope,\n ): Promise<void>\n\n /**\n * The identity a snapshot of `collection/recordId@version` must be **sealed\n * against** — its `_history` storage location (#1041).\n *\n * On the port because the kernel writes history snapshots but must not import\n * `with-commit` to learn its layout. Exposing it here keeps the derivation in\n * the module that owns the layout, and `saveHistory` uses the same function,\n * so the sealed identity and the put location cannot drift.\n */\n historyIdentity(collection: string, recordId: string, version: number): RecordIdentity\n\n /**\n * List history envelopes for a record, newest first. Throws under\n * `NO_HISTORY` — callers reach this via `collection.history()` /\n * `collection.getVersion()` / `collection.diff()`, which only work\n * with the strategy enabled.\n */\n getHistoryEntries(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n options?: HistoryOptions,\n ): Promise<EncryptedEnvelope[]>\n\n /**\n * Fetch a specific version's envelope. Throws under `NO_HISTORY`.\n */\n getVersionEnvelope(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n version: number,\n ): Promise<EncryptedEnvelope | null>\n\n /**\n * Prune history entries by retention rule. Returns `0` under\n * `NO_HISTORY`.\n */\n pruneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string | undefined,\n options: PruneOptions,\n ): Promise<number>\n\n /**\n * Clear all history for vault/collection/record. Returns `0` under\n * `NO_HISTORY`.\n */\n clearHistory(\n adapter: NoydbStore,\n vault: string,\n collection?: string,\n recordId?: string,\n ): Promise<number>\n\n /**\n * Crypto-shred (overwrite-to-tombstone) every `_history` version of a\n * record for GDPR erasure. Returns the number of versions newly\n * tombstoned, or `0` under `NO_HISTORY` (no history = nothing to shred).\n */\n tombstoneHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n actor: string,\n encrypted: boolean,\n ): Promise<number>\n\n /**\n * Re-key every `_history` snapshot of a record from `fromDek` to `toDek`\n * on a tier move (elevate/demote/putAtTier), mirroring the live-body\n * rewrap so prior versions are not left decryptable at rest under a tier\n * the record has moved away from. Optional `tier0Dek` enables the legacy\n * fallback for snapshots written before this rewrap existed (see\n * `history.ts` for the full contract). No-op under `NO_HISTORY` (no\n * history = nothing to rewrap).\n */\n rewrapHistory(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n recordId: string,\n fromDek: EnclaveKey,\n toDek: EnclaveKey,\n tier0Dek?: EnclaveKey,\n ): Promise<void>\n\n /**\n * Compute the SHA-256 hash of an envelope's encrypted payload, used\n * by `LedgerStore.append` to track tamper-evidence. Returns the\n * empty string under `NO_HISTORY` (the call site is gated by\n * `if (this.ledger)`, so the value is never observed).\n */\n envelopePayloadHash(envelope: EncryptedEnvelope | null): Promise<string>\n\n /**\n * Compute the JSON patch from `from` → `to`. Returns `[]` under\n * `NO_HISTORY`.\n */\n computePatch(from: unknown, to: unknown): JsonPatch\n\n /**\n * Compute the typed diff between two records. Throws under\n * `NO_HISTORY` — `collection.diff()` is a history-read API.\n */\n diff(recordA: unknown, recordB: unknown): DiffEntry[]\n\n /**\n * Construct (or return null) a `LedgerStore` for the vault. Returns\n * `null` under `NO_HISTORY`; the Vault treats null as \"no ledger\n * attached\" — collection write paths skip the append branch and the\n * public `vault.ledger()` accessor throws.\n */\n buildLedger(opts: BuildLedgerOptions): LedgerStore | null\n\n /**\n * Construct a `VaultInstant` for time-machine reads. Throws under\n * `NO_HISTORY`.\n */\n buildVaultInstant(engine: VaultEngine, timestamp: string): VaultInstant\n}\n\n/**\n * Error thrown when the consumer reaches a history-gated surface\n * without opting into the strategy. The message names the offending\n * operation and points to the subpath import.\n *\n * @internal\n */\nfunction notEnabled(op: string): Error {\n return new Error(\n `${op} requires the history strategy. Import ` +\n '`{ withHistory }` from \"@noy-db/hub/history\" and pass it to ' +\n '`createNoydb({ historyStrategy: withHistory() })`.',\n )\n}\n\n/**\n * No-history stub. Snapshots and prune/clear are no-ops; reads and\n * time-machine throw with an actionable message; ledger construction\n * returns null so the write-path's `if (this.ledger)` branch is dead\n * code in the bundle.\n *\n * @internal\n */\nexport const NO_HISTORY: HistoryStrategy = {\n async saveHistory() {},\n // Unreachable in practice — `saveHistory` above is a no-op, so nothing is\n // ever sealed. Returns the real layout rather than a sentinel so a future\n // caller that reads it without writing cannot be misled.\n historyIdentity: (collection, recordId, version) => historyIdentity(collection, recordId, version),\n async getHistoryEntries() { throw notEnabled('collection.history()') },\n async getVersionEnvelope() { throw notEnabled('collection.getVersion()') },\n async pruneHistory() { return 0 },\n async clearHistory() { return 0 },\n async tombstoneHistory() { return 0 },\n async rewrapHistory() {},\n async envelopePayloadHash() { return '' },\n computePatch() { return [] },\n diff() { throw notEnabled('collection.diff()') },\n buildLedger() { return null },\n buildVaultInstant() { throw notEnabled('vault.at() / vault.timeMachine()') },\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import {
|
|
2
2
|
pickLocale
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-LF6DMX4C.js";
|
|
4
4
|
import {
|
|
5
5
|
sha256Hex
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-W5LHQXZU.js";
|
|
7
7
|
import {
|
|
8
|
-
|
|
9
|
-
|
|
8
|
+
PodIntegrityError,
|
|
9
|
+
PodSealMismatchError,
|
|
10
10
|
ValidationError
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-JBIV4FLR.js";
|
|
12
12
|
|
|
13
13
|
// src/with-pod/format.ts
|
|
14
|
-
var
|
|
15
|
-
var
|
|
16
|
-
var
|
|
17
|
-
var
|
|
14
|
+
var NOYDB_POD_MAGIC = new Uint8Array([78, 68, 66, 49]);
|
|
15
|
+
var NOYDB_POD_PREFIX_BYTES = 10;
|
|
16
|
+
var NOYDB_POD_FORMAT_VERSION = 1;
|
|
17
|
+
var NOYDB_POD_FORMAT_VERSION_SIGNED = 2;
|
|
18
18
|
var FLAG_COMPRESSED = 1;
|
|
19
19
|
var FLAG_HAS_INTEGRITY_HASH = 2;
|
|
20
20
|
var COMPRESSION_NONE = 0;
|
|
@@ -63,7 +63,7 @@ var REDIRECT_REASONS = /* @__PURE__ */ new Set([
|
|
|
63
63
|
"tombstone",
|
|
64
64
|
"repoint"
|
|
65
65
|
]);
|
|
66
|
-
function
|
|
66
|
+
function validatePodHeaderFields(parsed) {
|
|
67
67
|
if (parsed === null || typeof parsed !== "object") {
|
|
68
68
|
throw new Error(
|
|
69
69
|
`.noydb bundle header must be a JSON object, got ${parsed === null ? "null" : typeof parsed}`
|
|
@@ -77,9 +77,9 @@ function validateBundleHeader(parsed) {
|
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
79
|
const h = parsed;
|
|
80
|
-
if (typeof h["formatVersion"] !== "number" || h["formatVersion"] !==
|
|
80
|
+
if (typeof h["formatVersion"] !== "number" || h["formatVersion"] !== NOYDB_POD_FORMAT_VERSION && h["formatVersion"] !== NOYDB_POD_FORMAT_VERSION_SIGNED) {
|
|
81
81
|
throw new Error(
|
|
82
|
-
`.noydb bundle header.formatVersion must be ${
|
|
82
|
+
`.noydb bundle header.formatVersion must be ${NOYDB_POD_FORMAT_VERSION} or ${NOYDB_POD_FORMAT_VERSION_SIGNED}, got ${String(h["formatVersion"])}. The reader does not support forward-compat versions; upgrade the reader to handle newer bundles.`
|
|
83
83
|
);
|
|
84
84
|
}
|
|
85
85
|
if (typeof h["handle"] !== "string" || !/^[0-9A-HJKMNP-TV-Z]{26}$/.test(h["handle"])) {
|
|
@@ -264,14 +264,14 @@ function validateBundleHeader(parsed) {
|
|
|
264
264
|
`.noydb bundle header.sig, .keyId, and .sigAlg must be present together or not at all (got ${sigFieldsPresent} of 3).`
|
|
265
265
|
);
|
|
266
266
|
}
|
|
267
|
-
if (sigFieldsPresent === 3 && h["formatVersion"] !==
|
|
267
|
+
if (sigFieldsPresent === 3 && h["formatVersion"] !== NOYDB_POD_FORMAT_VERSION_SIGNED) {
|
|
268
268
|
throw new Error(
|
|
269
|
-
`.noydb bundle header with sig/keyId/sigAlg must have formatVersion === ${
|
|
269
|
+
`.noydb bundle header with sig/keyId/sigAlg must have formatVersion === ${NOYDB_POD_FORMAT_VERSION_SIGNED}, got ${String(h["formatVersion"])}.`
|
|
270
270
|
);
|
|
271
271
|
}
|
|
272
272
|
}
|
|
273
|
-
function
|
|
274
|
-
|
|
273
|
+
function encodePodHeader(header) {
|
|
274
|
+
validatePodHeaderFields(header);
|
|
275
275
|
const json = JSON.stringify({
|
|
276
276
|
formatVersion: header.formatVersion,
|
|
277
277
|
handle: header.handle,
|
|
@@ -297,7 +297,7 @@ function encodeBundleHeader(header) {
|
|
|
297
297
|
});
|
|
298
298
|
return new TextEncoder().encode(json);
|
|
299
299
|
}
|
|
300
|
-
function
|
|
300
|
+
function decodePodHeader(bytes) {
|
|
301
301
|
const json = new TextDecoder("utf-8", { fatal: true }).decode(bytes);
|
|
302
302
|
let parsed;
|
|
303
303
|
try {
|
|
@@ -307,7 +307,7 @@ function decodeBundleHeader(bytes) {
|
|
|
307
307
|
`.noydb bundle header is not valid JSON: ${err.message}`
|
|
308
308
|
);
|
|
309
309
|
}
|
|
310
|
-
|
|
310
|
+
validatePodHeaderFields(parsed);
|
|
311
311
|
return parsed;
|
|
312
312
|
}
|
|
313
313
|
function readUint32BE(bytes, offset) {
|
|
@@ -319,10 +319,10 @@ function writeUint32BE(bytes, offset, value) {
|
|
|
319
319
|
bytes[offset + 2] = value >>> 8 & 255;
|
|
320
320
|
bytes[offset + 3] = value & 255;
|
|
321
321
|
}
|
|
322
|
-
function
|
|
323
|
-
if (bytes.length <
|
|
324
|
-
for (let i = 0; i <
|
|
325
|
-
if (bytes[i] !==
|
|
322
|
+
function hasNoydbPodMagic(bytes) {
|
|
323
|
+
if (bytes.length < NOYDB_POD_MAGIC.length) return false;
|
|
324
|
+
for (let i = 0; i < NOYDB_POD_MAGIC.length; i++) {
|
|
325
|
+
if (bytes[i] !== NOYDB_POD_MAGIC[i]) return false;
|
|
326
326
|
}
|
|
327
327
|
return true;
|
|
328
328
|
}
|
|
@@ -340,7 +340,7 @@ async function verifyRecord(publicKeyB64, sig, payload) {
|
|
|
340
340
|
return ed25519Verify(publicKeyB64, sig, signedBytes(payload));
|
|
341
341
|
}
|
|
342
342
|
|
|
343
|
-
// src/with-pod/
|
|
343
|
+
// src/with-pod/pod.ts
|
|
344
344
|
var WRITE_POD_OPTION_KEYS = [
|
|
345
345
|
"compression",
|
|
346
346
|
"collections",
|
|
@@ -447,7 +447,7 @@ function validateAutoUnlockOptions(opts, normalized) {
|
|
|
447
447
|
const provider = normalized.provider;
|
|
448
448
|
if (provider === void 0 || typeof provider.publishRecipientHint !== "function" || typeof provider.sealForRecipient !== "function") {
|
|
449
449
|
throw new ValidationError(
|
|
450
|
-
"writePod: `sealedCredentials.provider` for mode 'recipient-target' must be a RecipientSealer (publishRecipientHint + sealForRecipient). Self-only providers (
|
|
450
|
+
"writePod: `sealedCredentials.provider` for mode 'recipient-target' must be a RecipientSealer (publishRecipientHint + sealForRecipient). Self-only providers (MemorySealer, at-macos-keychain, etc.) do not satisfy this contract."
|
|
451
451
|
);
|
|
452
452
|
}
|
|
453
453
|
const hints = normalized.hints;
|
|
@@ -493,7 +493,7 @@ function validateAutoUnlockOptions(opts, normalized) {
|
|
|
493
493
|
}
|
|
494
494
|
if (normalized.provider === void 0) {
|
|
495
495
|
throw new ValidationError(
|
|
496
|
-
"writePod: `sealedCredentials.provider` (or `sealedSecrets.provider`) is required (a `
|
|
496
|
+
"writePod: `sealedCredentials.provider` (or `sealedSecrets.provider`) is required (a `NoydbSealer`)."
|
|
497
497
|
);
|
|
498
498
|
}
|
|
499
499
|
const userCount = Object.keys(normalized.perUser).length;
|
|
@@ -562,30 +562,30 @@ function parseAutoUnlockBody(bodyString) {
|
|
|
562
562
|
try {
|
|
563
563
|
parsed = JSON.parse(bodyString);
|
|
564
564
|
} catch (err) {
|
|
565
|
-
throw new
|
|
565
|
+
throw new PodIntegrityError(
|
|
566
566
|
"header declared autoUnlock but body could not be parsed as JSON wrapper: " + (err instanceof Error ? err.message : String(err))
|
|
567
567
|
);
|
|
568
568
|
}
|
|
569
569
|
if (typeof parsed !== "object" || parsed === null) {
|
|
570
|
-
throw new
|
|
570
|
+
throw new PodIntegrityError("autoUnlock body is not a JSON object");
|
|
571
571
|
}
|
|
572
572
|
const obj = parsed;
|
|
573
573
|
if (obj["_noydb_bundle_body"] !== 1) {
|
|
574
|
-
throw new
|
|
574
|
+
throw new PodIntegrityError(
|
|
575
575
|
"autoUnlock body missing `_noydb_bundle_body: 1` discriminator"
|
|
576
576
|
);
|
|
577
577
|
}
|
|
578
578
|
if (typeof obj["dump"] !== "string") {
|
|
579
|
-
throw new
|
|
579
|
+
throw new PodIntegrityError("autoUnlock body must carry a string `dump` field");
|
|
580
580
|
}
|
|
581
581
|
const blob = obj["_autoUnlock"];
|
|
582
582
|
if (typeof blob !== "object" || blob === null) {
|
|
583
|
-
throw new
|
|
583
|
+
throw new PodIntegrityError("autoUnlock body missing `_autoUnlock` blob");
|
|
584
584
|
}
|
|
585
585
|
const blobObj = blob;
|
|
586
586
|
const kind = blobObj["kind"];
|
|
587
587
|
if (kind !== "unsealed" && kind !== "sealed") {
|
|
588
|
-
throw new
|
|
588
|
+
throw new PodIntegrityError(
|
|
589
589
|
`autoUnlock blob has invalid kind ${String(kind)}; expected 'unsealed' or 'sealed'`
|
|
590
590
|
);
|
|
591
591
|
}
|
|
@@ -602,29 +602,29 @@ function parseExtractedPartitionBody(bodyString) {
|
|
|
602
602
|
try {
|
|
603
603
|
parsed = JSON.parse(bodyString);
|
|
604
604
|
} catch (err) {
|
|
605
|
-
throw new
|
|
605
|
+
throw new PodIntegrityError(
|
|
606
606
|
"header declared extracted-partition but body could not be parsed as JSON wrapper: " + (err instanceof Error ? err.message : String(err))
|
|
607
607
|
);
|
|
608
608
|
}
|
|
609
609
|
if (typeof parsed !== "object" || parsed === null) {
|
|
610
|
-
throw new
|
|
610
|
+
throw new PodIntegrityError("extracted-partition body is not a JSON object");
|
|
611
611
|
}
|
|
612
612
|
const obj = parsed;
|
|
613
613
|
if (obj["_noydb_bundle_body"] !== 1) {
|
|
614
|
-
throw new
|
|
614
|
+
throw new PodIntegrityError(
|
|
615
615
|
"extracted-partition body missing `_noydb_bundle_body: 1` discriminator"
|
|
616
616
|
);
|
|
617
617
|
}
|
|
618
618
|
if (typeof obj["dump"] !== "string") {
|
|
619
|
-
throw new
|
|
619
|
+
throw new PodIntegrityError("extracted-partition body must carry a string `dump` field");
|
|
620
620
|
}
|
|
621
621
|
const seal = obj["_transferSeal"];
|
|
622
622
|
if (typeof seal !== "object" || seal === null) {
|
|
623
|
-
throw new
|
|
623
|
+
throw new PodIntegrityError("extracted-partition body missing `_transferSeal` blob");
|
|
624
624
|
}
|
|
625
625
|
const s = seal;
|
|
626
626
|
if (s["v"] !== 1 || s["alg"] !== "aes-256-gcm-pre-shared" || typeof s["sealId"] !== "string" || typeof s["payload"] !== "string") {
|
|
627
|
-
throw new
|
|
627
|
+
throw new PodIntegrityError("extracted-partition `_transferSeal` blob is malformed");
|
|
628
628
|
}
|
|
629
629
|
return { dump: obj["dump"], seal };
|
|
630
630
|
}
|
|
@@ -670,7 +670,7 @@ async function resolveAutoUnlock(blob, opts) {
|
|
|
670
670
|
unsealedMap[userId] = { kind: credKind, value: entry.sealed };
|
|
671
671
|
continue;
|
|
672
672
|
}
|
|
673
|
-
throw new
|
|
673
|
+
throw new PodSealMismatchError(userId, entry.pid);
|
|
674
674
|
}
|
|
675
675
|
unsealedMap[userId] = { kind: credKind, value: opened };
|
|
676
676
|
continue;
|
|
@@ -679,7 +679,7 @@ async function resolveAutoUnlock(blob, opts) {
|
|
|
679
679
|
unsealedMap[userId] = { kind: credKind, value: entry.sealed };
|
|
680
680
|
continue;
|
|
681
681
|
}
|
|
682
|
-
throw new
|
|
682
|
+
throw new PodSealMismatchError(userId, entry.pid);
|
|
683
683
|
}
|
|
684
684
|
const plaintextBytes = await provider.unseal(base64ToBytes(entry.sealed));
|
|
685
685
|
unsealedMap[userId] = { kind: credKind, value: decoder.decode(plaintextBytes) };
|
|
@@ -812,7 +812,7 @@ async function applySatelliteLivenessFilter(vault, dumpJson) {
|
|
|
812
812
|
if (!backup.collections || typeof backup.collections !== "object") return dumpJson;
|
|
813
813
|
if (typeof vault._introspectState !== "function") return dumpJson;
|
|
814
814
|
const { adapter, name, getDEK } = vault._introspectState();
|
|
815
|
-
const { liveBaseIdSetsForBundle } = await import("./dead-filter-
|
|
815
|
+
const { liveBaseIdSetsForBundle } = await import("./dead-filter-QKU56XTQ.js");
|
|
816
816
|
const satLive = await liveBaseIdSetsForBundle(adapter, name, Object.keys(backup.collections), getDEK);
|
|
817
817
|
if (satLive.size === 0) return dumpJson;
|
|
818
818
|
const next = {};
|
|
@@ -852,7 +852,8 @@ async function applyPlaintextFilters(vault, dumpJson, opts) {
|
|
|
852
852
|
if (where !== void 0) {
|
|
853
853
|
const record = await vault._decryptEnvelopeForBundleFilter(
|
|
854
854
|
env,
|
|
855
|
-
collName
|
|
855
|
+
collName,
|
|
856
|
+
id
|
|
856
857
|
);
|
|
857
858
|
const ok = await where(record, { collection: collName, id });
|
|
858
859
|
if (!ok) continue;
|
|
@@ -864,13 +865,13 @@ async function applyPlaintextFilters(vault, dumpJson, opts) {
|
|
|
864
865
|
backup.collections = next;
|
|
865
866
|
return JSON.stringify(backup);
|
|
866
867
|
}
|
|
867
|
-
async function
|
|
868
|
+
async function assemblePodContainer(opts) {
|
|
868
869
|
const dumpBytes = new TextEncoder().encode(opts.bodyJsonStr);
|
|
869
870
|
const { format, streamFormat } = selectCompression(opts.compression);
|
|
870
871
|
const body = streamFormat === null ? dumpBytes : await pumpThroughStream(dumpBytes, new CompressionStream(streamFormat));
|
|
871
872
|
const bodySha256 = await sha256Hex2(body);
|
|
872
873
|
const header = {
|
|
873
|
-
formatVersion:
|
|
874
|
+
formatVersion: NOYDB_POD_FORMAT_VERSION,
|
|
874
875
|
handle: opts.handle,
|
|
875
876
|
bodyBytes: body.length,
|
|
876
877
|
bodySha256,
|
|
@@ -886,13 +887,13 @@ async function assembleBundleContainer(opts) {
|
|
|
886
887
|
...opts.headerExtras?.redirect !== void 0 ? { redirect: opts.headerExtras.redirect } : {}
|
|
887
888
|
};
|
|
888
889
|
const signed = opts.signer === void 0 ? header : await (async (s) => {
|
|
889
|
-
const toSign = { ...header, formatVersion:
|
|
890
|
+
const toSign = { ...header, formatVersion: NOYDB_POD_FORMAT_VERSION_SIGNED, keyId: s.keyId, sigAlg: "ed25519" };
|
|
890
891
|
const sig = await signRecord(s.privateKeyPkcs8B64, toSign);
|
|
891
892
|
return { ...toSign, sig };
|
|
892
893
|
})(opts.signer);
|
|
893
|
-
const headerBytes =
|
|
894
|
-
const prefix = new Uint8Array(
|
|
895
|
-
prefix.set(
|
|
894
|
+
const headerBytes = encodePodHeader(signed);
|
|
895
|
+
const prefix = new Uint8Array(NOYDB_POD_PREFIX_BYTES);
|
|
896
|
+
prefix.set(NOYDB_POD_MAGIC, 0);
|
|
896
897
|
prefix[4] = (streamFormat === null ? 0 : FLAG_COMPRESSED) | FLAG_HAS_INTEGRITY_HASH;
|
|
897
898
|
prefix[5] = format;
|
|
898
899
|
writeUint32BE(prefix, 6, headerBytes.length);
|
|
@@ -907,7 +908,7 @@ async function writePod(vault, opts = {}) {
|
|
|
907
908
|
}
|
|
908
909
|
const normalizedAutoUnlock = normalizeAutoUnlock(opts);
|
|
909
910
|
const autoUnlockMode = validateAutoUnlockOptions(opts, normalizedAutoUnlock);
|
|
910
|
-
const handle = await vault.
|
|
911
|
+
const handle = await vault.getPodHandle();
|
|
911
912
|
const dumpJson = await vault.dump();
|
|
912
913
|
const satelliteFiltered = await applySatelliteLivenessFilter(vault, dumpJson);
|
|
913
914
|
const rekeyed = await applyRecipientRewrap(vault, satelliteFiltered, opts);
|
|
@@ -916,7 +917,7 @@ async function writePod(vault, opts = {}) {
|
|
|
916
917
|
const bodyJsonStr = normalizedAutoUnlock === null ? filtered : JSON.stringify(await buildAutoUnlockWrapper(filtered, normalizedAutoUnlock));
|
|
917
918
|
const cover = await vault.getCover();
|
|
918
919
|
const signer = opts.sign === false ? void 0 : opts.sign !== void 0 ? opts.sign : await vault._loadPodSigner() ?? void 0;
|
|
919
|
-
return
|
|
920
|
+
return assemblePodContainer({
|
|
920
921
|
handle,
|
|
921
922
|
bodyJsonStr,
|
|
922
923
|
compression: opts.compression,
|
|
@@ -935,16 +936,15 @@ async function writePod(vault, opts = {}) {
|
|
|
935
936
|
...signer !== void 0 ? { signer } : {}
|
|
936
937
|
});
|
|
937
938
|
}
|
|
938
|
-
var writeNoydbBundle = writePod;
|
|
939
939
|
function parsePrefixAndHeader(bytes) {
|
|
940
|
-
if (!
|
|
940
|
+
if (!hasNoydbPodMagic(bytes)) {
|
|
941
941
|
throw new Error(
|
|
942
942
|
`Not a .noydb bundle: missing 'NDB1' magic prefix. The first 4 bytes are ${[...bytes.slice(0, 4)].map((b) => b.toString(16).padStart(2, "0")).join(" ")}.`
|
|
943
943
|
);
|
|
944
944
|
}
|
|
945
|
-
if (bytes.length <
|
|
945
|
+
if (bytes.length < NOYDB_POD_PREFIX_BYTES) {
|
|
946
946
|
throw new Error(
|
|
947
|
-
`Truncated .noydb bundle: file is only ${bytes.length} bytes, which is less than the ${
|
|
947
|
+
`Truncated .noydb bundle: file is only ${bytes.length} bytes, which is less than the ${NOYDB_POD_PREFIX_BYTES}-byte fixed prefix.`
|
|
948
948
|
);
|
|
949
949
|
}
|
|
950
950
|
const flags = bytes[4];
|
|
@@ -955,20 +955,19 @@ function parsePrefixAndHeader(bytes) {
|
|
|
955
955
|
);
|
|
956
956
|
}
|
|
957
957
|
const headerLength = readUint32BE(bytes, 6);
|
|
958
|
-
const bodyOffset =
|
|
958
|
+
const bodyOffset = NOYDB_POD_PREFIX_BYTES + headerLength;
|
|
959
959
|
if (bodyOffset > bytes.length) {
|
|
960
960
|
throw new Error(
|
|
961
961
|
`Truncated .noydb bundle: declared header length ${headerLength} would extend past end of file (${bytes.length} bytes).`
|
|
962
962
|
);
|
|
963
963
|
}
|
|
964
|
-
const headerBytes = bytes.slice(
|
|
965
|
-
const header =
|
|
964
|
+
const headerBytes = bytes.slice(NOYDB_POD_PREFIX_BYTES, bodyOffset);
|
|
965
|
+
const header = decodePodHeader(headerBytes);
|
|
966
966
|
return { header, bodyOffset, algo, flags };
|
|
967
967
|
}
|
|
968
968
|
function readPodHeader(bytes) {
|
|
969
969
|
return parsePrefixAndHeader(bytes).header;
|
|
970
970
|
}
|
|
971
|
-
var readNoydbBundleHeader = readPodHeader;
|
|
972
971
|
async function verifyPodHeader(bytes, trustedKeys) {
|
|
973
972
|
const { header } = parsePrefixAndHeader(bytes);
|
|
974
973
|
if (header.sig === void 0 || header.keyId === void 0 || header.sigAlg === void 0) {
|
|
@@ -1001,13 +1000,13 @@ async function readPod(bytes, opts = {}) {
|
|
|
1001
1000
|
const { header, bodyOffset, algo } = parsePrefixAndHeader(bytes);
|
|
1002
1001
|
const body = bytes.slice(bodyOffset);
|
|
1003
1002
|
if (body.length !== header.bodyBytes) {
|
|
1004
|
-
throw new
|
|
1003
|
+
throw new PodIntegrityError(
|
|
1005
1004
|
`body length ${body.length} does not match header.bodyBytes ${header.bodyBytes}. The bundle was truncated or padded between write and read.`
|
|
1006
1005
|
);
|
|
1007
1006
|
}
|
|
1008
1007
|
const actualSha = await sha256Hex2(body);
|
|
1009
1008
|
if (actualSha !== header.bodySha256) {
|
|
1010
|
-
throw new
|
|
1009
|
+
throw new PodIntegrityError(
|
|
1011
1010
|
`body sha256 ${actualSha} does not match header.bodySha256 ${header.bodySha256}. The bundle bytes were modified between write and read \u2014 refuse to decompress.`
|
|
1012
1011
|
);
|
|
1013
1012
|
}
|
|
@@ -1019,7 +1018,7 @@ async function readPod(bytes, opts = {}) {
|
|
|
1019
1018
|
try {
|
|
1020
1019
|
dumpBytes = await pumpThroughStream(body, new DecompressionStream(streamFormat));
|
|
1021
1020
|
} catch (err) {
|
|
1022
|
-
throw new
|
|
1021
|
+
throw new PodIntegrityError(
|
|
1023
1022
|
`decompression failed: ${err.message}. The bundle passed the integrity hash but the body is not valid ${streamFormat} data \u2014 likely a producer bug.`
|
|
1024
1023
|
);
|
|
1025
1024
|
}
|
|
@@ -1032,20 +1031,19 @@ async function readPod(bytes, opts = {}) {
|
|
|
1032
1031
|
const autoUnlock = await resolveAutoUnlock(blob, opts);
|
|
1033
1032
|
return { header, dumpJson: dump, autoUnlock };
|
|
1034
1033
|
}
|
|
1035
|
-
var readNoydbBundle = readPod;
|
|
1036
1034
|
|
|
1037
1035
|
export {
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1036
|
+
NOYDB_POD_MAGIC,
|
|
1037
|
+
NOYDB_POD_PREFIX_BYTES,
|
|
1038
|
+
NOYDB_POD_FORMAT_VERSION,
|
|
1041
1039
|
FLAG_COMPRESSED,
|
|
1042
1040
|
FLAG_HAS_INTEGRITY_HASH,
|
|
1043
1041
|
COMPRESSION_NONE,
|
|
1044
1042
|
COMPRESSION_GZIP,
|
|
1045
1043
|
COMPRESSION_BROTLI,
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1044
|
+
validatePodHeaderFields,
|
|
1045
|
+
encodePodHeader,
|
|
1046
|
+
hasNoydbPodMagic,
|
|
1049
1047
|
POD_SIG_ALG,
|
|
1050
1048
|
signedBytes,
|
|
1051
1049
|
signRecord,
|
|
@@ -1053,15 +1051,12 @@ export {
|
|
|
1053
1051
|
buildExtractedPartitionWrapper,
|
|
1054
1052
|
parseExtractedPartitionBody,
|
|
1055
1053
|
resetBrotliSupportCache,
|
|
1056
|
-
|
|
1054
|
+
assemblePodContainer,
|
|
1057
1055
|
writePod,
|
|
1058
|
-
writeNoydbBundle,
|
|
1059
1056
|
readPodHeader,
|
|
1060
|
-
readNoydbBundleHeader,
|
|
1061
1057
|
verifyPodHeader,
|
|
1062
1058
|
readPodCover,
|
|
1063
1059
|
readPodRedirect,
|
|
1064
|
-
readPod
|
|
1065
|
-
readNoydbBundle
|
|
1060
|
+
readPod
|
|
1066
1061
|
};
|
|
1067
|
-
//# sourceMappingURL=chunk-
|
|
1062
|
+
//# sourceMappingURL=chunk-6FOGTKBY.js.map
|