@noy-db/hub 0.6.0-pre.8 → 0.6.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 +7079 -0
- package/codemods/0.6.0-pre.json +211 -0
- package/dist/api-6X2VLZ7J.js +20 -0
- package/dist/attestation/index.js +19 -19
- package/dist/{backup-KULFZ2T4.js → backup-VL4GRIEW.js} +36 -18
- package/dist/backup-VL4GRIEW.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/cargo/index.js +35 -35
- package/dist/{chunk-KUDZVJKQ.js → chunk-22GR3O4J.js} +2 -2
- package/dist/{chunk-CCZJJ4I2.js → chunk-2CBFYXJX.js} +6 -6
- package/dist/{chunk-JJNOLSG5.js → chunk-2J5IT37K.js} +15 -16
- package/dist/chunk-2J5IT37K.js.map +1 -0
- package/dist/{chunk-PNKHAKQ7.js → chunk-2ZCWHCLF.js} +17 -10
- package/dist/chunk-2ZCWHCLF.js.map +1 -0
- package/dist/{chunk-2BMRJ6LQ.js → chunk-2ZT4INZ4.js} +8 -11
- package/dist/{chunk-2BMRJ6LQ.js.map → chunk-2ZT4INZ4.js.map} +1 -1
- package/dist/{chunk-FAXZQ5UF.js → chunk-323MN67Z.js} +2 -2
- package/dist/{chunk-VMCCGUQB.js → chunk-36CEG6CM.js} +2 -2
- package/dist/{chunk-PDLLCOGD.js → chunk-3OE2QNSM.js} +20 -17
- package/dist/chunk-3OE2QNSM.js.map +1 -0
- package/dist/{chunk-AHLJSVRL.js → chunk-3YGUHUJA.js} +5 -7
- package/dist/chunk-3YGUHUJA.js.map +1 -0
- package/dist/{chunk-ZJADGNYF.js → chunk-4AOERLTV.js} +1 -1
- package/dist/chunk-4AOERLTV.js.map +1 -0
- package/dist/{chunk-J7FM3RAU.js → chunk-4ATF4BLF.js} +87 -34
- package/dist/chunk-4ATF4BLF.js.map +1 -0
- package/dist/{chunk-747LRSOO.js → chunk-4K6BIMLF.js} +2 -2
- package/dist/{chunk-PXCBVDFY.js → chunk-5ATC6UT4.js} +40 -7
- package/dist/chunk-5ATC6UT4.js.map +1 -0
- package/dist/{chunk-4GZ6XOVW.js → chunk-5F7BZAGV.js} +44 -42
- package/dist/chunk-5F7BZAGV.js.map +1 -0
- package/dist/{chunk-FNSMZQS4.js → chunk-5IHGJHWC.js} +2 -2
- package/dist/{chunk-4I72F5DF.js → chunk-5LZZQMIC.js} +11 -14
- package/dist/chunk-5LZZQMIC.js.map +1 -0
- package/dist/{chunk-JXIDGFKS.js → chunk-5O5ZSW7N.js} +4 -2
- package/dist/chunk-5O5ZSW7N.js.map +1 -0
- package/dist/{chunk-CEJWMBXO.js → chunk-5OT4G5N5.js} +6 -2
- package/dist/chunk-5OT4G5N5.js.map +1 -0
- package/dist/{chunk-GAG7QOVO.js → chunk-64WHKBMP.js} +53 -18
- package/dist/chunk-64WHKBMP.js.map +1 -0
- package/dist/{chunk-7TSYBD3E.js → chunk-65JXA63J.js} +2 -2
- package/dist/{chunk-Z45YRGFO.js → chunk-6NR36UNB.js} +2 -2
- package/dist/{chunk-W77KZHCW.js → chunk-6RH7PRTL.js} +16 -17
- package/dist/chunk-6RH7PRTL.js.map +1 -0
- package/dist/{chunk-3JVXVJ7L.js → chunk-7OBIBPCV.js} +10 -10
- package/dist/{chunk-AR2JDFAE.js → chunk-7Q3RHOA5.js} +2 -2
- package/dist/chunk-7ZGPQOFV.js +190 -0
- package/dist/chunk-7ZGPQOFV.js.map +1 -0
- package/dist/{chunk-QULVCV3M.js → chunk-AJGGBXWA.js} +4 -4
- package/dist/{chunk-CADUYBQD.js → chunk-ATL3ZVXT.js} +2 -2
- package/dist/{chunk-DMQCLZ4Z.js → chunk-ATY3ZASK.js} +2 -2
- package/dist/{chunk-4HDYQL3J.js → chunk-B4CRUZPR.js} +2 -2
- package/dist/{chunk-IMZLOJTK.js → chunk-BMU2DS3S.js} +30 -21
- package/dist/chunk-BMU2DS3S.js.map +1 -0
- package/dist/{chunk-6SAFL5YE.js → chunk-BZ3WMOYX.js} +3 -3
- package/dist/{chunk-UHXCLPGC.js → chunk-C3XWJCG7.js} +2 -2
- package/dist/chunk-C3XWJCG7.js.map +1 -0
- package/dist/{chunk-HXGUIPQB.js → chunk-CKKN25P2.js} +3 -3
- package/dist/{chunk-3URQC7EH.js → chunk-CXPOG3ZY.js} +355 -132
- package/dist/chunk-CXPOG3ZY.js.map +1 -0
- package/dist/{chunk-3FSX6LDG.js → chunk-D2YFQ7XG.js} +18 -3
- package/dist/{chunk-3FSX6LDG.js.map → chunk-D2YFQ7XG.js.map} +1 -1
- package/dist/{chunk-52JPHN5N.js → chunk-D6SXRMZZ.js} +27 -149
- package/dist/chunk-D6SXRMZZ.js.map +1 -0
- package/dist/{chunk-2DHSSLOD.js → chunk-DECNV4QK.js} +13 -15
- package/dist/chunk-DECNV4QK.js.map +1 -0
- package/dist/{chunk-6BU3L4UE.js → chunk-DNKVKO7K.js} +7 -10
- package/dist/chunk-DNKVKO7K.js.map +1 -0
- package/dist/{chunk-6HFM7EIT.js → chunk-EHRIDNZX.js} +2 -2
- package/dist/{chunk-3737A6EA.js → chunk-EHW7NLGD.js} +127 -31
- package/dist/chunk-EHW7NLGD.js.map +1 -0
- package/dist/{chunk-BEFVYAR5.js → chunk-EQOTJL76.js} +4 -4
- package/dist/chunk-EQOTJL76.js.map +1 -0
- package/dist/{chunk-E6427JU2.js → chunk-EV2TDHQZ.js} +19 -3
- package/dist/chunk-EV2TDHQZ.js.map +1 -0
- package/dist/{chunk-WFUIE565.js → chunk-FNYCT27B.js} +17 -14
- package/dist/chunk-FNYCT27B.js.map +1 -0
- package/dist/{chunk-RTAMLDWP.js → chunk-FU5VYEYK.js} +2 -2
- package/dist/chunk-FX3UIDCS.js +66 -0
- package/dist/chunk-FX3UIDCS.js.map +1 -0
- package/dist/{chunk-7F4DBNSP.js → chunk-GANFIM2M.js} +135 -18
- package/dist/chunk-GANFIM2M.js.map +1 -0
- package/dist/{chunk-4VUPLMZ6.js → chunk-GCU42IG7.js} +66 -71
- package/dist/chunk-GCU42IG7.js.map +1 -0
- package/dist/{chunk-RXYYFSBB.js → chunk-GKTW3KLV.js} +4 -4
- package/dist/chunk-HK67PX4J.js +27 -0
- package/dist/chunk-HK67PX4J.js.map +1 -0
- package/dist/{chunk-OF3L2SD6.js → chunk-HOPNIR5R.js} +2 -2
- package/dist/{chunk-WLZ47GSL.js → chunk-HSJBJIB2.js} +12 -10
- package/dist/{chunk-WLZ47GSL.js.map → chunk-HSJBJIB2.js.map} +1 -1
- package/dist/{chunk-ADW22QSB.js → chunk-HWI7GHJZ.js} +4 -4
- package/dist/{chunk-GQ3BX5EA.js → chunk-I3ISCYT7.js} +2 -2
- package/dist/{chunk-YJ6IONGA.js → chunk-IWKCJCLP.js} +11 -3
- package/dist/{chunk-YJ6IONGA.js.map → chunk-IWKCJCLP.js.map} +1 -1
- package/dist/{chunk-NJDQ4YSV.js → chunk-IWQPYT6S.js} +4 -4
- package/dist/{chunk-JRKZTEZZ.js → chunk-J6I5VR6P.js} +444 -73
- package/dist/chunk-J6I5VR6P.js.map +1 -0
- package/dist/{chunk-2Z3NCLNX.js → chunk-JHYKSMVX.js} +7 -7
- package/dist/{chunk-6FJWSWFT.js → chunk-JIHWBKMQ.js} +3 -3
- package/dist/{chunk-YAWK6AWF.js → chunk-JKATP6OE.js} +2 -2
- package/dist/{chunk-PL2GHSCM.js → chunk-JMJSCI7U.js} +157 -90
- package/dist/chunk-JMJSCI7U.js.map +1 -0
- package/dist/{chunk-Q6TEJXBX.js → chunk-JXHNUYQO.js} +31 -49
- package/dist/chunk-JXHNUYQO.js.map +1 -0
- package/dist/{chunk-WK5XUYYF.js → chunk-JYPRZWCZ.js} +473 -231
- package/dist/chunk-JYPRZWCZ.js.map +1 -0
- package/dist/{chunk-5ZKS6ZE2.js → chunk-K6CPIK3R.js} +4 -4
- package/dist/chunk-K6CPIK3R.js.map +1 -0
- package/dist/{chunk-CDB2HVQW.js → chunk-KM6ZXG7U.js} +14 -15
- package/dist/chunk-KM6ZXG7U.js.map +1 -0
- package/dist/{chunk-DG27IUVI.js → chunk-LC6NE4IQ.js} +2 -2
- package/dist/{chunk-WASHZV34.js → chunk-LIR2DJWP.js} +63 -25
- package/dist/chunk-LIR2DJWP.js.map +1 -0
- package/dist/{chunk-VZ3XFUQ7.js → chunk-LUYPYCHY.js} +16 -22
- package/dist/chunk-LUYPYCHY.js.map +1 -0
- package/dist/{chunk-G6S5VVHP.js → chunk-M7WBE3OR.js} +10 -10
- package/dist/chunk-M7WBE3OR.js.map +1 -0
- package/dist/{chunk-VJFMXYKP.js → chunk-MPKP6L5E.js} +2 -2
- package/dist/{chunk-IGJCYUT5.js → chunk-NSITFOCJ.js} +1 -1
- package/dist/chunk-NSITFOCJ.js.map +1 -0
- package/dist/{chunk-FUHKW252.js → chunk-OCJ3JA4O.js} +2 -2
- package/dist/{chunk-VCETL77O.js → chunk-ONPVHX2Y.js} +36 -7
- package/dist/chunk-ONPVHX2Y.js.map +1 -0
- package/dist/{chunk-WLYIROCJ.js → chunk-OQMCFHUX.js} +2 -2
- package/dist/{chunk-JRCYZEHU.js → chunk-OR2FYRYR.js} +2 -2
- package/dist/{chunk-HNHCQ556.js → chunk-PFWE7FJG.js} +2 -2
- package/dist/{chunk-NPP5R7FF.js → chunk-PJX72ICF.js} +22 -18
- package/dist/chunk-PJX72ICF.js.map +1 -0
- package/dist/{chunk-U5O6GIWZ.js → chunk-POFYIGQ2.js} +3 -3
- package/dist/{chunk-35EBKWQU.js → chunk-QH47SQLD.js} +4 -4
- package/dist/{chunk-FZ6NYJ7L.js → chunk-QQRRKO7W.js} +11 -8
- package/dist/chunk-QQRRKO7W.js.map +1 -0
- package/dist/{chunk-HVQGCKY4.js → chunk-QVXZFJBU.js} +2 -2
- package/dist/{chunk-FMQJZH4R.js → chunk-RDB66EKD.js} +6 -6
- package/dist/{chunk-X56RTUK3.js → chunk-RJZQ2PVD.js} +3 -3
- package/dist/{chunk-SUFG5E73.js → chunk-RPRASGEY.js} +2 -2
- package/dist/{chunk-XWX7GL56.js → chunk-S2I5MYSA.js} +7 -10
- package/dist/chunk-S2I5MYSA.js.map +1 -0
- package/dist/{chunk-FFDNKRCY.js → chunk-S6PJ6ZKE.js} +2 -2
- package/dist/chunk-S6PJ6ZKE.js.map +1 -0
- package/dist/{chunk-JIUVJ4M7.js → chunk-S7PM7Z4K.js} +3 -3
- package/dist/{chunk-55LKVALY.js → chunk-T7IR4N2S.js} +1 -3
- package/dist/chunk-T7IR4N2S.js.map +1 -0
- package/dist/{chunk-N35NC4JH.js → chunk-TKBB62DN.js} +2 -2
- package/dist/{chunk-YPYHVOXP.js → chunk-UJ4Z67UQ.js} +2 -2
- package/dist/chunk-UJ4Z67UQ.js.map +1 -0
- package/dist/{chunk-7MNBICB5.js → chunk-W3HAIN6U.js} +16 -14
- package/dist/chunk-W3HAIN6U.js.map +1 -0
- package/dist/{chunk-4UVDI4XE.js → chunk-WPZ5FVAS.js} +4 -4
- package/dist/{chunk-MSWYQLMQ.js → chunk-XINT4VJA.js} +2 -2
- package/dist/{chunk-7G6VDWXB.js → chunk-XPEPMK4Y.js} +3 -3
- package/dist/chunk-XPEPMK4Y.js.map +1 -0
- package/dist/{chunk-W3TVWF6N.js → chunk-YCGLAANM.js} +2 -2
- package/dist/{chunk-O2ERS4UJ.js → chunk-YTUFV7U7.js} +80 -51
- package/dist/chunk-YTUFV7U7.js.map +1 -0
- package/dist/{chunk-FDX7OWWI.js → chunk-YYV53EHO.js} +2 -2
- package/dist/{chunk-HNGSV2YC.js → chunk-Z3BZXPRO.js} +67 -10
- package/dist/chunk-Z3BZXPRO.js.map +1 -0
- package/dist/{chunk-6NVPFKN3.js → chunk-ZIMQDXTQ.js} +92 -35
- package/dist/chunk-ZIMQDXTQ.js.map +1 -0
- package/dist/{chunk-5JY5TSVY.js → chunk-ZJUZOJVW.js} +25 -31
- package/dist/chunk-ZJUZOJVW.js.map +1 -0
- package/dist/{chunk-3IXIU6FP.js → chunk-ZY6P7M52.js} +7 -10
- package/dist/chunk-ZY6P7M52.js.map +1 -0
- package/dist/{chunk-H73G4XF4.js → chunk-ZYZJLYNS.js} +7 -11
- package/dist/chunk-ZYZJLYNS.js.map +1 -0
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-2KJAXRRO.js → classified-marker-AZDSDG6V.js} +3 -3
- package/dist/collection-facade-WSUAYFJ4.js +45 -0
- package/dist/{computed-6G5M3UPH.js → computed-VG2PCM4L.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-JNQNB3TA.js} +2 -2
- package/dist/debug/index.js +1 -1
- package/dist/{delegation-MO7YZYJS.js → delegation-5F36DRDH.js} +24 -23
- package/dist/delegation-5F36DRDH.js.map +1 -0
- package/dist/derivations/index.js +12 -12
- package/dist/derive-MPOGZ4NR.js +22 -0
- package/dist/directory/index.js +10 -10
- package/dist/{dispatch-MJ6SHB3Y.js → dispatch-3ZA733EY.js} +18 -18
- package/dist/{dispatch-FZEAWKVM.js → dispatch-TNM5CRLZ.js} +9 -6
- package/dist/dispatch-TNM5CRLZ.js.map +1 -0
- package/dist/{enclave-JU4YIEPB.js → enclave-Y2ALNDRD.js} +31 -9
- package/dist/executor-BBEEUFO3.js +9 -0
- package/dist/executor-G6G3YEWR.js +9 -0
- package/dist/executor-ZUTUMTPA.js +29 -0
- package/dist/export-accessible-S3KEB763.js +23 -0
- package/dist/extract-partition-KVCTSUVE.js +38 -0
- package/dist/{fanout-sidecar-NNAJQXMX.js → fanout-sidecar-3QZU7ZZX.js} +18 -27
- package/dist/fanout-sidecar-3QZU7ZZX.js.map +1 -0
- package/dist/find-V4FN5ITT.js +11 -0
- package/dist/forget/index.js +9 -9
- package/dist/guards/index.js +7 -7
- 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 +30 -13
- package/dist/index.js +180 -188
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +4 -4
- package/dist/introspection/index.js +11 -11
- package/dist/issue-5CFBWBRX.js +19 -0
- package/dist/kernel/collection.d.ts +8 -2
- 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 +132 -12
- package/dist/kernel/merge-authority.d.ts +25 -0
- package/dist/kernel/noydb.d.ts +27 -4
- 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/sync-policy.d.ts +0 -2
- package/dist/kernel/tier-visibility.d.ts +34 -0
- package/dist/kernel/types.d.ts +111 -13
- package/dist/kernel/vault.d.ts +14 -8
- package/dist/kernel/via/index.d.ts +11 -2
- package/dist/kernel/via/reconcile.d.ts +12 -0
- package/dist/{ledger-AETNF4OM.js → ledger-MQIIOTZB.js} +11 -11
- package/dist/liberate-LW7OKVBH.js +25 -0
- package/dist/{link-set-E5HNY67I.js → link-set-5PJBBR63.js} +11 -11
- package/dist/{managed-secret-CWQ6PND5.js → managed-secret-ETDG6AAE.js} +11 -3
- package/dist/materialized-views/index.js +24 -24
- package/dist/migrate-cek-V3VDRV24.js +19 -0
- package/dist/migrate-cek-V3VDRV24.js.map +1 -0
- package/dist/money/index.js +5 -5
- package/dist/noydb-LFDRMYZ5.js +85 -0
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +18 -12
- package/dist/pod/index.js +79 -89
- package/dist/pod-handle-AZ3CXY5Y.js +41 -0
- package/dist/pod-handle-AZ3CXY5Y.js.map +1 -0
- package/dist/policy/index.js +11 -4
- package/dist/port/to/index.d.ts +4 -4
- package/dist/port/to/locator.d.ts +54 -8
- 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 +2 -0
- 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-QCJYRMIK.js} +6 -6
- package/dist/query/index.js +6 -6
- package/dist/reduce/index.js +6 -6
- package/dist/register-JBOEHTVX.js +32 -0
- package/dist/registry-5DYHQFJS.js +9 -0
- package/dist/registry-EANV44W2.js +9 -0
- package/dist/registry-J25H6VB4.js +19 -0
- package/dist/registry-R23SQUQH.js +18 -0
- package/dist/request-withdrawal-KQ4W4UT5.js +31 -0
- package/dist/{reveal-BW36KCOQ.js → reveal-W7BKZSUP.js} +6 -6
- package/dist/revoke-H3VSTAIE.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-55FPOMYP.js} +20 -22
- package/dist/seed-55FPOMYP.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-53AQ3BU2.js +25 -0
- package/dist/snapshots/index.js +10 -10
- package/dist/snapshots/index.js.map +1 -1
- package/dist/{stale-ARHFVL5U.js → stale-TH7SSVRV.js} +10 -10
- package/dist/storage-WSF7ZKTL.js +23 -0
- package/dist/{store-coordination-provider-GFCUOBR6.js → store-coordination-provider-R27VRD6K.js} +18 -12
- package/dist/store-coordination-provider-R27VRD6K.js.map +1 -0
- package/dist/sync/index.js +11 -11
- package/dist/team/index.js +15 -14
- 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/util/index.js +1 -1
- package/dist/vault-head/index.js +115 -0
- package/dist/vault-head/index.js.map +1 -0
- package/dist/{verify-RO5RTZOJ.js → verify-M5LQH43C.js} +5 -5
- package/dist/via/blob/index.d.ts +3 -0
- package/dist/via/lookup/handle.d.ts +4 -1
- package/dist/walk-NABCHDZN.js +21 -0
- package/dist/with-audit/periods/index.d.ts +3 -3
- package/dist/with-audit/periods/periods.d.ts +82 -2
- package/dist/with-audit/periods/strategy.d.ts +1 -1
- package/dist/with-audit/periods/vault-facade.d.ts +54 -1
- package/dist/with-audit/periods/window.d.ts +10 -0
- 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 +1 -1
- package/dist/with-cargo/extract-partition.d.ts +1 -1
- package/dist/with-cargo/index.d.ts +1 -1
- 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/index.d.ts +1 -1
- package/dist/with-party/team/keyring.d.ts +139 -2
- package/dist/with-party/team/noydb-facade.d.ts +5 -1
- package/dist/with-party/team/roster-tag.d.ts +101 -0
- package/dist/with-party/team/tiers.d.ts +2 -1
- package/dist/with-pod/format.d.ts +10 -12
- 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} +11 -19
- 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/index.d.ts +1 -0
- package/dist/with-sync/engine.d.ts +54 -5
- package/dist/with-sync/strategy.d.ts +3 -0
- package/dist/withdraw-accessible-VCINIG6V.js +28 -0
- package/package.json +10 -4
- 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-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-CDB2HVQW.js.map +0 -1
- package/dist/chunk-CEJWMBXO.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-H73G4XF4.js.map +0 -1
- package/dist/chunk-HNGSV2YC.js.map +0 -1
- package/dist/chunk-IGJCYUT5.js.map +0 -1
- package/dist/chunk-IMZLOJTK.js.map +0 -1
- package/dist/chunk-J7FM3RAU.js.map +0 -1
- package/dist/chunk-JJNOLSG5.js.map +0 -1
- package/dist/chunk-JRKZTEZZ.js.map +0 -1
- package/dist/chunk-JXIDGFKS.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-PXCBVDFY.js.map +0 -1
- package/dist/chunk-Q6TEJXBX.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-WK5XUYYF.js.map +0 -1
- package/dist/chunk-XWX7GL56.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/find-RBBYKXI7.js +0 -11
- package/dist/issue-RIVHSY2S.js +0 -19
- package/dist/liberate-GFN4C7RR.js +0 -24
- package/dist/noydb-3MT74MZS.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-6X2VLZ7J.js.map} +0 -0
- /package/dist/{chunk-KUDZVJKQ.js.map → chunk-22GR3O4J.js.map} +0 -0
- /package/dist/{chunk-CCZJJ4I2.js.map → chunk-2CBFYXJX.js.map} +0 -0
- /package/dist/{chunk-FAXZQ5UF.js.map → chunk-323MN67Z.js.map} +0 -0
- /package/dist/{chunk-VMCCGUQB.js.map → chunk-36CEG6CM.js.map} +0 -0
- /package/dist/{chunk-747LRSOO.js.map → chunk-4K6BIMLF.js.map} +0 -0
- /package/dist/{chunk-FNSMZQS4.js.map → chunk-5IHGJHWC.js.map} +0 -0
- /package/dist/{chunk-7TSYBD3E.js.map → chunk-65JXA63J.js.map} +0 -0
- /package/dist/{chunk-Z45YRGFO.js.map → chunk-6NR36UNB.js.map} +0 -0
- /package/dist/{chunk-3JVXVJ7L.js.map → chunk-7OBIBPCV.js.map} +0 -0
- /package/dist/{chunk-AR2JDFAE.js.map → chunk-7Q3RHOA5.js.map} +0 -0
- /package/dist/{chunk-QULVCV3M.js.map → chunk-AJGGBXWA.js.map} +0 -0
- /package/dist/{chunk-CADUYBQD.js.map → chunk-ATL3ZVXT.js.map} +0 -0
- /package/dist/{chunk-DMQCLZ4Z.js.map → chunk-ATY3ZASK.js.map} +0 -0
- /package/dist/{chunk-4HDYQL3J.js.map → chunk-B4CRUZPR.js.map} +0 -0
- /package/dist/{chunk-6SAFL5YE.js.map → chunk-BZ3WMOYX.js.map} +0 -0
- /package/dist/{chunk-HXGUIPQB.js.map → chunk-CKKN25P2.js.map} +0 -0
- /package/dist/{chunk-6HFM7EIT.js.map → chunk-EHRIDNZX.js.map} +0 -0
- /package/dist/{chunk-RTAMLDWP.js.map → chunk-FU5VYEYK.js.map} +0 -0
- /package/dist/{chunk-RXYYFSBB.js.map → chunk-GKTW3KLV.js.map} +0 -0
- /package/dist/{chunk-OF3L2SD6.js.map → chunk-HOPNIR5R.js.map} +0 -0
- /package/dist/{chunk-ADW22QSB.js.map → chunk-HWI7GHJZ.js.map} +0 -0
- /package/dist/{chunk-GQ3BX5EA.js.map → chunk-I3ISCYT7.js.map} +0 -0
- /package/dist/{chunk-NJDQ4YSV.js.map → chunk-IWQPYT6S.js.map} +0 -0
- /package/dist/{chunk-2Z3NCLNX.js.map → chunk-JHYKSMVX.js.map} +0 -0
- /package/dist/{chunk-6FJWSWFT.js.map → chunk-JIHWBKMQ.js.map} +0 -0
- /package/dist/{chunk-YAWK6AWF.js.map → chunk-JKATP6OE.js.map} +0 -0
- /package/dist/{chunk-DG27IUVI.js.map → chunk-LC6NE4IQ.js.map} +0 -0
- /package/dist/{chunk-VJFMXYKP.js.map → chunk-MPKP6L5E.js.map} +0 -0
- /package/dist/{chunk-FUHKW252.js.map → chunk-OCJ3JA4O.js.map} +0 -0
- /package/dist/{chunk-WLYIROCJ.js.map → chunk-OQMCFHUX.js.map} +0 -0
- /package/dist/{chunk-JRCYZEHU.js.map → chunk-OR2FYRYR.js.map} +0 -0
- /package/dist/{chunk-HNHCQ556.js.map → chunk-PFWE7FJG.js.map} +0 -0
- /package/dist/{chunk-U5O6GIWZ.js.map → chunk-POFYIGQ2.js.map} +0 -0
- /package/dist/{chunk-35EBKWQU.js.map → chunk-QH47SQLD.js.map} +0 -0
- /package/dist/{chunk-HVQGCKY4.js.map → chunk-QVXZFJBU.js.map} +0 -0
- /package/dist/{chunk-FMQJZH4R.js.map → chunk-RDB66EKD.js.map} +0 -0
- /package/dist/{chunk-X56RTUK3.js.map → chunk-RJZQ2PVD.js.map} +0 -0
- /package/dist/{chunk-SUFG5E73.js.map → chunk-RPRASGEY.js.map} +0 -0
- /package/dist/{chunk-JIUVJ4M7.js.map → chunk-S7PM7Z4K.js.map} +0 -0
- /package/dist/{chunk-N35NC4JH.js.map → chunk-TKBB62DN.js.map} +0 -0
- /package/dist/{chunk-4UVDI4XE.js.map → chunk-WPZ5FVAS.js.map} +0 -0
- /package/dist/{chunk-MSWYQLMQ.js.map → chunk-XINT4VJA.js.map} +0 -0
- /package/dist/{chunk-W3TVWF6N.js.map → chunk-YCGLAANM.js.map} +0 -0
- /package/dist/{chunk-FDX7OWWI.js.map → chunk-YYV53EHO.js.map} +0 -0
- /package/dist/{classified-marker-2KJAXRRO.js.map → classified-marker-AZDSDG6V.js.map} +0 -0
- /package/dist/{collection-facade-QEJIM6BC.js.map → collection-facade-WSUAYFJ4.js.map} +0 -0
- /package/dist/{computed-6G5M3UPH.js.map → computed-VG2PCM4L.js.map} +0 -0
- /package/dist/{dead-filter-DCB62VWW.js.map → dead-filter-JNQNB3TA.js.map} +0 -0
- /package/dist/{derive-IUA6JFLB.js.map → derive-MPOGZ4NR.js.map} +0 -0
- /package/dist/{dispatch-MJ6SHB3Y.js.map → dispatch-3ZA733EY.js.map} +0 -0
- /package/dist/{enclave-JU4YIEPB.js.map → enclave-Y2ALNDRD.js.map} +0 -0
- /package/dist/{executor-CYJQLKKI.js.map → executor-BBEEUFO3.js.map} +0 -0
- /package/dist/{executor-S4QIKEHW.js.map → executor-G6G3YEWR.js.map} +0 -0
- /package/dist/{executor-YIQB2S6N.js.map → executor-ZUTUMTPA.js.map} +0 -0
- /package/dist/{export-accessible-4S36PQNR.js.map → export-accessible-S3KEB763.js.map} +0 -0
- /package/dist/{extract-partition-IO7FDZ2P.js.map → extract-partition-KVCTSUVE.js.map} +0 -0
- /package/dist/{find-RBBYKXI7.js.map → find-V4FN5ITT.js.map} +0 -0
- /package/dist/{issue-RIVHSY2S.js.map → issue-5CFBWBRX.js.map} +0 -0
- /package/dist/{ledger-AETNF4OM.js.map → ledger-MQIIOTZB.js.map} +0 -0
- /package/dist/{liberate-GFN4C7RR.js.map → liberate-LW7OKVBH.js.map} +0 -0
- /package/dist/{link-set-E5HNY67I.js.map → link-set-5PJBBR63.js.map} +0 -0
- /package/dist/{managed-secret-CWQ6PND5.js.map → managed-secret-ETDG6AAE.js.map} +0 -0
- /package/dist/{noydb-3MT74MZS.js.map → noydb-LFDRMYZ5.js.map} +0 -0
- /package/dist/{post-register-2XSSMGEQ.js.map → post-register-QCJYRMIK.js.map} +0 -0
- /package/dist/{register-4EFJCVYD.js.map → register-JBOEHTVX.js.map} +0 -0
- /package/dist/{registry-4SDHHOJ7.js.map → registry-5DYHQFJS.js.map} +0 -0
- /package/dist/{registry-CZVINVQH.js.map → registry-EANV44W2.js.map} +0 -0
- /package/dist/{registry-IKUR2MXD.js.map → registry-J25H6VB4.js.map} +0 -0
- /package/dist/{registry-OYTFGWVK.js.map → registry-R23SQUQH.js.map} +0 -0
- /package/dist/{request-withdrawal-KGXGDPVQ.js.map → request-withdrawal-KQ4W4UT5.js.map} +0 -0
- /package/dist/{reveal-BW36KCOQ.js.map → reveal-W7BKZSUP.js.map} +0 -0
- /package/dist/{revoke-JFN773KF.js.map → revoke-H3VSTAIE.js.map} +0 -0
- /package/dist/{signer-TA55QB6R.js.map → signer-53AQ3BU2.js.map} +0 -0
- /package/dist/{stale-ARHFVL5U.js.map → stale-TH7SSVRV.js.map} +0 -0
- /package/dist/{storage-V7MTFAQJ.js.map → storage-WSF7ZKTL.js.map} +0 -0
- /package/dist/{ulid-PTAIMDG4.js.map → ulid-VQW6ERQN.js.map} +0 -0
- /package/dist/{verify-RO5RTZOJ.js.map → verify-M5LQH43C.js.map} +0 -0
- /package/dist/{walk-3ZECBFDA.js.map → walk-NABCHDZN.js.map} +0 -0
- /package/dist/{withdraw-accessible-7PG4DYQK.js.map → withdraw-accessible-VCINIG6V.js.map} +0 -0
|
@@ -1,136 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
isRewrappedUnder,
|
|
6
|
-
openEnvelopeJson,
|
|
7
|
-
rewrapEnvelope
|
|
8
|
-
} from "./chunk-3URQC7EH.js";
|
|
2
|
+
getHistory,
|
|
3
|
+
historyIdentity
|
|
4
|
+
} from "./chunk-7ZGPQOFV.js";
|
|
9
5
|
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
} from "./chunk-7H73RIE3.js";
|
|
6
|
+
liveRecordIsElevated
|
|
7
|
+
} from "./chunk-D2YFQ7XG.js";
|
|
13
8
|
import {
|
|
14
|
-
|
|
15
|
-
} from "./chunk-
|
|
9
|
+
openEnvelopeJson
|
|
10
|
+
} from "./chunk-CXPOG3ZY.js";
|
|
16
11
|
import {
|
|
17
12
|
ReadOnlyAtInstantError
|
|
18
|
-
} from "./chunk-
|
|
19
|
-
|
|
20
|
-
// src/with-commit/history/history.ts
|
|
21
|
-
var HISTORY_COLLECTION = "_history";
|
|
22
|
-
var VERSION_PAD = 10;
|
|
23
|
-
function historyId(collection, recordId, version) {
|
|
24
|
-
return `${collection}:${recordId}:${String(version).padStart(VERSION_PAD, "0")}`;
|
|
25
|
-
}
|
|
26
|
-
function matchesPrefix(id, collection, recordId) {
|
|
27
|
-
if (recordId) {
|
|
28
|
-
return id.startsWith(`${collection}:${recordId}:`);
|
|
29
|
-
}
|
|
30
|
-
return id.startsWith(`${collection}:`);
|
|
31
|
-
}
|
|
32
|
-
async function saveHistory(adapter, vault, collection, recordId, envelope) {
|
|
33
|
-
const id = historyId(collection, recordId, envelope._v);
|
|
34
|
-
await adapter.put(vault, HISTORY_COLLECTION, id, envelope);
|
|
35
|
-
}
|
|
36
|
-
async function getHistory(adapter, vault, collection, recordId, options) {
|
|
37
|
-
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
38
|
-
const matchingIds = allIds.filter((id) => matchesPrefix(id, collection, recordId)).sort().reverse();
|
|
39
|
-
const entries = [];
|
|
40
|
-
for (const id of matchingIds) {
|
|
41
|
-
const envelope = await adapter.get(vault, HISTORY_COLLECTION, id);
|
|
42
|
-
if (!envelope) continue;
|
|
43
|
-
if (options?.from && envelope._ts < options.from) continue;
|
|
44
|
-
if (options?.to && envelope._ts > options.to) continue;
|
|
45
|
-
entries.push(envelope);
|
|
46
|
-
if (options?.limit && entries.length >= options.limit) break;
|
|
47
|
-
}
|
|
48
|
-
return entries;
|
|
49
|
-
}
|
|
50
|
-
async function getVersionEnvelope(adapter, vault, collection, recordId, version) {
|
|
51
|
-
const id = historyId(collection, recordId, version);
|
|
52
|
-
return adapter.get(vault, HISTORY_COLLECTION, id);
|
|
53
|
-
}
|
|
54
|
-
async function pruneHistory(adapter, vault, collection, recordId, options) {
|
|
55
|
-
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
56
|
-
const matchingIds = allIds.filter((id) => recordId ? matchesPrefix(id, collection, recordId) : matchesPrefix(id, collection)).sort();
|
|
57
|
-
let toDelete = [];
|
|
58
|
-
if (options.keepVersions !== void 0) {
|
|
59
|
-
const keep = options.keepVersions;
|
|
60
|
-
if (matchingIds.length > keep) {
|
|
61
|
-
toDelete = matchingIds.slice(0, matchingIds.length - keep);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
if (options.beforeDate) {
|
|
65
|
-
for (const id of matchingIds) {
|
|
66
|
-
if (toDelete.includes(id)) continue;
|
|
67
|
-
const envelope = await adapter.get(vault, HISTORY_COLLECTION, id);
|
|
68
|
-
if (envelope && envelope._ts < options.beforeDate) {
|
|
69
|
-
toDelete.push(id);
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const uniqueDeletes = [...new Set(toDelete)];
|
|
74
|
-
for (const id of uniqueDeletes) {
|
|
75
|
-
await adapter.delete(vault, HISTORY_COLLECTION, id);
|
|
76
|
-
}
|
|
77
|
-
return uniqueDeletes.length;
|
|
78
|
-
}
|
|
79
|
-
async function clearHistory(adapter, vault, collection, recordId) {
|
|
80
|
-
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
81
|
-
let toDelete;
|
|
82
|
-
if (collection && recordId) {
|
|
83
|
-
toDelete = allIds.filter((id) => matchesPrefix(id, collection, recordId));
|
|
84
|
-
} else if (collection) {
|
|
85
|
-
toDelete = allIds.filter((id) => matchesPrefix(id, collection));
|
|
86
|
-
} else {
|
|
87
|
-
toDelete = allIds;
|
|
88
|
-
}
|
|
89
|
-
for (const id of toDelete) {
|
|
90
|
-
await adapter.delete(vault, HISTORY_COLLECTION, id);
|
|
91
|
-
}
|
|
92
|
-
return toDelete.length;
|
|
93
|
-
}
|
|
94
|
-
async function tombstoneHistory(adapter, vault, collection, recordId, actor, encrypted) {
|
|
95
|
-
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
96
|
-
const matchingIds = allIds.filter((id) => matchesPrefix(id, collection, recordId));
|
|
97
|
-
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
98
|
-
let count = 0;
|
|
99
|
-
for (const id of matchingIds) {
|
|
100
|
-
const env = await adapter.get(vault, HISTORY_COLLECTION, id);
|
|
101
|
-
if (!env) continue;
|
|
102
|
-
if (isTombstone(env, encrypted)) continue;
|
|
103
|
-
const tombstone = {
|
|
104
|
-
_noydb: NOYDB_FORMAT_VERSION,
|
|
105
|
-
_v: env._v,
|
|
106
|
-
_ts: now,
|
|
107
|
-
_iv: "",
|
|
108
|
-
_data: "",
|
|
109
|
-
...actor ? { _by: actor } : {}
|
|
110
|
-
};
|
|
111
|
-
await adapter.put(vault, HISTORY_COLLECTION, id, tombstone);
|
|
112
|
-
count++;
|
|
113
|
-
}
|
|
114
|
-
return count;
|
|
115
|
-
}
|
|
116
|
-
async function rewrapHistory(adapter, vault, collection, recordId, fromDek, toDek, tier0Dek) {
|
|
117
|
-
const allIds = await adapter.list(vault, HISTORY_COLLECTION);
|
|
118
|
-
const matchingIds = allIds.filter((id) => matchesPrefix(id, collection, recordId));
|
|
119
|
-
for (const id of matchingIds) {
|
|
120
|
-
const env = await adapter.get(vault, HISTORY_COLLECTION, id);
|
|
121
|
-
if (!env) continue;
|
|
122
|
-
if (isTombstoneShape(env)) continue;
|
|
123
|
-
if (await isRewrappedUnder(env, toDek)) continue;
|
|
124
|
-
let next;
|
|
125
|
-
try {
|
|
126
|
-
next = await rewrapEnvelope(env, fromDek, toDek);
|
|
127
|
-
} catch (err) {
|
|
128
|
-
if (!tier0Dek) throw err;
|
|
129
|
-
next = await rewrapEnvelope(env, tier0Dek, toDek);
|
|
130
|
-
}
|
|
131
|
-
await adapter.put(vault, HISTORY_COLLECTION, id, next);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
13
|
+
} from "./chunk-Z3BZXPRO.js";
|
|
134
14
|
|
|
135
15
|
// src/with-commit/history/time-machine.ts
|
|
136
16
|
var VaultInstant = class {
|
|
@@ -170,9 +50,9 @@ var CollectionInstant = class {
|
|
|
170
50
|
* DEK directly.
|
|
171
51
|
*/
|
|
172
52
|
async get(id) {
|
|
173
|
-
const
|
|
174
|
-
if (!
|
|
175
|
-
const plaintext = this.engine.encrypted ? await openEnvelopeJson(envelope, await this.engine.getDEK(this.name)) : envelope._data;
|
|
53
|
+
const found = await this.resolveVisibleEnvelope(id);
|
|
54
|
+
if (!found) return null;
|
|
55
|
+
const plaintext = this.engine.encrypted ? await openEnvelopeJson(found.ref, found.envelope, await this.engine.getDEK(this.name)) : found.envelope._data;
|
|
176
56
|
return JSON.parse(plaintext);
|
|
177
57
|
}
|
|
178
58
|
/**
|
|
@@ -219,10 +99,10 @@ var CollectionInstant = class {
|
|
|
219
99
|
* just a decrypt failure.
|
|
220
100
|
*/
|
|
221
101
|
async resolveVisibleEnvelope(id) {
|
|
222
|
-
const
|
|
223
|
-
if (!
|
|
102
|
+
const found = await this.resolveEnvelope(id);
|
|
103
|
+
if (!found || (found.envelope._tier ?? 0) > 0) return null;
|
|
224
104
|
if (await liveRecordIsElevated(this.engine.adapter, this.engine.name, this.name, id)) return null;
|
|
225
|
-
return
|
|
105
|
+
return found;
|
|
226
106
|
}
|
|
227
107
|
/**
|
|
228
108
|
* Return the envelope that represents the record's state at
|
|
@@ -283,12 +163,14 @@ var CollectionInstant = class {
|
|
|
283
163
|
);
|
|
284
164
|
const live = await this.engine.adapter.get(this.engine.name, this.name, id);
|
|
285
165
|
const byVersion = /* @__PURE__ */ new Map();
|
|
286
|
-
for (const e of history)
|
|
287
|
-
|
|
166
|
+
for (const e of history) {
|
|
167
|
+
byVersion.set(e._v, { envelope: e, ref: historyIdentity(this.name, id, e._v) });
|
|
168
|
+
}
|
|
169
|
+
if (live) byVersion.set(live._v, { envelope: live, ref: { collection: this.name, id } });
|
|
288
170
|
const sorted = [...byVersion.values()].sort(
|
|
289
|
-
(a, b) => a._ts < b._ts ? 1 : a._ts > b._ts ? -1 : 0
|
|
171
|
+
(a, b) => a.envelope._ts < b.envelope._ts ? 1 : a.envelope._ts > b.envelope._ts ? -1 : 0
|
|
290
172
|
);
|
|
291
|
-
return sorted.find((e) => e._ts <= this.targetTs) ?? null;
|
|
173
|
+
return sorted.find((e) => e.envelope._ts <= this.targetTs) ?? null;
|
|
292
174
|
}
|
|
293
175
|
/**
|
|
294
176
|
* Fetch the envelope for a specific version. The live record (most
|
|
@@ -300,9 +182,12 @@ var CollectionInstant = class {
|
|
|
300
182
|
*/
|
|
301
183
|
async loadVersion(id, version) {
|
|
302
184
|
const live = await this.engine.adapter.get(this.engine.name, this.name, id);
|
|
303
|
-
if (live && live._v === version)
|
|
304
|
-
|
|
305
|
-
|
|
185
|
+
if (live && live._v === version) {
|
|
186
|
+
return { envelope: live, ref: { collection: this.name, id } };
|
|
187
|
+
}
|
|
188
|
+
const ref = historyIdentity(this.name, id, version);
|
|
189
|
+
const envelope = await this.engine.adapter.get(this.engine.name, ref.collection, ref.id);
|
|
190
|
+
return envelope ? { envelope, ref } : null;
|
|
306
191
|
}
|
|
307
192
|
};
|
|
308
193
|
async function collectHistoryIds(adapter, vault, collection) {
|
|
@@ -320,14 +205,7 @@ async function collectHistoryIds(adapter, vault, collection) {
|
|
|
320
205
|
}
|
|
321
206
|
|
|
322
207
|
export {
|
|
323
|
-
saveHistory,
|
|
324
|
-
getHistory,
|
|
325
|
-
getVersionEnvelope,
|
|
326
|
-
pruneHistory,
|
|
327
|
-
clearHistory,
|
|
328
|
-
tombstoneHistory,
|
|
329
|
-
rewrapHistory,
|
|
330
208
|
VaultInstant,
|
|
331
209
|
CollectionInstant
|
|
332
210
|
};
|
|
333
|
-
//# sourceMappingURL=chunk-
|
|
211
|
+
//# sourceMappingURL=chunk-D6SXRMZZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-commit/history/time-machine.ts"],"sourcesContent":["/**\n * Time-machine queries — point-in-time reads reconstructed from the\n * existing history + ledger infrastructure.\n *\n * ## Usage\n *\n * ```ts\n * const vault = await db.openVault('acme', { secret })\n * const q1End = vault.at('2026-03-31T23:59:59Z')\n * const invoice = await q1End.collection<Invoice>('invoices').get('inv-001')\n * // → the record as it stood at the close of Q1 2026\n * ```\n *\n * ## How it works\n *\n * Every write path already fans out into two persistence lanes:\n *\n * 1. `saveHistory(...)` persists a **full encrypted envelope snapshot**\n * per version under the `_history` collection (one envelope per\n * version, keyed by `{collection}:{id}:{paddedVersion}`). Each\n * envelope carries its own `_ts` (the write timestamp).\n * 2. `ledger.append(...)` appends a hash-chained audit entry that\n * records the `op` (put / delete), `version`, and `ts`.\n *\n * Reconstruction at a target timestamp T is therefore:\n *\n * - Find the newest history envelope for `(collection, id)` whose\n * `_ts ≤ T` — that's the state the record was in at T.\n * - Check the ledger for any `op: 'delete'` entry for the same\n * `(collection, id)` with `entry.ts` in `(latestEnvelope._ts, T]` —\n * if present, the record was deleted before T, so return `null`.\n * - Decrypt the surviving envelope with the current collection DEK\n * (DEKs are per-collection but stable across versions — the same\n * key encrypts v1 and v15 of a record).\n *\n * No delta replay. The existing `history.ts` module already stores\n * complete snapshots; we just pick the right one.\n *\n * ## Read-only contract\n *\n * Every write method on `CollectionInstant` throws\n * {@link ReadOnlyAtInstantError}. A historical view is a *read*\n * surface — mutating the past would require either a branch/shadow\n * mechanism (tracked under shadow vaults) or a rewrite of\n * history, which breaks the ledger's tamper-evidence guarantee.\n *\n * @module\n */\nimport type { EncryptedEnvelope, NoydbStore } from '../../kernel/types.js'\nimport type { LedgerStore } from './ledger/store.js'\nimport { getHistory, historyIdentity } from './history.js'\n\n/**\n * An envelope together with **the address it was fetched from**.\n *\n * The time machine resolves a record's state at an instant from two different\n * places — the live collection, or a `_history` snapshot — and those are sealed\n * against different identities (#1041). Returning the envelope alone discards\n * the one fact the reader needs to open it, which is precisely the read-side\n * data-flow gap that binding identity exposes.\n */\ninterface ResolvedEnvelope {\n readonly envelope: EncryptedEnvelope\n readonly ref: { readonly collection: string; readonly id: string }\n}\nimport { openEnvelopeJson, type EnclaveKey } from '../../kernel/enclave/index.js'\nimport { ReadOnlyAtInstantError } from '../../kernel/errors.js'\nimport { liveRecordIsElevated } from '../../kernel/tier-visibility.js'\n\n/**\n * Narrow view of a {@link Vault}'s internals that\n * {@link VaultInstant} needs. Passed in by `Vault.at()` rather than\n * constructed here so all crypto + adapter access stays inside the\n * Vault class.\n *\n * Not exported from the public barrel — consumers should get a\n * `VaultInstant` via `vault.at(ts)`, never by constructing one\n * directly.\n */\nexport interface VaultEngine {\n readonly adapter: NoydbStore\n /** Vault name (the compartment). */\n readonly name: string\n /**\n * `true` when the vault was opened with a secret (the normal\n * case). `false` in plaintext-mode vaults (`encrypt: false`) — in\n * that case `envelope._data` is raw JSON and we skip the DEK lookup.\n */\n readonly encrypted: boolean\n /**\n * Resolves the DEK used to decrypt a given collection's envelopes.\n * Not called when `encrypted` is false.\n */\n getDEK(collection: string): Promise<EnclaveKey>\n /**\n * Lazily-initialised ledger. We consult it to detect deletes that\n * happened between the latest history snapshot and the target\n * timestamp. `null` when history is disabled for this vault — in\n * that case time-machine reads fall back to history-only\n * reconstruction (which may miss deletes).\n */\n getLedger(): LedgerStore | null\n}\n\n/**\n * A vault at a fixed instant. Produced by `vault.at(timestamp)`.\n * Carries no session state of its own — every read is a fresh\n * lookup through the vault's adapter.\n *\n * Cheap to construct; safe to throw away. Create one per query.\n */\nexport class VaultInstant {\n constructor(\n private readonly engine: VaultEngine,\n /** Fully-resolved target timestamp (ISO-8601 UTC). */\n public readonly timestamp: string,\n ) {}\n\n /** Get a point-in-time view of a collection. */\n collection<T = unknown>(name: string): CollectionInstant<T> {\n return new CollectionInstant<T>(this.engine, this.timestamp, name)\n }\n}\n\n/**\n * A read-only collection view anchored to a past instant.\n *\n * Every write method throws {@link ReadOnlyAtInstantError} — see the\n * module docstring for why. The read surface is intentionally smaller\n * than the live {@link Collection}: `get` and `list` cover the\n * \"what did the books look like on date X\" use case without pulling\n * in the full query DSL / joins / aggregates at this stage. Follow-up\n * work tracked under.\n */\nexport class CollectionInstant<T = unknown> {\n constructor(\n private readonly engine: VaultEngine,\n private readonly targetTs: string,\n public readonly name: string,\n ) {}\n\n /**\n * Return the record as it existed at the target timestamp, or\n * `null` if the record had not been created yet or had already been\n * deleted by then.\n *\n * Gated on the LIVE record's current tier — #730, mirroring the #712\n * read-gate `history()`/`getVersion()` already apply: an elevated record\n * is invisible through the whole time-machine surface, not just a\n * decrypt failure. See {@link resolveVisibleEnvelope}.\n *\n * Decrypts through {@link openEnvelopeJson}, the `_cek`-aware envelope\n * body opener — a snapshot from a `perRecordKeys` collection is encrypted\n * under its own per-record CEK (wrapped in `_cek`), not the collection\n * DEK directly.\n */\n async get(id: string): Promise<T | null> {\n const found = await this.resolveVisibleEnvelope(id)\n if (!found) return null\n // The envelope may be the LIVE record or a `_history` snapshot, and the two\n // are sealed against different identities (#1041). `resolveEnvelope` carries\n // the address down with the bytes precisely so this read can name it.\n const plaintext = this.engine.encrypted\n ? await openEnvelopeJson(found.ref, found.envelope, await this.engine.getDEK(this.name))\n : found.envelope._data\n return JSON.parse(plaintext) as T\n }\n\n /**\n * IDs of records that existed (had at least one `put` and were not\n * subsequently deleted) at the target timestamp.\n *\n * Implemented as a linear scan over history + ledger. Performance\n * is bounded by total history size (not live-vault size), so the\n * memory-first vault-scale cap (1K–50K records × average history\n * depth) still applies.\n */\n async list(): Promise<string[]> {\n const historyIds = await collectHistoryIds(this.engine.adapter, this.engine.name, this.name)\n const liveIds = await this.engine.adapter.list(this.engine.name, this.name)\n const candidateIds = new Set<string>([...historyIds, ...liveIds])\n const alive: string[] = []\n for (const id of candidateIds) {\n const env = await this.resolveVisibleEnvelope(id)\n if (env) alive.push(id)\n }\n return alive.sort()\n }\n\n // ── write guards ───────────────────────────────────────────────────\n\n async put(_id: string, _record: T): Promise<never> {\n throw new ReadOnlyAtInstantError('put', this.targetTs)\n }\n async delete(_id: string): Promise<never> {\n throw new ReadOnlyAtInstantError('delete', this.targetTs)\n }\n async update(_id: string, _patch: Partial<T>): Promise<never> {\n throw new ReadOnlyAtInstantError('update', this.targetTs)\n }\n\n // ── internals ─────────────────────────────────────────────────────\n\n /**\n * {@link resolveEnvelope}, additionally gated on the record's LIVE\n * (current, not historical) tier — #730. Mirrors the #712 read-gate\n * `history()`/`getVersion()` apply: history snapshots keep their\n * tier-0-wrapped CEKs and carry no `_tier` of their own, so an elevated\n * record's prior versions would otherwise stay tier-0-decryptable here.\n * `null` for a resolved envelope carrying its own `_tier > 0` (a\n * tier-aware snapshot reached some other way) or whose LIVE record is\n * currently elevated — both `get()` and `list()` route through this so\n * the invisibility law holds on the whole time-machine read surface, not\n * just a decrypt failure.\n */\n private async resolveVisibleEnvelope(id: string): Promise<ResolvedEnvelope | null> {\n const found = await this.resolveEnvelope(id)\n if (!found || (found.envelope._tier ?? 0) > 0) return null\n if (await liveRecordIsElevated(this.engine.adapter, this.engine.name, this.name, id)) return null\n return found\n }\n\n /**\n * Return the envelope that represents the record's state at\n * `targetTs`, accounting for deletes. `null` if the record didn't\n * exist at that instant.\n *\n * ## Why we use the ledger as the authoritative timeline\n *\n * The per-version history snapshots saved by `saveHistory()` do\n * carry a `_ts` field, but that timestamp is the moment the\n * snapshot was *captured* (i.e. the instant right before the\n * subsequent overwrite), not the original write time. The ledger,\n * by contrast, records `ts` at the moment of each `put` / `delete`\n * — it's the only source that tracks the real timeline. So:\n *\n * 1. Walk the ledger; find the latest entry for `(collection, id)`\n * with `ts ≤ targetTs`.\n * 2. If that entry is a `delete`, the record was gone at the\n * target instant — return null.\n * 3. Otherwise it's a `put` with a specific `version`. Load the\n * envelope for that version from history, falling back to the\n * live collection for the most recent version.\n *\n * ## Fallback when the ledger is disabled\n *\n * If the vault has history disabled, `getLedger()` returns null and\n * we fall back to comparing envelope `_ts` fields. This is\n * approximate and gets the *last write* right but may confuse the\n * intermediate versions; adopters needing accurate time-machine\n * reads should leave history enabled.\n */\n private async resolveEnvelope(id: string): Promise<ResolvedEnvelope | null> {\n const ledger = this.engine.getLedger()\n if (ledger) {\n return this.resolveViaLedger(id, ledger)\n }\n return this.resolveViaEnvelopeTs(id)\n }\n\n private async resolveViaLedger(id: string, ledger: LedgerStore): Promise<ResolvedEnvelope | null> {\n const entries = await ledger.entries()\n // Entries are already ordered by index which is the mutation order.\n let latest: { op: 'put' | 'delete'; version: number } | null = null\n for (const e of entries) {\n if (e.collection !== this.name || e.id !== id) continue\n if (e.ts > this.targetTs) break // entries are time-ordered by index\n // `amendment` + `lifecycle` entries are audit-only summaries — they\n // carry no (collection, id) tuple of their own and would never match\n // the filter above. The narrow here is a type guard, not a runtime\n // skip.\n // `forget` is a subject-erasure summary with empty (collection, id) —\n // never matches the filter above; the narrow is a type guard.\n if (e.op === 'amendment' || e.op === 'lifecycle' || e.op === 'forget') continue\n // `migration` is a record rewrite (cutover) — resolve it like a put.\n latest = { op: e.op === 'migration' ? 'put' : e.op, version: e.version }\n }\n if (!latest) return null\n if (latest.op === 'delete') return null\n return this.loadVersion(id, latest.version)\n }\n\n private async resolveViaEnvelopeTs(id: string): Promise<ResolvedEnvelope | null> {\n const history = await getHistory(\n this.engine.adapter, this.engine.name, this.name, id,\n )\n const live = await this.engine.adapter.get(this.engine.name, this.name, id)\n // Each candidate keeps the address it came from — a snapshot and the live\n // record are sealed against different identities, and this map is exactly\n // where that provenance used to be discarded (#1041).\n const byVersion = new Map<number, ResolvedEnvelope>()\n for (const e of history) {\n byVersion.set(e._v, { envelope: e, ref: historyIdentity(this.name, id, e._v) })\n }\n if (live) byVersion.set(live._v, { envelope: live, ref: { collection: this.name, id } })\n const sorted = [...byVersion.values()].sort((a, b) =>\n a.envelope._ts < b.envelope._ts ? 1 : a.envelope._ts > b.envelope._ts ? -1 : 0,\n )\n return sorted.find((e) => e.envelope._ts <= this.targetTs) ?? null\n }\n\n /**\n * Fetch the envelope for a specific version. The live record (most\n * recent put) lives in the main collection; prior versions live in\n * `_history`. We check live first because the common case after a\n * delete is that we're trying to load the last-live version from\n * history, and skipping live for the current-version case avoids a\n * redundant lookup.\n */\n private async loadVersion(id: string, version: number): Promise<ResolvedEnvelope | null> {\n const live = await this.engine.adapter.get(this.engine.name, this.name, id)\n if (live && live._v === version) {\n return { envelope: live, ref: { collection: this.name, id } }\n }\n\n // Direct lookup by (collection, id, version) — avoids scanning all history.\n //\n // This used to rebuild the key inline as\n // `${name}:${id}:${padStart(10,'0')}` — a SECOND definition of the history\n // layout, free to drift from `historyId`'s. It now goes through\n // `historyIdentity`, the same function `saveHistory` writes with, so the\n // read address and the write address cannot disagree (#1041).\n const ref = historyIdentity(this.name, id, version)\n const envelope = await this.engine.adapter.get(this.engine.name, ref.collection, ref.id)\n return envelope ? { envelope, ref } : null\n }\n}\n\n/**\n * Scan the `_history` collection once and collect every distinct\n * `recordId` for the given collection. History keys follow the\n * shape `<collection>:<recordId>:<paddedVersion>`; we split on the\n * last two colons (delimiter-safe because `paddedVersion` is\n * exactly 10 digits).\n */\nasync function collectHistoryIds(\n adapter: NoydbStore,\n vault: string,\n collection: string,\n): Promise<string[]> {\n const all = await adapter.list(vault, '_history')\n const prefix = `${collection}:`\n const seen = new Set<string>()\n for (const key of all) {\n if (!key.startsWith(prefix)) continue\n const lastColon = key.lastIndexOf(':')\n if (lastColon <= prefix.length) continue\n const middle = key.slice(prefix.length, lastColon)\n seen.add(middle)\n }\n return [...seen]\n}\n"],"mappings":"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","names":[]}
|
|
@@ -3,22 +3,22 @@ import {
|
|
|
3
3
|
} from "./chunk-EPFF7LOX.js";
|
|
4
4
|
import {
|
|
5
5
|
loadFence
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-DNKVKO7K.js";
|
|
7
7
|
import {
|
|
8
8
|
SCHEMAS_COLLECTION,
|
|
9
9
|
loadPersistedSchema
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-KM6ZXG7U.js";
|
|
11
11
|
import {
|
|
12
12
|
canonicalJson,
|
|
13
13
|
sha256Hex
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-BZ3WMOYX.js";
|
|
15
15
|
import {
|
|
16
16
|
openEnvelopeJson,
|
|
17
17
|
writeEnvelopeBody
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-CXPOG3ZY.js";
|
|
19
19
|
import {
|
|
20
|
-
|
|
21
|
-
} from "./chunk-
|
|
20
|
+
buildSealedRecordEnvelope
|
|
21
|
+
} from "./chunk-FX3UIDCS.js";
|
|
22
22
|
|
|
23
23
|
// src/with-shape/manifest/types.ts
|
|
24
24
|
var MANIFEST_SCHEMA_RECORD_ID = "schema";
|
|
@@ -29,7 +29,7 @@ async function loadSchemaManifestEntry(store, vault, getDEK) {
|
|
|
29
29
|
if (!envelope) return void 0;
|
|
30
30
|
const dek = await getDEK(MANIFEST_COLLECTION);
|
|
31
31
|
try {
|
|
32
|
-
const plaintext = await openEnvelopeJson(envelope, dek);
|
|
32
|
+
const plaintext = await openEnvelopeJson({ collection: MANIFEST_COLLECTION, id: MANIFEST_SCHEMA_RECORD_ID }, envelope, dek);
|
|
33
33
|
const parsed = JSON.parse(plaintext);
|
|
34
34
|
if (parsed.v !== 1 || parsed.kind !== "schema") return void 0;
|
|
35
35
|
return { version: envelope._v, manifest: parsed };
|
|
@@ -40,13 +40,11 @@ async function loadSchemaManifestEntry(store, vault, getDEK) {
|
|
|
40
40
|
async function saveSchemaManifest(store, vault, manifest, expectedVersion, getDEK) {
|
|
41
41
|
const dek = await getDEK(MANIFEST_COLLECTION);
|
|
42
42
|
const json = JSON.stringify(manifest);
|
|
43
|
-
const
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
...body
|
|
49
|
-
};
|
|
43
|
+
const env = await buildSealedRecordEnvelope(
|
|
44
|
+
{ collection: MANIFEST_COLLECTION, id: MANIFEST_SCHEMA_RECORD_ID, version: expectedVersion + 1 },
|
|
45
|
+
(identity) => writeEnvelopeBody(identity, json, dek),
|
|
46
|
+
{}
|
|
47
|
+
);
|
|
50
48
|
await store.put(vault, MANIFEST_COLLECTION, MANIFEST_SCHEMA_RECORD_ID, env, expectedVersion);
|
|
51
49
|
}
|
|
52
50
|
async function computeAggregateHash(collections) {
|
|
@@ -88,4 +86,4 @@ export {
|
|
|
88
86
|
saveSchemaManifest,
|
|
89
87
|
deriveSchemaManifest
|
|
90
88
|
};
|
|
91
|
-
//# sourceMappingURL=chunk-
|
|
89
|
+
//# sourceMappingURL=chunk-DECNV4QK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-shape/manifest/types.ts","../src/with-shape/manifest/storage.ts","../src/with-shape/manifest/derive.ts"],"sourcesContent":["/**\n * The pod-wide **schema manifest** record type (#941).\n *\n * This is an INDEX, not a full-inline manifest: `SchemaManifest.collections`\n * carries per-collection *metadata* (generation / content hash / field ids),\n * never the JSON Schema body itself. The JSON Schema stays the source of\n * truth at `_schemas/<collection>`, encrypted under that collection's own\n * DEK (see `with-shape/persisted-schemas`). Inlining full schemas into one\n * pod-wide manifest record would either leak every collection's schema to a\n * principal scoped to a single collection, or force the manifest itself\n * onto a collection-DEK it has no business holding — the index preserves\n * per-collection DEK isolation while still giving a single place to answer\n * \"what schema generation is this pod at, and does collection X's stored\n * schema match its declared content hash.\"\n *\n * `aggregateHash` binds the whole per-collection index's content: it is\n * `sha256Hex(canonicalJson(collections))`, so any change to any collection's\n * entry (a new generation, a changed hash, added/renamed field ids) changes\n * `aggregateHash` too. Canonical JSON (sorted object keys, no whitespace)\n * makes the hash independent of the map's key insertion order.\n *\n * @module\n */\n\n/** Per-collection entry inside a {@link SchemaManifest}'s `collections` index. */\nexport interface SchemaManifestEntry {\n /** The vault-wide schema-fence generation this collection's schema was last written at. */\n readonly generation: number\n /** SHA-256 (hex) of the collection's canonicalised JSON Schema (see `persisted-schemas/derive.ts`). */\n readonly contentHash: string\n /** Stable per-field ids (#946), keyed by the field's current name. Absent when the collection has none. */\n readonly fieldIds?: Record<string, string>\n}\n\n/**\n * The pod-wide schema manifest — one record per pod, stored at\n * `_manifest/schema` (see `storage.ts`). An INDEX over the per-collection\n * `_schemas/<collection>` entries, not the schemas themselves.\n */\nexport interface SchemaManifest {\n readonly v: 1\n readonly kind: 'schema'\n /** Pod-wide schema-fence generation (`FenceDoc.currentSchemaVersion`) as of this manifest's derivation. */\n readonly generation: number\n /** Per-collection index: collection name → its manifest entry. */\n readonly collections: Record<string, SchemaManifestEntry>\n /** `sha256Hex(canonicalJson(collections))` — the pod-wide content binding over the index. */\n readonly aggregateHash: string\n}\n\n/** The record id the schema manifest is stored under inside `_manifest`. */\nexport const MANIFEST_SCHEMA_RECORD_ID = 'schema' as const\n","/**\n * Read / write the pod-wide `_manifest/schema` envelope.\n *\n * Mirrors `with-shape/persisted-schemas/storage.ts`'s shape: the same\n * standard noy-db record envelope, AES-GCM encrypted with a collection DEK\n * (here, the `_manifest` collection's own DEK — the manifest INDEX\n * discloses collection names + hashes + generations + field ids, metadata\n * rather than schema bodies, so it gets the same encryption grain as\n * `_schemas` itself).\n *\n * Storage layout:\n *\n * <vault>/_manifest/schema → EncryptedEnvelope\n *\n * Unlike `persisted-schemas/storage.ts` (which takes an already-resolved\n * `EnclaveKey`), these functions take a `getDEK` resolver and call\n * `getDEK(MANIFEST_COLLECTION)` themselves — there is exactly one manifest\n * record per pod, so there is no per-collection DEK the caller needs to\n * pick; resolving it here keeps every manifest call-site symmetric.\n *\n * @module\n */\n\nimport { buildSealedRecordEnvelope, openEnvelopeJson, writeEnvelopeBody, type EnclaveKey } from '../../kernel/enclave/index.js'\nimport { canonicalJson, sha256Hex } from '../../with-commit/history/ledger/index.js'\nimport type { NoydbStore } from '../../kernel/types.js'\nimport { MANIFEST_COLLECTION } from './reserved-collections.js'\nimport { MANIFEST_SCHEMA_RECORD_ID, type SchemaManifest, type SchemaManifestEntry } from './types.js'\n\n/** A resolver for a collection's DEK — the same shape as `Vault`'s internal `getDEK`. */\nexport type GetManifestDEK = (collectionName: string) => Promise<EnclaveKey>\n\n/**\n * A decrypted schema-manifest read paired with the wrapping envelope's `_v`\n * — the optimistic-concurrency token. Pass `version` back to\n * {@link saveSchemaManifest} (via `writeSchemaManifest`'s `expectedVersion`)\n * to make the write a strict CAS.\n */\nexport interface LoadedSchemaManifest {\n /** Wrapping envelope `_v`. */\n readonly version: number\n /** Decrypted schema manifest. */\n readonly manifest: SchemaManifest\n}\n\n/**\n * Read the `_manifest/schema` envelope together with its wrapping `_v`.\n * Returns `undefined` when no manifest has ever been written, when the\n * envelope fails to decrypt (wrong DEK), or when it doesn't parse as a\n * `v: 1, kind: 'schema'` manifest.\n */\nexport async function loadSchemaManifestEntry(\n store: NoydbStore,\n vault: string,\n getDEK: GetManifestDEK,\n): Promise<LoadedSchemaManifest | undefined> {\n const envelope = await store.get(vault, MANIFEST_COLLECTION, MANIFEST_SCHEMA_RECORD_ID)\n if (!envelope) return undefined\n const dek = await getDEK(MANIFEST_COLLECTION)\n try {\n const plaintext = await openEnvelopeJson({ collection: MANIFEST_COLLECTION, id: MANIFEST_SCHEMA_RECORD_ID }, envelope, dek)\n const parsed = JSON.parse(plaintext) as SchemaManifest\n if (parsed.v !== 1 || parsed.kind !== 'schema') return undefined\n return { version: envelope._v, manifest: parsed }\n } catch {\n return undefined\n }\n}\n\n/**\n * Encrypt and persist the schema manifest as a strict CAS write:\n * `expectedVersion` must match the stored envelope's `_v` (0 when no\n * envelope exists yet) or `store.put` throws `ConflictError` — surfaced by\n * `writer.ts`'s `writeSchemaManifest` as `ManifestConflictError` rather than\n * retried.\n */\nexport async function saveSchemaManifest(\n store: NoydbStore,\n vault: string,\n manifest: SchemaManifest,\n expectedVersion: number,\n getDEK: GetManifestDEK,\n): Promise<void> {\n const dek = await getDEK(MANIFEST_COLLECTION)\n const json = JSON.stringify(manifest)\n const env = await buildSealedRecordEnvelope(\n { collection: MANIFEST_COLLECTION, id: MANIFEST_SCHEMA_RECORD_ID, version: expectedVersion + 1 },\n (identity) => writeEnvelopeBody(identity, json, dek),\n {},\n )\n await store.put(vault, MANIFEST_COLLECTION, MANIFEST_SCHEMA_RECORD_ID, env, expectedVersion)\n}\n\n/**\n * `sha256Hex(canonicalJson(collections))` — the pod-wide content binding\n * over a schema manifest's per-collection index. Canonical JSON sorts\n * object keys at every depth, so the result is independent of the map's\n * key insertion order. Shared by the writer's tests and (#941 Task 3) the\n * derivation path, so the hash is computed identically everywhere.\n */\nexport async function computeAggregateHash(\n collections: Record<string, SchemaManifestEntry>,\n): Promise<string> {\n return sha256Hex(canonicalJson(collections))\n}\n","/**\n * Derive the pod-wide {@link SchemaManifest} from the per-collection\n * `_schemas/<collection>` records — the source of truth (#941 Task 3).\n *\n * The manifest is an INDEX, never a cache with independent state: every\n * field in a {@link SchemaManifestEntry} is a direct projection of the\n * matching `PersistedSchemaEnvelope` (`hash` → `contentHash`, `fieldIds` →\n * `fieldIds`, `generation` → `generation`, falling back to the live fence's\n * `currentSchemaVersion` for a legacy pre-#946 envelope that never got a\n * generation stamp). Re-running this function against the same stored state\n * always produces the same manifest — that's what makes round-trip identity\n * (AC #2: dump → restore → re-derive matches the original) hold for free,\n * with no special-cased restore logic.\n *\n * A collection whose `_schemas/<collection>` envelope decrypts successfully\n * but has no derivable content (`hash === null` — a stub envelope for a\n * non-Zod validator) is legitimately omitted from the index: there is no\n * content hash to bind.\n *\n * ## Scoped principals: \"cannot decrypt\" is NOT \"doesn't exist\"\n *\n * A `_schemas/<collection>` envelope is encrypted under **that data\n * collection's own DEK** — the same key its records use — NOT a shared\n * `_schemas`-wide key. In a team vault, a collection-scoped grantee (e.g.\n * `grant(..., { role: 'operator', permissions: { invoices: 'rw' } })`) holds\n * only the DEKs their `permissions` name, plus every system-prefixed (`_*`)\n * collection's DEK — `_manifest` included, by `grant()`'s \"propagate system\n * collections to every role\" rule (`keyring.ts`). So a member scoped to\n * `invoices` CAN decrypt `_manifest/schema` (the pod-wide index) but CANNOT\n * decrypt a sibling's `_schemas/customers` envelope — even though that\n * envelope is right there in `store.list(vault, SCHEMAS_COLLECTION)`.\n *\n * `lookupDEK` (the {@link LookupDEK} passed in) reflects this: it returns\n * `undefined` for a collection name whose DEK the caller does not hold —\n * deliberately NEVER minting a fresh one (see the module doc on\n * `LookupDEK` for why). This function distinguishes that case\n * (`undecodableCollections`) from \"the schema envelope legitimately has no\n * derivable content\" (`hash === null`) — the caller (`sync.ts`) MUST treat\n * an incomplete view differently: writing a manifest derived from a\n * partial view would silently drop every collection this principal can't\n * see. See `sync.ts`'s module doc for how the sync path handles this.\n *\n * @module\n */\n\nimport type { EnclaveKey } from '../../kernel/enclave/index.js'\nimport { loadFence } from '../schema-update/fence.js'\nimport { loadPersistedSchema, SCHEMAS_COLLECTION } from '../persisted-schemas/storage.js'\nimport { computeAggregateHash } from './storage.js'\nimport type { NoydbStore } from '../../kernel/types.js'\nimport type { SchemaManifest, SchemaManifestEntry } from './types.js'\n\n/**\n * A NON-MINTING DEK lookup: returns the collection's DEK if the caller\n * already holds it, `undefined` otherwise. Deliberately distinct from\n * `storage.ts`'s `GetManifestDEK` (which mints+persists a fresh DEK for an\n * absent collection — correct for a caller about to WRITE that collection,\n * e.g. `_manifest` itself). `deriveSchemaManifest` only ever READS sibling\n * collections it never created and has no business minting keys for — an\n * absent DEK here means \"not my collection to see,\" never \"new collection\n * that needs a key.\" Minting here would be worse than a no-op: it would\n * silently persist a garbage DEK into the caller's OWN `_keyring/<user>`\n * file (via `ensureCollectionDEK`'s `persistKeyring` side effect) that\n * still can't decrypt anything — see `sync.ts` / `with-pod/open.ts`'s\n * fix notes (#941 review).\n */\nexport type LookupDEK = (collectionName: string) => Promise<EnclaveKey | undefined>\n\nexport interface DeriveSchemaManifestResult {\n /** The derived manifest — an index over every collection this principal could decrypt. */\n readonly manifest: SchemaManifest\n /**\n * Names present in `_schemas` (per `store.list`) whose envelope this\n * principal could NOT decrypt — either no DEK held for that collection,\n * or the DEK held failed to decrypt/parse it (treated the same: the\n * caller cannot verify what's there, so it cannot safely be omitted or\n * asserted). Empty for a principal with full visibility (typically the\n * owner/admin/custodian). Non-empty means `manifest.collections` is\n * DEFINITELY INCOMPLETE relative to the pod's true collection set —\n * see `sync.ts` for why that must gate whether the manifest gets written.\n */\n readonly undecodableCollections: readonly string[]\n}\n\n/**\n * Read the fence generation + every `_schemas/<collection>` envelope this\n * principal can decrypt, and project them into a fresh {@link SchemaManifest}.\n * `lookupDEK` is called once per collection found under `_schemas` (never\n * mints — see {@link LookupDEK}). Names whose DEK isn't held, or whose\n * envelope fails to decrypt/parse despite holding a DEK, are reported via\n * `undecodableCollections` rather than silently dropped from the result.\n */\nexport async function deriveSchemaManifest(\n store: NoydbStore,\n vault: string,\n lookupDEK: LookupDEK,\n): Promise<DeriveSchemaManifestResult> {\n const fence = await loadFence(store, vault)\n const collectionNames = await store.list(vault, SCHEMAS_COLLECTION)\n\n const collections: Record<string, SchemaManifestEntry> = {}\n const undecodableCollections: string[] = []\n for (const name of collectionNames) {\n const dek = await lookupDEK(name)\n if (dek === undefined) {\n undecodableCollections.push(name) // present in _schemas, but not decodable by this principal\n continue\n }\n\n const payload = await loadPersistedSchema(store, vault, name, dek)\n if (!payload) {\n // Held a DEK but still couldn't decrypt/parse — cannot distinguish\n // \"wrong key after all\" from real corruption from here; treat as\n // undecodable (never silently drop) rather than \"no content.\"\n undecodableCollections.push(name)\n continue\n }\n if (payload.hash === null) continue // legitimately no derivable content (stub envelope)\n\n const entry: SchemaManifestEntry = {\n generation: payload.generation ?? fence.currentSchemaVersion,\n contentHash: payload.hash,\n }\n collections[name] = payload.fieldIds !== undefined ? { ...entry, fieldIds: payload.fieldIds } : entry\n }\n\n const aggregateHash = await computeAggregateHash(collections)\n const manifest: SchemaManifest = { v: 1, kind: 'schema', generation: fence.currentSchemaVersion, collections, aggregateHash }\n return { manifest, undecodableCollections }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAmDO,IAAM,4BAA4B;;;ACAzC,eAAsB,wBACpB,OACA,OACA,QAC2C;AAC3C,QAAM,WAAW,MAAM,MAAM,IAAI,OAAO,qBAAqB,yBAAyB;AACtF,MAAI,CAAC,SAAU,QAAO;AACtB,QAAM,MAAM,MAAM,OAAO,mBAAmB;AAC5C,MAAI;AACF,UAAM,YAAY,MAAM,iBAAiB,EAAE,YAAY,qBAAqB,IAAI,0BAA0B,GAAG,UAAU,GAAG;AAC1H,UAAM,SAAS,KAAK,MAAM,SAAS;AACnC,QAAI,OAAO,MAAM,KAAK,OAAO,SAAS,SAAU,QAAO;AACvD,WAAO,EAAE,SAAS,SAAS,IAAI,UAAU,OAAO;AAAA,EAClD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AASA,eAAsB,mBACpB,OACA,OACA,UACA,iBACA,QACe;AACf,QAAM,MAAM,MAAM,OAAO,mBAAmB;AAC5C,QAAM,OAAO,KAAK,UAAU,QAAQ;AACpC,QAAM,MAAM,MAAM;AAAA,IAChB,EAAE,YAAY,qBAAqB,IAAI,2BAA2B,SAAS,kBAAkB,EAAE;AAAA,IAC/F,CAAC,aAAa,kBAAkB,UAAU,MAAM,GAAG;AAAA,IACnD,CAAC;AAAA,EACH;AACA,QAAM,MAAM,IAAI,OAAO,qBAAqB,2BAA2B,KAAK,eAAe;AAC7F;AASA,eAAsB,qBACpB,aACiB;AACjB,SAAO,UAAU,cAAc,WAAW,CAAC;AAC7C;;;ACZA,eAAsB,qBACpB,OACA,OACA,WACqC;AACrC,QAAM,QAAQ,MAAM,UAAU,OAAO,KAAK;AAC1C,QAAM,kBAAkB,MAAM,MAAM,KAAK,OAAO,kBAAkB;AAElE,QAAM,cAAmD,CAAC;AAC1D,QAAM,yBAAmC,CAAC;AAC1C,aAAW,QAAQ,iBAAiB;AAClC,UAAM,MAAM,MAAM,UAAU,IAAI;AAChC,QAAI,QAAQ,QAAW;AACrB,6BAAuB,KAAK,IAAI;AAChC;AAAA,IACF;AAEA,UAAM,UAAU,MAAM,oBAAoB,OAAO,OAAO,MAAM,GAAG;AACjE,QAAI,CAAC,SAAS;AAIZ,6BAAuB,KAAK,IAAI;AAChC;AAAA,IACF;AACA,QAAI,QAAQ,SAAS,KAAM;AAE3B,UAAM,QAA6B;AAAA,MACjC,YAAY,QAAQ,cAAc,MAAM;AAAA,MACxC,aAAa,QAAQ;AAAA,IACvB;AACA,gBAAY,IAAI,IAAI,QAAQ,aAAa,SAAY,EAAE,GAAG,OAAO,UAAU,QAAQ,SAAS,IAAI;AAAA,EAClG;AAEA,QAAM,gBAAgB,MAAM,qBAAqB,WAAW;AAC5D,QAAM,WAA2B,EAAE,GAAG,GAAG,MAAM,UAAU,YAAY,MAAM,sBAAsB,aAAa,cAAc;AAC5H,SAAO,EAAE,UAAU,uBAAuB;AAC5C;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
} from "./chunk-
|
|
2
|
+
buildRecordEnvelope
|
|
3
|
+
} from "./chunk-FX3UIDCS.js";
|
|
4
4
|
|
|
5
5
|
// src/with-shape/schema-update/fence.ts
|
|
6
6
|
var FENCE_RECORD_ID = "schema-fence";
|
|
@@ -18,13 +18,10 @@ async function loadFence(store, vault) {
|
|
|
18
18
|
}
|
|
19
19
|
}
|
|
20
20
|
async function saveFence(store, vault, fence) {
|
|
21
|
-
const envelope =
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
_iv: "",
|
|
26
|
-
_data: JSON.stringify(fence)
|
|
27
|
-
};
|
|
21
|
+
const envelope = buildRecordEnvelope(
|
|
22
|
+
{ collection: META_COLLECTION, id: FENCE_RECORD_ID, version: 1 },
|
|
23
|
+
{ iv: "", data: JSON.stringify(fence) }
|
|
24
|
+
);
|
|
28
25
|
await store.put(vault, META_COLLECTION, FENCE_RECORD_ID, envelope);
|
|
29
26
|
}
|
|
30
27
|
function isFenceDoc(x) {
|
|
@@ -39,4 +36,4 @@ export {
|
|
|
39
36
|
loadFence,
|
|
40
37
|
saveFence
|
|
41
38
|
};
|
|
42
|
-
//# sourceMappingURL=chunk-
|
|
39
|
+
//# sourceMappingURL=chunk-DNKVKO7K.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/with-shape/schema-update/fence.ts"],"sourcesContent":["/**\n * Schema-fence document. Vault-level generation counter + drain\n * state, stored at `_meta/schema-fence` using the plaintext-envelope\n * pattern of `_meta/policy` (no PII — a counter + a state enum).\n */\nimport type { NoydbStore } from '../../kernel/types.js'\nimport { buildRecordEnvelope } from '../../kernel/enclave/index.js'\n\nexport type FenceState = 'normal' | 'draining' | 'migrating' | 'complete'\n\nexport interface FenceDoc {\n readonly currentSchemaVersion: number\n readonly fenceState: FenceState\n /**\n * Content hash (`PersistedSchemaEnvelope.hash`) of the schema most\n * recently persisted while the vault sat at `currentSchemaVersion` —\n * binds \"generation N\" to a concrete schema-content hash (#946), so\n * \"which schema is generation N\" is answerable from `schemaFenceState()`\n * alone. Optional: absent on a fresh vault (generation 0, nothing\n * persisted yet) and on a fence document written before #946.\n */\n readonly schemaHash?: string\n}\n\nexport const FENCE_RECORD_ID = 'schema-fence'\nconst META_COLLECTION = '_meta'\n\nexport const DEFAULT_FENCE: FenceDoc = { currentSchemaVersion: 0, fenceState: 'normal' }\n\nexport async function loadFence(store: NoydbStore, vault: string): Promise<FenceDoc> {\n const envelope = await store.get(vault, META_COLLECTION, FENCE_RECORD_ID)\n if (!envelope) return DEFAULT_FENCE\n try {\n const parsed = JSON.parse(envelope._data) as unknown\n if (!isFenceDoc(parsed)) return DEFAULT_FENCE\n return parsed\n } catch {\n return DEFAULT_FENCE\n }\n}\n\nexport async function saveFence(store: NoydbStore, vault: string, fence: FenceDoc): Promise<void> {\n const envelope = buildRecordEnvelope(\n { collection: META_COLLECTION, id: FENCE_RECORD_ID, version: 1 },\n { iv: '', data: JSON.stringify(fence) },\n )\n await store.put(vault, META_COLLECTION, FENCE_RECORD_ID, envelope)\n}\n\nfunction isFenceDoc(x: unknown): x is FenceDoc {\n if (x === null || typeof x !== 'object') return false\n const o = x as Record<string, unknown>\n if (typeof o['currentSchemaVersion'] !== 'number') return false\n if (o['fenceState'] !== 'normal' && o['fenceState'] !== 'draining'\n && o['fenceState'] !== 'migrating' && o['fenceState'] !== 'complete') return false\n // schemaHash is optional (#946) — a legacy fence doc without it is still valid.\n return o['schemaHash'] === undefined || typeof o['schemaHash'] === 'string'\n}\n"],"mappings":";;;;;AAwBO,IAAM,kBAAkB;AAC/B,IAAM,kBAAkB;AAEjB,IAAM,gBAA0B,EAAE,sBAAsB,GAAG,YAAY,SAAS;AAEvF,eAAsB,UAAU,OAAmB,OAAkC;AACnF,QAAM,WAAW,MAAM,MAAM,IAAI,OAAO,iBAAiB,eAAe;AACxE,MAAI,CAAC,SAAU,QAAO;AACtB,MAAI;AACF,UAAM,SAAS,KAAK,MAAM,SAAS,KAAK;AACxC,QAAI,CAAC,WAAW,MAAM,EAAG,QAAO;AAChC,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,UAAU,OAAmB,OAAe,OAAgC;AAChG,QAAM,WAAW;AAAA,IACf,EAAE,YAAY,iBAAiB,IAAI,iBAAiB,SAAS,EAAE;AAAA,IAC/D,EAAE,IAAI,IAAI,MAAM,KAAK,UAAU,KAAK,EAAE;AAAA,EACxC;AACA,QAAM,MAAM,IAAI,OAAO,iBAAiB,iBAAiB,QAAQ;AACnE;AAEA,SAAS,WAAW,GAA2B;AAC7C,MAAI,MAAM,QAAQ,OAAO,MAAM,SAAU,QAAO;AAChD,QAAM,IAAI;AACV,MAAI,OAAO,EAAE,sBAAsB,MAAM,SAAU,QAAO;AAC1D,MAAI,EAAE,YAAY,MAAM,YAAY,EAAE,YAAY,MAAM,cACnD,EAAE,YAAY,MAAM,eAAe,EAAE,YAAY,MAAM,WAAY,QAAO;AAE/E,SAAO,EAAE,YAAY,MAAM,UAAa,OAAO,EAAE,YAAY,MAAM;AACrE;","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ValidationError
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-Z3BZXPRO.js";
|
|
4
4
|
|
|
5
5
|
// src/with-formula/derivations/with-derivation.ts
|
|
6
6
|
function withDerivation(spec) {
|
|
@@ -126,4 +126,4 @@ export {
|
|
|
126
126
|
withDerivation,
|
|
127
127
|
withRollup
|
|
128
128
|
};
|
|
129
|
-
//# sourceMappingURL=chunk-
|
|
129
|
+
//# sourceMappingURL=chunk-EHRIDNZX.js.map
|