@noy-db/hub 0.3.0-pre.8 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/aggregate/index.js +9 -8
- package/dist/aggregate/index.js.map +1 -1
- package/dist/api-ZGS6LCOF.js +20 -0
- package/dist/as/index.js +11 -11
- package/dist/attestation/index.js +18 -18
- package/dist/backup-BJ57IKAO.js +242 -0
- package/dist/backup-BJ57IKAO.js.map +1 -0
- package/dist/blobs/index.js +13 -11
- package/dist/blobs/index.js.map +1 -1
- package/dist/broker/index.js +92 -0
- package/dist/broker/index.js.map +1 -0
- package/dist/bundle/index.js +25 -22
- package/dist/bundle/index.js.map +1 -1
- package/dist/by/index.js +2 -2
- package/dist/cargo/index.js +31 -31
- package/dist/chunk-2NVOWNI3.js +167 -0
- package/dist/chunk-2NVOWNI3.js.map +1 -0
- package/dist/chunk-3B5VVCNY.js +71 -0
- package/dist/chunk-3LQ2YKO4.js +230 -0
- package/dist/chunk-3QCRBHCY.js +54 -0
- package/dist/chunk-454JXE57.js +1697 -0
- package/dist/chunk-454JXE57.js.map +1 -0
- package/dist/chunk-4CTHCN4J.js +480 -0
- package/dist/chunk-4CTHCN4J.js.map +1 -0
- package/dist/chunk-4GPE63GU.js +111 -0
- package/dist/chunk-4GPE63GU.js.map +1 -0
- package/dist/chunk-4JBYV75E.js +150 -0
- package/dist/chunk-4NXKCLLQ.js +97 -0
- package/dist/chunk-4VNQOLML.js +29 -0
- package/dist/chunk-4VNQOLML.js.map +1 -0
- package/dist/chunk-5M5DVGV7.js +69 -0
- package/dist/chunk-5O3XF4DV.js +150 -0
- package/dist/chunk-5O3XF4DV.js.map +1 -0
- package/dist/chunk-5YOLBEQ6.js +30 -0
- package/dist/chunk-6CRIV7DE.js +129 -0
- package/dist/chunk-6JTIAGHD.js +621 -0
- package/dist/chunk-6JTIAGHD.js.map +1 -0
- package/dist/chunk-6QTNZJBS.js +255 -0
- package/dist/chunk-6T2SCQRU.js +86 -0
- package/dist/chunk-7DSTRQIJ.js +45 -0
- package/dist/chunk-AUSTCW2X.js +589 -0
- package/dist/chunk-B3HJYUOF.js +209 -0
- package/dist/chunk-BDVFPG6Y.js +164 -0
- package/dist/chunk-BIOUI4HL.js +1554 -0
- package/dist/chunk-BIOUI4HL.js.map +1 -0
- package/dist/chunk-CAF6WOK7.js +36 -0
- package/dist/chunk-CDUQTA3Z.js +381 -0
- package/dist/chunk-CDUQTA3Z.js.map +1 -0
- package/dist/chunk-CIE2BASH.js +404 -0
- package/dist/chunk-CRI4OUV4.js +42 -0
- package/dist/chunk-DLG74CNB.js +91 -0
- package/dist/chunk-E5ZQT5KX.js +30 -0
- package/dist/chunk-E5ZQT5KX.js.map +1 -0
- package/dist/chunk-EQO2UVP4.js +247 -0
- package/dist/chunk-EQO2UVP4.js.map +1 -0
- package/dist/chunk-ERJ7FU55.js +367 -0
- package/dist/chunk-EVVGJDRQ.js +205 -0
- package/dist/chunk-EVX47VBM.js +74 -0
- package/dist/chunk-EVX47VBM.js.map +1 -0
- package/dist/chunk-EXK7QRWF.js +59 -0
- package/dist/chunk-EYZ6IQ6X.js +202 -0
- package/dist/chunk-F64IRYG3.js +45 -0
- package/dist/chunk-FHS2HQSH.js +823 -0
- package/dist/chunk-FM3G3NOY.js +206 -0
- package/dist/chunk-FM3G3NOY.js.map +1 -0
- package/dist/chunk-FUG4SFN3.js +36 -0
- package/dist/chunk-FUG4SFN3.js.map +1 -0
- package/dist/chunk-GKEWXIV5.js +80 -0
- package/dist/chunk-GTGPO5KW.js +59 -0
- package/dist/chunk-HB3RFQSC.js +95 -0
- package/dist/chunk-HDMEGAQE.js +957 -0
- package/dist/chunk-HDMEGAQE.js.map +1 -0
- package/dist/chunk-HDQIIUPH.js +135 -0
- package/dist/chunk-HDQIIUPH.js.map +1 -0
- package/dist/chunk-HTJQYHZP.js +344 -0
- package/dist/chunk-HTJQYHZP.js.map +1 -0
- package/dist/chunk-I6GALP6E.js +99 -0
- package/dist/chunk-IGJCYUT5.js +99 -0
- package/dist/chunk-IGJCYUT5.js.map +1 -0
- package/dist/chunk-IL6POWCW.js +130 -0
- package/dist/chunk-IU6SNYX6.js +117 -0
- package/dist/chunk-J2ZX2XUV.js +778 -0
- package/dist/chunk-JIF24JPM.js +495 -0
- package/dist/chunk-JIF24JPM.js.map +1 -0
- package/dist/chunk-JK733I5V.js +23 -0
- package/dist/chunk-JK733I5V.js.map +1 -0
- package/dist/chunk-JKJOGPZN.js +29 -0
- package/dist/chunk-JNAI2HN2.js +32 -0
- package/dist/chunk-JNAI2HN2.js.map +1 -0
- package/dist/chunk-JZUV47FZ.js +41 -0
- package/dist/chunk-K5IMOGHB.js +30 -0
- package/dist/chunk-KPZS5QAQ.js +151 -0
- package/dist/chunk-KPZS5QAQ.js.map +1 -0
- package/dist/chunk-KSKBRKGJ.js +291 -0
- package/dist/chunk-KSKBRKGJ.js.map +1 -0
- package/dist/chunk-LASZKVMO.js +382 -0
- package/dist/chunk-LXEXBTKL.js +515 -0
- package/dist/chunk-LXEXBTKL.js.map +1 -0
- package/dist/chunk-M4CV6BRT.js +524 -0
- package/dist/chunk-M4CV6BRT.js.map +1 -0
- package/dist/chunk-MEFJPTZ4.js +371 -0
- package/dist/chunk-MEFJPTZ4.js.map +1 -0
- package/dist/chunk-MV43JSJF.js +265 -0
- package/dist/chunk-MV43JSJF.js.map +1 -0
- package/dist/chunk-NJ4EOKMB.js +392 -0
- package/dist/chunk-NJ4EOKMB.js.map +1 -0
- package/dist/chunk-NR5LT5RY.js +135 -0
- package/dist/chunk-NWSGI5C7.js +261 -0
- package/dist/chunk-NWSGI5C7.js.map +1 -0
- package/dist/chunk-OSDB5WW3.js +739 -0
- package/dist/chunk-OSDB5WW3.js.map +1 -0
- package/dist/chunk-PN2XMATY.js +37 -0
- package/dist/chunk-PN2XMATY.js.map +1 -0
- package/dist/chunk-Q5VNKNE5.js +70 -0
- package/dist/chunk-QLWMEXCT.js +21 -0
- package/dist/chunk-QRB7NAOJ.js +123 -0
- package/dist/chunk-R4ROFEYC.js +74 -0
- package/dist/chunk-RCVJZMFE.js +164 -0
- package/dist/chunk-RCVJZMFE.js.map +1 -0
- package/dist/chunk-RIX4V2TB.js +367 -0
- package/dist/chunk-RYCTDFUX.js +40 -0
- package/dist/chunk-RZ5SVOYR.js +155 -0
- package/dist/chunk-SLFHQTTW.js +99 -0
- package/dist/chunk-SNZ6URZZ.js +2782 -0
- package/dist/chunk-SNZ6URZZ.js.map +1 -0
- package/dist/chunk-T2FFWNPK.js +75 -0
- package/dist/chunk-T2FFWNPK.js.map +1 -0
- package/dist/chunk-UNFPPVNI.js +23 -0
- package/dist/chunk-VFUPHI2Z.js +333 -0
- package/dist/chunk-VFUPHI2Z.js.map +1 -0
- package/dist/chunk-VLFCJYTL.js +235 -0
- package/dist/chunk-VN3DBQAU.js +124 -0
- package/dist/chunk-VYYM3MEN.js +98 -0
- package/dist/chunk-VYYM3MEN.js.map +1 -0
- package/dist/chunk-VZRODIM3.js +49 -0
- package/dist/chunk-W22IKJE2.js +94 -0
- package/dist/chunk-X3YYQWOQ.js +155 -0
- package/dist/chunk-X7QBD67R.js +14405 -0
- package/dist/chunk-X7QBD67R.js.map +1 -0
- package/dist/chunk-XDYREZWE.js +1128 -0
- package/dist/chunk-XDYREZWE.js.map +1 -0
- package/dist/chunk-XWZVFISC.js +720 -0
- package/dist/chunk-XWZVFISC.js.map +1 -0
- package/dist/chunk-YFXZEAYK.js +85 -0
- package/dist/chunk-ZAJAVEXY.js +50 -0
- package/dist/chunk-ZICD77GM.js +34 -0
- package/dist/chunk-ZJ2AK4V7.js +38 -0
- package/dist/chunk-ZJ2AK4V7.js.map +1 -0
- package/dist/chunk-ZUODRVHY.js +14 -0
- package/dist/classified/index.js +5 -3
- package/dist/classified-marker-CZKA6ITE.js +28 -0
- package/dist/classified-marker-CZKA6ITE.js.map +1 -0
- package/dist/collection-facade-TLWIPI76.js +44 -0
- package/dist/computed-ZIQTYTDI.js +11 -0
- package/dist/consent/index.js +9 -9
- package/dist/crdt/index.js +1 -1
- package/dist/dead-filter-ESOBZZP5.js +28 -0
- package/dist/delegation-W7ZV2322.js +25 -0
- package/dist/derivations/index.js +12 -11
- package/dist/derive-H2BJTLUI.js +21 -0
- package/dist/enclave-AP3I5W7O.js +141 -0
- package/dist/executor-KGWTNEQD.js +9 -0
- package/dist/executor-OVEXR6RT.js +9 -0
- package/dist/executor-UNEH5ZYH.js +25 -0
- package/dist/export-accessible-PCMXSUZS.js +23 -0
- package/dist/extract-partition-SWHFSYJO.js +38 -0
- package/dist/fanout-sidecar-A765THMX.js +74 -0
- package/dist/find-N6345CNT.js +11 -0
- package/dist/forget/index.js +10 -10
- package/dist/forget/index.js.map +1 -1
- package/dist/guards/index.js +6 -6
- package/dist/history/index.js +14 -11
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +50 -37
- package/dist/i18n/index.js.map +1 -1
- package/dist/index.d.ts +307 -1459
- package/dist/index.js +595 -198
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +7 -7
- package/dist/indexing/index.js.map +1 -1
- package/dist/issue-5OKB6I2R.js +19 -0
- package/dist/kernel/best-effort-revert.d.ts +52 -0
- package/dist/kernel/cache/index.d.ts +10 -0
- package/dist/kernel/cache/lru.d.ts +97 -0
- package/dist/kernel/cache/policy.d.ts +32 -0
- package/dist/kernel/collection-config.d.ts +809 -0
- package/dist/kernel/collection.d.ts +1522 -0
- package/dist/kernel/constants.d.ts +18 -0
- package/dist/kernel/debug.d.ts +25 -0
- package/dist/kernel/enclave/broker/proof.d.ts +154 -0
- package/dist/kernel/enclave/classify/bidx.d.ts +77 -0
- package/dist/kernel/enclave/classify/compare.d.ts +10 -0
- package/dist/kernel/enclave/classify/digest.d.ts +8 -0
- package/dist/kernel/enclave/classify/find.d.ts +36 -0
- package/dist/kernel/enclave/classify/kofn.d.ts +7 -0
- package/dist/kernel/enclave/classify/normalize.d.ts +7 -0
- package/dist/kernel/enclave/classify/reveal.d.ts +10 -0
- package/dist/kernel/enclave/classify/vdig.d.ts +39 -0
- package/dist/kernel/enclave/classify/verify.d.ts +36 -0
- package/dist/kernel/enclave/classify/write.d.ts +8 -0
- package/dist/kernel/enclave/crypto.d.ts +263 -0
- package/dist/kernel/enclave/index.d.ts +79 -0
- package/dist/kernel/enclave/record-keys/deterministic.d.ts +55 -0
- package/dist/kernel/enclave/record-keys/envelope-body.d.ts +79 -0
- package/dist/kernel/enclave/record-keys/lifecycle.d.ts +107 -0
- package/dist/kernel/enclave/record-keys/record-codec.d.ts +328 -0
- package/dist/kernel/enclave/record-keys/sealed-slot.d.ts +14 -0
- package/dist/kernel/enclave/record-keys/sealed-slots.d.ts +123 -0
- package/dist/kernel/enclave/record-keys/sealing.d.ts +70 -0
- package/dist/kernel/enclave/record-keys/tombstone.d.ts +57 -0
- package/dist/kernel/env-check.d.ts +1 -0
- package/dist/kernel/errors.d.ts +1922 -0
- package/dist/kernel/events.d.ts +11 -0
- package/dist/kernel/lazy-count.d.ts +13 -0
- package/dist/kernel/memory-store.d.ts +17 -0
- package/dist/kernel/mutation.d.ts +14 -0
- package/dist/kernel/noydb.d.ts +826 -0
- package/dist/kernel/paths.d.ts +25 -0
- package/dist/kernel/query/builder.d.ts +520 -0
- package/dist/kernel/query/index.d.ts +31 -0
- package/dist/kernel/query/join.d.ts +205 -0
- package/dist/kernel/query/live.d.ts +111 -0
- package/dist/kernel/query/predicate.d.ts +139 -0
- package/dist/kernel/query/scan-builder.d.ts +334 -0
- package/dist/kernel/refs.d.ts +205 -0
- package/dist/kernel/schema.d.ts +134 -0
- package/dist/kernel/sync-policy.d.ts +188 -0
- package/dist/kernel/tier-visibility.d.ts +54 -0
- package/dist/kernel/types.d.ts +3239 -0
- package/dist/kernel/util/discriminant.d.ts +58 -0
- package/dist/kernel/util/index.d.ts +14 -0
- package/dist/kernel/util/sanitize-filename.d.ts +75 -0
- package/dist/kernel/validation.d.ts +130 -0
- package/dist/kernel/vault.d.ts +1740 -0
- package/dist/kernel/via/compose.d.ts +144 -0
- package/dist/kernel/via/dispatch.d.ts +195 -0
- package/dist/kernel/via/graph-wiring.d.ts +145 -0
- package/dist/kernel/via/graph.d.ts +166 -0
- package/dist/kernel/via/index.d.ts +200 -0
- package/dist/kernel/via/pipeline.d.ts +266 -0
- package/dist/kernel/via/reconcile.d.ts +153 -0
- package/dist/kernel/via/taint-binding.d.ts +66 -0
- package/dist/kernel/write-queue.d.ts +46 -0
- package/dist/ledger-GFBKVPV4.js +42 -0
- package/dist/legacy/bundle.d.ts +30 -0
- package/dist/legacy/kernel.d.ts +33 -0
- package/dist/liberate-3VDOT4KO.js +24 -0
- package/dist/link-set-Z7Q2ASFX.js +31 -0
- package/dist/materialized-views/index.js +19 -15
- package/dist/noydb-ZCJOYBDI.js +68 -0
- package/dist/on/index.js +9 -9
- package/dist/overlay-views/index.js +4 -4
- package/dist/periods/index.js +12 -12
- package/dist/pod/index.js +11 -11
- package/dist/policy-Z3RUAIY2.js +41 -0
- package/dist/port/as/index.d.ts +26 -0
- package/dist/port/at/index.d.ts +18 -0
- package/dist/port/by/default-provider.d.ts +9 -0
- package/dist/port/by/index.d.ts +17 -0
- package/dist/port/by/types.d.ts +86 -0
- package/dist/port/in/index.d.ts +21 -0
- package/dist/port/on/index.d.ts +27 -0
- package/dist/port/to/index.d.ts +19 -0
- package/dist/port/ui/index.d.ts +21 -0
- package/dist/port/with/blob-strategy.d.ts +98 -0
- package/dist/port/with/broker-strategy.d.ts +84 -0
- package/dist/port/with/capabilities.d.ts +31 -0
- package/dist/port/with/classified-marker.d.ts +9 -0
- package/dist/port/with/classified-strategy.d.ts +62 -0
- package/dist/port/with/computed-strategy.d.ts +19 -0
- package/dist/port/with/i18n-strategy.d.ts +175 -0
- package/dist/port/with/index.d.ts +18 -0
- package/dist/port/with/lazy-strategy.d.ts +48 -0
- package/dist/port/with/lookup-strategy.d.ts +129 -0
- package/dist/port/with/service-bus.d.ts +156 -0
- package/dist/port/with/team-strategy.d.ts +36 -0
- package/dist/port/with/write-hooks.d.ts +34 -0
- package/dist/portability/index.js +8 -8
- package/dist/post-register-JTH76BLY.js +60 -0
- package/dist/post-register-JTH76BLY.js.map +1 -0
- package/dist/public-envelope-B4KNWVUA.js +32 -0
- package/dist/purge-scope-FGNNLWHD.js +24 -0
- package/dist/purge-scope-FGNNLWHD.js.map +1 -0
- package/dist/query/index.js +9 -6
- package/dist/read-only-facade-CHCKSEPD.js +8 -0
- package/dist/register-VAHONCID.js +23 -0
- package/dist/registry-7MLVD3VO.js +19 -0
- package/dist/registry-EPKPD5SM.js +18 -0
- package/dist/registry-P5T7PS2U.js +9 -0
- package/dist/request-withdrawal-TI3A5WPS.js +31 -0
- package/dist/reveal-DIBHLUZX.js +38 -0
- package/dist/reveal-DIBHLUZX.js.map +1 -0
- package/dist/revoke-FDRD6GRW.js +24 -0
- package/dist/satellites/index.js +1 -1
- package/dist/sealed-record/index.js +12 -12
- package/dist/seed-Q6M2IZFL.js +231 -0
- package/dist/seed-Q6M2IZFL.js.map +1 -0
- package/dist/session/index.js +9 -9
- package/dist/shadow/index.js +2 -2
- package/dist/signer-MUWEIUI6.js +25 -0
- package/dist/snapshots/index.js +10 -10
- package/dist/stale-OSQ7J3AA.js +29 -0
- package/dist/storage-MVFCGEQE.js +23 -0
- package/dist/store-coordination-provider-64OEZFGS.js +142 -0
- package/dist/sync/index.js +9 -9
- package/dist/team/index.js +15 -15
- package/dist/tiers/index.js +14 -10
- package/dist/to/index.js +1 -2
- package/dist/tx/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/verify-ZASTRNPR.js +140 -0
- package/dist/verify-ZASTRNPR.js.map +1 -0
- package/dist/via/blob/active.d.ts +34 -0
- package/dist/via/blob/binding.d.ts +86 -0
- package/dist/via/blob/index.d.ts +34 -0
- package/dist/via/classified/active.d.ts +3 -0
- package/dist/via/classified/binding.d.ts +83 -0
- package/dist/via/classified/config-drift.d.ts +34 -0
- package/dist/via/classified/descriptor.d.ts +66 -0
- package/dist/via/classified/errors.d.ts +19 -0
- package/dist/via/classified/guards.d.ts +23 -0
- package/dist/via/classified/index.d.ts +11 -0
- package/dist/via/classified/presets.d.ts +65 -0
- package/dist/via/classified/resolve.d.ts +9 -0
- package/dist/via/classified/strategy.d.ts +11 -0
- package/dist/via/classified/validators.d.ts +3 -0
- package/dist/via/classified/write.d.ts +4 -0
- package/dist/via/computed/binding.d.ts +34 -0
- package/dist/via/computed/descriptor.d.ts +35 -0
- package/dist/via/i18n/active.d.ts +28 -0
- package/dist/via/i18n/binding.d.ts +36 -0
- package/dist/via/i18n/core.d.ts +267 -0
- package/dist/via/i18n/densify.d.ts +24 -0
- package/dist/via/i18n/dictionary.d.ts +200 -0
- package/dist/via/i18n/index.d.ts +21 -0
- package/dist/via/i18n/policy.d.ts +44 -0
- package/dist/via/i18n/script.d.ts +26 -0
- package/dist/via/i18n/strategy.d.ts +13 -0
- package/dist/via/lookup/active.d.ts +19 -0
- package/dist/via/lookup/binding.d.ts +99 -0
- package/dist/via/lookup/descriptor.d.ts +123 -0
- package/dist/via/lookup/handle.d.ts +220 -0
- package/dist/via/lookup/index.d.ts +17 -0
- package/dist/via/lookup/registry.d.ts +228 -0
- package/dist/via/lookup/snapshot.d.ts +67 -0
- package/dist/via/money/arith.d.ts +68 -0
- package/dist/via/money/binding.d.ts +21 -0
- package/dist/via/money/branded.d.ts +61 -0
- package/dist/via/money/descriptor.d.ts +73 -0
- package/dist/via/money/fixed-point.d.ts +51 -0
- package/dist/via/money/index.d.ts +15 -0
- package/dist/via/money/iso4217.d.ts +6 -0
- package/dist/via/money/money-reducer.d.ts +33 -0
- package/dist/via/money/normalize.d.ts +105 -0
- package/dist/via/money/paths.d.ts +61 -0
- package/dist/via/money/where.d.ts +127 -0
- package/dist/walk-SVNDIZ62.js +241 -0
- package/dist/with/index.js +11 -11
- package/dist/with-audit/attestation/active.d.ts +10 -0
- package/dist/with-audit/attestation/index.d.ts +16 -0
- package/dist/with-audit/attestation/issue.d.ts +29 -0
- package/dist/with-audit/attestation/revoke.d.ts +15 -0
- package/dist/with-audit/attestation/signer.d.ts +33 -0
- package/dist/with-audit/attestation/strategy.d.ts +44 -0
- package/dist/with-audit/attestation/vault-facade.d.ts +62 -0
- package/dist/with-audit/consent/active.d.ts +14 -0
- package/dist/with-audit/consent/consent.d.ts +114 -0
- package/dist/with-audit/consent/index.d.ts +14 -0
- package/dist/with-audit/consent/strategy.d.ts +36 -0
- package/dist/with-audit/forget/active.d.ts +31 -0
- package/dist/with-audit/forget/index.d.ts +28 -0
- package/dist/with-audit/forget/purge-scope.d.ts +54 -0
- package/dist/with-audit/forget/strategy.d.ts +199 -0
- package/dist/with-audit/forget/subject-index.d.ts +83 -0
- package/dist/with-audit/guards/executor.d.ts +26 -0
- package/dist/with-audit/guards/immutable-guard.d.ts +63 -0
- package/dist/with-audit/guards/index.d.ts +10 -0
- package/dist/with-audit/guards/read-only-facade.d.ts +31 -0
- package/dist/with-audit/guards/registry.d.ts +83 -0
- package/dist/with-audit/guards/transition-guard.d.ts +82 -0
- package/dist/with-audit/guards/types.d.ts +134 -0
- package/dist/with-audit/guards/with-guard.d.ts +15 -0
- package/dist/with-audit/periods/active.d.ts +11 -0
- package/dist/with-audit/periods/index.d.ts +18 -0
- package/dist/with-audit/periods/periods.d.ts +417 -0
- package/dist/with-audit/periods/strategy.d.ts +32 -0
- package/dist/with-audit/periods/vault-facade.d.ts +95 -0
- package/dist/with-audit/portability/active.d.ts +11 -0
- package/dist/with-audit/portability/export-accessible.d.ts +46 -0
- package/dist/with-audit/portability/index.d.ts +18 -0
- package/dist/with-audit/portability/request-withdrawal.d.ts +85 -0
- package/dist/with-audit/portability/strategy.d.ts +31 -0
- package/dist/with-audit/portability/withdraw-accessible.d.ts +82 -0
- package/dist/with-audit/sealed-record/active.d.ts +9 -0
- package/dist/with-audit/sealed-record/index.d.ts +55 -0
- package/dist/with-audit/sealed-record/strategy.d.ts +34 -0
- package/dist/with-audit/sealed-record/types.d.ts +27 -0
- package/dist/with-audit/tiers/active.d.ts +9 -0
- package/dist/with-audit/tiers/index.d.ts +394 -0
- package/dist/with-audit/tiers/strategy.d.ts +36 -0
- package/dist/with-cargo/active.d.ts +11 -0
- package/dist/with-cargo/adopt-partition.d.ts +81 -0
- package/dist/with-cargo/decrypt-partition.d.ts +19 -0
- package/dist/with-cargo/describe-extraction.d.ts +41 -0
- package/dist/with-cargo/extract-partition.d.ts +155 -0
- package/dist/with-cargo/index.d.ts +33 -0
- package/dist/with-cargo/strategy.d.ts +30 -0
- package/dist/with-cargo/vault-diff.d.ts +144 -0
- package/dist/with-cargo/walk-closure.d.ts +67 -0
- package/dist/with-commit/crdt/active.d.ts +25 -0
- package/dist/with-commit/crdt/crdt.d.ts +42 -0
- package/dist/with-commit/crdt/index.d.ts +16 -0
- package/dist/with-commit/crdt/strategy.d.ts +25 -0
- package/dist/with-commit/history/active.d.ts +40 -0
- package/dist/with-commit/history/diff.d.ts +23 -0
- package/dist/with-commit/history/history.d.ts +73 -0
- package/dist/with-commit/history/index.d.ts +30 -0
- package/dist/with-commit/history/ledger/constants.d.ts +37 -0
- package/dist/with-commit/history/ledger/entry.d.ts +195 -0
- package/dist/with-commit/history/ledger/hash.d.ts +30 -0
- package/dist/with-commit/history/ledger/index.d.ts +19 -0
- package/dist/with-commit/history/ledger/patch.d.ts +99 -0
- package/dist/with-commit/history/ledger/store.d.ts +356 -0
- package/dist/with-commit/history/strategy.d.ts +136 -0
- package/dist/with-commit/history/time-machine.d.ts +202 -0
- package/dist/with-commit/numbering/descriptor.d.ts +27 -0
- package/dist/with-commit/numbering/index.d.ts +69 -0
- package/dist/with-commit/sequence/active.d.ts +10 -0
- package/dist/with-commit/sequence/index.d.ts +150 -0
- package/dist/with-commit/sequence/strategy.d.ts +26 -0
- package/dist/with-commit/tx/active.d.ts +27 -0
- package/dist/with-commit/tx/dry-run.d.ts +29 -0
- package/dist/with-commit/tx/elevated-handle.d.ts +59 -0
- package/dist/with-commit/tx/index.d.ts +13 -0
- package/dist/with-commit/tx/invariants.d.ts +68 -0
- package/dist/with-commit/tx/strategy.d.ts +23 -0
- package/dist/with-commit/tx/transaction.d.ts +212 -0
- package/dist/with-fork/archive/engine.d.ts +71 -0
- package/dist/with-fork/archive/index.d.ts +23 -0
- package/dist/with-fork/shadow/active.d.ts +6 -0
- package/dist/with-fork/shadow/index.d.ts +14 -0
- package/dist/with-fork/shadow/strategy.d.ts +28 -0
- package/dist/with-fork/shadow/vault-frame.d.ts +93 -0
- package/dist/with-fork/snapshots/active.d.ts +20 -0
- package/dist/with-fork/snapshots/engine.d.ts +36 -0
- package/dist/with-fork/snapshots/index.d.ts +5 -0
- package/dist/with-fork/snapshots/noydb-facade.d.ts +64 -0
- package/dist/with-fork/snapshots/policy.d.ts +23 -0
- package/dist/with-fork/snapshots/scheduler.d.ts +34 -0
- package/dist/with-fork/snapshots/strategy.d.ts +48 -0
- package/dist/with-formula/computed/index.d.ts +48 -0
- package/dist/with-formula/computed/lazy.d.ts +13 -0
- package/dist/with-formula/derivations/executor.d.ts +61 -0
- package/dist/with-formula/derivations/fanout-sidecar.d.ts +75 -0
- package/dist/with-formula/derivations/index.d.ts +6 -0
- package/dist/with-formula/derivations/registry.d.ts +67 -0
- package/dist/with-formula/derivations/stale.d.ts +39 -0
- package/dist/with-formula/derivations/strategy-hash.d.ts +1 -0
- package/dist/with-formula/derivations/types.d.ts +248 -0
- package/dist/with-formula/derivations/with-derivation.d.ts +10 -0
- package/dist/with-formula/derivations/with-rollup.d.ts +34 -0
- package/dist/with-formula/materialized-views/dependency-analyzer.d.ts +58 -0
- package/dist/with-formula/materialized-views/executor.d.ts +80 -0
- package/dist/with-formula/materialized-views/index.d.ts +11 -0
- package/dist/with-formula/materialized-views/query-hash.d.ts +23 -0
- package/dist/with-formula/materialized-views/registry.d.ts +99 -0
- package/dist/with-formula/materialized-views/stale.d.ts +113 -0
- package/dist/with-formula/materialized-views/types.d.ts +318 -0
- package/dist/with-formula/materialized-views/with-materialized-view.d.ts +24 -0
- package/dist/with-formula/overlay-views/index.d.ts +5 -0
- package/dist/with-formula/overlay-views/registry.d.ts +42 -0
- package/dist/with-formula/overlay-views/types.d.ts +97 -0
- package/dist/with-formula/overlay-views/virtual-collection.d.ts +90 -0
- package/dist/with-formula/overlay-views/with-overlayed-view.d.ts +9 -0
- package/dist/with-lookup/aggregate/active.d.ts +33 -0
- package/dist/with-lookup/aggregate/aggregation.d.ts +166 -0
- package/dist/with-lookup/aggregate/canonical-key.d.ts +16 -0
- package/dist/with-lookup/aggregate/groupby.d.ts +280 -0
- package/dist/with-lookup/aggregate/index.d.ts +23 -0
- package/dist/with-lookup/aggregate/reducers.d.ts +257 -0
- package/dist/with-lookup/aggregate/strategy.d.ts +59 -0
- package/dist/with-lookup/embeddings/cosine.d.ts +2 -0
- package/dist/with-lookup/embeddings/descriptor.d.ts +8 -0
- package/dist/with-lookup/embeddings/index.d.ts +4 -0
- package/dist/with-lookup/embeddings/vec-id.d.ts +47 -0
- package/dist/with-lookup/embeddings/vector-set.d.ts +19 -0
- package/dist/with-lookup/indexing/active.d.ts +30 -0
- package/dist/with-lookup/indexing/collection-facade.d.ts +157 -0
- package/dist/with-lookup/indexing/eager-indexes.d.ts +122 -0
- package/dist/with-lookup/indexing/index.d.ts +27 -0
- package/dist/with-lookup/indexing/lazy-builder.d.ts +102 -0
- package/dist/with-lookup/indexing/persisted-indexes.d.ts +229 -0
- package/dist/with-lookup/indexing/strategy.d.ts +56 -0
- package/dist/with-lookup/indexing/unique-constraints.d.ts +74 -0
- package/dist/with-lookup/search/active.d.ts +10 -0
- package/dist/with-lookup/search/build-docs.d.ts +15 -0
- package/dist/with-lookup/search/collection-facade.d.ts +163 -0
- package/dist/with-lookup/search/fuse.d.ts +22 -0
- package/dist/with-lookup/search/index-store.d.ts +19 -0
- package/dist/with-lookup/search/index.d.ts +19 -0
- package/dist/with-lookup/search/inverted-index.d.ts +47 -0
- package/dist/with-lookup/search/persisted-index-store.d.ts +121 -0
- package/dist/with-lookup/search/retrieve-types.d.ts +29 -0
- package/dist/with-lookup/search/scan.d.ts +28 -0
- package/dist/with-lookup/search/segment.d.ts +15 -0
- package/dist/with-lookup/search/serialize.d.ts +4 -0
- package/dist/with-lookup/search/snippet.d.ts +5 -0
- package/dist/with-lookup/search/strategy.d.ts +41 -0
- package/dist/with-lookup/search/tokenize.d.ts +12 -0
- package/dist/with-party/auth-introspection/index.d.ts +44 -0
- package/dist/with-party/broker/active.d.ts +23 -0
- package/dist/with-party/broker/index.d.ts +28 -0
- package/dist/with-party/broker/seed.d.ts +77 -0
- package/dist/with-party/custody/active.d.ts +10 -0
- package/dist/with-party/custody/index.d.ts +69 -0
- package/dist/with-party/custody/liberate.d.ts +64 -0
- package/dist/with-party/custody/strategy.d.ts +48 -0
- package/dist/with-party/directory/index.d.ts +11 -0
- package/dist/with-party/directory/public-envelope/index.d.ts +12 -0
- package/dist/with-party/directory/public-envelope/schema.d.ts +24 -0
- package/dist/with-party/directory/public-envelope/storage.d.ts +59 -0
- package/dist/with-party/directory/public-envelope/types.d.ts +80 -0
- package/dist/with-party/directory/storage.d.ts +33 -0
- package/dist/with-party/directory/types.d.ts +43 -0
- package/dist/with-party/directory/user-envelope/api.d.ts +201 -0
- package/dist/with-party/directory/user-envelope/index.d.ts +12 -0
- package/dist/with-party/directory/user-envelope/storage.d.ts +54 -0
- package/dist/with-party/directory/visibility.d.ts +47 -0
- package/dist/with-party/policy/engine.d.ts +60 -0
- package/dist/with-party/policy/index.d.ts +15 -0
- package/dist/with-party/policy/noydb-facade.d.ts +39 -0
- package/dist/with-party/policy/presets.d.ts +38 -0
- package/dist/with-party/policy/storage.d.ts +31 -0
- package/dist/with-party/session/active.d.ts +34 -0
- package/dist/with-party/session/dev-unlock.d.ts +128 -0
- package/dist/with-party/session/index.d.ts +23 -0
- package/dist/with-party/session/session-policy.d.ts +92 -0
- package/dist/with-party/session/session.d.ts +131 -0
- package/dist/with-party/session/strategy.d.ts +42 -0
- package/dist/with-party/session/unlock-state.d.ts +47 -0
- package/dist/with-party/sync/index.d.ts +31 -0
- package/dist/with-party/tab-coordination.d.ts +73 -0
- package/dist/with-party/tab-write-relay.d.ts +39 -0
- package/dist/with-party/team/active.d.ts +13 -0
- package/dist/with-party/team/authenticators.d.ts +95 -0
- package/dist/with-party/team/deed.d.ts +97 -0
- package/dist/with-party/team/delegation.d.ts +88 -0
- package/dist/with-party/team/index.d.ts +38 -0
- package/dist/with-party/team/keyring.d.ts +318 -0
- package/dist/with-party/team/magic-link-grant.d.ts +152 -0
- package/dist/with-party/team/managed-passphrase.d.ts +280 -0
- package/dist/with-party/team/noydb-facade.d.ts +484 -0
- package/dist/with-party/team/peer-recover.d.ts +81 -0
- package/dist/with-party/team/presence.d.ts +81 -0
- package/dist/with-party/team/recovery.d.ts +191 -0
- package/dist/with-party/team/reserved-secret-collections.d.ts +41 -0
- package/dist/with-party/team/rotate-recover.d.ts +275 -0
- package/dist/with-party/team/shamir-recovery-provider.d.ts +15 -0
- package/dist/with-party/team/strategy.d.ts +9 -0
- package/dist/with-party/team/sync-active.d.ts +33 -0
- package/dist/with-party/team/sync-credentials.d.ts +113 -0
- package/dist/with-party/team/sync-strategy.d.ts +67 -0
- package/dist/with-party/team/sync-transaction.d.ts +39 -0
- package/dist/with-party/team/sync.d.ts +174 -0
- package/dist/with-party/team/tiers.d.ts +39 -0
- package/dist/with-party/team/wrapped-deks.d.ts +86 -0
- package/dist/with-pod/backup.d.ts +74 -0
- package/dist/with-pod/bundle.d.ts +414 -0
- package/dist/with-pod/format.d.ts +203 -0
- package/dist/with-pod/index.d.ts +20 -0
- package/dist/with-pod/pod-store.d.ts +54 -0
- package/dist/with-pod/ulid.d.ts +64 -0
- package/dist/with-shape/blobs/blob-compaction.d.ts +170 -0
- package/dist/with-shape/blobs/blob-intent.d.ts +153 -0
- package/dist/with-shape/blobs/blob-set.d.ts +1286 -0
- package/dist/with-shape/blobs/export-blobs.d.ts +110 -0
- package/dist/with-shape/blobs/import-external.d.ts +50 -0
- package/dist/with-shape/blobs/mime-magic.d.ts +48 -0
- package/dist/with-shape/blobs/object-projection.d.ts +70 -0
- package/dist/with-shape/introspection/describe.d.ts +237 -0
- package/dist/with-shape/introspection/field-meta.d.ts +61 -0
- package/dist/with-shape/introspection/fields.d.ts +14 -0
- package/dist/with-shape/introspection/index.d.ts +12 -0
- package/dist/with-shape/introspection/json-schema.d.ts +13 -0
- package/dist/with-shape/introspection/meta.d.ts +22 -0
- package/dist/with-shape/introspection/projection.d.ts +13 -0
- package/dist/with-shape/introspection/types.d.ts +154 -0
- package/dist/with-shape/introspection/walk.d.ts +50 -0
- package/dist/with-shape/links/lazy-handle.d.ts +36 -0
- package/dist/with-shape/links/link-set.d.ts +67 -0
- package/dist/with-shape/links/names.d.ts +65 -0
- package/dist/with-shape/links/vault-facade.d.ts +211 -0
- package/dist/with-shape/persisted-schemas/canonicalize.d.ts +11 -0
- package/dist/with-shape/persisted-schemas/derive.d.ts +29 -0
- package/dist/with-shape/persisted-schemas/index.d.ts +21 -0
- package/dist/with-shape/persisted-schemas/register.d.ts +66 -0
- package/dist/with-shape/persisted-schemas/storage.d.ts +61 -0
- package/dist/with-shape/persisted-schemas/types.d.ts +54 -0
- package/dist/with-shape/satellites/dead-filter.d.ts +21 -0
- package/dist/with-shape/satellites/declare.d.ts +60 -0
- package/dist/with-shape/satellites/existence.d.ts +5 -0
- package/dist/with-shape/satellites/fanout.d.ts +38 -0
- package/dist/with-shape/satellites/forget.d.ts +47 -0
- package/dist/with-shape/satellites/index.d.ts +3 -0
- package/dist/with-shape/satellites/joined.d.ts +19 -0
- package/dist/with-shape/satellites/marker.d.ts +10 -0
- package/dist/with-shape/satellites/migrate-cek.d.ts +26 -0
- package/dist/with-shape/satellites/post-register.d.ts +6 -0
- package/dist/with-shape/satellites/proxy.d.ts +37 -0
- package/dist/with-shape/satellites/raw-target.d.ts +14 -0
- package/dist/with-shape/satellites/registry.d.ts +19 -0
- package/dist/with-shape/satellites/types.d.ts +37 -0
- package/dist/with-shape/satellites/validate.d.ts +17 -0
- package/dist/with-shape/schema-update/client-registry.d.ts +35 -0
- package/dist/with-shape/schema-update/cutover.d.ts +5 -0
- package/dist/with-shape/schema-update/delta.d.ts +2 -0
- package/dist/with-shape/schema-update/dispatch.d.ts +3 -0
- package/dist/with-shape/schema-update/fence-controller.d.ts +62 -0
- package/dist/with-shape/schema-update/fence-watcher.d.ts +37 -0
- package/dist/with-shape/schema-update/fence.d.ts +15 -0
- package/dist/with-shape/schema-update/gate.d.ts +16 -0
- package/dist/with-shape/schema-update/index.d.ts +6 -0
- package/dist/with-shape/schema-update/store-coordination-provider.d.ts +29 -0
- package/dist/with-shape/schema-update/strategies.d.ts +12 -0
- package/dist/with-shape/schema-update/types.d.ts +53 -0
- package/dist/with-store/index.d.ts +15 -0
- package/dist/with-store/lazy/active.d.ts +12 -0
- package/dist/with-store/lazy/index.d.ts +14 -0
- package/dist/with-store/lazy/strategy.d.ts +9 -0
- package/dist/with-store/route-store.d.ts +259 -0
- package/dist/with-store/store-middleware.d.ts +189 -0
- package/dist/withdraw-accessible-WZIEVWSR.js +28 -0
- package/package.json +47 -55
- package/dist/adapter/index.d.ts +0 -5
- package/dist/adapter/index.js +0 -15
- package/dist/aggregate/index.d.ts +0 -42
- package/dist/api-JDWL67WL.js +0 -20
- package/dist/as/index.d.ts +0 -7
- package/dist/at/index.d.ts +0 -5
- package/dist/attestation/index.d.ts +0 -20
- package/dist/backup-WRGNTGJF.js +0 -225
- package/dist/backup-WRGNTGJF.js.map +0 -1
- package/dist/blobs/index.d.ts +0 -44
- package/dist/bundle/index.d.ts +0 -122
- package/dist/bundle-DzWtVw7w.d.ts +0 -548
- package/dist/by/index.d.ts +0 -1
- package/dist/cargo/index.d.ts +0 -9
- package/dist/chunk-25G7PUTA.js +0 -235
- package/dist/chunk-26FSVNBL.js +0 -34
- package/dist/chunk-2PJB6H3H.js +0 -167
- package/dist/chunk-2PJB6H3H.js.map +0 -1
- package/dist/chunk-37JZR7CY.js +0 -91
- package/dist/chunk-3KBK5LU4.js +0 -117
- package/dist/chunk-3YKBGS3I.js +0 -686
- package/dist/chunk-3YKBGS3I.js.map +0 -1
- package/dist/chunk-44DV37ZV.js +0 -75
- package/dist/chunk-44DV37ZV.js.map +0 -1
- package/dist/chunk-47C4CI7R.js +0 -108
- package/dist/chunk-47C4CI7R.js.map +0 -1
- package/dist/chunk-4VDFUBTS.js +0 -275
- package/dist/chunk-4VDFUBTS.js.map +0 -1
- package/dist/chunk-55LSDABW.js +0 -94
- package/dist/chunk-56JB2BGI.js +0 -13003
- package/dist/chunk-56JB2BGI.js.map +0 -1
- package/dist/chunk-5GQE5IDB.js +0 -513
- package/dist/chunk-5GQE5IDB.js.map +0 -1
- package/dist/chunk-5HRJQSKN.js +0 -202
- package/dist/chunk-5HZULLHE.js +0 -404
- package/dist/chunk-5JQMX2EH.js +0 -50
- package/dist/chunk-5UOPIPZC.js +0 -95
- package/dist/chunk-5YBUFCFF.js +0 -135
- package/dist/chunk-62APEMF3.js +0 -280
- package/dist/chunk-62APEMF3.js.map +0 -1
- package/dist/chunk-6P5AJ2ZS.js +0 -120
- package/dist/chunk-6P5AJ2ZS.js.map +0 -1
- package/dist/chunk-6PALJTC2.js +0 -430
- package/dist/chunk-6PALJTC2.js.map +0 -1
- package/dist/chunk-6S7T6WC4.js +0 -111
- package/dist/chunk-6S7T6WC4.js.map +0 -1
- package/dist/chunk-6Z435B6N.js +0 -1656
- package/dist/chunk-6Z435B6N.js.map +0 -1
- package/dist/chunk-723XB5NX.js +0 -86
- package/dist/chunk-7CZ6YXMO.js +0 -124
- package/dist/chunk-7KTL4RHZ.js +0 -120
- package/dist/chunk-7KTL4RHZ.js.map +0 -1
- package/dist/chunk-7TAV3BFQ.js +0 -766
- package/dist/chunk-7TAV3BFQ.js.map +0 -1
- package/dist/chunk-BASCPHNM.js +0 -380
- package/dist/chunk-BASCPHNM.js.map +0 -1
- package/dist/chunk-BGIZAFY7.js +0 -1
- package/dist/chunk-BJ2XF2RC.js +0 -823
- package/dist/chunk-BM6E4MUT.js +0 -881
- package/dist/chunk-BM6E4MUT.js.map +0 -1
- package/dist/chunk-BTFTHF6Q.js +0 -42
- package/dist/chunk-C4NOLA5X.js +0 -132
- package/dist/chunk-C4NOLA5X.js.map +0 -1
- package/dist/chunk-CHK5VVMI.js +0 -155
- package/dist/chunk-DCVVCJVB.js +0 -45
- package/dist/chunk-EU7HDMT3.js +0 -54
- package/dist/chunk-F3EKFGUS.js +0 -99
- package/dist/chunk-FCOZ7DEC.js +0 -355
- package/dist/chunk-FCOZ7DEC.js.map +0 -1
- package/dist/chunk-FWART3VA.js +0 -205
- package/dist/chunk-FZK3JJJK.js +0 -150
- package/dist/chunk-GDOOG5YQ.js +0 -382
- package/dist/chunk-GLVXQU3E.js +0 -155
- package/dist/chunk-HU55NPHZ.js +0 -80
- package/dist/chunk-I6JJ6VJS.js +0 -97
- package/dist/chunk-I6URUNTD.js +0 -59
- package/dist/chunk-IARAK3PK.js +0 -14
- package/dist/chunk-II6DLDZM.js +0 -30
- package/dist/chunk-J5YUA6JB.js +0 -23
- package/dist/chunk-J7OH6R4K.js +0 -49
- package/dist/chunk-K2WCO3NX.js +0 -1
- package/dist/chunk-L6Q5NA22.js +0 -40
- package/dist/chunk-LFGJG4XZ.js +0 -30
- package/dist/chunk-M3OYTM5Z.js +0 -85
- package/dist/chunk-MOQ5M46U.js +0 -209
- package/dist/chunk-NTPWQH4S.js +0 -589
- package/dist/chunk-OJ64XMPJ.js +0 -1434
- package/dist/chunk-OJ64XMPJ.js.map +0 -1
- package/dist/chunk-OWGAXPRE.js +0 -129
- package/dist/chunk-P2PEPSPK.js +0 -230
- package/dist/chunk-P6TZ3IVN.js +0 -453
- package/dist/chunk-P6TZ3IVN.js.map +0 -1
- package/dist/chunk-PAJCRV7O.js +0 -123
- package/dist/chunk-PMMV5SQC.js +0 -416
- package/dist/chunk-PMMV5SQC.js.map +0 -1
- package/dist/chunk-PPPZIBKY.js +0 -261
- package/dist/chunk-PPPZIBKY.js.map +0 -1
- package/dist/chunk-PVC2FBCQ.js +0 -45
- package/dist/chunk-PYIUDUGS.js +0 -36
- package/dist/chunk-QABECTNN.js +0 -255
- package/dist/chunk-QYMMMKOO.js +0 -164
- package/dist/chunk-R4IVPJHN.js +0 -130
- package/dist/chunk-REWTMYSF.js +0 -32
- package/dist/chunk-REWTMYSF.js.map +0 -1
- package/dist/chunk-RNYDHIQL.js +0 -367
- package/dist/chunk-RUIMKQTA.js +0 -23
- package/dist/chunk-RUIMKQTA.js.map +0 -1
- package/dist/chunk-TCGVRKOS.js +0 -367
- package/dist/chunk-TIAYXOEI.js +0 -99
- package/dist/chunk-TQ3REHVF.js +0 -95
- package/dist/chunk-TQ3REHVF.js.map +0 -1
- package/dist/chunk-TUL5YQWF.js +0 -777
- package/dist/chunk-U7LV2DUN.js +0 -74
- package/dist/chunk-UB3XHGFG.js +0 -181
- package/dist/chunk-UB3XHGFG.js.map +0 -1
- package/dist/chunk-UMH35AQV.js +0 -70
- package/dist/chunk-UWZ7O4NR.js +0 -29
- package/dist/chunk-V76PHWLE.js +0 -41
- package/dist/chunk-VFQOE76I.js +0 -69
- package/dist/chunk-VIWOGJ2O.js +0 -71
- package/dist/chunk-VK6OC22R.js +0 -37
- package/dist/chunk-VK6OC22R.js.map +0 -1
- package/dist/chunk-VVLOWY74.js +0 -150
- package/dist/chunk-VVLOWY74.js.map +0 -1
- package/dist/chunk-W3JABOVB.js +0 -53
- package/dist/chunk-W3JABOVB.js.map +0 -1
- package/dist/chunk-WPNP3NF5.js +0 -1221
- package/dist/chunk-WPNP3NF5.js.map +0 -1
- package/dist/chunk-X5QZAJDB.js +0 -59
- package/dist/chunk-X6VNIRHS.js +0 -239
- package/dist/chunk-X6VNIRHS.js.map +0 -1
- package/dist/chunk-XBPUVQDO.js +0 -664
- package/dist/chunk-XBPUVQDO.js.map +0 -1
- package/dist/chunk-XW5LZYV4.js +0 -21
- package/dist/chunk-YTCCC6NG.js +0 -320
- package/dist/chunk-YTCCC6NG.js.map +0 -1
- package/dist/classified/index.d.ts +0 -17
- package/dist/collection-facade-EJVIN2BY.js +0 -39
- package/dist/computed-6FOFXQPE.js +0 -11
- package/dist/config-drift-RFEVGBKR.js +0 -24
- package/dist/config-drift-RFEVGBKR.js.map +0 -1
- package/dist/consent/index.d.ts +0 -23
- package/dist/crdt/index.d.ts +0 -34
- package/dist/dead-filter-RHMNYOXP.js +0 -28
- package/dist/decrypt-partition-IHtxEnTi.d.ts +0 -21
- package/dist/delegation-IHXOASHV.js +0 -25
- package/dist/derivations/index.d.ts +0 -70
- package/dist/derive-CD3ZVIXK.js +0 -21
- package/dist/describe/index.d.ts +0 -1
- package/dist/describe/index.js +0 -1
- package/dist/describe-C6iHNlqJ.d.ts +0 -162
- package/dist/dev-unlock-wgQ7Ci5I.d.ts +0 -263
- package/dist/discriminant-BN9REW3o.d.ts +0 -60
- package/dist/enclave-KGEUW2GL.js +0 -123
- package/dist/executor-EUPYHCLU.js +0 -9
- package/dist/executor-KZ4B3PRT.js +0 -9
- package/dist/executor-MHUM2VZK.js +0 -21
- package/dist/export-accessible-Z3NSZZHN.js +0 -23
- package/dist/extract-partition-VSKT35JG.js +0 -36
- package/dist/fanout-sidecar-NBDKKCHT.js +0 -74
- package/dist/find-OH4BEULF.js +0 -11
- package/dist/forget/index.d.ts +0 -36
- package/dist/guards/index.d.ts +0 -35
- package/dist/hash-CwHnoKyW.d.ts +0 -72
- package/dist/history/index.d.ts +0 -61
- package/dist/i18n/index.d.ts +0 -37
- package/dist/in/index.d.ts +0 -5
- package/dist/index-B9QdHytu.d.ts +0 -123
- package/dist/index-CTvUp94-.d.ts +0 -123
- package/dist/index-Dn5GzPg_.d.ts +0 -22138
- package/dist/indexing/index.d.ts +0 -39
- package/dist/issue-AEOL6RXA.js +0 -19
- package/dist/kernel/index.d.ts +0 -32
- package/dist/kernel/index.js +0 -59
- package/dist/lazy/index.d.ts +0 -21
- package/dist/ledger-3LR3YO2W.js +0 -42
- package/dist/liberate-XSEPRWEA.js +0 -24
- package/dist/link-set-NSUIX6BR.js +0 -31
- package/dist/materialized-views/index.d.ts +0 -173
- package/dist/mime-magic-CYbFNQ4h.d.ts +0 -103
- package/dist/noydb-POVTIVQ6.js +0 -62
- package/dist/on/index.d.ts +0 -5
- package/dist/overlay-views/index.d.ts +0 -98
- package/dist/periods/index.d.ts +0 -20
- package/dist/pod/index.d.ts +0 -63
- package/dist/policy-Y7HL2KGA.js +0 -41
- package/dist/portability/index.d.ts +0 -20
- package/dist/post-register-KOFRTCDD.js +0 -55
- package/dist/post-register-KOFRTCDD.js.map +0 -1
- package/dist/public-envelope-NC7SPNMV.js +0 -32
- package/dist/query/index.d.ts +0 -5
- package/dist/read-only-facade-5ADRJVTM.js +0 -8
- package/dist/register-3D6R2MKN.js +0 -23
- package/dist/registry-AI4E46PD.js +0 -19
- package/dist/registry-HSNQ4NBP.js +0 -9
- package/dist/registry-WIX6QCV5.js +0 -17
- package/dist/request-withdrawal-GU4XS2R5.js +0 -31
- package/dist/reveal-5Y777N5Q.js +0 -38
- package/dist/reveal-5Y777N5Q.js.map +0 -1
- package/dist/revoke-ZFETCLYV.js +0 -24
- package/dist/revoke-ZFETCLYV.js.map +0 -1
- package/dist/satellites/index.d.ts +0 -5
- package/dist/sealed-record/index.d.ts +0 -69
- package/dist/session/index.d.ts +0 -44
- package/dist/shadow/index.d.ts +0 -15
- package/dist/signer-GAIMQQ2J.js +0 -25
- package/dist/signer-GAIMQQ2J.js.map +0 -1
- package/dist/snapshots/index.d.ts +0 -26
- package/dist/stale-77LP2EEF.js +0 -14
- package/dist/stale-77LP2EEF.js.map +0 -1
- package/dist/storage-KEXIXLGM.js +0 -23
- package/dist/storage-KEXIXLGM.js.map +0 -1
- package/dist/store-coordination-provider-NJDDZ264.js +0 -142
- package/dist/subject-index-O75wKshW.d.ts +0 -362
- package/dist/sync/index.d.ts +0 -41
- package/dist/team/index.d.ts +0 -155
- package/dist/tiers/index.d.ts +0 -5
- package/dist/to/index.d.ts +0 -5
- package/dist/transition-guard-D5RLJv8S.d.ts +0 -165
- package/dist/tx/index.d.ts +0 -35
- package/dist/ui/index.d.ts +0 -1
- package/dist/ulid-DRH25k3y.d.ts +0 -66
- package/dist/util/index.d.ts +0 -79
- package/dist/validators-C3lrVF-c.d.ts +0 -101
- package/dist/vault-diff-_LSIcOMv.d.ts +0 -147
- package/dist/verify-CAYGXYNO.js +0 -139
- package/dist/verify-CAYGXYNO.js.map +0 -1
- package/dist/walk-SMAE4IEI.js +0 -241
- package/dist/with/index.d.ts +0 -38
- package/dist/with-materialized-view-Xv1-9Bh0.d.ts +0 -27
- package/dist/with-overlayed-view-CuWhq_-C.d.ts +0 -12
- package/dist/with-rollup-K_iwal4b.d.ts +0 -47
- package/dist/withdraw-accessible-Q7BULAN5.js +0 -28
- package/dist/withdraw-accessible-Q7BULAN5.js.map +0 -1
- /package/dist/{adapter/index.js.map → api-ZGS6LCOF.js.map} +0 -0
- /package/dist/{chunk-VIWOGJ2O.js.map → chunk-3B5VVCNY.js.map} +0 -0
- /package/dist/{chunk-P2PEPSPK.js.map → chunk-3LQ2YKO4.js.map} +0 -0
- /package/dist/{chunk-EU7HDMT3.js.map → chunk-3QCRBHCY.js.map} +0 -0
- /package/dist/{chunk-FZK3JJJK.js.map → chunk-4JBYV75E.js.map} +0 -0
- /package/dist/{chunk-I6JJ6VJS.js.map → chunk-4NXKCLLQ.js.map} +0 -0
- /package/dist/{chunk-VFQOE76I.js.map → chunk-5M5DVGV7.js.map} +0 -0
- /package/dist/{chunk-LFGJG4XZ.js.map → chunk-5YOLBEQ6.js.map} +0 -0
- /package/dist/{chunk-OWGAXPRE.js.map → chunk-6CRIV7DE.js.map} +0 -0
- /package/dist/{chunk-QABECTNN.js.map → chunk-6QTNZJBS.js.map} +0 -0
- /package/dist/{chunk-723XB5NX.js.map → chunk-6T2SCQRU.js.map} +0 -0
- /package/dist/{chunk-PVC2FBCQ.js.map → chunk-7DSTRQIJ.js.map} +0 -0
- /package/dist/{chunk-NTPWQH4S.js.map → chunk-AUSTCW2X.js.map} +0 -0
- /package/dist/{chunk-MOQ5M46U.js.map → chunk-B3HJYUOF.js.map} +0 -0
- /package/dist/{chunk-QYMMMKOO.js.map → chunk-BDVFPG6Y.js.map} +0 -0
- /package/dist/{chunk-PYIUDUGS.js.map → chunk-CAF6WOK7.js.map} +0 -0
- /package/dist/{chunk-5HZULLHE.js.map → chunk-CIE2BASH.js.map} +0 -0
- /package/dist/{chunk-BTFTHF6Q.js.map → chunk-CRI4OUV4.js.map} +0 -0
- /package/dist/{chunk-37JZR7CY.js.map → chunk-DLG74CNB.js.map} +0 -0
- /package/dist/{chunk-TCGVRKOS.js.map → chunk-ERJ7FU55.js.map} +0 -0
- /package/dist/{chunk-FWART3VA.js.map → chunk-EVVGJDRQ.js.map} +0 -0
- /package/dist/{chunk-X5QZAJDB.js.map → chunk-EXK7QRWF.js.map} +0 -0
- /package/dist/{chunk-5HRJQSKN.js.map → chunk-EYZ6IQ6X.js.map} +0 -0
- /package/dist/{chunk-DCVVCJVB.js.map → chunk-F64IRYG3.js.map} +0 -0
- /package/dist/{chunk-BJ2XF2RC.js.map → chunk-FHS2HQSH.js.map} +0 -0
- /package/dist/{chunk-HU55NPHZ.js.map → chunk-GKEWXIV5.js.map} +0 -0
- /package/dist/{chunk-I6URUNTD.js.map → chunk-GTGPO5KW.js.map} +0 -0
- /package/dist/{chunk-5UOPIPZC.js.map → chunk-HB3RFQSC.js.map} +0 -0
- /package/dist/{chunk-F3EKFGUS.js.map → chunk-I6GALP6E.js.map} +0 -0
- /package/dist/{chunk-R4IVPJHN.js.map → chunk-IL6POWCW.js.map} +0 -0
- /package/dist/{chunk-3KBK5LU4.js.map → chunk-IU6SNYX6.js.map} +0 -0
- /package/dist/{chunk-TUL5YQWF.js.map → chunk-J2ZX2XUV.js.map} +0 -0
- /package/dist/{chunk-UWZ7O4NR.js.map → chunk-JKJOGPZN.js.map} +0 -0
- /package/dist/{chunk-V76PHWLE.js.map → chunk-JZUV47FZ.js.map} +0 -0
- /package/dist/{chunk-II6DLDZM.js.map → chunk-K5IMOGHB.js.map} +0 -0
- /package/dist/{chunk-GDOOG5YQ.js.map → chunk-LASZKVMO.js.map} +0 -0
- /package/dist/{chunk-5YBUFCFF.js.map → chunk-NR5LT5RY.js.map} +0 -0
- /package/dist/{chunk-UMH35AQV.js.map → chunk-Q5VNKNE5.js.map} +0 -0
- /package/dist/{chunk-XW5LZYV4.js.map → chunk-QLWMEXCT.js.map} +0 -0
- /package/dist/{chunk-PAJCRV7O.js.map → chunk-QRB7NAOJ.js.map} +0 -0
- /package/dist/{chunk-U7LV2DUN.js.map → chunk-R4ROFEYC.js.map} +0 -0
- /package/dist/{chunk-RNYDHIQL.js.map → chunk-RIX4V2TB.js.map} +0 -0
- /package/dist/{chunk-L6Q5NA22.js.map → chunk-RYCTDFUX.js.map} +0 -0
- /package/dist/{chunk-CHK5VVMI.js.map → chunk-RZ5SVOYR.js.map} +0 -0
- /package/dist/{chunk-TIAYXOEI.js.map → chunk-SLFHQTTW.js.map} +0 -0
- /package/dist/{chunk-J5YUA6JB.js.map → chunk-UNFPPVNI.js.map} +0 -0
- /package/dist/{chunk-25G7PUTA.js.map → chunk-VLFCJYTL.js.map} +0 -0
- /package/dist/{chunk-7CZ6YXMO.js.map → chunk-VN3DBQAU.js.map} +0 -0
- /package/dist/{chunk-J7OH6R4K.js.map → chunk-VZRODIM3.js.map} +0 -0
- /package/dist/{chunk-55LSDABW.js.map → chunk-W22IKJE2.js.map} +0 -0
- /package/dist/{chunk-GLVXQU3E.js.map → chunk-X3YYQWOQ.js.map} +0 -0
- /package/dist/{chunk-M3OYTM5Z.js.map → chunk-YFXZEAYK.js.map} +0 -0
- /package/dist/{chunk-5JQMX2EH.js.map → chunk-ZAJAVEXY.js.map} +0 -0
- /package/dist/{chunk-26FSVNBL.js.map → chunk-ZICD77GM.js.map} +0 -0
- /package/dist/{chunk-IARAK3PK.js.map → chunk-ZUODRVHY.js.map} +0 -0
- /package/dist/{api-JDWL67WL.js.map → collection-facade-TLWIPI76.js.map} +0 -0
- /package/dist/{chunk-BGIZAFY7.js.map → computed-ZIQTYTDI.js.map} +0 -0
- /package/dist/{dead-filter-RHMNYOXP.js.map → dead-filter-ESOBZZP5.js.map} +0 -0
- /package/dist/{chunk-K2WCO3NX.js.map → delegation-W7ZV2322.js.map} +0 -0
- /package/dist/{collection-facade-EJVIN2BY.js.map → derive-H2BJTLUI.js.map} +0 -0
- /package/dist/{computed-6FOFXQPE.js.map → enclave-AP3I5W7O.js.map} +0 -0
- /package/dist/{delegation-IHXOASHV.js.map → executor-KGWTNEQD.js.map} +0 -0
- /package/dist/{derive-CD3ZVIXK.js.map → executor-OVEXR6RT.js.map} +0 -0
- /package/dist/{describe/index.js.map → executor-UNEH5ZYH.js.map} +0 -0
- /package/dist/{enclave-KGEUW2GL.js.map → export-accessible-PCMXSUZS.js.map} +0 -0
- /package/dist/{executor-EUPYHCLU.js.map → extract-partition-SWHFSYJO.js.map} +0 -0
- /package/dist/{fanout-sidecar-NBDKKCHT.js.map → fanout-sidecar-A765THMX.js.map} +0 -0
- /package/dist/{executor-KZ4B3PRT.js.map → find-N6345CNT.js.map} +0 -0
- /package/dist/{executor-MHUM2VZK.js.map → issue-5OKB6I2R.js.map} +0 -0
- /package/dist/{export-accessible-Z3NSZZHN.js.map → ledger-GFBKVPV4.js.map} +0 -0
- /package/dist/{extract-partition-VSKT35JG.js.map → liberate-3VDOT4KO.js.map} +0 -0
- /package/dist/{find-OH4BEULF.js.map → link-set-Z7Q2ASFX.js.map} +0 -0
- /package/dist/{issue-AEOL6RXA.js.map → noydb-ZCJOYBDI.js.map} +0 -0
- /package/dist/{kernel/index.js.map → policy-Z3RUAIY2.js.map} +0 -0
- /package/dist/{ledger-3LR3YO2W.js.map → public-envelope-B4KNWVUA.js.map} +0 -0
- /package/dist/{liberate-XSEPRWEA.js.map → read-only-facade-CHCKSEPD.js.map} +0 -0
- /package/dist/{link-set-NSUIX6BR.js.map → register-VAHONCID.js.map} +0 -0
- /package/dist/{noydb-POVTIVQ6.js.map → registry-7MLVD3VO.js.map} +0 -0
- /package/dist/{policy-Y7HL2KGA.js.map → registry-EPKPD5SM.js.map} +0 -0
- /package/dist/{public-envelope-NC7SPNMV.js.map → registry-P5T7PS2U.js.map} +0 -0
- /package/dist/{read-only-facade-5ADRJVTM.js.map → request-withdrawal-TI3A5WPS.js.map} +0 -0
- /package/dist/{register-3D6R2MKN.js.map → revoke-FDRD6GRW.js.map} +0 -0
- /package/dist/{registry-AI4E46PD.js.map → signer-MUWEIUI6.js.map} +0 -0
- /package/dist/{registry-HSNQ4NBP.js.map → stale-OSQ7J3AA.js.map} +0 -0
- /package/dist/{registry-WIX6QCV5.js.map → storage-MVFCGEQE.js.map} +0 -0
- /package/dist/{store-coordination-provider-NJDDZ264.js.map → store-coordination-provider-64OEZFGS.js.map} +0 -0
- /package/dist/{walk-SMAE4IEI.js.map → walk-SVNDIZ62.js.map} +0 -0
- /package/dist/{request-withdrawal-GU4XS2R5.js.map → withdraw-accessible-WZIEVWSR.js.map} +0 -0
|
@@ -0,0 +1,1286 @@
|
|
|
1
|
+
import type { NoydbStore, BlobObject, SlotInfo, VersionRecord, BlobPutOptions, BlobResponseOptions } from '../../kernel/types.js';
|
|
2
|
+
import type { ObjectProjection } from './object-projection.js';
|
|
3
|
+
import type { BlobFieldsConfig } from './blob-compaction.js';
|
|
4
|
+
import { type EnclaveKey } from '../../kernel/enclave/index.js';
|
|
5
|
+
import type { UnlockedKeyring } from '../../with-party/team/keyring.js';
|
|
6
|
+
/**
|
|
7
|
+
* DEK slot name for vault-shared blob data. Calling `getDEK('_blob')`
|
|
8
|
+
* auto-creates a blob DEK the first time — same lazy-creation mechanism
|
|
9
|
+
* used for any user-defined collection.
|
|
10
|
+
*/
|
|
11
|
+
export declare const BLOB_COLLECTION = "_blob";
|
|
12
|
+
/** Stores `BlobObject` metadata envelopes, keyed by eTag. */
|
|
13
|
+
export declare const BLOB_INDEX_COLLECTION = "_blob_index";
|
|
14
|
+
/**
|
|
15
|
+
* Stores encrypted chunk envelopes, keyed by `{eTag}/{chunkIndex}`.
|
|
16
|
+
* NOT loaded into the in-memory query layer. Fetched on demand by
|
|
17
|
+
* `BlobSet.get()` / `BlobSet.response()`.
|
|
18
|
+
*/
|
|
19
|
+
export declare const BLOB_CHUNKS_COLLECTION = "_blob_chunks";
|
|
20
|
+
/** Prefix for per-collection slot metadata collections. */
|
|
21
|
+
export declare const BLOB_SLOTS_PREFIX = "_blob_slots_";
|
|
22
|
+
/** Prefix for per-collection version records. */
|
|
23
|
+
export declare const BLOB_VERSIONS_PREFIX = "_blob_versions_";
|
|
24
|
+
/**
|
|
25
|
+
* Default chunk size: 256 KB raw bytes.
|
|
26
|
+
* After AES-GCM (same size) + base64 (~33% inflation) → ~342 KB per
|
|
27
|
+
* envelope, safely within DynamoDB's 400 KB item limit.
|
|
28
|
+
*/
|
|
29
|
+
export declare const DEFAULT_CHUNK_SIZE: number;
|
|
30
|
+
/**
|
|
31
|
+
* Handle for reading, writing, versioning, and deleting binary blobs
|
|
32
|
+
* on a specific record.
|
|
33
|
+
*
|
|
34
|
+
* Obtained via `collection.blob(id)`. No I/O is performed until you
|
|
35
|
+
* call a method.
|
|
36
|
+
*
|
|
37
|
+
* ## Storage layout
|
|
38
|
+
*
|
|
39
|
+
* ```
|
|
40
|
+
* _blob_index/{eTag} BlobObject metadata (vault-shared DEK)
|
|
41
|
+
* _blob_chunks/{eTag}/{chunkIndex} Encrypted chunk data (vault-shared DEK + AAD)
|
|
42
|
+
* _blob_slots_{collection}/{recordId} Slot map (parent collection DEK)
|
|
43
|
+
* _blob_versions_{collection}/{recordId}/{slot}/{label} Published versions (parent collection DEK)
|
|
44
|
+
* ```
|
|
45
|
+
*
|
|
46
|
+
* ## Deduplication
|
|
47
|
+
*
|
|
48
|
+
* `put()` computes `eTag = HMAC-SHA-256(blobDEK, plaintext)` — keyed so the
|
|
49
|
+
* store cannot predict eTags for known content. If another record already
|
|
50
|
+
* uploaded the same bytes, the chunks are reused and `refCount` is incremented.
|
|
51
|
+
*
|
|
52
|
+
* ## Chunk integrity
|
|
53
|
+
*
|
|
54
|
+
* Each chunk is encrypted with AES-256-GCM using AAD = `{eTag}:{index}:{count}`,
|
|
55
|
+
* preventing chunk reorder, substitution, and truncation attacks.
|
|
56
|
+
*/
|
|
57
|
+
export declare class BlobSet {
|
|
58
|
+
private readonly store;
|
|
59
|
+
private readonly vault;
|
|
60
|
+
private readonly collection;
|
|
61
|
+
private readonly recordId;
|
|
62
|
+
private readonly getDEK;
|
|
63
|
+
private readonly encrypted;
|
|
64
|
+
private readonly userId;
|
|
65
|
+
private readonly maxBlobBytes;
|
|
66
|
+
private readonly erasableBlobs;
|
|
67
|
+
private readonly tiersActive;
|
|
68
|
+
private readonly debugPlaintext;
|
|
69
|
+
private readonly objectStore;
|
|
70
|
+
private readonly blobFields;
|
|
71
|
+
private readonly keyring;
|
|
72
|
+
/**
|
|
73
|
+
* Set only on the cleared clone `atTier()` returns (#749) — never by
|
|
74
|
+
* `openSlot`/`Collection.blob()`. Its presence is what makes a `BlobSet`
|
|
75
|
+
* a cleared view: see `ownerRecordElevated()`/`ownerTier()`.
|
|
76
|
+
*/
|
|
77
|
+
private readonly clearedTier;
|
|
78
|
+
constructor(opts: {
|
|
79
|
+
store: NoydbStore;
|
|
80
|
+
vault: string;
|
|
81
|
+
collection: string;
|
|
82
|
+
recordId: string;
|
|
83
|
+
getDEK: (name: string) => Promise<EnclaveKey>;
|
|
84
|
+
encrypted: boolean;
|
|
85
|
+
userId?: string;
|
|
86
|
+
maxBlobBytes?: number;
|
|
87
|
+
erasableBlobs?: boolean;
|
|
88
|
+
tiersActive?: boolean;
|
|
89
|
+
debugPlaintext?: boolean;
|
|
90
|
+
objectStore?: ObjectProjection;
|
|
91
|
+
blobFields?: BlobFieldsConfig;
|
|
92
|
+
keyring?: UnlockedKeyring;
|
|
93
|
+
clearedTier?: number;
|
|
94
|
+
});
|
|
95
|
+
/**
|
|
96
|
+
* #724 I1 completion: a legacy (non-`perRecordKeys`) blob has no per-blob
|
|
97
|
+
* `_cek`, so `rehomeForTier` can never tier-isolate it on elevate/demote —
|
|
98
|
+
* it stays decryptable under the flat tier-0 `_blob` DEK at rest even
|
|
99
|
+
* after the owning record is elevated. The construction-time mandate
|
|
100
|
+
* (`resolveCollectionConfig`) only catches this when `blobFields` is
|
|
101
|
+
* DECLARED; a collection with an undeclared field (or no `blobFields` at
|
|
102
|
+
* all) constructs fine and reaches this write path unguarded. Refuse the
|
|
103
|
+
* write itself instead of broadening the construction mandate, which
|
|
104
|
+
* would over-refuse blobless tiered collections (`blobStrategy` is
|
|
105
|
+
* vault-wide, not per-collection). Called from every content-write entry
|
|
106
|
+
* (`put()`, `publish()`) — never from a read path, so a pre-existing
|
|
107
|
+
* legacy blob stays readable (back-compat).
|
|
108
|
+
*/
|
|
109
|
+
private assertBlobWritable;
|
|
110
|
+
/**
|
|
111
|
+
* #748: `adoptExternal()`/`setExternalMeta()` write an `external` slot
|
|
112
|
+
* reference directly — unlike `put()`, which only takes the external path
|
|
113
|
+
* when `blobFields[slotName].external` is declared (the construction-time
|
|
114
|
+
* tiers×blobFields mandate, `collection-config.ts`, then applies). Without
|
|
115
|
+
* this gate, either method can attach an external reference to a slot the
|
|
116
|
+
* collection never declared `external` — bypassing that mandate on a tiered
|
|
117
|
+
* collection. Mirrors `put()`'s own gate.
|
|
118
|
+
*/
|
|
119
|
+
private assertExternalDeclared;
|
|
120
|
+
/**
|
|
121
|
+
* Resolve the key the blob's CHUNKS are encrypted under.
|
|
122
|
+
*
|
|
123
|
+
* - `_cek` present (erasable blob) → unwrap the per-blob content CEK under
|
|
124
|
+
* `blobDEK`. Deleting the BlobObject (at `refCount → 0`) makes this
|
|
125
|
+
* key unrecoverable → the chunks are crypto-shredded.
|
|
126
|
+
* - `_cek` absent (legacy) → `blobDEK` encrypts chunks directly.
|
|
127
|
+
* - unencrypted vault → `null` (chunks stored as plaintext base64).
|
|
128
|
+
*
|
|
129
|
+
* `blobDEK` defaults to this record's own (tier-0) `_blob` DEK — every
|
|
130
|
+
* pre-#724-T3 call site. `rehomeForTier`'s isolate-fork path (#724 Arc 10
|
|
131
|
+
* Task 3) passes the `fromTier`-scoped DEK explicitly to read a shared
|
|
132
|
+
* blob's plaintext under the key it's CURRENTLY wrapped under, reusing
|
|
133
|
+
* this one `_cek` unwrap site rather than adding a new raw access.
|
|
134
|
+
*/
|
|
135
|
+
private resolveChunkKey;
|
|
136
|
+
/**
|
|
137
|
+
* #724 Arc 10 Task 1: the same "elevated ≡ invisible" clearance check
|
|
138
|
+
* `collection.get()` applies to the owning record (`liveRecordIsElevated`,
|
|
139
|
+
* #701/#707/#709/#712) — reused here, not reinvented, so a blob content
|
|
140
|
+
* read on an elevated record is refused exactly like a `get()` on it
|
|
141
|
+
* would be. Reads only the owning record's `_tier` envelope metadata;
|
|
142
|
+
* runs before any blob decrypt.
|
|
143
|
+
*
|
|
144
|
+
* #749: a cleared clone (`this.clearedTier !== undefined`, produced only by
|
|
145
|
+
* `atTier()`) short-circuits to `false` — its whole purpose is to see past
|
|
146
|
+
* this gate, having already paid the `assertTierAccess` cost `atTier()`
|
|
147
|
+
* charged to get here. No live envelope peek needed on that path.
|
|
148
|
+
*/
|
|
149
|
+
private ownerRecordElevated;
|
|
150
|
+
/**
|
|
151
|
+
* #724 Arc 10 Task 4: the tier this record's LIVE envelope currently
|
|
152
|
+
* carries — `loadSlots`/`saveSlots` default to resolving the slot map's
|
|
153
|
+
* collection DEK here, so the slot map (filenames/eTags/mimeTypes) is
|
|
154
|
+
* read/written wherever a prior `rehomeForTier` call physically re-keyed
|
|
155
|
+
* it to. `rehomeForTier` itself passes an EXPLICIT tier instead of
|
|
156
|
+
* relying on this default (see its own doc comment): by the time it
|
|
157
|
+
* runs, the owning record's live `_tier` has ALREADY moved to `toTier`
|
|
158
|
+
* (the collection-level `elevate`/`demote`/`putAtTier` writes the record
|
|
159
|
+
* before invoking `syncBlobs`), while the slot map is still physically at
|
|
160
|
+
* `fromTier` until `rehomeForTier`'s own move step lands — so this peek
|
|
161
|
+
* would resolve the wrong DEK mid-move.
|
|
162
|
+
*
|
|
163
|
+
* #749: a cleared clone reports its fixed `clearedTier` instead of
|
|
164
|
+
* re-peeking — a stable view for the caller's whole session with it. A
|
|
165
|
+
* concurrent demote/elevate on the underlying record is invisible to an
|
|
166
|
+
* already-cleared handle; call `atTier()` again to see it. This is not a
|
|
167
|
+
* silent-corruption risk: a WRITE through a stale clone after a concurrent
|
|
168
|
+
* move fails loud, not quiet — the slot map/index envelope has already
|
|
169
|
+
* been physically re-keyed to the record's new tier by `rehomeForTier`, so
|
|
170
|
+
* the stale clone's `clearedTier`-pinned DEK can no longer open it and the
|
|
171
|
+
* write throws an AEAD decrypt error rather than silently writing under
|
|
172
|
+
* the wrong key.
|
|
173
|
+
*/
|
|
174
|
+
private ownerTier;
|
|
175
|
+
/**
|
|
176
|
+
* The sanctioned cleared-read path to an elevated record's blobs (#749).
|
|
177
|
+
*
|
|
178
|
+
* The law: `blob(id)` is the tier-0 surface — `get()`/`list()`/`blobInfo()`/
|
|
179
|
+
* etc. all hide an elevated record's blobs from EVERYONE, unconditionally
|
|
180
|
+
* (`ownerRecordElevated()`, #724 Task 1), with no cleared path of their own.
|
|
181
|
+
* `atTier()` is that cleared path, the `getAtTier()` analogue for blobs:
|
|
182
|
+
* live-peeks the owning record's tier, and for `tier > 0` runs
|
|
183
|
+
* `assertTierAccess` — the SAME gate `putAtTier`/`elevate`/`demote` run
|
|
184
|
+
* before ever touching a tier DEK — then returns a NEW `BlobSet` bound to
|
|
185
|
+
* that tier. Every subsequent call on the returned handle (`get()`,
|
|
186
|
+
* `list()`, `publish()`, …) sees through the gate as if the record were at
|
|
187
|
+
* tier 0.
|
|
188
|
+
*
|
|
189
|
+
* `assertTierAccess` — not a bare `getDEK` call — IS the authorization
|
|
190
|
+
* check: owner/admin/custodian bypass it (their on-demand tier-DEK mint is
|
|
191
|
+
* sanctioned), everyone else must already hold the tier DEK (via a prior
|
|
192
|
+
* grant or delegation) or it throws `TierNotGrantedError`. A bare `getDEK`
|
|
193
|
+
* would not gate anything here — it silently mints a fresh DEK for ANY
|
|
194
|
+
* caller when one is missing, which is exactly the "non-cleared caller
|
|
195
|
+
* creating tier key material inside the trust boundary" hazard
|
|
196
|
+
* `assertTierAccess`'s own doc comment (`with-party/team/tiers.ts`) warns
|
|
197
|
+
* against; running it BEFORE any `getDEK` call is what keeps an ungranted
|
|
198
|
+
* member's failed `atTier()` call from minting junk key material into
|
|
199
|
+
* their keyring as a side effect. No tier DEK is resolved here at all —
|
|
200
|
+
* every actual read still resolves its DEK lazily, same as today.
|
|
201
|
+
*
|
|
202
|
+
* `this.keyring` is undefined only on a construction path that never
|
|
203
|
+
* threads one through `openSlot` (`Collection.blob()` always does) — that
|
|
204
|
+
* can't prove clearance for anyone, so it throws the same
|
|
205
|
+
* `TierNotGrantedError` an ungranted caller would get.
|
|
206
|
+
*/
|
|
207
|
+
atTier(): Promise<BlobSet>;
|
|
208
|
+
/** The internal collection that holds slot metadata for this collection's blobs. */
|
|
209
|
+
private get slotsCollection();
|
|
210
|
+
/** The internal collection that holds published versions for this collection's blobs. */
|
|
211
|
+
private get versionsCollection();
|
|
212
|
+
/**
|
|
213
|
+
* @param tier #724 Arc 10 Task 4: explicit tier to resolve the slot map's
|
|
214
|
+
* collection DEK at — `getDEK(dekKey(this.collection, tier))`. Omitted →
|
|
215
|
+
* resolves via `ownerTier()` (the record's CURRENT live tier), correct
|
|
216
|
+
* for every call site except `rehomeForTier`'s own internal reads, which
|
|
217
|
+
* must pin `fromTier` explicitly (see `ownerTier()`'s doc comment).
|
|
218
|
+
*/
|
|
219
|
+
private loadSlots;
|
|
220
|
+
/**
|
|
221
|
+
* Resumable slot-map read for `runRehomeSteps` (#746 spec §7 §2d bullet
|
|
222
|
+
* 1): try `fromTier` (the map's pre-move physical location) first; on a
|
|
223
|
+
* decrypt failure (wrong key, not "missing" — mirrors `loadBlobObject`'s
|
|
224
|
+
* own TamperedError-only fallback trigger) retry `toTier` — the signal
|
|
225
|
+
* that a prior (crashed) run's own move step already landed. `atTier`
|
|
226
|
+
* reports which one opened it. A missing envelope reports `atTier:
|
|
227
|
+
* fromTier` (arbitrary — the `Object.keys(slots).length > 0` gate the
|
|
228
|
+
* caller applies makes the value moot for an empty map).
|
|
229
|
+
*/
|
|
230
|
+
private loadSlotsTolerant;
|
|
231
|
+
/** @param tier See {@link loadSlots}'s `tier` param — same resolution. */
|
|
232
|
+
private saveSlots;
|
|
233
|
+
/**
|
|
234
|
+
* CAS retry loop for slot metadata updates. Re-reads slots on conflict
|
|
235
|
+
* and re-applies the mutation function.
|
|
236
|
+
*
|
|
237
|
+
* #724 re-review (High): when the mutation empties the slot map (the
|
|
238
|
+
* last slot was deleted), the `_blob_slots_{collection}/{recordId}` row
|
|
239
|
+
* is DELETED rather than saved as an empty-but-present envelope. An
|
|
240
|
+
* empty envelope left in place would still be tier-keyed at whatever
|
|
241
|
+
* tier it was last written at; `rehomeForTier`'s `slots exist` guard
|
|
242
|
+
* (`Object.keys(slots).length > 0`) would then skip re-keying it on a
|
|
243
|
+
* later elevate/demote, stranding it at the wrong tier's DEK —
|
|
244
|
+
* `TamperedError` on every later access. Deleting the row instead makes
|
|
245
|
+
* "no slots" and "no envelope" the SAME state, so a record that once
|
|
246
|
+
* had a blob and a record that never had one behave identically once
|
|
247
|
+
* empty.
|
|
248
|
+
*
|
|
249
|
+
* @param tier See {@link loadSlots}'s `tier` param — threaded through so
|
|
250
|
+
* `rehomeForTier`'s isolate-fork writes (via `putUnderDEK`) target the
|
|
251
|
+
* slot map's CURRENT (fromTier) location during the move.
|
|
252
|
+
*/
|
|
253
|
+
private casUpdateSlots;
|
|
254
|
+
/**
|
|
255
|
+
* Clear a slot's `pendingRelease` breadcrumb once its release has landed
|
|
256
|
+
* (#746 spec §7 review, carried finding (b)) — a no-op CAS if the field is
|
|
257
|
+
* already gone (idempotent, safe to call again on resume) or no longer
|
|
258
|
+
* matches `expected` (a NEWER put() on this slot already moved past it).
|
|
259
|
+
*/
|
|
260
|
+
private clearPendingRelease;
|
|
261
|
+
/**
|
|
262
|
+
* `runRehomeSteps`'s FIRST step (#746 spec §7 review, carried finding
|
|
263
|
+
* (b)) — reconcile any `pendingRelease` breadcrumb left on `slots` by a
|
|
264
|
+
* PRIOR (crashed) run of THIS SAME marker-governed rehome (`opId`
|
|
265
|
+
* identifies it). `putUnderDEK`'s slot-CAS (pointing the slot at its new
|
|
266
|
+
* eTag) and its old-eTag release are two separate writes; a crash between
|
|
267
|
+
* them strands the release — the slot map has already moved past the old
|
|
268
|
+
* eTag, so a plain re-derivation of "which eTags need releasing" from the
|
|
269
|
+
* CURRENT slot map can never find it again (a permanent leak, not merely
|
|
270
|
+
* a delayed one). Durably recording the old eTag ON the slot record
|
|
271
|
+
* itself (in the SAME CAS write that moves it) survives exactly the crash
|
|
272
|
+
* window that loses an in-memory breadcrumb, and this pass is what
|
|
273
|
+
* consumes it on the next attempt — completing the release (idempotent
|
|
274
|
+
* via the SAME row-scoped stamp `putUnderDEK` used) and clearing the
|
|
275
|
+
* field. C10: the release is NOT swallowed — a failure here must keep the
|
|
276
|
+
* marker alive (propagates), not silently strand it a second way.
|
|
277
|
+
*/
|
|
278
|
+
private reconcilePendingReleases;
|
|
279
|
+
/**
|
|
280
|
+
* #747: the `_blob_index` envelope follows the eTag's HOME tier — the
|
|
281
|
+
* same tier the `_cek` payload wrapped inside it has been scoped to since
|
|
282
|
+
* #724. That fix only tier-scoped the WRAPPED content CEK; the outer
|
|
283
|
+
* index envelope itself stayed flat, so a tier-0 DEK holder could still
|
|
284
|
+
* read an elevated record's blob metadata (size/mimeType/compression/
|
|
285
|
+
* chunkCount/refCount/createdAt) straight off `_blob_index` at rest.
|
|
286
|
+
*
|
|
287
|
+
* `tier` defaults to `ownerTier()`, mirroring `loadSlots`. Two-tier mode
|
|
288
|
+
* (#753 spec §7 C7 / §2d): try `tier`'s DEK first; on a decrypt failure
|
|
289
|
+
* (wrong key — AES-GCM auth fails, not "missing") retry under
|
|
290
|
+
* `alsoTryTier`'s DEK. `atTier` reports which key actually opened it, so a
|
|
291
|
+
* caller mutating the object (`casUpdateRefCount`) can write it back
|
|
292
|
+
* under that SAME key — never lifting a flat dedup/legacy object onto the
|
|
293
|
+
* owner's tier (or vice versa) as a side effect of a refCount change.
|
|
294
|
+
*
|
|
295
|
+
* `alsoTryTier` defaults to `0` when `tier` resolves `> 0` and no explicit
|
|
296
|
+
* value is given — this is #747's original tier-then-flat fallback,
|
|
297
|
+
* preserved byte-identical for every pre-#753 call site (none of which
|
|
298
|
+
* pass `alsoTryTier`). It covers the two legitimate classes that stay
|
|
299
|
+
* flat even for an elevated owner: a `dedup`-policy shared object (#741,
|
|
300
|
+
* left in place on purpose) and a legacy `_cek`-less object (chunks
|
|
301
|
+
* direct under the flat DEK, never tier-isolated — #724 I1). When `tier`
|
|
302
|
+
* resolves to `0` and no `alsoTryTier` is given, there is no fallback
|
|
303
|
+
* attempt at all (matches pre-#753 behavior exactly) — but a `tier === 0`
|
|
304
|
+
* caller MAY now pass an elevated `alsoTryTier` explicitly (the rehome
|
|
305
|
+
* resume path, §2d: "try `fromTier`, fall back to `toTier`", either of
|
|
306
|
+
* which may be 0). Passing `alsoTryTier === tier` is a no-op fallback (no
|
|
307
|
+
* second attempt — nothing new to try).
|
|
308
|
+
*
|
|
309
|
+
* No migration/compat path: the whole tiers×blobs arc is unpublished, so
|
|
310
|
+
* there is no previously-published elevated blob whose index envelope is
|
|
311
|
+
* stuck flat at rest — every elevated write from here on is born
|
|
312
|
+
* tier-keyed.
|
|
313
|
+
*/
|
|
314
|
+
private loadBlobObject;
|
|
315
|
+
/**
|
|
316
|
+
* `runRehomeSteps`'s per-eTag resume tolerance (#746 spec §7 §2d bullet 2)
|
|
317
|
+
* — `loadBlobObject(eTag, fromTier, toTier)`, `alsoTryTier`'s first real
|
|
318
|
+
* caller: `atTier === toTier` on return means this eTag's object already
|
|
319
|
+
* opens under the DESTINATION tier — either a prior (crashed) run's own
|
|
320
|
+
* re-`put()` already landed for it (skip: already moved), or it's a
|
|
321
|
+
* `dedup`-policy/legacy object that happens to sit flat at tier 0 and
|
|
322
|
+
* `toTier === 0` (skip either way — see the call site's doc comment).
|
|
323
|
+
*
|
|
324
|
+
* When `toTier !== 0`, that flat-at-0 legacy/dedup case is NOT covered by
|
|
325
|
+
* the two tiers already tried — `loadBlobObject`'s own default fallback
|
|
326
|
+
* (implicit `alsoTryTier: 0` when the primary tier is `> 0`) is exactly
|
|
327
|
+
* what closes it for a non-resumable caller, but passing `toTier`
|
|
328
|
+
* explicitly here overrides that default. So on a `TamperedError` from
|
|
329
|
+
* both `fromTier` and `toTier`, retry once more at flat `0` — the SAME
|
|
330
|
+
* fallback `loadBlobObject`'s own default already provides, just chained
|
|
331
|
+
* behind the resume signal instead of replacing it.
|
|
332
|
+
*/
|
|
333
|
+
private loadBlobObjectResumable;
|
|
334
|
+
/**
|
|
335
|
+
* @param tier See {@link loadBlobObject}'s `tier` param — same resolution.
|
|
336
|
+
* A caller mutating an EXISTING object must pass the tier that OPENED it
|
|
337
|
+
* (`loadBlobObject`'s `atTier`), never its own ask — see
|
|
338
|
+
* `casUpdateRefCount`.
|
|
339
|
+
*/
|
|
340
|
+
private writeBlobObject;
|
|
341
|
+
/**
|
|
342
|
+
* CAS retry loop for refCount changes on a BlobObject.
|
|
343
|
+
*
|
|
344
|
+
* @param tier Resolves the READ side (see {@link loadBlobObject}). The
|
|
345
|
+
* WRITE-back always uses `atTier` — the tier that actually opened the
|
|
346
|
+
* object — never `tier` itself: a dedup-shared or legacy object left flat
|
|
347
|
+
* on purpose must stay flat even when asked for under an elevated
|
|
348
|
+
* owner's tier, or a refCount change would silently lift it there (#747).
|
|
349
|
+
*/
|
|
350
|
+
private casUpdateRefCount;
|
|
351
|
+
/**
|
|
352
|
+
* Stamp-aware CAS retry loop for refCount changes (#753 spec §7 C2/C4) —
|
|
353
|
+
* the journal primitive `casUpdateRefCount` itself is deliberately left
|
|
354
|
+
* untouched (every existing call site passes no stamp and must stay
|
|
355
|
+
* byte-identical). A distinct method rather than an optional param on
|
|
356
|
+
* `casUpdateRefCount` keeps the return shape type-clean: this one reports
|
|
357
|
+
* whether ITS delta was newly applied, not just the resulting count.
|
|
358
|
+
*
|
|
359
|
+
* C4: the membership check lives INSIDE the retry loop — every (re)read,
|
|
360
|
+
* including retries after a losing CAS attempt, checks `blob.lastOps` for
|
|
361
|
+
* `stamp` FIRST, before computing a delta. This is what makes it a true
|
|
362
|
+
* test-and-set rather than a check-then-act with a TOCTOU window: two
|
|
363
|
+
* concurrent callers racing the SAME stamp can each land on any attempt,
|
|
364
|
+
* but only the one that reads `lastOps` without the stamp present ever
|
|
365
|
+
* applies the delta — the other, whichever attempt it lands on, always
|
|
366
|
+
* observes the stamp (either already there, or freshly appended by the
|
|
367
|
+
* winner) and skips.
|
|
368
|
+
*
|
|
369
|
+
* On apply: the stamp is appended to the bounded ring (`appendStamp`,
|
|
370
|
+
* K=8) in the SAME `writeBlobObject` CAS write as the delta — no window
|
|
371
|
+
* between them (spec C2's atomicity requirement).
|
|
372
|
+
*
|
|
373
|
+
* @returns `{ applied: true, refCount }` when this call's delta was freshly
|
|
374
|
+
* applied (or `{ applied: false, refCount }` when `stamp` was already
|
|
375
|
+
* present — the delta from a PRIOR call with this exact stamp already
|
|
376
|
+
* landed; `refCount` reflects the object's current count, unchanged by
|
|
377
|
+
* this call).
|
|
378
|
+
* @param tier See {@link loadBlobObject}'s `tier` param — same resolution
|
|
379
|
+
* and the same atTier write-back rule as `casUpdateRefCount`.
|
|
380
|
+
*/
|
|
381
|
+
private casUpdateRefCountStamped;
|
|
382
|
+
/**
|
|
383
|
+
* Release `n` references to a blob and reclaim it at refCount 0.
|
|
384
|
+
*
|
|
385
|
+
* The single reclaim choke point for every reference-drop path — slot
|
|
386
|
+
* delete/overwrite, published-version delete, and `forget()` shred — so the
|
|
387
|
+
* refCount-0 policy is uniform:
|
|
388
|
+
* - **erasable blob** (`_cek` present) → delete the `BlobObject` (the SOLE
|
|
389
|
+
* copy of the wrapped content CEK → chunks permanently undecryptable) and
|
|
390
|
+
* reclaim the chunks. The crypto-shred is EAGER on every path: GDPR erasure
|
|
391
|
+
* must not wait on orphan retention.
|
|
392
|
+
* - **legacy blob** (no `_cek`) → reclaimed only when `reclaimLegacy` (the
|
|
393
|
+
* `forget()` erasure path); otherwise left for deferred GC so the existing
|
|
394
|
+
* `BlobLifecyclePolicy.orphanRetentionDays` semantics are preserved.
|
|
395
|
+
*
|
|
396
|
+
* @returns `'shredded'` (erasable, refCount 0, chunks dead) · `'retainedShared'`
|
|
397
|
+
* (erasable, still referenced) · `'residue'` (legacy — not a crypto-shred).
|
|
398
|
+
*
|
|
399
|
+
* @param tier See {@link loadBlobObject}'s `tier` param — forwarded to both
|
|
400
|
+
* the read and the refCount write-back (which resolves its own `atTier`
|
|
401
|
+
* from the read, per `casUpdateRefCount`'s doc comment).
|
|
402
|
+
*
|
|
403
|
+
* @param stamp #753 spec §7 C1 journal primitive: when present, this call
|
|
404
|
+
* is a (possibly-resumed) journaled release and the CAS goes through
|
|
405
|
+
* {@link casUpdateRefCountStamped} instead, under the two-armed resume
|
|
406
|
+
* rule:
|
|
407
|
+
* - `lastOps` already has `stamp` && `refCount > 0` → this stamp's
|
|
408
|
+
* decrement already landed and the object is still referenced elsewhere
|
|
409
|
+
* — skip re-decrementing, report the same outcome a fresh call would
|
|
410
|
+
* (`retainedShared`/`residue`).
|
|
411
|
+
* - `lastOps` already has `stamp` && `refCount <= 0` → this stamp's
|
|
412
|
+
* decrement already landed, but the crash window sat BETWEEN the
|
|
413
|
+
* decrement CAS and the index+chunk deletion below — COMPLETE that
|
|
414
|
+
* deletion now (idempotent: both `store.delete` calls are void on an
|
|
415
|
+
* already-absent key).
|
|
416
|
+
* - not yet stamped → apply via `casUpdateRefCountStamped`, then proceed
|
|
417
|
+
* exactly like the unstamped path below.
|
|
418
|
+
*
|
|
419
|
+
* A crash can also land AFTER the index row is deleted but BEFORE every
|
|
420
|
+
* chunk is — `loadBlobObject` then returns null (indistinguishable from
|
|
421
|
+
* "never existed") and the object's `chunkCount` is gone with it. A
|
|
422
|
+
* stamped caller who knows the true count (the journal marker's captured
|
|
423
|
+
* `holds`, once that plumbing lands) supplies it via `chunkCountHint` so
|
|
424
|
+
* this call can still finish the chunk deletion; without it, an
|
|
425
|
+
* already-index-gone eTag is reported `'shredded'` same as today (best
|
|
426
|
+
* effort — nothing left to key the cleanup off of).
|
|
427
|
+
*/
|
|
428
|
+
private releaseRef;
|
|
429
|
+
/**
|
|
430
|
+
* Crypto-shred this record's blob attachments — called by
|
|
431
|
+
* `vault.forget()`.
|
|
432
|
+
*
|
|
433
|
+
* For each distinct eTag the record references (a record may attach the same
|
|
434
|
+
* content under several slot names → several refCount holds): decrement the
|
|
435
|
+
* blob's refCount by that many. When it reaches 0:
|
|
436
|
+
* - **erasable blob** (`_cek` present) → delete the `BlobObject` (the SOLE
|
|
437
|
+
* recoverable copy of the wrapped content CEK → chunks permanently
|
|
438
|
+
* undecryptable) and reclaim the chunk bytes. This is the crypto-shred.
|
|
439
|
+
* - **legacy blob** (no `_cek`) → chunks are under the shared `_blob` DEK and
|
|
440
|
+
* stay decryptable until byte-deleted; we delete the orphaned chunks +
|
|
441
|
+
* index but report it as residue, not a cryptographic erasure.
|
|
442
|
+
* When refCount stays > 0 the content legitimately persists for its other
|
|
443
|
+
* owner — reported as `retainedShared` (or `residue` if legacy).
|
|
444
|
+
*
|
|
445
|
+
* Finally drops the record's slot map, severing the subject's link.
|
|
446
|
+
*
|
|
447
|
+
* @param ownerTier #724 Arc 10 C3: `vault.forget()` writes the record's
|
|
448
|
+
* tombstone (which drops `_tier`) BEFORE calling this method, so the
|
|
449
|
+
* `ownerTier()` default — a fresh peek at the now-tombstoned envelope —
|
|
450
|
+
* would resolve tier 0 and decrypt the tier-scoped slot map under the
|
|
451
|
+
* wrong DEK (`TamperedError`, erasure aborted mid-shred). `forget()` reads
|
|
452
|
+
* the LIVE record first and passes its pre-tombstone tier here instead.
|
|
453
|
+
*
|
|
454
|
+
* #724 re-review (Critical) defense-in-depth: an unreadable slot map must
|
|
455
|
+
* not abort the whole erasure cascade — `casUpdateSlots` deleting the row
|
|
456
|
+
* instead of leaving it empty-but-present (rather than a stray mis-keyed
|
|
457
|
+
* envelope) is what makes an ABSENT row the normal "no blobs" case, and
|
|
458
|
+
* `loadSlots` already returns `{ slots: {}, version: 0 }` cleanly for
|
|
459
|
+
* that, never throwing. So the only way this catch fires is a row that IS
|
|
460
|
+
* present failing to decrypt — genuine corruption/mis-key/tamper — and
|
|
461
|
+
* that must never be swallowed as "no blobs to shred": it is pushed onto
|
|
462
|
+
* `residue` so `forget()` surfaces it via `blobResidueCollections` rather
|
|
463
|
+
* than silently reporting a clean erasure while un-shredded blobs remain.
|
|
464
|
+
*
|
|
465
|
+
* #750: published versions (`_blob_versions_{collection}/{recordId}::*`)
|
|
466
|
+
* take an INDEPENDENT refCount hold on a `BlobObject`, separate from the
|
|
467
|
+
* slot map (see `publish()`) — the slot loop above never sees them. Left
|
|
468
|
+
* untouched, that hold (and the version-held content, if the slot was
|
|
469
|
+
* later overwritten) survives `forget()` — a GDPR-erasure hole. So this
|
|
470
|
+
* method also enumerates the record's version rows via
|
|
471
|
+
* `collectVersionHolds`, folds each version's hold into the SAME `holds`
|
|
472
|
+
* map (a shared eTag reports ONE outcome, not two), and deletes the
|
|
473
|
+
* readable version rows once their holds are released.
|
|
474
|
+
*
|
|
475
|
+
* **#753 spec §7 (crash-idempotent shred):** the holds used for the
|
|
476
|
+
* actual release loop below come from a `_blob_intent` MARKER, never
|
|
477
|
+
* re-collected from rows on resume:
|
|
478
|
+
* - `forget()` mints the marker PRE-tombstone (`mintShredIntent`,
|
|
479
|
+
* C5) — the normal case, so a marker is ALREADY present by the time
|
|
480
|
+
* this method runs and `intent.ownerTier` (captured live, before the
|
|
481
|
+
* tombstone dropped `_tier`) is authoritative even when the caller's
|
|
482
|
+
* own `ownerTier` argument is stale (a crash-retried `forget()`
|
|
483
|
+
* re-reads the now-tombstoned record and can only pass `0`).
|
|
484
|
+
* - Called WITHOUT a pre-existing marker (defensive/non-forget callers,
|
|
485
|
+
* or the direct-call path this suite exercises) — one is minted here
|
|
486
|
+
* from the live rows, exactly like `mintShredIntent` does, so the
|
|
487
|
+
* crash matrix holds regardless of caller (spec §2c).
|
|
488
|
+
* - A pending `op:'rehome'` marker is resumed to completion FIRST (#746
|
|
489
|
+
* spec §7 Q1 — "supersession is resume-then-shred": a half-done rehome
|
|
490
|
+
* can leave a row-unreferenced destination object that shred's
|
|
491
|
+
* row-derived holds can never see; replacing the marker instead of
|
|
492
|
+
* resuming it would leak that object past `forget()` permanently), via
|
|
493
|
+
* {@link resolveShredIntent} — then a fresh SHRED marker is minted (or
|
|
494
|
+
* discovered, if the resume's own completion raced with another
|
|
495
|
+
* minter) exactly as the no-marker branch below does.
|
|
496
|
+
*
|
|
497
|
+
* **Whole-branch review (#753):** the marker is a crash-safety
|
|
498
|
+
* ENHANCEMENT, not a precondition for erasure. If the no-marker branch's
|
|
499
|
+
* own mint fails (transient store error, `getDEK` failure — possibly the
|
|
500
|
+
* same failure that already sent `forget()`'s pre-tombstone mint to
|
|
501
|
+
* residue), this degrades to {@link unmarkedShred} — a best-effort
|
|
502
|
+
* UNMARKED shred, exactly the pre-#753 behavior — rather than aborting
|
|
503
|
+
* and leaving the blobs un-shredded.
|
|
504
|
+
*
|
|
505
|
+
* **#746 review Critical 1:** that degradation covers ONLY a genuine
|
|
506
|
+
* no-marker mint failure — nothing was in flight, so a live-row
|
|
507
|
+
* best-effort re-collection is safe. A REHOME-resume failure is a
|
|
508
|
+
* DIFFERENT failure mode: a marker WAS present and its holds are
|
|
509
|
+
* ambiguous mid-move (C10's whole point). `resolveShredIntent` below
|
|
510
|
+
* therefore never wraps `consumeRehomeIntent` in the mint's degradation
|
|
511
|
+
* try/catch — a resume failure propagates all the way out of this
|
|
512
|
+
* method uncaught, leaving the rehome marker alive (never `deleteIntent`d)
|
|
513
|
+
* for a later resume, instead of silently falling through to
|
|
514
|
+
* `unmarkedShred`, which would both clobber rows the ambiguous rehome
|
|
515
|
+
* still needs and abandon the marker forever (the exact permanent-leak
|
|
516
|
+
* shape the journal exists to prevent).
|
|
517
|
+
*
|
|
518
|
+
* `collectShredHolds` is re-run here (idempotent — a corrupt/unreadable
|
|
519
|
+
* row stays corrupt/unreadable on re-read; an already-deleted row reads
|
|
520
|
+
* back cleanly empty) purely to derive the slot-map/version-row DELETE
|
|
521
|
+
* targets and residue notices — never to recompute the release counts,
|
|
522
|
+
* which are fixed for the operation's lifetime in the marker (C1/C2).
|
|
523
|
+
*/
|
|
524
|
+
shredAllForRecord(ownerTier?: number): Promise<{
|
|
525
|
+
shredded: string[];
|
|
526
|
+
retainedShared: string[];
|
|
527
|
+
residue: string[];
|
|
528
|
+
}>;
|
|
529
|
+
/**
|
|
530
|
+
* Resolve a SHRED `BlobIntent` for this record, or `null` when the entry
|
|
531
|
+
* mint itself failed and nothing was in flight (the caller degrades to
|
|
532
|
+
* {@link unmarkedShred}) — `shredAllForRecord`'s entry logic (#746 spec §7
|
|
533
|
+
* Q1), factored out so the two failure modes stay structurally separate
|
|
534
|
+
* (#746 review Critical 1):
|
|
535
|
+
*
|
|
536
|
+
* - A pending REHOME marker — found up front OR discovered via a raced
|
|
537
|
+
* `createIntent` inside `mintFreshShredIntent` — is resumed via
|
|
538
|
+
* {@link consumeRehomeIntent} OUTSIDE the `try` below. Its failure
|
|
539
|
+
* PROPAGATES to the caller uncaught: holds are ambiguous mid-move, so
|
|
540
|
+
* this must surface, never silently degrade.
|
|
541
|
+
* - Only `mintFreshShredIntent` itself (the create-a-fresh-SHRED-marker
|
|
542
|
+
* step, reached with no rehome in flight) is wrapped — its failure is
|
|
543
|
+
* the ONLY thing `null` reports, matching the whole-branch-review
|
|
544
|
+
* degrade contract exactly.
|
|
545
|
+
*
|
|
546
|
+
* The loop re-attempts the mint after resuming a raced rehome discovery,
|
|
547
|
+
* mirroring `resolveToShredIntent`'s prior recursive shape without ever
|
|
548
|
+
* routing a `consumeRehomeIntent` call through the mint's own catch.
|
|
549
|
+
*/
|
|
550
|
+
private resolveShredIntent;
|
|
551
|
+
/**
|
|
552
|
+
* Best-effort UNMARKED shred (#753 whole-branch review) — reached only
|
|
553
|
+
* when `shredAllForRecord`'s own entry-mint threw, so there is no marker
|
|
554
|
+
* to journal against. Reproduces the pre-#753 `shredAllForRecord` body:
|
|
555
|
+
* collect this record's holds from the live rows, release each unstamped
|
|
556
|
+
* (no journal — a crash here reverts to the pre-#753 stranding-eTag
|
|
557
|
+
* exposure, exactly like main before this arc), then unconditionally drop
|
|
558
|
+
* the slot map / readable version rows. The mint failure itself is
|
|
559
|
+
* reported as `_blob_intent` residue so `forget()` surfaces the
|
|
560
|
+
* degraded crash-safety posture via `blobResidueCollections`, never
|
|
561
|
+
* silently.
|
|
562
|
+
*/
|
|
563
|
+
private unmarkedShred;
|
|
564
|
+
/**
|
|
565
|
+
* Collect this record's CURRENT blob holds (slot map + published
|
|
566
|
+
* versions) at `tier` — the shred journal's single hold-collection
|
|
567
|
+
* routine (#753 spec §7), shared by `mintFreshShredIntent` (to seed a
|
|
568
|
+
* fresh marker's authoritative `holds`) and `shredAllForRecord`/
|
|
569
|
+
* `resolvePendingIntent` (to derive delete targets + residue on
|
|
570
|
+
* consumption — see {@link shredAllForRecord}'s doc comment for why that
|
|
571
|
+
* second use never feeds the release loop). Mirrors the pre-#753
|
|
572
|
+
* inline collection logic byte-for-byte; `chunkCount` per hold (C5) is
|
|
573
|
+
* best-effort — an unreadable index row just means the marker's hint is
|
|
574
|
+
* absent, `releaseRef`'s own chunkCountHint fallback still applies.
|
|
575
|
+
*/
|
|
576
|
+
private collectShredHolds;
|
|
577
|
+
/**
|
|
578
|
+
* Collect this record's current holds and CAS-create a fresh `_blob_intent`
|
|
579
|
+
* SHRED marker from them (#753 spec §7 C8). Used by `mintShredIntent`
|
|
580
|
+
* (forget()'s pre-tombstone step) and `shredAllForRecord`'s no-marker
|
|
581
|
+
* (defensive/direct-call) branch.
|
|
582
|
+
*
|
|
583
|
+
* C4: a concurrent minter for this SAME record can win the create race —
|
|
584
|
+
* `createIntent` throws `BlobIntentPendingError`, and the winner's marker
|
|
585
|
+
* (whatever op it turns out to be) is returned instead; the caller decides
|
|
586
|
+
* how to handle a raced rehome marker.
|
|
587
|
+
*/
|
|
588
|
+
private mintFreshShredIntent;
|
|
589
|
+
/**
|
|
590
|
+
* Release every hold in `intent.holds` (stamped with `intent.opId`), then
|
|
591
|
+
* delete the slot map / readable version rows / the marker itself — the
|
|
592
|
+
* shred journal's consume step (#753 spec §7 §2c), shared by
|
|
593
|
+
* `shredAllForRecord` and `resolvePendingIntent`.
|
|
594
|
+
*
|
|
595
|
+
* **C10 (no swallowed releases under a marker):** a release that THROWS
|
|
596
|
+
* (as opposed to returning `'residue'`, a normal non-error outcome for a
|
|
597
|
+
* legacy blob) is caught, reported as residue, and marks the whole
|
|
598
|
+
* consumption incomplete — the slot map, version rows, and the marker
|
|
599
|
+
* itself are then left IN PLACE (not deleted) so a later resume retries
|
|
600
|
+
* every hold. Stamped holds that already landed skip re-decrementing
|
|
601
|
+
* (C1/C4's test-and-set), so redoing the full loop on retry is safe.
|
|
602
|
+
*/
|
|
603
|
+
private consumeShredIntent;
|
|
604
|
+
/**
|
|
605
|
+
* Resume gate (#753/#746 spec §7 C6): every refCount/slot mutator calls
|
|
606
|
+
* this FIRST. A pending SHRED marker means a previous `forget()`/
|
|
607
|
+
* `shredAllForRecord()` crashed mid-flight — refCounts are ambiguous
|
|
608
|
+
* until it's resumed, so no new blob write may proceed over them; this
|
|
609
|
+
* resumes it to completion before the caller's own mutation runs. A
|
|
610
|
+
* pending REHOME marker means a previous tier move crashed mid-flight —
|
|
611
|
+
* resumed to completion the SAME way (§2d), via {@link consumeRehomeIntent}
|
|
612
|
+
* using the marker's OWN captured `fromTier`/`toTier`/`policy`/`opId`,
|
|
613
|
+
* never the caller's own ask (which may be a totally unrelated write).
|
|
614
|
+
*
|
|
615
|
+
* Never called from `shredAllForRecord`/`mintShredIntent`/
|
|
616
|
+
* `mintFreshShredIntent`/`collectShredHolds`/`consumeShredIntent`/
|
|
617
|
+
* `sweepPendingShredIntents`/`runRehomeSteps`/`consumeRehomeIntent`
|
|
618
|
+
* themselves — those ARE the resume machinery; routing them back through
|
|
619
|
+
* this gate would recurse.
|
|
620
|
+
*/
|
|
621
|
+
private resolvePendingIntent;
|
|
622
|
+
/**
|
|
623
|
+
* Resume a pending REHOME marker to completion: run {@link
|
|
624
|
+
* runRehomeSteps} (never the public `rehomeForTier`/`syncTierMove` —
|
|
625
|
+
* both would re-enter `resolvePendingIntent` on the SAME marker and
|
|
626
|
+
* recurse) using the marker's own captured `fromTier`/`toTier`/`policy`/
|
|
627
|
+
* `opId`, then delete it. Shared by `resolvePendingIntent`'s rehome
|
|
628
|
+
* branch and `resolveToShredIntent` (#746 spec §7 Q1: forget() resumes a
|
|
629
|
+
* pending rehome before shredding).
|
|
630
|
+
*/
|
|
631
|
+
private consumeRehomeIntent;
|
|
632
|
+
/**
|
|
633
|
+
* Resume every stranded SHRED marker in THIS collection (#753 spec §7 —
|
|
634
|
+
* `sweepBlobIntents`'s first real production caller, Task 3 item 5).
|
|
635
|
+
* Scoped to `this.collection` rather than the whole vault: `forget()`
|
|
636
|
+
* already iterates per-ref-collection, so calling this from
|
|
637
|
+
* `mintShredIntent` once per ref opportunistically heals any OTHER
|
|
638
|
+
* record's marker left behind by a previous crashed operation in the
|
|
639
|
+
* same collection — "heals untouched ones" (spec C5's retry contract),
|
|
640
|
+
* without a separate vault-open hook. A pending REHOME marker on a
|
|
641
|
+
* sibling record is left alone here (out of THIS sweep's scope — it heals
|
|
642
|
+
* on its OWN record's next write/tier-op via `resolvePendingIntent`,
|
|
643
|
+
* §2d's "who resumes") rather than surfaced as a resume failure.
|
|
644
|
+
* `sweepBlobIntents`'s own per-marker
|
|
645
|
+
* isolation (blob-intent.ts) means one corrupt sibling never blocks
|
|
646
|
+
* another record's healthy resume.
|
|
647
|
+
*/
|
|
648
|
+
private sweepPendingShredIntents;
|
|
649
|
+
/**
|
|
650
|
+
* Mint the `_blob_intent` SHRED marker for this record — `vault.forget()`'s
|
|
651
|
+
* PRE-tombstone step (#753 spec §7 C5). Captures this record's CURRENT
|
|
652
|
+
* blob holds (slot map + published versions, at `ownerTier` — the LIVE
|
|
653
|
+
* pre-tombstone tier) into a fresh marker before any destructive write
|
|
654
|
+
* happens, so a crash between here and `shredAllForRecord`'s completion —
|
|
655
|
+
* including one straddling the tombstone itself, which drops `_tier` and
|
|
656
|
+
* would otherwise strand an elevated record's holds unrecoverably on
|
|
657
|
+
* retry — leaves a resumable, tier-correct record of what must still be
|
|
658
|
+
* released.
|
|
659
|
+
*
|
|
660
|
+
* First sweeps this collection for any stranded marker
|
|
661
|
+
* (`sweepPendingShredIntents`) — this resumes a PRE-EXISTING marker for
|
|
662
|
+
* THIS record (a previous forget() attempt crashed mid-shred) to
|
|
663
|
+
* completion before minting fresh (C8: never overwrite a pending
|
|
664
|
+
* marker — that would orphan its op-stamps), as a side effect of the
|
|
665
|
+
* same collection-wide sweep.
|
|
666
|
+
*/
|
|
667
|
+
mintShredIntent(ownerTier: number): Promise<void>;
|
|
668
|
+
/**
|
|
669
|
+
* #750: enumerate this record's published-version rows (`{recordId}::*` in
|
|
670
|
+
* `_blob_versions_{collection}` — the same raw prefix scan as
|
|
671
|
+
* `rehomeVersionRecords`) and fold each version's independent refCount hold
|
|
672
|
+
* into `holds`. Returns the READABLE version keys — safe to delete once
|
|
673
|
+
* their holds are released. An unreadable row is pushed onto `residue` and
|
|
674
|
+
* NOT returned: deleting it blind would orphan its refCount hold and strand
|
|
675
|
+
* the content undecryptable-but-undeleted forever, so it stays in place for
|
|
676
|
+
* out-of-band repair (mirrors the unreadable-slot-map posture above).
|
|
677
|
+
*/
|
|
678
|
+
private collectVersionHolds;
|
|
679
|
+
/**
|
|
680
|
+
* Rehome this record's blobs after a tier move (#724 Arc 10 Task 2,
|
|
681
|
+
* at-rest isolation) — called by `TiersContext.syncBlobs`. A blob's home
|
|
682
|
+
* tier is its owning record's tier: the `_blob` DEK is tier-scoped via
|
|
683
|
+
* `dekKey('_blob', tier)`, so moving a record's tier must move the
|
|
684
|
+
* wrapping key of any blob it exclusively owns, or a tier-0-cleared
|
|
685
|
+
* caller could still unwrap the content CEK off the store at rest even
|
|
686
|
+
* though the runtime read gate (Task 1) hides it through the API.
|
|
687
|
+
*
|
|
688
|
+
* Every read/write of the slot map INSIDE this method pins `fromTier`
|
|
689
|
+
* explicitly (never the `loadSlots()`/`saveSlots()` default) — by the
|
|
690
|
+
* time this runs, the owning record's live `_tier` envelope has ALREADY
|
|
691
|
+
* moved to `toTier` (the collection-level `elevate`/`demote`/`putAtTier`
|
|
692
|
+
* writes the record before invoking `syncBlobs`), but the slot map itself
|
|
693
|
+
* is still physically encrypted at `fromTier` until this method's own
|
|
694
|
+
* move step (last) lands. `ownerTier()`'s default would resolve the
|
|
695
|
+
* wrong DEK for every read until then.
|
|
696
|
+
*
|
|
697
|
+
* Enumerates the record's eTags via the slot map — mirrors
|
|
698
|
+
* `shredAllForRecord`'s `loadSlots()` → `holds` enumeration above. For
|
|
699
|
+
* each distinct eTag:
|
|
700
|
+
* - **solo** (`refCount === 1`) and **shared `isolate`** (`refCount > 1`,
|
|
701
|
+
* default policy) are UNIFIED (#724 Arc 10 correction, closes C1): both
|
|
702
|
+
* re-`put()` the plaintext under `toBlobDEK` for every one of this
|
|
703
|
+
* record's slots pointing at the eTag. That mints a fresh, tier-scoped
|
|
704
|
+
* eTag/`_cek` (HMAC + wrap keyed by `toBlobDEK`) and, via `put()`'s own
|
|
705
|
+
* existing old-eTag decrement, releases this record's hold on the old
|
|
706
|
+
* object — a solo blob's old object drops to refCount 0 and is
|
|
707
|
+
* crypto-shredded; a shared co-owner keeps its unchanged refCount. The
|
|
708
|
+
* OLD in-place rewrap (`wrapCek(unwrapCek(_cek, fromDEK), toDEK)`, eTag
|
|
709
|
+
* held stable) is UNSAFE — it leaves the eTag in the FROM tier's HMAC
|
|
710
|
+
* namespace, so a later same-bytes put computed under that tier's DEK
|
|
711
|
+
* dedup-*hits* the wrapped object (cross-tier corruption of an
|
|
712
|
+
* uninvolved writer). Re-`put()`ing makes that structurally
|
|
713
|
+
* impossible: different tiers hash to different eTags. Landing at
|
|
714
|
+
* `toTier === 0` naturally REJOINS the tier-0 dedup pool if a co-owner
|
|
715
|
+
* already holds the content there (`put()`'s own dedup check matches
|
|
716
|
+
* on the recomputed tier-0-native eTag) — this is how `demote(→0)`
|
|
717
|
+
* reverses an `elevate()` fork.
|
|
718
|
+
* - **shared `dedup`** (#741, opt-in, only for `refCount > 1`): NO-OP.
|
|
719
|
+
* The slot keeps pointing at the shared eTag. The Task-1 runtime read
|
|
720
|
+
* gate still hides it from a tier-0 caller; the chunks remain
|
|
721
|
+
* decryptable at rest under the flat `_blob` DEK (documented residue).
|
|
722
|
+
* - **legacy** (`_cek` absent — chunks direct under the flat `_blob`
|
|
723
|
+
* DEK): NO-OP. Tiered collections mandate `perRecordKeys`, so new
|
|
724
|
+
* blob data is always erasable; a legacy blob reaching this method
|
|
725
|
+
* would need a chunk re-encrypt (not attempted here).
|
|
726
|
+
*
|
|
727
|
+
* #724 Arc 10 Task 4 — slot-map metadata move: LAST step, after every
|
|
728
|
+
* fork/rewrap/reconcile write above (which all operated on the slot map
|
|
729
|
+
* via the explicit `fromTier`, its still-current physical location).
|
|
730
|
+
* Re-reads (to pick up any fork/reconcile-produced eTag changes from the
|
|
731
|
+
* loop) and re-encrypts the SAME `_blob_slots_{collection}/{recordId}`
|
|
732
|
+
* row under the `toTier` collection DEK — filenames/sizes/mimeTypes/eTags
|
|
733
|
+
* are no longer tier-0-readable at rest for an elevated record. No
|
|
734
|
+
* separate delete: it's the same physical row, just re-keyed in place
|
|
735
|
+
* (mirrors `history.ts`'s `rewrapHistory`).
|
|
736
|
+
*
|
|
737
|
+
* @param opId #753/#746 spec §7 C3: the governing `_blob_intent` rehome
|
|
738
|
+
* marker's op-stamp identity, threaded through by `syncTierMove`. Omitted
|
|
739
|
+
* (a direct call, e.g. tests) → byte-identical unstamped behavior. When
|
|
740
|
+
* present, every DESTINATION refCount `+1` this call performs (the slot
|
|
741
|
+
* loop's dedup-hit re-put below, and `rehomeVersionETag`'s own increment)
|
|
742
|
+
* carries a ROW-SCOPED stamp — `${opId}:${slotName}` / `${opId}:${versionKey}`,
|
|
743
|
+
* never the bare opId — so a resumed re-put's `+1` is idempotent per row
|
|
744
|
+
* without collapsing N legitimate `+1`s onto one destination eTag into one.
|
|
745
|
+
*
|
|
746
|
+
* The direct-call entry point: resumes a pending SHRED marker first
|
|
747
|
+
* (unchanged, #753 C6), or a pending REHOME marker for a DIFFERENT prior
|
|
748
|
+
* op (#746 Q1 — resumed via its OWN stored fromTier/toTier/opId before
|
|
749
|
+
* this call's requested move proceeds), then runs {@link runRehomeSteps}.
|
|
750
|
+
* `syncTierMove` — the real tier-op seam (`syncBlobs`) — calls
|
|
751
|
+
* `runRehomeSteps` directly instead, after minting/consuming its own
|
|
752
|
+
* marker (calling back through here would re-enter `resolvePendingIntent`
|
|
753
|
+
* on the marker `syncTierMove` itself just created).
|
|
754
|
+
*/
|
|
755
|
+
rehomeForTier(fromTier: number, toTier: number, policy: 'isolate' | 'dedup', opId?: string): Promise<void>;
|
|
756
|
+
/**
|
|
757
|
+
* The tier-op → rehome seam (#746 spec §7 §2d) — called by
|
|
758
|
+
* `TiersContext.syncBlobs` (`collection.ts`), replacing the pre-#746
|
|
759
|
+
* unstamped `rehomeForTier` call. Mints the governing `_blob_intent`
|
|
760
|
+
* REHOME marker BEFORE the first write (CAS create-if-absent), resuming
|
|
761
|
+
* any marker already pending for this record first — a stale rehome from
|
|
762
|
+
* an earlier, different move, or a shred, per the same C6/Q1 resume-first
|
|
763
|
+
* law `rehomeForTier`'s own entry follows. Deletes the marker as the LAST
|
|
764
|
+
* step, once every phase of {@link runRehomeSteps} completes without
|
|
765
|
+
* throwing (a failure — including a C10 unswallowed release — leaves the
|
|
766
|
+
* marker in place for the next resume).
|
|
767
|
+
*/
|
|
768
|
+
syncTierMove(fromTier: number, toTier: number, policy: 'isolate' | 'dedup'): Promise<void>;
|
|
769
|
+
/**
|
|
770
|
+
* #746 whole-branch review Hardening 1: `syncTierMove` runs on EVERY tier
|
|
771
|
+
* move (`elevate`/`demote`/`putAtTier`) — including the common case of a
|
|
772
|
+
* record that has never attached a blob. Minting-then-deleting a marker
|
|
773
|
+
* for such a record is pure overhead (~4 extra adapter ops on every
|
|
774
|
+
* bulk elevate/demote of blob-less records) protecting nothing: an empty
|
|
775
|
+
* slot map AND no published versions means there is genuinely no content
|
|
776
|
+
* this op could strand. Checked AFTER `resolvePendingIntent` (a pending
|
|
777
|
+
* marker, however stale, is always resumed first regardless of current
|
|
778
|
+
* blob state — it may reference content this check alone wouldn't see)
|
|
779
|
+
* and BEFORE minting a new one.
|
|
780
|
+
*/
|
|
781
|
+
private isBlobFree;
|
|
782
|
+
/**
|
|
783
|
+
* The resumable rehome executor (#746 spec §7 §2d) — `rehomeForTier`'s
|
|
784
|
+
* pre-#746 body, factored out so it can be invoked WITHOUT re-entering
|
|
785
|
+
* `resolvePendingIntent` (which would recurse: this method IS part of the
|
|
786
|
+
* resume machinery, called from `resolvePendingIntent`'s own rehome
|
|
787
|
+
* branch and from `syncTierMove` after its marker is already settled).
|
|
788
|
+
*
|
|
789
|
+
* Per-step resume tolerance:
|
|
790
|
+
* - Slot map: {@link loadSlotsTolerant} tries `fromTier` then `toTier` —
|
|
791
|
+
* if it opens at `toTier`, a prior run's move step already landed, so
|
|
792
|
+
* the ENTIRE per-eTag loop (strictly sequenced before the move) is
|
|
793
|
+
* also already done — skip both, but first reconstruct `rehomedETags`
|
|
794
|
+
* (see below) so the version pass's same-eTag fast path still works
|
|
795
|
+
* (carried finding (a)).
|
|
796
|
+
* - Per-eTag: {@link loadBlobObjectResumable} — an eTag that only opens
|
|
797
|
+
* under `toTier` means THIS slot's re-put already landed on a prior
|
|
798
|
+
* run — skip re-processing it.
|
|
799
|
+
* - Slot-CAS→release gap (carried finding (b)): {@link
|
|
800
|
+
* reconcilePendingReleases} runs FIRST, completing any old-eTag
|
|
801
|
+
* release a prior run's `putUnderDEK` left stranded (slot already
|
|
802
|
+
* moved to the new eTag, release not yet applied) before either the
|
|
803
|
+
* "already moved" or "still moving" branch below runs.
|
|
804
|
+
* - Version pass: same per-key tolerance, in `rehomeVersionRecords`.
|
|
805
|
+
* - Destination `+1`s (#746 whole-branch review, K=8 stamp-ring
|
|
806
|
+
* blocker): `knownApplied` — this op's marker-backed
|
|
807
|
+
* `appliedStamps`, read ONCE here — makes every row-scoped
|
|
808
|
+
* increment idempotent INDEPENDENTLY of `BlobObject.lastOps`'s
|
|
809
|
+
* bounded ring; see {@link applyStampedIncrement}'s doc comment.
|
|
810
|
+
*/
|
|
811
|
+
private runRehomeSteps;
|
|
812
|
+
/**
|
|
813
|
+
* Rehome this record's PUBLISHED VERSIONS after a tier move — the second
|
|
814
|
+
* half of `rehomeForTier` (#724 Arc 10 Task 2, closes C4). Enumerates
|
|
815
|
+
* every `_blob_versions_{collection}/{recordId}::*` row (mirrors
|
|
816
|
+
* `listVersions`'s raw prefix scan, but across ALL slots on this record,
|
|
817
|
+
* not one) and, for each:
|
|
818
|
+
* - rehomes its held eTag via {@link rehomeVersionETag} (reusing the slot
|
|
819
|
+
* loop's result when the version happens to hold the SAME eTag a slot
|
|
820
|
+
* held — see that method's doc comment), and
|
|
821
|
+
* - re-keys the version RECORD itself onto the `toTier` collection DEK,
|
|
822
|
+
* regardless of whether the content moved — metadata protection is
|
|
823
|
+
* orthogonal to the shared-content dedup policy (matches the slot-map
|
|
824
|
+
* move, which always relocates even for a `dedup`-left-in-place blob).
|
|
825
|
+
*
|
|
826
|
+
* Per-key resume tolerance (#746 spec §7 §2d bullet 3): each key's
|
|
827
|
+
* metadata is read via {@link loadVersionRecordAtKeyTolerant} (try
|
|
828
|
+
* `fromTier` then `toTier`) — a key whose metadata already opens at
|
|
829
|
+
* `toTier` had its `resolveRehomedVersionETag` call AND its
|
|
830
|
+
* `writeVersionRecordAtKey` BOTH already land on a prior run (the
|
|
831
|
+
* metadata write is sequenced strictly after the eTag rehome, which
|
|
832
|
+
* itself completes the old-eTag release under C1's two-armed resume rule
|
|
833
|
+
* — same order as the slot loop's own CAS-then-release), so it's skipped
|
|
834
|
+
* entirely.
|
|
835
|
+
*
|
|
836
|
+
* Known residual gap (documented, not closed by this task — see the T2
|
|
837
|
+
* report): if a version's OLD eTag is held ONLY by that version (never
|
|
838
|
+
* shared with any slot), a crash strictly between
|
|
839
|
+
* `resolveRehomedVersionETag`'s release (drops it to refCount 0,
|
|
840
|
+
* crypto-shredding a solo-held erasable object) and THIS method's
|
|
841
|
+
* metadata write would leave the version pointing at an eTag whose sole
|
|
842
|
+
* copy is already gone. This mirrors the slot-side "carried finding (b)"
|
|
843
|
+
* shape but on the version side; closing it durably (a `pendingRelease`-
|
|
844
|
+
* style breadcrumb on `VersionRecord`, filtered from the public
|
|
845
|
+
* `listVersions()` surface) is out of scope for this task.
|
|
846
|
+
*/
|
|
847
|
+
private rehomeVersionRecords;
|
|
848
|
+
/**
|
|
849
|
+
* Resumable per-key version-record metadata read (#746 spec §7 §2d bullet
|
|
850
|
+
* 3) — mirrors {@link loadSlotsTolerant}: try `fromTier` first, fall back
|
|
851
|
+
* to `toTier` on a decrypt failure. `atTier === toTier` on return is the
|
|
852
|
+
* "already fully rehomed" signal `rehomeVersionRecords` skips on.
|
|
853
|
+
*/
|
|
854
|
+
private loadVersionRecordAtKeyTolerant;
|
|
855
|
+
/**
|
|
856
|
+
* Rehome ONE version's independently-held eTag — both the DESTINATION
|
|
857
|
+
* `+1`/create AND the OLD eTag's release, in that order (mirrors the slot
|
|
858
|
+
* loop's own CAS-then-release sequencing, and matches C1's two-armed
|
|
859
|
+
* resume rule: a crash after the release CAS lands but before the index
|
|
860
|
+
* row's delete completes is resumable — `already`/`loadBlobObject` still
|
|
861
|
+
* find the row at `fromTier` on a re-run, since the CALLER's metadata
|
|
862
|
+
* write hasn't happened yet). Returns the eTag the version should now
|
|
863
|
+
* point at (unchanged if legacy/missing/left `dedup`-shared) — the caller
|
|
864
|
+
* (`rehomeVersionRecords`) writes the version's metadata after this
|
|
865
|
+
* returns.
|
|
866
|
+
*
|
|
867
|
+
* If the version happened to hold the SAME eTag a slot held (the common
|
|
868
|
+
* case: publish right after put, no later overwrite), the slot loop in
|
|
869
|
+
* `runRehomeSteps` already re-`put()` the content under `toBlobDEK` —
|
|
870
|
+
* `rehomedETags` (content-addressed, so deterministic) tells us the
|
|
871
|
+
* resulting destination eTag without a redundant fetch+re-encrypt; we
|
|
872
|
+
* only need to move THIS hold's refCount onto it. Otherwise (the version
|
|
873
|
+
* outlived its slot, or was never in the slot map) this re-`put()`s the
|
|
874
|
+
* plaintext itself via `writeBlobContent` — the same content-write core
|
|
875
|
+
* `put()`/the slot loop use, no new crypto — mirroring the slot case's
|
|
876
|
+
* legacy/`dedup`-shared skip conditions.
|
|
877
|
+
*
|
|
878
|
+
* @param fromTier / @param toTier #747: same from/to split as the slot
|
|
879
|
+
* loop above — the read of the version's CURRENTLY-held eTag pins
|
|
880
|
+
* `fromTier`; the re-put and the refCount bump onto an already-rehomed
|
|
881
|
+
* (slot-loop-produced) eTag pin `toTier`.
|
|
882
|
+
*
|
|
883
|
+
* @param stamp #753/#746 spec §7 C3: when present (a marker-governed
|
|
884
|
+
* rehome), every destination `+1` this call performs — both the
|
|
885
|
+
* `already`-rehomed fast path's explicit CAS and the `writeBlobContent`
|
|
886
|
+
* re-put's own dedup-hit CAS — carries the row-scoped stamp
|
|
887
|
+
* `${opId}:${versionKey}` the caller computed, never the bare opId (see
|
|
888
|
+
* `rehomeForTier`'s `opId` doc comment).
|
|
889
|
+
* @param knownApplied #746 whole-branch review (K=8 stamp-ring blocker):
|
|
890
|
+
* this op's marker-backed confirmed-stamps set — see
|
|
891
|
+
* {@link applyStampedIncrement}. Threaded through to the
|
|
892
|
+
* `writeBlobContent` re-put's own dedup-hit CAS too.
|
|
893
|
+
*/
|
|
894
|
+
private resolveRehomedVersionETag;
|
|
895
|
+
/**
|
|
896
|
+
* CAS retry loop for an arbitrary BlobObject mutation. Used only by
|
|
897
|
+
* `migrate()`, which is legacy-only by definition — a legacy object is
|
|
898
|
+
* always flat-keyed — so the tier is pinned to `0` explicitly rather than
|
|
899
|
+
* left to `loadBlobObject`/`writeBlobObject`'s independent `ownerTier()`
|
|
900
|
+
* defaults, which could diverge on an elevated owner and re-key the
|
|
901
|
+
* envelope under the elevated tier DEK while chunks stay flat (#747 review).
|
|
902
|
+
*/
|
|
903
|
+
private casUpdateBlobObject;
|
|
904
|
+
/**
|
|
905
|
+
* Migrate this record's LEGACY blobs (no `_cek`, chunks under the shared
|
|
906
|
+
* `_blob` DEK) to per-blob content CEKs so they become crypto-shreddable.
|
|
907
|
+
* Returns the eTags migrated vs. already-erasable.
|
|
908
|
+
*
|
|
909
|
+
* **Explicit maintenance pass** (mirrors the record-CEK migration posture):
|
|
910
|
+
* re-encrypts the existing compressed chunks IN PLACE under a fresh content
|
|
911
|
+
* CEK — preserving the eTag, chunkCount, chunkSize, and compression — then
|
|
912
|
+
* flips the `_cek` discriminant. Crash-safe + idempotent via `_cekPending`:
|
|
913
|
+
* 1. persist the wrapped content CEK in `_cekPending` (readers ignore it →
|
|
914
|
+
* the blob stays readable under the `_blob` DEK; the key survives a crash);
|
|
915
|
+
* 2. re-encrypt each chunk under the content CEK (a resume reads an
|
|
916
|
+
* already-migrated chunk under the content CEK, else under the `_blob` DEK);
|
|
917
|
+
* 3. promote `_cekPending` → `_cek` (atomic flip). Reads now use the CEK.
|
|
918
|
+
* A re-run after a crash resumes from whichever phase was reached.
|
|
919
|
+
*
|
|
920
|
+
* Dedup-safe: migrating a shared blob (refCount > 1) re-keys it for every
|
|
921
|
+
* referencer at once; a non-erasable collection still reads it (it unwraps
|
|
922
|
+
* `_cek` under the `_blob` DEK it holds).
|
|
923
|
+
*/
|
|
924
|
+
migrate(): Promise<{
|
|
925
|
+
migrated: string[];
|
|
926
|
+
alreadyErasable: string[];
|
|
927
|
+
}>;
|
|
928
|
+
private writeChunk;
|
|
929
|
+
private readChunk;
|
|
930
|
+
/** #752: '::' is the version-key separator (`versionKey`) — a recordId/slotName/label
|
|
931
|
+
* containing it makes the `{recordId}::` prefix scans (listVersions / rehomeVersionRecords /
|
|
932
|
+
* collectVersionHolds) match ACROSS records, which escalated from mis-read to destructive
|
|
933
|
+
* with #750's shred path. Also refused: a part that starts or ends with ':' — otherwise a
|
|
934
|
+
* boundary colon re-segments the key (recordId `"a:"` + slotName `"slot"` yields
|
|
935
|
+
* `"a:::slot::label"`, which starts with `"a::"` and prefix-matches record `"a"`'s rows).
|
|
936
|
+
* With both rules, every '::' in a stored key is exactly a component separator — the grammar
|
|
937
|
+
* is unambiguous by construction. Refused at the write surface only: legacy '::' data stays
|
|
938
|
+
* readable/sheddable. */
|
|
939
|
+
private assertKeyPartSafe;
|
|
940
|
+
/** #752: `recordId`/`slotName`/`label` must not contain '::' — see `assertKeyPartSafe`. */
|
|
941
|
+
private versionKey;
|
|
942
|
+
/**
|
|
943
|
+
* @param tier #724 Arc 10 Task 2: explicit tier to resolve the version
|
|
944
|
+
* record's collection DEK at — `getDEK(dekKey(this.collection, tier))`,
|
|
945
|
+
* mirroring `loadSlots`'s `tier` param. Omitted → resolves via
|
|
946
|
+
* `ownerTier()` (the record's CURRENT live tier); `rehomeForTier`'s own
|
|
947
|
+
* reads pin `fromTier`/`toTier` explicitly instead (see `ownerTier()`'s
|
|
948
|
+
* doc comment for why the default would be wrong mid-move).
|
|
949
|
+
*/
|
|
950
|
+
private loadVersionRecord;
|
|
951
|
+
/** @param tier See {@link loadVersionRecord}'s `tier` param — same resolution. */
|
|
952
|
+
private writeVersionRecord;
|
|
953
|
+
/**
|
|
954
|
+
* `writeVersionRecord`'s body, addressed by an explicit raw store key
|
|
955
|
+
* instead of `slotName`+`label` — used by `rehomeVersionRecords` (#724
|
|
956
|
+
* Arc 10 Task 2), which already has the key from its raw `store.list()`
|
|
957
|
+
* scan across ALL of this record's version slots.
|
|
958
|
+
*/
|
|
959
|
+
private writeVersionRecordAtKey;
|
|
960
|
+
private deleteVersionRecord;
|
|
961
|
+
private effectiveChunkSize;
|
|
962
|
+
/**
|
|
963
|
+
* #747/#749 whole-branch review I1: when `loadBlobObject`'s tier-scoped open
|
|
964
|
+
* fell through to the flat retry while a CLEARED higher-tier view (#749)
|
|
965
|
+
* was reading (`this.clearedTier > 0`, `result.atTier === 0`), the
|
|
966
|
+
* `_blob_index` row that "won" the read is not necessarily the one this
|
|
967
|
+
* handle's `assertTierAccess` grant vouches for. Chunk AAD
|
|
968
|
+
* (`{eTag}:{index}:{count}`) is attacker-computable, and a legacy
|
|
969
|
+
* (`_cek`-less) object has no wrapped content CEK to unwrap under a key
|
|
970
|
+
* the attacker doesn't hold — so ANY flat `_blob` DEK holder with store
|
|
971
|
+
* write access can plant a `_cek`-less forgery at `_blob_index/{eTag}`
|
|
972
|
+
* (this elevated blob's own address) whose chunks are their own flat
|
|
973
|
+
* bytes, and it will decrypt cleanly under the flat DEK the fallback
|
|
974
|
+
* already tries.
|
|
975
|
+
*
|
|
976
|
+
* `verifyFlatETag`, when set, is the eTag the CALLER originally asked
|
|
977
|
+
* for (the slot/version's `.eTag` — never `blob.eTag`, which is
|
|
978
|
+
* attacker-controlled content pulled from the same forged row and would
|
|
979
|
+
* make the check tautological). After assembling the plaintext, we
|
|
980
|
+
* recompute the SAME content address every write path mints
|
|
981
|
+
* (`hmacSha256Hex(flatBlobDEK, plaintext)` — `writeBlobContent`'s Step 1,
|
|
982
|
+
* unconditional on `_cek`) and compare it to that requested eTag. A
|
|
983
|
+
* forged row can produce valid ciphertext under the flat DEK, but can't
|
|
984
|
+
* produce plaintext that re-hashes to an address it doesn't control.
|
|
985
|
+
*
|
|
986
|
+
* Both legitimate flat-fallback classes — a `dedup`-policy shared object
|
|
987
|
+
* (#741) and a legacy `_cek`-less object (#724 I1) — were minted this
|
|
988
|
+
* same way, so an honest read's recomputed hash always matches and this
|
|
989
|
+
* is a no-op for them.
|
|
990
|
+
*/
|
|
991
|
+
private fetchAllChunks;
|
|
992
|
+
/**
|
|
993
|
+
* #747/#749 review I1: the eTag to pass as `fetchAllChunks`'s `verifyFlatETag` — set
|
|
994
|
+
* only when `loadBlobObject` fell through to the flat retry
|
|
995
|
+
* (`resolvedAtTier === 0`) on a CLEARED higher-tier view
|
|
996
|
+
* (`this.clearedTier > 0`). Every ordinary (non-cleared) call reaching
|
|
997
|
+
* a content-fetch site already has `ownerTier() === 0` (elevated records
|
|
998
|
+
* are hidden by `ownerRecordElevated()` before this point), so
|
|
999
|
+
* `loadBlobObject` never even attempts the tier branch for them — no
|
|
1000
|
+
* fallback occurred, nothing to verify.
|
|
1001
|
+
*/
|
|
1002
|
+
private flatFallbackVerifyETag;
|
|
1003
|
+
/**
|
|
1004
|
+
* Upload bytes and attach them to this record under `slotName`.
|
|
1005
|
+
*
|
|
1006
|
+
* 1. Computes `eTag = HMAC-SHA-256(blobDEK, plaintext)` for keyed content-addressing.
|
|
1007
|
+
* 2. Auto-detects MIME type from magic bytes if not provided.
|
|
1008
|
+
* 3. If a blob with this eTag already exists, skips chunk upload (deduplication)
|
|
1009
|
+
* and CAS-increments refCount.
|
|
1010
|
+
* 4. Otherwise: compresses → splits into chunks → encrypts each chunk with
|
|
1011
|
+
* AAD binding → writes `_blob_chunks` → writes `BlobObject` to `_blob_index`.
|
|
1012
|
+
* 5. CAS-updates the slot metadata in `_blob_slots_{collection}`.
|
|
1013
|
+
* If overwriting an existing slot, decrements the old eTag's refCount.
|
|
1014
|
+
*/
|
|
1015
|
+
put(slotName: string, data: Uint8Array, opts?: BlobPutOptions): Promise<void>;
|
|
1016
|
+
/**
|
|
1017
|
+
* The slot-attachment core of `put()` (Step 7 — CAS the slot metadata),
|
|
1018
|
+
* parameterized by which `_blob` DEK to hash the eTag and wrap the
|
|
1019
|
+
* content CEK under. Steps 1-6 (hash/dedup/compress/chunk/index-write)
|
|
1020
|
+
* are `writeBlobContent` (#724 Arc 10 Task 2 extraction, so `rehomeForTier`
|
|
1021
|
+
* can reuse them for a version-held eTag without touching the slot map).
|
|
1022
|
+
* `put()` always passes this record's own OWNER-TIER blob DEK (#724 Arc
|
|
1023
|
+
* 10 correction) — `dekKey(BLOB_COLLECTION, 0)` for a tier-0 record.
|
|
1024
|
+
*
|
|
1025
|
+
* `rehomeForTier` is the other caller: on every tier move it re-`put()`s
|
|
1026
|
+
* each owned blob's plaintext under the `toTier`-scoped DEK — solo and
|
|
1027
|
+
* shared-isolate alike — so the moved copy gets a private, tier-scoped
|
|
1028
|
+
* eTag and `_cek` wrap from the moment it's written. The move never
|
|
1029
|
+
* routes through public `put()` under the wrong key, and this method
|
|
1030
|
+
* adds no new raw `_cek`/`_iv`/`_data` access (identical bodies, just
|
|
1031
|
+
* parameterized).
|
|
1032
|
+
*
|
|
1033
|
+
* @param slotsTier #724 Arc 10 Task 4: pins the slot-map CAS update
|
|
1034
|
+
* (Step 7) to a specific tier instead of the caller's `ownerTier()`
|
|
1035
|
+
* default — `rehomeForTier` passes `fromTier`, since mid-move the slot
|
|
1036
|
+
* map is still physically there (see `ownerTier()`'s doc comment). The
|
|
1037
|
+
* old eTag being replaced lives wherever the slot map itself is
|
|
1038
|
+
* physically keyed, so its release (#747, below) reuses this SAME value
|
|
1039
|
+
* rather than a separate param.
|
|
1040
|
+
* @param contentTier #747: pins the `_blob_index` read/write inside
|
|
1041
|
+
* `writeBlobContent` to a specific tier — `rehomeForTier` passes `toTier`
|
|
1042
|
+
* (matching `blobDEK`, already resolved at `toTier`), since mid-move
|
|
1043
|
+
* `ownerTier()` already reads `toTier` too but this is more direct.
|
|
1044
|
+
* Omitted → `ownerTier()`, correct for `put()`'s ordinary (non-rehome) call.
|
|
1045
|
+
* @param opId #753/#746 spec §7 C3: `rehomeForTier`'s governing marker
|
|
1046
|
+
* op-stamp identity (omitted → `undefined`, `put()`'s ordinary call and
|
|
1047
|
+
* every pre-existing caller, byte-identical unstamped behavior). When
|
|
1048
|
+
* present, the ROW-SCOPED stamp `${opId}:${slotName}` — never the bare
|
|
1049
|
+
* opId — governs BOTH this call's destination `+1` (via
|
|
1050
|
+
* `writeBlobContent`'s dedup-hit CAS) and its old-eTag release below: two
|
|
1051
|
+
* different `BlobObject`s (destination vs. source), so the shared stamp
|
|
1052
|
+
* string collides with neither, and a resumed re-put of THIS slot can
|
|
1053
|
+
* neither double-apply the `+1` nor double-release the old object. Two
|
|
1054
|
+
* DIFFERENT slots on this record legitimately re-putting the SAME
|
|
1055
|
+
* destination eTag each get their OWN stamp (their own `slotName`) — the
|
|
1056
|
+
* row scope is what lets N slots' `+1`s all land on one destination
|
|
1057
|
+
* object instead of the first silently absorbing the rest.
|
|
1058
|
+
*/
|
|
1059
|
+
private putUnderDEK;
|
|
1060
|
+
/**
|
|
1061
|
+
* C10 (#753/#746 spec §7): under a marker-governed (`stamp` present)
|
|
1062
|
+
* rehome, a failed old-eTag release must not be silently swallowed — it
|
|
1063
|
+
* is the crypto-shred of the FROM-tier object, and swallowing it during a
|
|
1064
|
+
* documented-exactly-once op is the bug C10 closes. Propagating keeps the
|
|
1065
|
+
* governing `_blob_intent` marker alive (never deleted) so a later resume
|
|
1066
|
+
* retries it, rather than completing the op over a residue that never
|
|
1067
|
+
* surfaces. Unstamped (ordinary `put()`/`delete()`) calls keep the
|
|
1068
|
+
* pre-#753 best-effort posture unchanged — a missed decrement there is
|
|
1069
|
+
* reconciled by a later pass, same as always.
|
|
1070
|
+
*/
|
|
1071
|
+
private releaseOldETagAfterMove;
|
|
1072
|
+
/**
|
|
1073
|
+
* Durably confirm a rehome row-stamp's `+1` in the governing marker —
|
|
1074
|
+
* #746 whole-branch review (K=8 stamp-ring blocker). No-op when there is
|
|
1075
|
+
* no marker to record against (a direct `rehomeForTier(..., opId)` call
|
|
1076
|
+
* with no real `_blob_intent` row, e.g. this suite's Task-1 tests —
|
|
1077
|
+
* byte-identical ring-only behavior for that path, unchanged). NOT
|
|
1078
|
+
* swallowed on failure (mirrors C10): a failed confirmation write must
|
|
1079
|
+
* keep the governing marker's op from completing silently over an
|
|
1080
|
+
* unconfirmed increment, not be dropped.
|
|
1081
|
+
*/
|
|
1082
|
+
private recordAppliedRehomeStamp;
|
|
1083
|
+
/**
|
|
1084
|
+
* Apply ONE destination `+1` under a row-scoped rehome stamp, made
|
|
1085
|
+
* idempotent INDEPENDENTLY of `BlobObject.lastOps`'s bounded ring (#746
|
|
1086
|
+
* whole-branch review — see `BlobIntent.appliedStamps`'s doc comment for
|
|
1087
|
+
* the full hazard). `knownApplied` — this op's OWN marker-backed,
|
|
1088
|
+
* unbounded record of confirmed stamps, read ONCE at the top of
|
|
1089
|
+
* `runRehomeSteps` — is consulted FIRST: a hit means this exact row's
|
|
1090
|
+
* `+1` was already confirmed on a PRIOR run, so the CAS is skipped
|
|
1091
|
+
* entirely regardless of whether the shared destination's ring has since
|
|
1092
|
+
* evicted it (another 8+ rows — from THIS record's own fan-out, or from
|
|
1093
|
+
* unrelated CONCURRENT rehomes converging on the same destination —
|
|
1094
|
+
* could have pushed it out). A miss falls through to the existing
|
|
1095
|
+
* ring-based stamped CAS (correct and sufficient for the overwhelming
|
|
1096
|
+
* majority of resumes — same-session or shortly-after), and on success
|
|
1097
|
+
* (freshly applied OR the ring itself already had it) records the stamp
|
|
1098
|
+
* into the marker so THIS row is never re-examined again by a later
|
|
1099
|
+
* resume, no matter how much unrelated activity lands on the destination
|
|
1100
|
+
* in between.
|
|
1101
|
+
*/
|
|
1102
|
+
private applyStampedIncrement;
|
|
1103
|
+
/**
|
|
1104
|
+
* The chunk/CEK/dedup core of `put()` (former Steps 1-6 of `putUnderDEK`,
|
|
1105
|
+
* extracted #724 Arc 10 Task 2 so `rehomeVersionETag` can write a
|
|
1106
|
+
* version-held blob's content under a target tier's DEK WITHOUT touching
|
|
1107
|
+
* the slot map — `putUnderDEK`'s remaining Step 7 is slot-specific).
|
|
1108
|
+
* Content-addressed and dedup-aware exactly like `put()`: hashing the same
|
|
1109
|
+
* plaintext under the same `blobDEK` twice always lands on the same eTag.
|
|
1110
|
+
*
|
|
1111
|
+
* @param tier #747: the index-envelope tier to read/write at (see
|
|
1112
|
+
* {@link loadBlobObject}'s `tier` param) — `putUnderDEK`'s `contentTier`,
|
|
1113
|
+
* matching whichever tier `blobDEK` itself was resolved at. Omitted →
|
|
1114
|
+
* `ownerTier()`, correct for `put()`'s ordinary (non-rehome) call.
|
|
1115
|
+
* @param incrementStamp #753/#746 spec §7 C3: when present, a dedup hit at
|
|
1116
|
+
* Step 3 applies its `+1` via {@link casUpdateRefCountStamped} under this
|
|
1117
|
+
* stamp instead of the plain {@link casUpdateRefCount} — the row-scoped
|
|
1118
|
+
* identity `putUnderDEK`/`rehomeVersionETag` compute so a resumed re-put's
|
|
1119
|
+
* destination increment is idempotent per row. Omitted (every call site
|
|
1120
|
+
* before this arc) → byte-identical unstamped behavior.
|
|
1121
|
+
*
|
|
1122
|
+
* ALSO seeds `lastOps: [incrementStamp]` on the fresh-object create path
|
|
1123
|
+
* (Step 6, review finding on #746 C3): a solo blob has no pre-existing
|
|
1124
|
+
* destination object for a resumed re-put to dedup-hit against a stamp on
|
|
1125
|
+
* — the FIRST attempt's create is itself the only write, and a crash
|
|
1126
|
+
* after it lands but before the slot/version CAS leaves the object
|
|
1127
|
+
* present at refCount 1 with NO stamp. An unseeded resume then
|
|
1128
|
+
* re-executes Step 3, finds that same object, and — finding no matching
|
|
1129
|
+
* stamp — applies a SECOND, spurious `+1` (1 → 2), the exact over-count
|
|
1130
|
+
* hazard this stamping arc exists to close. Seeding the ring at create
|
|
1131
|
+
* time closes that: the resumed re-put's Step 3 dedup-hit against THIS
|
|
1132
|
+
* object finds its own stamp already present and skips, matching the
|
|
1133
|
+
* dedup-hit branch's behavior exactly.
|
|
1134
|
+
*/
|
|
1135
|
+
private writeBlobContent;
|
|
1136
|
+
/**
|
|
1137
|
+
* Fetch all bytes for the named slot.
|
|
1138
|
+
* Returns `null` if the slot does not exist.
|
|
1139
|
+
* Throws `NotFoundError` if the index entry exists but a chunk is missing.
|
|
1140
|
+
*/
|
|
1141
|
+
get(slotName: string): Promise<Uint8Array | null>;
|
|
1142
|
+
/**
|
|
1143
|
+
* A URL to fetch an `external` slot's object directly — presigned
|
|
1144
|
+
* (time-limited) or public, per the projection. Returns `null` if the slot
|
|
1145
|
+
* does not exist. Throws for a non-external slot (use `get()`/`response()`).
|
|
1146
|
+
*/
|
|
1147
|
+
url(slotName: string, opts?: {
|
|
1148
|
+
expiresInSeconds?: number;
|
|
1149
|
+
}): Promise<string | null>;
|
|
1150
|
+
/**
|
|
1151
|
+
* Build the backlink stamped onto an external object's metadata — the
|
|
1152
|
+
* self-describing "secondary store" reference back to this record. See
|
|
1153
|
+
* {@link BlobFieldPolicy.backlink}. Returns the `userMeta` to attach and, for
|
|
1154
|
+
* `opaque-token`, the `token` to record on the slot.
|
|
1155
|
+
*/
|
|
1156
|
+
private buildBacklink;
|
|
1157
|
+
/**
|
|
1158
|
+
* Adopt an EXISTING object in the projection into this slot **without
|
|
1159
|
+
* re-uploading** — used by import/bootstrap to anchor objects already in the
|
|
1160
|
+
* bucket. Writes the external slot record (the catalog entry).
|
|
1161
|
+
*/
|
|
1162
|
+
adoptExternal(slotName: string, ref: {
|
|
1163
|
+
key: string;
|
|
1164
|
+
size?: number;
|
|
1165
|
+
contentType?: string;
|
|
1166
|
+
public?: boolean;
|
|
1167
|
+
backlink?: string;
|
|
1168
|
+
meta?: Record<string, unknown>;
|
|
1169
|
+
}): Promise<void>;
|
|
1170
|
+
/**
|
|
1171
|
+
* Merge derived metadata (video `duration`, image `width`/`height`, arbitrary
|
|
1172
|
+
* metatags) into an external slot's secondary metadata store. Typically called
|
|
1173
|
+
* from an AWS-side processing callback (MediaConvert / ffprobe / Rekognition)
|
|
1174
|
+
* once it has probed the object. No-op for a missing or non-external slot.
|
|
1175
|
+
*/
|
|
1176
|
+
setExternalMeta(slotName: string, meta: Record<string, unknown>): Promise<void>;
|
|
1177
|
+
/**
|
|
1178
|
+
* Read an external slot's synced derived metadata (the secondary store).
|
|
1179
|
+
* Returns `null` for a missing or non-external slot, `{}` if none synced yet.
|
|
1180
|
+
*/
|
|
1181
|
+
externalMeta(slotName: string): Promise<Record<string, unknown> | null>;
|
|
1182
|
+
/**
|
|
1183
|
+
* List all slot entries for this record.
|
|
1184
|
+
* Returns metadata only — no chunk data is loaded.
|
|
1185
|
+
*/
|
|
1186
|
+
list(): Promise<SlotInfo[]>;
|
|
1187
|
+
/**
|
|
1188
|
+
* Delete the named slot from this record.
|
|
1189
|
+
* Decrements refCount on the blob. Chunks are GC'd by `vault.blobGC()`.
|
|
1190
|
+
*/
|
|
1191
|
+
delete(slotName: string): Promise<void>;
|
|
1192
|
+
/**
|
|
1193
|
+
* Return a native `Response` whose body streams the decrypted,
|
|
1194
|
+
* decompressed blob bytes with full HTTP metadata headers.
|
|
1195
|
+
*
|
|
1196
|
+
* Note: implementation is buffered — all chunks are loaded into
|
|
1197
|
+
* memory before being enqueued. True streaming deferred to.
|
|
1198
|
+
*
|
|
1199
|
+
* Returns `null` if the slot does not exist.
|
|
1200
|
+
*/
|
|
1201
|
+
response(slotName: string, opts?: BlobResponseOptions): Promise<Response | null>;
|
|
1202
|
+
/**
|
|
1203
|
+
* Decrypt the slot and wrap the bytes in a browser ObjectURL ready
|
|
1204
|
+
* to feed into `<img src>`, `<a href>`, etc. The caller MUST call
|
|
1205
|
+
* `revoke()` when the URL is no longer needed — otherwise the URL
|
|
1206
|
+
* (and the underlying decrypted Blob) are pinned for the lifetime
|
|
1207
|
+
* of the document, which leaks memory in long-lived pages.
|
|
1208
|
+
*
|
|
1209
|
+
* Returns `null` when the slot does not exist.
|
|
1210
|
+
*
|
|
1211
|
+
* Throws when `URL.createObjectURL` is unavailable in the host
|
|
1212
|
+
* environment (Node without DOM, restricted workers). Framework
|
|
1213
|
+
* adapters — `useBlobURL` in `@noy-db/in-vue`, etc. — guard against
|
|
1214
|
+
* this for SSR contexts and stay at `null` instead of propagating.
|
|
1215
|
+
*/
|
|
1216
|
+
objectURL(slotName: string, opts?: {
|
|
1217
|
+
mimeType?: string;
|
|
1218
|
+
}): Promise<{
|
|
1219
|
+
url: string;
|
|
1220
|
+
revoke: () => void;
|
|
1221
|
+
} | null>;
|
|
1222
|
+
/**
|
|
1223
|
+
* Publish the current slot content as a named version snapshot.
|
|
1224
|
+
*
|
|
1225
|
+
* The published version holds an independent refCount reference to
|
|
1226
|
+
* the blob. Even if the slot is later overwritten or deleted, the
|
|
1227
|
+
* published version keeps the blob data alive.
|
|
1228
|
+
*
|
|
1229
|
+
* Publishing with an existing label overwrites it — if the eTags differ,
|
|
1230
|
+
* refCounts are adjusted accordingly.
|
|
1231
|
+
*
|
|
1232
|
+
* #724 Arc 10 Task 2 (C4): the version record is written under the owning
|
|
1233
|
+
* record's CURRENT tier — a version published on a tier-N record is keyed
|
|
1234
|
+
* at tier N, mirroring `put()`'s owner-tier resolution (Task 1). The
|
|
1235
|
+
* refCount hold it takes lands on `slot.eTag`, which is already
|
|
1236
|
+
* tier-scoped (born there by `put()`, or moved there by a prior
|
|
1237
|
+
* `rehomeForTier`) — no separate tier-scoping needed for the content side.
|
|
1238
|
+
*/
|
|
1239
|
+
publish(slotName: string, label: string): Promise<void>;
|
|
1240
|
+
/**
|
|
1241
|
+
* Fetch bytes for a published version.
|
|
1242
|
+
* Returns `null` if the version does not exist.
|
|
1243
|
+
*/
|
|
1244
|
+
getVersion(slotName: string, label: string): Promise<Uint8Array | null>;
|
|
1245
|
+
/**
|
|
1246
|
+
* List all published versions for a slot.
|
|
1247
|
+
*/
|
|
1248
|
+
listVersions(slotName: string): Promise<VersionRecord[]>;
|
|
1249
|
+
/**
|
|
1250
|
+
* Delete a published version. Decrements refCount on its blob.
|
|
1251
|
+
*/
|
|
1252
|
+
deleteVersion(slotName: string, label: string): Promise<void>;
|
|
1253
|
+
/**
|
|
1254
|
+
* Return a `Response` for a published version — same as `response()`
|
|
1255
|
+
* but reads from the version record's eTag instead of the current slot.
|
|
1256
|
+
*/
|
|
1257
|
+
responseVersion(slotName: string, label: string, opts?: BlobResponseOptions): Promise<Response | null>;
|
|
1258
|
+
/**
|
|
1259
|
+
* Return the `BlobObject` metadata for the named slot.
|
|
1260
|
+
* Returns `null` if the slot or blob does not exist.
|
|
1261
|
+
*/
|
|
1262
|
+
blobInfo(slotName: string): Promise<BlobObject | null>;
|
|
1263
|
+
/**
|
|
1264
|
+
* Generate a presigned URL for direct client download of the blob's
|
|
1265
|
+
* ciphertext. Only works when the blob store supports `presignUrl`.
|
|
1266
|
+
*
|
|
1267
|
+
* **Important:** The URL returns encrypted data. The caller must
|
|
1268
|
+
* decrypt client-side using `decryptResponse()` or a service worker.
|
|
1269
|
+
*
|
|
1270
|
+
* Returns `null` if the slot doesn't exist or the store doesn't support presigning.
|
|
1271
|
+
*/
|
|
1272
|
+
presignedUrl(slotName: string, expiresInSeconds?: number): Promise<string | null>;
|
|
1273
|
+
/**
|
|
1274
|
+
* Decrypt a ciphertext Response (e.g. from a presigned URL fetch)
|
|
1275
|
+
* back into a plaintext Response with correct headers.
|
|
1276
|
+
*
|
|
1277
|
+
* Usage with service worker or client-side fetch:
|
|
1278
|
+
* ```ts
|
|
1279
|
+
* const url = await blobs.presignedUrl('invoice.pdf')
|
|
1280
|
+
* const cipherResponse = await fetch(url)
|
|
1281
|
+
* const plainResponse = await blobs.decryptResponse('invoice.pdf', cipherResponse)
|
|
1282
|
+
* ```
|
|
1283
|
+
*/
|
|
1284
|
+
decryptResponse(slotName: string, cipherResponse: Response): Promise<Response | null>;
|
|
1285
|
+
private buildResponse;
|
|
1286
|
+
}
|