@noy-db/hub 0.3.0-pre.12 → 0.3.0-pre.13
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 +4 -4
- package/dist/api-ZGS6LCOF.js +20 -0
- package/dist/as/index.js +11 -11
- package/dist/attestation/index.js +18 -18
- package/dist/{backup-2WVBIVXW.js → backup-BJ57IKAO.js} +28 -11
- package/dist/backup-BJ57IKAO.js.map +1 -0
- package/dist/blobs/index.js +12 -10
- package/dist/blobs/index.js.map +1 -1
- package/dist/broker/index.js +12 -12
- 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 +22 -22
- package/dist/{chunk-ZL6PRULX.js → chunk-2NVOWNI3.js} +4 -4
- package/dist/{chunk-WEHIQYQH.js → chunk-3B5VVCNY.js} +2 -2
- package/dist/{chunk-FF7S3XDW.js → chunk-3LQ2YKO4.js} +2 -2
- package/dist/{chunk-NAR6IDKH.js → chunk-3QCRBHCY.js} +2 -2
- package/dist/{chunk-SXPCZ6LL.js → chunk-454JXE57.js} +3 -3
- package/dist/{chunk-R3NHNVS5.js → chunk-4CTHCN4J.js} +12 -10
- package/dist/{chunk-R3NHNVS5.js.map → chunk-4CTHCN4J.js.map} +1 -1
- package/dist/{chunk-JGUZMC3I.js → chunk-4JBYV75E.js} +5 -5
- package/dist/{chunk-RXTMLYJS.js → chunk-4NXKCLLQ.js} +2 -2
- package/dist/{chunk-GXLZXD2W.js → chunk-4VNQOLML.js} +2 -2
- package/dist/{chunk-45QPICLE.js → chunk-5M5DVGV7.js} +2 -2
- package/dist/{chunk-EHW5KTTA.js → chunk-5O3XF4DV.js} +4 -4
- package/dist/chunk-5O3XF4DV.js.map +1 -0
- package/dist/{chunk-S2OWPVSO.js → chunk-5YOLBEQ6.js} +2 -2
- package/dist/{chunk-BDEMZD4F.js → chunk-6CRIV7DE.js} +2 -2
- package/dist/{chunk-VCUQR6ZL.js → chunk-6JTIAGHD.js} +3 -3
- package/dist/{chunk-K2DLLK34.js → chunk-6QTNZJBS.js} +3 -3
- package/dist/{chunk-UMC5QZTX.js → chunk-6T2SCQRU.js} +4 -4
- package/dist/{chunk-J3JIYFYL.js → chunk-7DSTRQIJ.js} +2 -2
- package/dist/{chunk-3QSOFZQB.js → chunk-AUSTCW2X.js} +10 -10
- package/dist/{chunk-PN5332SU.js → chunk-B3HJYUOF.js} +2 -2
- package/dist/{chunk-DIB2BOIH.js → chunk-BDVFPG6Y.js} +5 -5
- package/dist/{chunk-FZCGIJEJ.js → chunk-BIOUI4HL.js} +50 -1
- package/dist/chunk-BIOUI4HL.js.map +1 -0
- package/dist/{chunk-FYNE4WLC.js → chunk-CAF6WOK7.js} +2 -2
- package/dist/{chunk-AKEOHKMT.js → chunk-CDUQTA3Z.js} +110 -11
- package/dist/chunk-CDUQTA3Z.js.map +1 -0
- package/dist/{chunk-37WOJQWY.js → chunk-CIE2BASH.js} +2 -2
- package/dist/{chunk-BLUT46UP.js → chunk-CRI4OUV4.js} +2 -2
- package/dist/{chunk-Y5TWPBNW.js → chunk-DLG74CNB.js} +4 -4
- package/dist/{chunk-HIOLCOK3.js → chunk-E5ZQT5KX.js} +2 -2
- package/dist/{chunk-IQIVD7TP.js → chunk-EQO2UVP4.js} +6 -6
- package/dist/{chunk-US34HTOI.js → chunk-ERJ7FU55.js} +3 -3
- package/dist/{chunk-S7TAPIRS.js → chunk-EVVGJDRQ.js} +3 -3
- package/dist/{chunk-EXGDL2UQ.js → chunk-EVX47VBM.js} +2 -2
- package/dist/{chunk-NT2ZO4KI.js → chunk-EXK7QRWF.js} +5 -5
- package/dist/{chunk-7QLY64AD.js → chunk-EYZ6IQ6X.js} +5 -5
- package/dist/{chunk-QF5LGMSV.js → chunk-F64IRYG3.js} +2 -2
- package/dist/{chunk-PH7G7ZI7.js → chunk-FHS2HQSH.js} +5 -5
- package/dist/{chunk-HG76BZ6G.js → chunk-FM3G3NOY.js} +27 -9
- package/dist/chunk-FM3G3NOY.js.map +1 -0
- package/dist/{chunk-ZHOJOT6S.js → chunk-FUG4SFN3.js} +2 -2
- package/dist/{chunk-JRKE5MAZ.js → chunk-GKEWXIV5.js} +2 -2
- package/dist/{chunk-6MA575R5.js → chunk-GTGPO5KW.js} +5 -5
- package/dist/{chunk-XS6DLN67.js → chunk-HB3RFQSC.js} +3 -3
- package/dist/{chunk-VXZNSPJM.js → chunk-HDMEGAQE.js} +5 -5
- package/dist/chunk-HDQIIUPH.js +135 -0
- package/dist/chunk-HDQIIUPH.js.map +1 -0
- package/dist/{chunk-DJ7MRXNA.js → chunk-HTJQYHZP.js} +2 -2
- package/dist/{chunk-NRYNRSGV.js → chunk-I6GALP6E.js} +6 -6
- package/dist/{chunk-GL3JV5EV.js → chunk-IL6POWCW.js} +6 -6
- package/dist/{chunk-NEYKOESM.js → chunk-IU6SNYX6.js} +5 -5
- package/dist/{chunk-CCIR2OJH.js → chunk-J2ZX2XUV.js} +5 -5
- package/dist/{chunk-F3LGBRSV.js → chunk-JIF24JPM.js} +57 -15
- package/dist/chunk-JIF24JPM.js.map +1 -0
- package/dist/{chunk-NM3IFKBL.js → chunk-JKJOGPZN.js} +2 -2
- package/dist/{chunk-JC75UBMT.js → chunk-JNAI2HN2.js} +1 -1
- package/dist/{chunk-JC75UBMT.js.map → chunk-JNAI2HN2.js.map} +1 -1
- package/dist/{chunk-TVS6BUUR.js → chunk-JZUV47FZ.js} +2 -2
- package/dist/{chunk-5HNX4OD4.js → chunk-K5IMOGHB.js} +2 -2
- package/dist/{chunk-XJ47GS53.js → chunk-KSKBRKGJ.js} +3 -3
- package/dist/{chunk-INBQ43DI.js → chunk-LASZKVMO.js} +3 -3
- package/dist/{chunk-EVHBK7BN.js → chunk-LXEXBTKL.js} +4 -4
- package/dist/{chunk-6S7ENMRE.js → chunk-M4CV6BRT.js} +2 -2
- package/dist/{chunk-AAIIDAUC.js → chunk-MEFJPTZ4.js} +3 -3
- package/dist/{chunk-WHQHTNT7.js → chunk-MV43JSJF.js} +4 -4
- package/dist/{chunk-F44XWXOA.js → chunk-NJ4EOKMB.js} +4 -4
- package/dist/{chunk-ILF5GARW.js → chunk-NR5LT5RY.js} +7 -7
- package/dist/{chunk-TBNF5DV5.js → chunk-NWSGI5C7.js} +3 -3
- package/dist/{chunk-BDPAVYGJ.js → chunk-OSDB5WW3.js} +92 -15
- 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-EIZ4YOG2.js → chunk-Q5VNKNE5.js} +3 -3
- package/dist/{chunk-TVOHSPVK.js → chunk-QLWMEXCT.js} +2 -2
- package/dist/{chunk-7GAXFU2O.js → chunk-QRB7NAOJ.js} +2 -2
- package/dist/{chunk-X6Y5MXTH.js → chunk-R4ROFEYC.js} +2 -2
- package/dist/{chunk-4BQXMCE5.js → chunk-RCVJZMFE.js} +4 -4
- package/dist/{chunk-QG5RQQBO.js → chunk-RIX4V2TB.js} +3 -3
- package/dist/{chunk-SAL5X5OK.js → chunk-RYCTDFUX.js} +2 -2
- package/dist/{chunk-CXC3JLAQ.js → chunk-RZ5SVOYR.js} +2 -2
- package/dist/{chunk-44IL5G3W.js → chunk-SLFHQTTW.js} +5 -5
- package/dist/chunk-SNZ6URZZ.js +2782 -0
- package/dist/chunk-SNZ6URZZ.js.map +1 -0
- package/dist/{chunk-2MTRJCBI.js → chunk-T2FFWNPK.js} +3 -3
- package/dist/{chunk-QYPDYN23.js → chunk-UNFPPVNI.js} +2 -2
- package/dist/{chunk-RNXJ2VO6.js → chunk-VFUPHI2Z.js} +63 -10
- package/dist/chunk-VFUPHI2Z.js.map +1 -0
- package/dist/{chunk-7ZOSHEVS.js → chunk-VLFCJYTL.js} +9 -9
- package/dist/{chunk-APHLCXVC.js → chunk-VN3DBQAU.js} +2 -2
- package/dist/{chunk-HK4XTXO4.js → chunk-VZRODIM3.js} +4 -4
- package/dist/{chunk-P2LJI6JE.js → chunk-W22IKJE2.js} +2 -2
- package/dist/{chunk-FJTWLQV3.js → chunk-X3YYQWOQ.js} +3 -3
- package/dist/{chunk-YCXKFB7J.js → chunk-X7QBD67R.js} +498 -274
- package/dist/chunk-X7QBD67R.js.map +1 -0
- package/dist/{chunk-HA6ZQWA2.js → chunk-XDYREZWE.js} +82 -10
- package/dist/chunk-XDYREZWE.js.map +1 -0
- package/dist/{chunk-HBBZWEC5.js → chunk-XWZVFISC.js} +40 -6
- package/dist/{chunk-HBBZWEC5.js.map → chunk-XWZVFISC.js.map} +1 -1
- package/dist/{chunk-SGJGWBSC.js → chunk-YFXZEAYK.js} +6 -6
- package/dist/{chunk-SIAIYP6G.js → chunk-ZAJAVEXY.js} +2 -2
- package/dist/{chunk-KKYEZCQG.js → chunk-ZICD77GM.js} +2 -2
- package/dist/{chunk-HGAB325C.js → chunk-ZJ2AK4V7.js} +2 -2
- package/dist/{chunk-HYG32HCM.js → chunk-ZUODRVHY.js} +2 -2
- package/dist/classified/index.js +5 -5
- package/dist/{classified-marker-M7K3OJPM.js → classified-marker-CZKA6ITE.js} +3 -3
- package/dist/collection-facade-TLWIPI76.js +44 -0
- package/dist/{computed-ORCGM5JE.js → computed-ZIQTYTDI.js} +3 -3
- package/dist/consent/index.js +9 -9
- package/dist/{dead-filter-OV5FGKOG.js → dead-filter-ESOBZZP5.js} +2 -2
- package/dist/delegation-W7ZV2322.js +25 -0
- package/dist/derivations/index.js +12 -12
- package/dist/derive-H2BJTLUI.js +21 -0
- package/dist/{enclave-XXFUKJC6.js → enclave-AP3I5W7O.js} +15 -9
- 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-IO2KDUWV.js → fanout-sidecar-A765THMX.js} +9 -9
- package/dist/find-N6345CNT.js +11 -0
- package/dist/forget/index.js +9 -9
- package/dist/guards/index.js +3 -3
- package/dist/history/index.js +14 -11
- package/dist/history/index.js.map +1 -1
- package/dist/i18n/index.js +14 -14
- package/dist/index.d.ts +5 -1
- package/dist/index.js +108 -89
- package/dist/index.js.map +1 -1
- package/dist/indexing/index.js +2 -2
- package/dist/issue-5OKB6I2R.js +19 -0
- package/dist/kernel/collection-config.d.ts +20 -0
- package/dist/kernel/collection.d.ts +31 -28
- package/dist/kernel/enclave/classify/verify.d.ts +3 -0
- package/dist/kernel/enclave/index.d.ts +2 -1
- package/dist/kernel/enclave/record-keys/deterministic.d.ts +1 -0
- package/dist/kernel/enclave/record-keys/lifecycle.d.ts +50 -0
- package/dist/kernel/enclave/record-keys/record-codec.d.ts +27 -0
- package/dist/kernel/errors.d.ts +74 -0
- package/dist/kernel/lazy-count.d.ts +13 -0
- package/dist/kernel/tier-visibility.d.ts +54 -0
- package/dist/kernel/types.d.ts +73 -0
- package/dist/kernel/vault.d.ts +8 -5
- package/dist/kernel/via/dispatch.d.ts +10 -0
- package/dist/{ledger-UAQKPWNM.js → ledger-GFBKVPV4.js} +11 -11
- package/dist/legacy/bundle.d.ts +1 -1
- package/dist/liberate-3VDOT4KO.js +24 -0
- package/dist/{link-set-DGYUOFVD.js → link-set-Z7Q2ASFX.js} +11 -11
- package/dist/materialized-views/index.js +18 -18
- 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-5POYLI26.js → policy-Z3RUAIY2.js} +5 -5
- package/dist/port/with/blob-strategy.d.ts +17 -0
- package/dist/portability/index.js +8 -8
- package/dist/{post-register-LB3P4XQU.js → post-register-JTH76BLY.js} +6 -6
- package/dist/{public-envelope-GOG4LUM7.js → public-envelope-B4KNWVUA.js} +4 -4
- package/dist/query/index.js +5 -5
- 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-NPVROV4D.js → reveal-DIBHLUZX.js} +7 -7
- 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-VI4FU7UH.js → seed-Q6M2IZFL.js} +11 -11
- 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-5KDS2RRP.js → store-coordination-provider-64OEZFGS.js} +3 -3
- 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 -1
- package/dist/tx/index.js +3 -3
- package/dist/util/index.js +1 -1
- package/dist/{verify-QK76NJ4G.js → verify-ZASTRNPR.js} +9 -8
- package/dist/verify-ZASTRNPR.js.map +1 -0
- package/dist/{walk-XQCBKSBW.js → walk-SVNDIZ62.js} +11 -11
- package/dist/with/index.js +11 -11
- package/dist/with-audit/forget/strategy.d.ts +22 -0
- package/dist/with-audit/tiers/index.d.ts +275 -3
- package/dist/with-audit/tiers/strategy.d.ts +5 -4
- package/dist/with-cargo/describe-extraction.d.ts +9 -1
- package/dist/with-cargo/extract-partition.d.ts +9 -1
- package/dist/with-cargo/walk-closure.d.ts +32 -3
- package/dist/with-commit/history/history.d.ts +46 -0
- package/dist/with-commit/history/ledger/store.d.ts +21 -0
- package/dist/with-commit/history/strategy.d.ts +10 -0
- package/dist/with-commit/history/time-machine.d.ts +23 -0
- package/dist/with-commit/tx/elevated-handle.d.ts +2 -1
- package/dist/with-formula/materialized-views/executor.d.ts +9 -0
- package/dist/with-formula/materialized-views/stale.d.ts +52 -1
- package/dist/with-lookup/embeddings/index.d.ts +1 -0
- package/dist/with-lookup/embeddings/vec-id.d.ts +47 -0
- package/dist/with-lookup/indexing/collection-facade.d.ts +38 -1
- package/dist/with-lookup/search/collection-facade.d.ts +40 -0
- package/dist/with-lookup/search/persisted-index-store.d.ts +82 -2
- package/dist/with-lookup/search/strategy.d.ts +4 -0
- package/dist/with-shape/blobs/blob-intent.d.ts +153 -0
- package/dist/with-shape/blobs/blob-set.d.ts +949 -5
- package/dist/withdraw-accessible-WZIEVWSR.js +28 -0
- package/package.json +3 -3
- package/dist/api-3TH2GOFQ.js +0 -20
- package/dist/backup-2WVBIVXW.js.map +0 -1
- package/dist/chunk-65VLRG3I.js +0 -54
- package/dist/chunk-65VLRG3I.js.map +0 -1
- package/dist/chunk-AKEOHKMT.js.map +0 -1
- package/dist/chunk-BDPAVYGJ.js.map +0 -1
- package/dist/chunk-CZMCOFEA.js +0 -1221
- package/dist/chunk-CZMCOFEA.js.map +0 -1
- package/dist/chunk-EHW5KTTA.js.map +0 -1
- package/dist/chunk-F3LGBRSV.js.map +0 -1
- package/dist/chunk-FZCGIJEJ.js.map +0 -1
- package/dist/chunk-HA6ZQWA2.js.map +0 -1
- package/dist/chunk-HG76BZ6G.js.map +0 -1
- package/dist/chunk-RNXJ2VO6.js.map +0 -1
- package/dist/chunk-YCXKFB7J.js.map +0 -1
- package/dist/collection-facade-DWA735G2.js +0 -39
- package/dist/delegation-YVSHMIZZ.js +0 -25
- package/dist/derive-BUO555L5.js +0 -21
- package/dist/executor-6OCCE5VM.js +0 -25
- package/dist/executor-JFVAJY42.js +0 -9
- package/dist/executor-UPSH5O3F.js +0 -9
- package/dist/export-accessible-L4A2QZA5.js +0 -23
- package/dist/extract-partition-ZHQ4RGGM.js +0 -36
- package/dist/find-ZFZDZQ2U.js +0 -11
- package/dist/issue-OG4V23SQ.js +0 -19
- package/dist/liberate-GFUQJRK5.js +0 -24
- package/dist/noydb-AKH4AMCR.js +0 -67
- package/dist/register-ZI7YI7US.js +0 -23
- package/dist/registry-DZ2T4LL7.js +0 -9
- package/dist/registry-NVWEQ2GU.js +0 -18
- package/dist/registry-SEKL74ET.js +0 -19
- package/dist/request-withdrawal-ZP3JIRVS.js +0 -31
- package/dist/reveal-NPVROV4D.js.map +0 -1
- package/dist/revoke-VF6TAJK2.js +0 -24
- package/dist/signer-DRDDCCHW.js +0 -25
- package/dist/stale-TJXFQKOJ.js +0 -14
- package/dist/storage-GR7KZRH4.js +0 -23
- package/dist/verify-QK76NJ4G.js.map +0 -1
- package/dist/withdraw-accessible-FMN4LPJZ.js +0 -28
- /package/dist/{api-3TH2GOFQ.js.map → api-ZGS6LCOF.js.map} +0 -0
- /package/dist/{chunk-ZL6PRULX.js.map → chunk-2NVOWNI3.js.map} +0 -0
- /package/dist/{chunk-WEHIQYQH.js.map → chunk-3B5VVCNY.js.map} +0 -0
- /package/dist/{chunk-FF7S3XDW.js.map → chunk-3LQ2YKO4.js.map} +0 -0
- /package/dist/{chunk-NAR6IDKH.js.map → chunk-3QCRBHCY.js.map} +0 -0
- /package/dist/{chunk-SXPCZ6LL.js.map → chunk-454JXE57.js.map} +0 -0
- /package/dist/{chunk-JGUZMC3I.js.map → chunk-4JBYV75E.js.map} +0 -0
- /package/dist/{chunk-RXTMLYJS.js.map → chunk-4NXKCLLQ.js.map} +0 -0
- /package/dist/{chunk-GXLZXD2W.js.map → chunk-4VNQOLML.js.map} +0 -0
- /package/dist/{chunk-45QPICLE.js.map → chunk-5M5DVGV7.js.map} +0 -0
- /package/dist/{chunk-S2OWPVSO.js.map → chunk-5YOLBEQ6.js.map} +0 -0
- /package/dist/{chunk-BDEMZD4F.js.map → chunk-6CRIV7DE.js.map} +0 -0
- /package/dist/{chunk-VCUQR6ZL.js.map → chunk-6JTIAGHD.js.map} +0 -0
- /package/dist/{chunk-K2DLLK34.js.map → chunk-6QTNZJBS.js.map} +0 -0
- /package/dist/{chunk-UMC5QZTX.js.map → chunk-6T2SCQRU.js.map} +0 -0
- /package/dist/{chunk-J3JIYFYL.js.map → chunk-7DSTRQIJ.js.map} +0 -0
- /package/dist/{chunk-3QSOFZQB.js.map → chunk-AUSTCW2X.js.map} +0 -0
- /package/dist/{chunk-PN5332SU.js.map → chunk-B3HJYUOF.js.map} +0 -0
- /package/dist/{chunk-DIB2BOIH.js.map → chunk-BDVFPG6Y.js.map} +0 -0
- /package/dist/{chunk-FYNE4WLC.js.map → chunk-CAF6WOK7.js.map} +0 -0
- /package/dist/{chunk-37WOJQWY.js.map → chunk-CIE2BASH.js.map} +0 -0
- /package/dist/{chunk-BLUT46UP.js.map → chunk-CRI4OUV4.js.map} +0 -0
- /package/dist/{chunk-Y5TWPBNW.js.map → chunk-DLG74CNB.js.map} +0 -0
- /package/dist/{chunk-HIOLCOK3.js.map → chunk-E5ZQT5KX.js.map} +0 -0
- /package/dist/{chunk-IQIVD7TP.js.map → chunk-EQO2UVP4.js.map} +0 -0
- /package/dist/{chunk-US34HTOI.js.map → chunk-ERJ7FU55.js.map} +0 -0
- /package/dist/{chunk-S7TAPIRS.js.map → chunk-EVVGJDRQ.js.map} +0 -0
- /package/dist/{chunk-EXGDL2UQ.js.map → chunk-EVX47VBM.js.map} +0 -0
- /package/dist/{chunk-NT2ZO4KI.js.map → chunk-EXK7QRWF.js.map} +0 -0
- /package/dist/{chunk-7QLY64AD.js.map → chunk-EYZ6IQ6X.js.map} +0 -0
- /package/dist/{chunk-QF5LGMSV.js.map → chunk-F64IRYG3.js.map} +0 -0
- /package/dist/{chunk-PH7G7ZI7.js.map → chunk-FHS2HQSH.js.map} +0 -0
- /package/dist/{chunk-ZHOJOT6S.js.map → chunk-FUG4SFN3.js.map} +0 -0
- /package/dist/{chunk-JRKE5MAZ.js.map → chunk-GKEWXIV5.js.map} +0 -0
- /package/dist/{chunk-6MA575R5.js.map → chunk-GTGPO5KW.js.map} +0 -0
- /package/dist/{chunk-XS6DLN67.js.map → chunk-HB3RFQSC.js.map} +0 -0
- /package/dist/{chunk-VXZNSPJM.js.map → chunk-HDMEGAQE.js.map} +0 -0
- /package/dist/{chunk-DJ7MRXNA.js.map → chunk-HTJQYHZP.js.map} +0 -0
- /package/dist/{chunk-NRYNRSGV.js.map → chunk-I6GALP6E.js.map} +0 -0
- /package/dist/{chunk-GL3JV5EV.js.map → chunk-IL6POWCW.js.map} +0 -0
- /package/dist/{chunk-NEYKOESM.js.map → chunk-IU6SNYX6.js.map} +0 -0
- /package/dist/{chunk-CCIR2OJH.js.map → chunk-J2ZX2XUV.js.map} +0 -0
- /package/dist/{chunk-NM3IFKBL.js.map → chunk-JKJOGPZN.js.map} +0 -0
- /package/dist/{chunk-TVS6BUUR.js.map → chunk-JZUV47FZ.js.map} +0 -0
- /package/dist/{chunk-5HNX4OD4.js.map → chunk-K5IMOGHB.js.map} +0 -0
- /package/dist/{chunk-XJ47GS53.js.map → chunk-KSKBRKGJ.js.map} +0 -0
- /package/dist/{chunk-INBQ43DI.js.map → chunk-LASZKVMO.js.map} +0 -0
- /package/dist/{chunk-EVHBK7BN.js.map → chunk-LXEXBTKL.js.map} +0 -0
- /package/dist/{chunk-6S7ENMRE.js.map → chunk-M4CV6BRT.js.map} +0 -0
- /package/dist/{chunk-AAIIDAUC.js.map → chunk-MEFJPTZ4.js.map} +0 -0
- /package/dist/{chunk-WHQHTNT7.js.map → chunk-MV43JSJF.js.map} +0 -0
- /package/dist/{chunk-F44XWXOA.js.map → chunk-NJ4EOKMB.js.map} +0 -0
- /package/dist/{chunk-ILF5GARW.js.map → chunk-NR5LT5RY.js.map} +0 -0
- /package/dist/{chunk-TBNF5DV5.js.map → chunk-NWSGI5C7.js.map} +0 -0
- /package/dist/{chunk-EIZ4YOG2.js.map → chunk-Q5VNKNE5.js.map} +0 -0
- /package/dist/{chunk-TVOHSPVK.js.map → chunk-QLWMEXCT.js.map} +0 -0
- /package/dist/{chunk-7GAXFU2O.js.map → chunk-QRB7NAOJ.js.map} +0 -0
- /package/dist/{chunk-X6Y5MXTH.js.map → chunk-R4ROFEYC.js.map} +0 -0
- /package/dist/{chunk-4BQXMCE5.js.map → chunk-RCVJZMFE.js.map} +0 -0
- /package/dist/{chunk-QG5RQQBO.js.map → chunk-RIX4V2TB.js.map} +0 -0
- /package/dist/{chunk-SAL5X5OK.js.map → chunk-RYCTDFUX.js.map} +0 -0
- /package/dist/{chunk-CXC3JLAQ.js.map → chunk-RZ5SVOYR.js.map} +0 -0
- /package/dist/{chunk-44IL5G3W.js.map → chunk-SLFHQTTW.js.map} +0 -0
- /package/dist/{chunk-2MTRJCBI.js.map → chunk-T2FFWNPK.js.map} +0 -0
- /package/dist/{chunk-QYPDYN23.js.map → chunk-UNFPPVNI.js.map} +0 -0
- /package/dist/{chunk-7ZOSHEVS.js.map → chunk-VLFCJYTL.js.map} +0 -0
- /package/dist/{chunk-APHLCXVC.js.map → chunk-VN3DBQAU.js.map} +0 -0
- /package/dist/{chunk-HK4XTXO4.js.map → chunk-VZRODIM3.js.map} +0 -0
- /package/dist/{chunk-P2LJI6JE.js.map → chunk-W22IKJE2.js.map} +0 -0
- /package/dist/{chunk-FJTWLQV3.js.map → chunk-X3YYQWOQ.js.map} +0 -0
- /package/dist/{chunk-SGJGWBSC.js.map → chunk-YFXZEAYK.js.map} +0 -0
- /package/dist/{chunk-SIAIYP6G.js.map → chunk-ZAJAVEXY.js.map} +0 -0
- /package/dist/{chunk-KKYEZCQG.js.map → chunk-ZICD77GM.js.map} +0 -0
- /package/dist/{chunk-HGAB325C.js.map → chunk-ZJ2AK4V7.js.map} +0 -0
- /package/dist/{chunk-HYG32HCM.js.map → chunk-ZUODRVHY.js.map} +0 -0
- /package/dist/{classified-marker-M7K3OJPM.js.map → classified-marker-CZKA6ITE.js.map} +0 -0
- /package/dist/{collection-facade-DWA735G2.js.map → collection-facade-TLWIPI76.js.map} +0 -0
- /package/dist/{computed-ORCGM5JE.js.map → computed-ZIQTYTDI.js.map} +0 -0
- /package/dist/{dead-filter-OV5FGKOG.js.map → dead-filter-ESOBZZP5.js.map} +0 -0
- /package/dist/{delegation-YVSHMIZZ.js.map → delegation-W7ZV2322.js.map} +0 -0
- /package/dist/{derive-BUO555L5.js.map → derive-H2BJTLUI.js.map} +0 -0
- /package/dist/{enclave-XXFUKJC6.js.map → enclave-AP3I5W7O.js.map} +0 -0
- /package/dist/{executor-6OCCE5VM.js.map → executor-KGWTNEQD.js.map} +0 -0
- /package/dist/{executor-JFVAJY42.js.map → executor-OVEXR6RT.js.map} +0 -0
- /package/dist/{executor-UPSH5O3F.js.map → executor-UNEH5ZYH.js.map} +0 -0
- /package/dist/{export-accessible-L4A2QZA5.js.map → export-accessible-PCMXSUZS.js.map} +0 -0
- /package/dist/{extract-partition-ZHQ4RGGM.js.map → extract-partition-SWHFSYJO.js.map} +0 -0
- /package/dist/{fanout-sidecar-IO2KDUWV.js.map → fanout-sidecar-A765THMX.js.map} +0 -0
- /package/dist/{find-ZFZDZQ2U.js.map → find-N6345CNT.js.map} +0 -0
- /package/dist/{issue-OG4V23SQ.js.map → issue-5OKB6I2R.js.map} +0 -0
- /package/dist/{ledger-UAQKPWNM.js.map → ledger-GFBKVPV4.js.map} +0 -0
- /package/dist/{liberate-GFUQJRK5.js.map → liberate-3VDOT4KO.js.map} +0 -0
- /package/dist/{link-set-DGYUOFVD.js.map → link-set-Z7Q2ASFX.js.map} +0 -0
- /package/dist/{noydb-AKH4AMCR.js.map → noydb-ZCJOYBDI.js.map} +0 -0
- /package/dist/{policy-5POYLI26.js.map → policy-Z3RUAIY2.js.map} +0 -0
- /package/dist/{post-register-LB3P4XQU.js.map → post-register-JTH76BLY.js.map} +0 -0
- /package/dist/{public-envelope-GOG4LUM7.js.map → public-envelope-B4KNWVUA.js.map} +0 -0
- /package/dist/{register-ZI7YI7US.js.map → register-VAHONCID.js.map} +0 -0
- /package/dist/{registry-DZ2T4LL7.js.map → registry-7MLVD3VO.js.map} +0 -0
- /package/dist/{registry-NVWEQ2GU.js.map → registry-EPKPD5SM.js.map} +0 -0
- /package/dist/{registry-SEKL74ET.js.map → registry-P5T7PS2U.js.map} +0 -0
- /package/dist/{request-withdrawal-ZP3JIRVS.js.map → request-withdrawal-TI3A5WPS.js.map} +0 -0
- /package/dist/{revoke-VF6TAJK2.js.map → revoke-FDRD6GRW.js.map} +0 -0
- /package/dist/{seed-VI4FU7UH.js.map → seed-Q6M2IZFL.js.map} +0 -0
- /package/dist/{signer-DRDDCCHW.js.map → signer-MUWEIUI6.js.map} +0 -0
- /package/dist/{stale-TJXFQKOJ.js.map → stale-OSQ7J3AA.js.map} +0 -0
- /package/dist/{storage-GR7KZRH4.js.map → storage-MVFCGEQE.js.map} +0 -0
- /package/dist/{store-coordination-provider-5KDS2RRP.js.map → store-coordination-provider-64OEZFGS.js.map} +0 -0
- /package/dist/{walk-XQCBKSBW.js.map → walk-SVNDIZ62.js.map} +0 -0
- /package/dist/{withdraw-accessible-FMN4LPJZ.js.map → withdraw-accessible-WZIEVWSR.js.map} +0 -0
|
@@ -216,6 +216,27 @@ export declare class LedgerStore {
|
|
|
216
216
|
* backward" signal and falls back to the on-disk current value.
|
|
217
217
|
*/
|
|
218
218
|
loadDelta(index: number): Promise<JsonPatch | null>;
|
|
219
|
+
/**
|
|
220
|
+
* Purge a record's tier-0-era plaintext deltas (#729). Deletes each
|
|
221
|
+
* `_ledger_deltas/<paddedIndex>` row whose entry matches
|
|
222
|
+
* `(collection, id)` and carries a delta, then returns the count
|
|
223
|
+
* deleted.
|
|
224
|
+
*
|
|
225
|
+
* Chain-safe by construction: `verify()` recomputes the tamper-chain
|
|
226
|
+
* from each `_ledger` entry's own canonical fields — including the
|
|
227
|
+
* stored `deltaHash` field, which lives on the entry, not on the
|
|
228
|
+
* `_ledger_deltas` row — and never re-reads `_ledger_deltas`.
|
|
229
|
+
* Deleting a delta row therefore cannot break `verify()`.
|
|
230
|
+
* `reconstruct()` already treats a missing delta (`loadDelta` →
|
|
231
|
+
* `null`) as a pruned stop, so a purge just makes the pre-purge
|
|
232
|
+
* plaintext unreachable rather than corrupting anything.
|
|
233
|
+
*
|
|
234
|
+
* No `_ledger` entry is touched and nothing is re-encrypted — this
|
|
235
|
+
* is irreversible (the deleted plaintext cannot be recovered) but
|
|
236
|
+
* leaves the entry metadata (that the record was mutated, at which
|
|
237
|
+
* version/timestamp/actor) fully intact for audit purposes.
|
|
238
|
+
*/
|
|
239
|
+
purgeRecordDeltas(collection: string, id: string): Promise<number>;
|
|
219
240
|
/** Encrypt a JSON Patch into an envelope for storage. Mirrors encryptEntry. */
|
|
220
241
|
private encryptDelta;
|
|
221
242
|
/**
|
|
@@ -85,6 +85,16 @@ export interface HistoryStrategy {
|
|
|
85
85
|
* tombstoned, or `0` under `NO_HISTORY` (no history = nothing to shred).
|
|
86
86
|
*/
|
|
87
87
|
tombstoneHistory(adapter: NoydbStore, vault: string, collection: string, recordId: string, actor: string, encrypted: boolean): Promise<number>;
|
|
88
|
+
/**
|
|
89
|
+
* Re-key every `_history` snapshot of a record from `fromDek` to `toDek`
|
|
90
|
+
* on a tier move (elevate/demote/putAtTier), mirroring the live-body
|
|
91
|
+
* rewrap so prior versions are not left decryptable at rest under a tier
|
|
92
|
+
* the record has moved away from. Optional `tier0Dek` enables the legacy
|
|
93
|
+
* fallback for snapshots written before this rewrap existed (see
|
|
94
|
+
* `history.ts` for the full contract). No-op under `NO_HISTORY` (no
|
|
95
|
+
* history = nothing to rewrap).
|
|
96
|
+
*/
|
|
97
|
+
rewrapHistory(adapter: NoydbStore, vault: string, collection: string, recordId: string, fromDek: EnclaveKey, toDek: EnclaveKey, tier0Dek?: EnclaveKey): Promise<void>;
|
|
88
98
|
/**
|
|
89
99
|
* Compute the SHA-256 hash of an envelope's encrypted payload, used
|
|
90
100
|
* by `LedgerStore.append` to track tamper-evidence. Returns the
|
|
@@ -119,6 +119,16 @@ export declare class CollectionInstant<T = unknown> {
|
|
|
119
119
|
* Return the record as it existed at the target timestamp, or
|
|
120
120
|
* `null` if the record had not been created yet or had already been
|
|
121
121
|
* deleted by then.
|
|
122
|
+
*
|
|
123
|
+
* Gated on the LIVE record's current tier — #730, mirroring the #712
|
|
124
|
+
* read-gate `history()`/`getVersion()` already apply: an elevated record
|
|
125
|
+
* is invisible through the whole time-machine surface, not just a
|
|
126
|
+
* decrypt failure. See {@link resolveVisibleEnvelope}.
|
|
127
|
+
*
|
|
128
|
+
* Decrypts through {@link openEnvelopeJson}, the `_cek`-aware envelope
|
|
129
|
+
* body opener — a snapshot from a `perRecordKeys` collection is encrypted
|
|
130
|
+
* under its own per-record CEK (wrapped in `_cek`), not the collection
|
|
131
|
+
* DEK directly.
|
|
122
132
|
*/
|
|
123
133
|
get(id: string): Promise<T | null>;
|
|
124
134
|
/**
|
|
@@ -134,6 +144,19 @@ export declare class CollectionInstant<T = unknown> {
|
|
|
134
144
|
put(_id: string, _record: T): Promise<never>;
|
|
135
145
|
delete(_id: string): Promise<never>;
|
|
136
146
|
update(_id: string, _patch: Partial<T>): Promise<never>;
|
|
147
|
+
/**
|
|
148
|
+
* {@link resolveEnvelope}, additionally gated on the record's LIVE
|
|
149
|
+
* (current, not historical) tier — #730. Mirrors the #712 read-gate
|
|
150
|
+
* `history()`/`getVersion()` apply: history snapshots keep their
|
|
151
|
+
* tier-0-wrapped CEKs and carry no `_tier` of their own, so an elevated
|
|
152
|
+
* record's prior versions would otherwise stay tier-0-decryptable here.
|
|
153
|
+
* `null` for a resolved envelope carrying its own `_tier > 0` (a
|
|
154
|
+
* tier-aware snapshot reached some other way) or whose LIVE record is
|
|
155
|
+
* currently elevated — both `get()` and `list()` route through this so
|
|
156
|
+
* the invisibility law holds on the whole time-machine read surface, not
|
|
157
|
+
* just a decrypt failure.
|
|
158
|
+
*/
|
|
159
|
+
private resolveVisibleEnvelope;
|
|
137
160
|
/**
|
|
138
161
|
* Return the envelope that represents the record's state at
|
|
139
162
|
* `targetTs`, accounting for deletes. `null` if the record didn't
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Vault } from '../../kernel/vault.js';
|
|
2
|
+
import type { TierMoveResult } from '../../with-audit/tiers/index.js';
|
|
2
3
|
/**
|
|
3
4
|
* Reserved collection that holds the audit ledger of elevation
|
|
4
5
|
* sessions. One envelope per `vault.elevate(...)` call.
|
|
@@ -44,7 +45,7 @@ export declare class ElevatedHandle {
|
|
|
44
45
|
* unprivileged" trivially true.
|
|
45
46
|
*/
|
|
46
47
|
collection<T>(name: string): {
|
|
47
|
-
put(id: string, record: T): Promise<
|
|
48
|
+
put(id: string, record: T): Promise<TierMoveResult>;
|
|
48
49
|
};
|
|
49
50
|
/**
|
|
50
51
|
* Manually revert the elevation. Idempotent — calling twice (or
|
|
@@ -36,6 +36,15 @@ export interface RefreshResult {
|
|
|
36
36
|
deleted: number;
|
|
37
37
|
/** Failed row writes (non-strict mode). */
|
|
38
38
|
failed: number;
|
|
39
|
+
/** #782/#785 — `outputCollection:id` entries from the tombstone pass whose ownership stamp
|
|
40
|
+
* couldn't be decoded under the collection's default DEK (undecodable, mirroring
|
|
41
|
+
* `invalidateMVAtRest`'s #776 posture) — ownership UNCONFIRMED. Only populated when
|
|
42
|
+
* `onEmpty: 'delete'`. */
|
|
43
|
+
residueUndecodable: string[];
|
|
44
|
+
/** #782/#785 — `outputCollection:id` entries that decoded, stamp-matched this MV, but
|
|
45
|
+
* `_internalDelete` declined (the #718 tier-elevation gate) — ownership CONFIRMED, a real
|
|
46
|
+
* silent survival, surfaced rather than dropped. Only populated when `onEmpty: 'delete'`. */
|
|
47
|
+
residueDeclined: string[];
|
|
39
48
|
}
|
|
40
49
|
/**
|
|
41
50
|
* Run an MV's `query()` and write the result rows to the output
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { Collection } from '../../kernel/collection.js';
|
|
2
2
|
import type { TxContext } from '../../with-commit/tx/transaction.js';
|
|
3
3
|
import type { PutDerivedOutputCtx } from '../../kernel/via/dispatch.js';
|
|
4
|
-
import type { MaterializedViewRegistry } from './registry.js';
|
|
4
|
+
import type { MaterializedViewRegistry, RegisteredMV } from './registry.js';
|
|
5
5
|
import type { MVQueryContext } from './types.js';
|
|
6
|
+
import type { NoydbStore } from '../../kernel/types.js';
|
|
6
7
|
/**
|
|
7
8
|
* Accessor shape passed in from the owning Vault. Provides the
|
|
8
9
|
* registry (used as a stable WeakMap key + to look up MVs by output
|
|
@@ -30,6 +31,48 @@ export declare function markMVStale(registry: MaterializedViewRegistry, mvName:
|
|
|
30
31
|
* @internal
|
|
31
32
|
*/
|
|
32
33
|
export declare function isMVStale(registry: MaterializedViewRegistry, mvName: string): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Reserved collection holding CONTENT-FREE lazy-stale markers (record id =
|
|
36
|
+
* MV name, plaintext `_iv: ''` envelope, no payload) — mirrors the
|
|
37
|
+
* `_meta`/schema-fence marker envelope shape. Written only from the
|
|
38
|
+
* delete/forget/elevate dispatcher (#736); ordinary source writes stay
|
|
39
|
+
* in-memory-only (the cheap path). Read via the adapter directly, never
|
|
40
|
+
* through `vault.collection()` — same reserved-collection convention as
|
|
41
|
+
* `_subject_index`/`_meta`.
|
|
42
|
+
*/
|
|
43
|
+
export declare const MV_STALE_COLLECTION = "_mv_stale";
|
|
44
|
+
/**
|
|
45
|
+
* Invalidate an MV from the delete/forget/elevate dispatcher (#736) — the ordinary
|
|
46
|
+
* source-write path (`dispatchMaterializedViews`) never calls this. Deletes EVERY
|
|
47
|
+
* persisted row in `reg.outputCollection` via `_internalDelete` (the at-rest law: a
|
|
48
|
+
* stale mark alone leaves the elevated/forgotten source's plaintext sitting in the
|
|
49
|
+
* output row) using the adapter directly so the read-path's `resolveStaleMVOnRead`
|
|
50
|
+
* isn't triggered mid-invalidation. `mode: 'lazy'` also persists the stale mark so a
|
|
51
|
+
* cold session recomputes on next read; `'manual'` gets the purge only — the MV
|
|
52
|
+
* serves empty until an explicit `vault.refreshView()` (erasure wins). Deletion is
|
|
53
|
+
* stamp-scoped (`_materializedFrom.mvName === reg.spec.name` — see the loop below),
|
|
54
|
+
* so another registered MV sharing this output collection keeps its own rows intact:
|
|
55
|
+
* no cross-MV re-marking is needed here, only `reg` itself is marked stale.
|
|
56
|
+
*
|
|
57
|
+
* Returns the count of rows actually `_internalDelete`d (#761 item 1) — folded by the
|
|
58
|
+
* caller into `dispatchMaterializedViewsOnDelete`'s `deleted` so `ForgetResult.derivedRecordsErased`
|
|
59
|
+
* counts lazy/manual purges too, not just the eager executor's tombstone leg — plus
|
|
60
|
+
* `residueUndecodable`, the bare ids whose ownership stamp could NOT be decoded (#776): a
|
|
61
|
+
* candidate row that fails to decode under the collection's default DEK (e.g. elevated above
|
|
62
|
+
* tier 0 on a tiered output collection) has UNKNOWN ownership — it might be this MV's own
|
|
63
|
+
* output, or (same-collection shape) a plain user record — so it is never erased, but it must
|
|
64
|
+
* be SURFACED rather than silently skipped (the #724 posture), since it may still hold the
|
|
65
|
+
* forgotten/pre-elevation contribution, decryptable by tier-holders — and `residueDeclined`
|
|
66
|
+
* (#785), the bare ids that DID decode and stamp-match but whose `_internalDelete` declined
|
|
67
|
+
* (ownership CONFIRMED, erasure declined).
|
|
68
|
+
*
|
|
69
|
+
* @internal
|
|
70
|
+
*/
|
|
71
|
+
export declare function invalidateMVAtRest(accessor: MVStaleAccessor, reg: RegisteredMV, mode: 'lazy' | 'manual'): Promise<{
|
|
72
|
+
deleted: number;
|
|
73
|
+
residueUndecodable: string[];
|
|
74
|
+
residueDeclined: string[];
|
|
75
|
+
}>;
|
|
33
76
|
/**
|
|
34
77
|
* Called from `Collection.get` (and any reader that materializes the
|
|
35
78
|
* MV's output collection). If any MV producing `outputCollection` is
|
|
@@ -60,3 +103,11 @@ export declare function resolveStaleMVOnRead(accessor: MVStaleAccessor, outputCo
|
|
|
60
103
|
* @internal
|
|
61
104
|
*/
|
|
62
105
|
export declare function clearMVStale(registry: MaterializedViewRegistry, mvName: string): void;
|
|
106
|
+
/**
|
|
107
|
+
* `clearMVStale` plus the persisted marker (#736) — `Vault.refreshView()`'s
|
|
108
|
+
* completion path. A lingering persisted marker after a manual refresh would
|
|
109
|
+
* make the NEXT cold session recompute redundantly.
|
|
110
|
+
*
|
|
111
|
+
* @internal
|
|
112
|
+
*/
|
|
113
|
+
export declare function clearMVStaleFully(adapter: NoydbStore, vault: string, registry: MaterializedViewRegistry, mvName: string): Promise<void>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Collection-namespaced `_vec` side-car ids (#726).
|
|
3
|
+
*
|
|
4
|
+
* `_vec` embedding side-cars used to be keyed by the bare record id,
|
|
5
|
+
* vault-wide — two collections sharing a record id shared one `_vec` row.
|
|
6
|
+
* This was verified to be a clobber/crash bug, NOT a confidentiality leak:
|
|
7
|
+
* every collection has its own DEK, and AES-GCM auth-tag verification means
|
|
8
|
+
* decrypting a foreign collection's `_vec` row under the wrong DEK throws
|
|
9
|
+
* `TamperedError` rather than returning wrong plaintext — no disclosure
|
|
10
|
+
* mechanism exists. The real bug was id collision: a same-id write/forget in
|
|
11
|
+
* one collection could clobber or delete the other collection's row, and a
|
|
12
|
+
* collection whose `similarTo()` / cold semantic `retrieve()` encountered a
|
|
13
|
+
* foreign same-id row crashed with an uncaught `TamperedError` (a DoS). The
|
|
14
|
+
* store-collection bucket stays the literal `'_vec'`; the id becomes
|
|
15
|
+
* composite: `${collection}/${recordId}`. Mirrors `encodeIdxId`
|
|
16
|
+
* (`../indexing/persisted-indexes.js`).
|
|
17
|
+
*
|
|
18
|
+
* Decode is deliberately NOT split-on-`/`: the collection is always known
|
|
19
|
+
* at the decode site (`ctx.name`), so `decodeVecId` strips that known
|
|
20
|
+
* prefix — correct even when `recordId` itself contains `/`.
|
|
21
|
+
*
|
|
22
|
+
* Precondition: `collection` itself must not contain `/` — otherwise
|
|
23
|
+
* `${collection}/${recordId}` is ambiguous (e.g. collection `'a'` would
|
|
24
|
+
* misattribute collection `'a/b'`'s rows via prefix match in `isVecIdFor`).
|
|
25
|
+
* Collection names are NOT currently restricted to a `/`-free charset by
|
|
26
|
+
* `vault.collection()`, so `encodeVecId` enforces the precondition itself,
|
|
27
|
+
* failing loud at the write boundary rather than silently misencoding.
|
|
28
|
+
*/
|
|
29
|
+
/**
|
|
30
|
+
* Encode the `_vec` side-car id for a (collection, recordId) pair.
|
|
31
|
+
* Format: `<collection>/<recordId>` — no escaping; `recordId` may contain `/`.
|
|
32
|
+
*
|
|
33
|
+
* Throws if `collection` contains `/`: that would make the composite id
|
|
34
|
+
* ambiguous against `isVecIdFor`'s prefix match (collection `'a'` would
|
|
35
|
+
* appear to own collection `'a/b'`'s rows), reintroducing the clobber/crash
|
|
36
|
+
* risk the namespacing fix exists to close.
|
|
37
|
+
*/
|
|
38
|
+
export declare function encodeVecId(collection: string, recordId: string): string;
|
|
39
|
+
/**
|
|
40
|
+
* Decode a `_vec` id back to the bare record id, given the KNOWN owning
|
|
41
|
+
* collection — strips the `<collection>/` prefix rather than splitting on
|
|
42
|
+
* `/`, so a `recordId` containing `/` round-trips correctly. Returns `null`
|
|
43
|
+
* if `vecId` does not belong to `collection`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function decodeVecId(collection: string, vecId: string): string | null;
|
|
46
|
+
/** Predicate form of {@link decodeVecId} — used to filter `list()` results. */
|
|
47
|
+
export declare function isVecIdFor(collection: string, vecId: string): boolean;
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* Internal service — not exported as a `@noy-db/hub/*` subpath.
|
|
22
22
|
*/
|
|
23
|
-
import type { NoydbStore } from '../../kernel/types.js';
|
|
23
|
+
import type { NoydbStore, EncryptedEnvelope } from '../../kernel/types.js';
|
|
24
24
|
import type { RecordCodec } from '../../kernel/enclave/index.js';
|
|
25
25
|
import type { NoydbEventEmitter } from '../../kernel/events.js';
|
|
26
26
|
import type { CollectionIndexes } from './eager-indexes.js';
|
|
@@ -118,3 +118,40 @@ export declare function purgePersistedIndexes<T>(ctx: IndexingContext<T>, id: st
|
|
|
118
118
|
purged: number;
|
|
119
119
|
residue: string[];
|
|
120
120
|
}>;
|
|
121
|
+
/**
|
|
122
|
+
* Sync this collection's indexes after a tier move (#709). Persisted
|
|
123
|
+
* `_idx/<field>/<recordId>` side-cars are always encrypted under the
|
|
124
|
+
* tier-0 DEK regardless of the record's own tier, and the eager in-memory
|
|
125
|
+
* `CollectionIndexes` mirror holds plaintext bucket values too — so both
|
|
126
|
+
* leak an elevated record's indexed field values unless swept the same way
|
|
127
|
+
* `purgePersistedIndexes` already sweeps them for `forget()` ("forget()
|
|
128
|
+
* crypto-shreds the body but keeps the collection DEK, under which these
|
|
129
|
+
* side-cars are encrypted — so without this they leave the indexed field
|
|
130
|
+
* VALUES readable", `purgePersistedIndexes` above).
|
|
131
|
+
*
|
|
132
|
+
* `record === null` — the record just left tier 0: purge its persisted
|
|
133
|
+
* side-cars (content-free, no decrypt needed) and drop its eager-mirror
|
|
134
|
+
* entry, read from `ctx.cache` (the caller's pre-write value — the caller
|
|
135
|
+
* MUST invoke this before evicting/overwriting that cache entry, so it
|
|
136
|
+
* still reflects the value being replaced).
|
|
137
|
+
*
|
|
138
|
+
* `record` given — the record is tier-0 again: (re)build its entries from
|
|
139
|
+
* that record, using the SAME pre-write `ctx.cache` read as the previous
|
|
140
|
+
* value so a stale bucket (e.g. a same-tier `putAtTier` value change) is
|
|
141
|
+
* cleaned up rather than left as a false-positive hit. `version` stamps
|
|
142
|
+
* the rebuilt side-car's own envelope version.
|
|
143
|
+
*
|
|
144
|
+
* `priorEnvelope` (#720) — the RAW envelope the caller read BEFORE its own
|
|
145
|
+
* overwrite landed (`putAtTier`'s `existing` / `demote`'s pre-move
|
|
146
|
+
* `envelope`), for the `ctx.cache`-miss lazy case: by this call's time the
|
|
147
|
+
* adapter already holds the NEW envelope, so a `ctx.adapter.get()` here
|
|
148
|
+
* would only ever re-observe the write just made — useless for recovering
|
|
149
|
+
* what a same-tier `putAtTier` may have dropped. Optional: the null-record
|
|
150
|
+
* branches (elevate / demote-to-intermediate / putAtTier(tier>0)) never
|
|
151
|
+
* need it — their only prior-dependent step, the eager `indexes.remove`
|
|
152
|
+
* below, already has what it needs from `ctx.cache` (eager mode is
|
|
153
|
+
* unaffected by the raw-envelope overwrite; lazy mode has no eager mirror).
|
|
154
|
+
*
|
|
155
|
+
* No-ops fast when the collection has neither index kind declared.
|
|
156
|
+
*/
|
|
157
|
+
export declare function syncTierIndexes<T>(ctx: IndexingContext<T>, id: string, record: T | null, version: number, priorEnvelope?: EncryptedEnvelope): Promise<void>;
|
|
@@ -121,3 +121,43 @@ export declare function similarTo<T>(ctx: SearchContext<T>, vector: Float32Array
|
|
|
121
121
|
* (`Collection.put`) only invokes this when `embeddings` is declared.
|
|
122
122
|
*/
|
|
123
123
|
export declare function embedOnWrite<T>(ctx: SearchContext<T>, id: string, record: T, version: number): Promise<void>;
|
|
124
|
+
/**
|
|
125
|
+
* Force-re-derive every eligible tier-0 record's `_vec` sidecar once (#788).
|
|
126
|
+
* Opt-in bulk repair for the #726 re-namespace: legacy bare-id rows are
|
|
127
|
+
* unreachable to `buildVectorLoad` (it only recognises `<collection>/<id>`
|
|
128
|
+
* keys) and otherwise self-heal only when a record is next `put()` — this
|
|
129
|
+
* lets an adopter recover recall immediately instead of waiting on writes.
|
|
130
|
+
*
|
|
131
|
+
* **Skips elevated records** (`liveRecordIsElevated`) rather than refusing
|
|
132
|
+
* the whole walk — the OPPOSITE of `_applyCutoverTransform`'s
|
|
133
|
+
* `assertCutoverTierSafe` refuse-whole-batch precedent. An elevated record is
|
|
134
|
+
* SUPPOSED to have no `_vec` (`syncTierSearch` purges it on elevate);
|
|
135
|
+
* re-embedding one here would write searchable plaintext-derived data above
|
|
136
|
+
* tier 0. Load-bearing: never write a `_vec` row for an elevated record.
|
|
137
|
+
*
|
|
138
|
+
* Tombstones, delete markers, and a raw `get` racing a delete between `list`
|
|
139
|
+
* and `get` all decrypt to `null` (`decryptRecord` already folds
|
|
140
|
+
* tombstone/delete-marker into that null) and are skipped the same way.
|
|
141
|
+
* Unconditional re-derive, no already-migrated check — safe to re-run after
|
|
142
|
+
* a partial failure (each id is independently idempotent).
|
|
143
|
+
*/
|
|
144
|
+
export declare function rebuildEmbeddings<T>(ctx: SearchContext<T>): Promise<{
|
|
145
|
+
rebuilt: number;
|
|
146
|
+
skipped: number;
|
|
147
|
+
}>;
|
|
148
|
+
/**
|
|
149
|
+
* Sync the collection's SEARCH artifacts after a tier move (#721). Both the
|
|
150
|
+
* lexical `_ftindex` blob and the `_vec/<id>` embedding are encrypted under
|
|
151
|
+
* the tier-0 DEK and hold the record's derived plaintext (full field text /
|
|
152
|
+
* a text-invertible vector), so leaving them means elevation never hid what
|
|
153
|
+
* the record was searchable by — the `forget()` precedent, unapplied to
|
|
154
|
+
* elevate. `null` → the record left tier 0: purge its `_vec` sidecar (mirrors
|
|
155
|
+
* `Collection._purgeVector`), and invalidate the `_ftindex` blob (mirrors
|
|
156
|
+
* `Collection._purgeSearchIndex`: deletes the persisted blob when persisted,
|
|
157
|
+
* else drops the in-memory index) so the next `retrieve()` rebuilds from the
|
|
158
|
+
* elevated-free `ctx.cache`. A record → it is tier-0 again: re-embed it via
|
|
159
|
+
* {@link embedOnWrite}, then invalidate `_ftindex` so the rebuild includes it
|
|
160
|
+
* again. No-op fast when the collection has neither a lexical index nor a
|
|
161
|
+
* vector set.
|
|
162
|
+
*/
|
|
163
|
+
export declare function syncTierSearch<T>(ctx: SearchContext<T>, id: string, record: T | null, version?: number): Promise<void>;
|
|
@@ -4,6 +4,20 @@
|
|
|
4
4
|
* live (L1 behavior); persists an opaque snapshot via a debounced flush, and
|
|
5
5
|
* validates a loaded blob against a {count,maxVersion} fingerprint so a stale
|
|
6
6
|
* blob is never used — only rebuilt.
|
|
7
|
+
*
|
|
8
|
+
* #725: a debounced save (encrypt + adapter.put) racing a purge (removePersisted,
|
|
9
|
+
* called by elevate's tier purge and forget's erasure) is guarded by an epoch counter
|
|
10
|
+
* — see the `epoch` field doc for the mechanism and why it also closes the issue's
|
|
11
|
+
* variant (b) for free. Residual gap, structurally unavoidable without a durable
|
|
12
|
+
* write-ahead log: a process CRASH strictly between a stale save's `adapter.put`
|
|
13
|
+
* landing and its compensating `remove()` running (or between the compensating
|
|
14
|
+
* remove landing and `pendingCompensation` being persisted somewhere durable — it is
|
|
15
|
+
* in-memory only) leaves the resurrected blob at rest until the next natural
|
|
16
|
+
* rebuild-persist. This is on par with the gate-before-put optimization's own crash
|
|
17
|
+
* residual (a crash between `isStale()` returning false and the put landing) — both
|
|
18
|
+
* are eliminated only by making the purge and the save's commit point transactional
|
|
19
|
+
* with the store, which is out of scope for an in-memory debounce layer over an
|
|
20
|
+
* arbitrary opaque-blob backend.
|
|
7
21
|
*/
|
|
8
22
|
import { InvertedIndex, type IndexDoc } from './inverted-index.js';
|
|
9
23
|
import type { IndexStore } from './index-store.js';
|
|
@@ -16,7 +30,14 @@ export interface PersistedIndexCallbacks {
|
|
|
16
30
|
json: string;
|
|
17
31
|
fingerprint: Fingerprint;
|
|
18
32
|
} | null>;
|
|
19
|
-
|
|
33
|
+
/** `isStale()` reflects whether a purge (removePersisted) has landed since this
|
|
34
|
+
* save's epoch was captured — check it AFTER any async encrypt step and BEFORE
|
|
35
|
+
* the actual adapter.put, skipping the write when true (#725 review: shrinks the
|
|
36
|
+
* at-rest window for purge-beats-encrypt orderings to zero). Belt-and-suspenders:
|
|
37
|
+
* PersistedIndexStore's own post-save epoch check (persist(), below) is the
|
|
38
|
+
* backstop that catches every other ordering, including a purge landing during
|
|
39
|
+
* the put itself. */
|
|
40
|
+
save(json: string, fp: Fingerprint, isStale: () => boolean): Promise<void>;
|
|
20
41
|
remove(): Promise<void>;
|
|
21
42
|
currentFingerprint(): Fingerprint;
|
|
22
43
|
debounceMs?: number;
|
|
@@ -27,15 +48,74 @@ export declare class PersistedIndexStore implements IndexStore {
|
|
|
27
48
|
private timer;
|
|
28
49
|
private lastBuild;
|
|
29
50
|
private readonly debounceMs;
|
|
51
|
+
/**
|
|
52
|
+
* Bumped by every purge (removePersisted). A save() captured under a since-stale
|
|
53
|
+
* epoch undoes its own effect once it settles, however it interleaves with the
|
|
54
|
+
* purge's own delete — a delete can never be overtaken by a save that was
|
|
55
|
+
* scheduled before it (#725).
|
|
56
|
+
*
|
|
57
|
+
* Subsumes the issue's variant (b) (a stale, pre-purge in-memory index getting
|
|
58
|
+
* paired with a live, post-purge fingerprint and TRUSTED by a cold load, defeating
|
|
59
|
+
* the fingerprint backstop) for free — no separate handling needed: removePersisted()
|
|
60
|
+
* always resets `index` to undefined in the SAME synchronous step that bumps the
|
|
61
|
+
* epoch (below), and the only two paths that can repopulate `index` (ensureBuilt's
|
|
62
|
+
* cold rebuild, rebuildAndPersist's rebuild) do so strictly from `lastBuild()`, which
|
|
63
|
+
* the collection wires to read its LIVE cache at call time — not a frozen snapshot.
|
|
64
|
+
* Cache eviction (the collection dropping the purged/forgotten record) always
|
|
65
|
+
* precedes removePersisted() in both the elevate and forget call paths (#721's
|
|
66
|
+
* syncCache eviction / forget's tombstone write both land before syncSearch /
|
|
67
|
+
* _purgeSearchIndex runs). So any rebuild that executes strictly after
|
|
68
|
+
* removePersisted() — the only way `index` becomes defined again post-purge —
|
|
69
|
+
* necessarily observes the post-purge cache, and any rebuild that predates
|
|
70
|
+
* removePersisted() has its `index` wiped by it. There is no ordering in which a
|
|
71
|
+
* stale (pre-purge) index survives to be skip-rebuilt and persisted under a
|
|
72
|
+
* matching live fingerprint. Regression-pinned in
|
|
73
|
+
* `search-persisted-index-store.test.ts` ("variant (b) is subsumed...").
|
|
74
|
+
*/
|
|
75
|
+
private epoch;
|
|
76
|
+
/**
|
|
77
|
+
* Set when a compensating/purging remove() (`compensate()` undoing a stale
|
|
78
|
+
* save, or `removePersisted()`'s own purge, #764) fails. Unlike the routine
|
|
79
|
+
* best-effort swallow on the debounced flush path (markDirty's timer
|
|
80
|
+
* .catch(), below — safe there because the fingerprint backstop forces a
|
|
81
|
+
* rebuild on the next cold load), a failed removal leaves a resurrected or
|
|
82
|
+
* un-purged blob at rest whose fingerprint can still match the live cache —
|
|
83
|
+
* a cold load would TRUST it, not rebuild past it. So this is never silently
|
|
84
|
+
* dropped: every subsequent store entrypoint (ensureBuilt, rebuildAndPersist,
|
|
85
|
+
* removePersisted) retries the remove first and refuses to proceed past it
|
|
86
|
+
* until it succeeds (#725 review), and the raw adapter error is wrapped in
|
|
87
|
+
* {@link PersistedIndexCompensationError} (#764) so a caller can catch a
|
|
88
|
+
* stuck removal deliberately instead of an indistinguishable adapter error.
|
|
89
|
+
* A crash between a landed put and its compensating remove (before this
|
|
90
|
+
* flag or a retry can run) is a residual gap — see the class doc.
|
|
91
|
+
*/
|
|
92
|
+
private pendingCompensation;
|
|
30
93
|
constructor(cb: PersistedIndexCallbacks);
|
|
31
94
|
get built(): boolean;
|
|
32
95
|
ensureBuilt(build: () => ReadonlyArray<IndexDoc>): Promise<InvertedIndex>;
|
|
33
96
|
markDirty(): void;
|
|
34
97
|
/** Force an immediate persist (cancels any pending debounce). */
|
|
35
98
|
flush(): Promise<void>;
|
|
36
|
-
/** Delete the persisted blob and drop the in-memory index (forget/erasure
|
|
99
|
+
/** Delete the persisted blob and drop the in-memory index (forget/erasure/tier
|
|
100
|
+
* move). A failed purge is wrapped in {@link PersistedIndexCompensationError}
|
|
101
|
+
* (#764) and left sticky (`pendingCompensation`) so the next store entrypoint
|
|
102
|
+
* retries it — never silently dropped, same posture #725 established for a
|
|
103
|
+
* stale save's own compensating remove. */
|
|
37
104
|
removePersisted(): Promise<void>;
|
|
38
105
|
/** Rebuild using the last known build thunk, then persist. */
|
|
39
106
|
private rebuildAndPersist;
|
|
107
|
+
/** Persist the current index, then undo it if a purge (removePersisted) landed
|
|
108
|
+
* while the save was in flight — a delete can never be overtaken by a save
|
|
109
|
+
* that was scheduled before it (#725). A failed undo does not silently vanish:
|
|
110
|
+
* see `pendingCompensation`. */
|
|
40
111
|
private persist;
|
|
112
|
+
/** Undo a stale save. Failure is sticky, not swallowed: see `pendingCompensation`.
|
|
113
|
+
* Wraps the raw adapter error in {@link PersistedIndexCompensationError} (#764) so
|
|
114
|
+
* a caller (e.g. the tier ops' `syncTierSearch`) can catch a stuck compensation
|
|
115
|
+
* deliberately instead of treating it as an indistinguishable adapter failure. */
|
|
116
|
+
private compensate;
|
|
117
|
+
/** Retries a sticky compensation before any store entrypoint proceeds. Failure
|
|
118
|
+
* re-wraps the raw adapter error the same way `compensate()` does (#764) — the
|
|
119
|
+
* flag stays set (untouched here) so the NEXT entrypoint retries again. */
|
|
120
|
+
private retryPendingCompensation;
|
|
41
121
|
}
|
|
@@ -28,6 +28,10 @@ export interface SearchStrategy {
|
|
|
28
28
|
warmIndex<T>(ctx: SearchContext<T>): Promise<void>;
|
|
29
29
|
flushIndex<T>(ctx: SearchContext<T>): Promise<void>;
|
|
30
30
|
embedOnWrite<T>(ctx: SearchContext<T>, id: string, record: T, version: number): Promise<void>;
|
|
31
|
+
rebuildEmbeddings<T>(ctx: SearchContext<T>): Promise<{
|
|
32
|
+
rebuilt: number;
|
|
33
|
+
skipped: number;
|
|
34
|
+
}>;
|
|
31
35
|
}
|
|
32
36
|
/**
|
|
33
37
|
* No-op stub — the floor default. Every capability method (and the embedding
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `_blob_intent` — the blob durability journal marker (#753, spec §7).
|
|
3
|
+
*
|
|
4
|
+
* One row per in-flight multi-step blob operation (`shred` | `rehome`),
|
|
5
|
+
* written BEFORE the first destructive/movement step and deleted as the
|
|
6
|
+
* operation's LAST step. An absent marker means "no operation in flight"
|
|
7
|
+
* (the normal state, zero cost on every path that doesn't crash); a present
|
|
8
|
+
* marker means the operation MUST be resumed before any other blob work on
|
|
9
|
+
* that record proceeds.
|
|
10
|
+
*
|
|
11
|
+
* **Pattern honesty (C9):** this is the family's FIRST content-bearing
|
|
12
|
+
* ENCRYPTED reserved marker. The prior reserved-collection precedent,
|
|
13
|
+
* `_mv_stale` (`with-formula/materialized-views/stale.ts`), is
|
|
14
|
+
* content-free plaintext (`{ _iv: '', _data: '{}' }` — the row's only
|
|
15
|
+
* payload is its key). `_blob_intent` carries real operational metadata
|
|
16
|
+
* (op, tiers, eTags + counts) and is encrypted, so its codec/CAS/backup/
|
|
17
|
+
* sweep conventions below are new to the codebase, not a copy of an
|
|
18
|
+
* existing pattern.
|
|
19
|
+
*
|
|
20
|
+
* **Key management (spec §4):** encrypted under the record's OWNING
|
|
21
|
+
* collection's tier-0 DEK — `getDEK(collection)`, which resolves to
|
|
22
|
+
* `dekKey(collection, 0) === collection` (see `with-party/team/tiers.ts`).
|
|
23
|
+
* Every legitimate resumer (forget()-retry, blob write entry points,
|
|
24
|
+
* tier ops) already holds this DEK; minting an elevated DEK for the
|
|
25
|
+
* marker itself would make resume impossible for a tier-0-only resumer.
|
|
26
|
+
* Documented residue: a tier-0 DEK holder can learn that an elevated
|
|
27
|
+
* record's shred/rehome was in flight and which eTags it touched —
|
|
28
|
+
* existence-adjacent, consistent with the already-documented
|
|
29
|
+
* dedup-policy residue (#741).
|
|
30
|
+
*
|
|
31
|
+
* **Key grammar (C11):** `{collection}::{recordId}`. Blob-bearing record
|
|
32
|
+
* ids already refuse `::` at the write surface (`blob-set.ts`'s
|
|
33
|
+
* `assertKeyPartSafe`, #752) — re-validated here defensively so the
|
|
34
|
+
* sweep's prefix-free key list stays unambiguous regardless of caller.
|
|
35
|
+
*
|
|
36
|
+
* Wired by `shredAllForRecord`/`forget()` (PR-1 Task 3, shred) and by
|
|
37
|
+
* `BlobSet.syncTierMove`/`rehomeForTier`/`resolvePendingIntent` (PR-2 Task
|
|
38
|
+
* 2, rehome — mint/resume/consume for `op:'rehome'` markers).
|
|
39
|
+
*/
|
|
40
|
+
import type { NoydbStore } from '../../kernel/types.js';
|
|
41
|
+
import { type EnclaveKey } from '../../kernel/enclave/index.js';
|
|
42
|
+
/** Reserved collection holding `_blob_intent` marker rows. */
|
|
43
|
+
export declare const BLOB_INTENT_COLLECTION = "_blob_intent";
|
|
44
|
+
/**
|
|
45
|
+
* One captured refCount hold on an eTag, authoritative on resume (spec §2a,
|
|
46
|
+
* amended by C5). `chunkCount` lets a resumed release complete chunk
|
|
47
|
+
* cleanup even if the `_blob_index` row itself is already gone (mirrors
|
|
48
|
+
* `releaseRef`'s `chunkCountHint` parameter, Task 1).
|
|
49
|
+
*/
|
|
50
|
+
export interface BlobIntentHold {
|
|
51
|
+
readonly eTag: string;
|
|
52
|
+
readonly n: number;
|
|
53
|
+
readonly chunkCount: number;
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* The intent marker's decrypted payload (spec §2a, amended by C5: `holds`
|
|
57
|
+
* entries carry `{ eTag, n, chunkCount }` rather than the original bare
|
|
58
|
+
* `{ eTag, n }`).
|
|
59
|
+
*/
|
|
60
|
+
export interface BlobIntent {
|
|
61
|
+
readonly op: 'shred' | 'rehome';
|
|
62
|
+
/** Random nonce minted at marker creation (`crypto.getRandomValues`) — the op-stamp identity. */
|
|
63
|
+
readonly opId: string;
|
|
64
|
+
/** Captured ONCE at marker creation; authoritative on every resume. */
|
|
65
|
+
readonly holds?: readonly BlobIntentHold[];
|
|
66
|
+
readonly ownerTier?: number;
|
|
67
|
+
readonly fromTier?: number;
|
|
68
|
+
readonly toTier?: number;
|
|
69
|
+
readonly policy?: 'isolate' | 'dedup';
|
|
70
|
+
/**
|
|
71
|
+
* Rehome destination `+1` row-stamps (`${opId}:${slotName}` /
|
|
72
|
+
* `${opId}:${versionKey}`) CONFIRMED applied — #746 whole-branch review
|
|
73
|
+
* (K=8 stamp-ring blocker). `BlobObject.lastOps` is a BOUNDED ring (K=8,
|
|
74
|
+
* spec C2) — correct as the sole idempotency source for SHRED (one
|
|
75
|
+
* decrement per eTag, count captured in `holds`) but not for REHOME,
|
|
76
|
+
* whose row-scoped increments can exceed K on a single destination via
|
|
77
|
+
* either ≥9 rows of identical content on ONE record, or ≥8 CONCURRENT
|
|
78
|
+
* rehomes converging on one shared destination between a crashed op's
|
|
79
|
+
* stamp-write and its resume — either way, an evicted-but-unapplied-
|
|
80
|
+
* looking stamp gets re-applied, over-counting the destination's
|
|
81
|
+
* refCount and permanently stranding it above 0. This field is THIS
|
|
82
|
+
* op's own UNBOUNDED, per-record backstop: appended (via
|
|
83
|
+
* {@link recordAppliedStamp}) immediately after a stamped `+1` lands
|
|
84
|
+
* (whether freshly applied or found already in the ring), consulted
|
|
85
|
+
* BEFORE attempting the CAS so a resume that finds its own row-stamp
|
|
86
|
+
* here skips the increment entirely — independent of the shared
|
|
87
|
+
* destination object's bounded ring and of how many OTHER ops have
|
|
88
|
+
* touched it since. Absent/empty is the normal case (no rehome — or no
|
|
89
|
+
* increments yet — in flight).
|
|
90
|
+
*/
|
|
91
|
+
readonly appliedStamps?: readonly string[];
|
|
92
|
+
}
|
|
93
|
+
/** Resume callback signature for {@link sweepBlobIntents} — supplied by the caller (Task 3 / PR-2). */
|
|
94
|
+
export type BlobIntentResume = (collection: string, recordId: string, intent: BlobIntent) => Promise<void>;
|
|
95
|
+
/**
|
|
96
|
+
* Read the `_blob_intent` marker for `{collection}::{recordId}`, or `null`
|
|
97
|
+
* if none is pending. The resume-gate check every future blob mutator
|
|
98
|
+
* (Task 3 / PR-2) runs before proceeding.
|
|
99
|
+
*/
|
|
100
|
+
export declare function getIntent(adapter: NoydbStore, vault: string, collection: string, recordId: string, getDEK: (collection: string) => Promise<EnclaveKey>): Promise<BlobIntent | null>;
|
|
101
|
+
/**
|
|
102
|
+
* Create a `_blob_intent` marker for `{collection}::{recordId}` — CAS
|
|
103
|
+
* create-if-absent (C8). `store.put(..., expectedVersion: 0)` succeeds only
|
|
104
|
+
* when no row is present (every real adapter treats a missing record +
|
|
105
|
+
* `expectedVersion: 0` as a no-conflict write — the same convention
|
|
106
|
+
* `loadOrCreateSigner` uses in `with-audit/attestation/signer.ts`); a
|
|
107
|
+
* present row always carries `_v >= 1`, so the CAS throws `ConflictError`
|
|
108
|
+
* and is converted here into {@link BlobIntentPendingError} — the signal
|
|
109
|
+
* a caller catches to resume the PENDING operation before starting a new
|
|
110
|
+
* one, rather than silently clobbering it (which would orphan the prior
|
|
111
|
+
* op's op-stamps).
|
|
112
|
+
*/
|
|
113
|
+
export declare function createIntent(adapter: NoydbStore, vault: string, collection: string, recordId: string, getDEK: (collection: string) => Promise<EnclaveKey>, intent: BlobIntent): Promise<void>;
|
|
114
|
+
/** Delete the `_blob_intent` marker for `{collection}::{recordId}` — the operation's LAST step. */
|
|
115
|
+
export declare function deleteIntent(adapter: NoydbStore, vault: string, collection: string, recordId: string): Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Durably record that a rehome destination row-stamp has been CONFIRMED
|
|
118
|
+
* applied — #746 whole-branch review (K=8 stamp-ring blocker). Appends
|
|
119
|
+
* `stamp` to the marker's `appliedStamps` (idempotent no-op if already
|
|
120
|
+
* present), CAS-retried against concurrent resumers touching the SAME
|
|
121
|
+
* marker (mirrors `BlobSet.casUpdateSlots`'s retry shape).
|
|
122
|
+
*
|
|
123
|
+
* A no-op — never throws — when the marker is already gone: that only
|
|
124
|
+
* happens if the whole op already completed and deleted it (this call is
|
|
125
|
+
* racing its own operation's tail) or a sibling resumer already finished
|
|
126
|
+
* it; either way there is nothing left to record against. A marker whose
|
|
127
|
+
* `op` is NOT `'rehome'` (should be structurally impossible — only
|
|
128
|
+
* `BlobSet`'s own rehome machinery calls this, against its own marker) is
|
|
129
|
+
* treated the same way: nothing to record.
|
|
130
|
+
*/
|
|
131
|
+
export declare function recordAppliedStamp(adapter: NoydbStore, vault: string, collection: string, recordId: string, getDEK: (collection: string) => Promise<EnclaveKey>, stamp: string): Promise<void>;
|
|
132
|
+
/**
|
|
133
|
+
* List every persisted `_blob_intent` marker and resume each via the
|
|
134
|
+
* caller-supplied `resume` callback (the forget-entry / vault-open sweep,
|
|
135
|
+
* mirroring `_mv_stale`'s `hydratePersistedStaleMarkers`/orphan-sweep
|
|
136
|
+
* pattern).
|
|
137
|
+
*
|
|
138
|
+
* **Per-marker isolation (#753 Task 3, carried finding from the Task 2
|
|
139
|
+
* review):** each marker's decode + `resume` runs in its own try/catch — a
|
|
140
|
+
* corrupt/DEK-mismatched marker, or a marker whose resume genuinely fails
|
|
141
|
+
* (e.g. a store error mid-release), is reported via `onResumeError` and
|
|
142
|
+
* skipped, never aborting the loop and never silently swallowed. Earlier
|
|
143
|
+
* (Task 2) this loop had no try/catch at all; that was safe only because
|
|
144
|
+
* nothing called `resume` with real logic yet — `BlobSet.mintShredIntent`'s
|
|
145
|
+
* collection-scoped sweep (this function's first real caller, Task 3) can
|
|
146
|
+
* hit a genuinely corrupt sibling marker and must not let it block a
|
|
147
|
+
* healthy one (mirrors `stale.ts`'s orphan-sweep defensive posture, #736).
|
|
148
|
+
*
|
|
149
|
+
* `resume` is the per-marker resume action (Task 3: `BlobSet`'s
|
|
150
|
+
* `resolvePendingIntent`-equivalent for a shred marker; a rehome marker is
|
|
151
|
+
* PR-2 scope and should be skipped by the callback, not thrown into here).
|
|
152
|
+
*/
|
|
153
|
+
export declare function sweepBlobIntents(adapter: NoydbStore, vault: string, getDEK: (collection: string) => Promise<EnclaveKey>, resume: BlobIntentResume, onResumeError?: (collection: string, recordId: string, err: unknown) => void): Promise<void>;
|