lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit 4d31459a64b8f9ff7575417c9c3c502b6a578095
parent 04668a47aedc03ccab5ea37b220324037b490e26
Author: triesap <tyson@radroots.org>
Date:   Tue, 28 Jul 2026 15:47:15 +0000

event_store: cover store authority conflicts

- reject cursor updates without prior state
- preserve expected and actual conflict context
- detect forged stored classification
- bind diagnostics to the corrupted event

Diffstat:
Mcrates/event_store/src/store.rs | 41+++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+), 0 deletions(-)

diff --git a/crates/event_store/src/store.rs b/crates/event_store/src/store.rs @@ -4331,6 +4331,19 @@ mod tests { let generation = store.source_generation().await.expect("generation"); + let missing_update = RadrootsProjectionCursor::new("missing-update", 1, generation, 1, 28) + .expect("missing update cursor"); + assert!(matches!( + store + .compare_and_swap_projection_cursor(&missing_update, Some(0)) + .await, + Err(RadrootsEventStoreError::ProjectionCursorConflict { + projection_id, + expected: Some(0), + actual: None, + }) if projection_id == "missing-update" + )); + let missing_success_ticket = store .prepare_projection_cursor_rebuild("missing-success", 1) .await @@ -5372,6 +5385,34 @@ CREATE TABLE aux.event_transport_observation (event_id TEXT);", } #[tokio::test] + async fn status_summary_rejects_stored_classification_drift() { + let store = RadrootsEventStore::open_memory().await.expect("open"); + let event = signed_event(KIND_POST, 10, Vec::new(), "classification authority"); + let event_id = event.id_str().to_owned(); + store + .ingest_event(RadrootsEventIngest::new(event, 1_000)) + .await + .expect("event ingest"); + + sqlx::query("DROP TRIGGER radroots_event_store_event_envelopes_derived_update_guard") + .execute(store.pool()) + .await + .expect("remove derived classification guard"); + sqlx::query("UPDATE event_envelopes SET projection_eligible = 0 WHERE event_id = ?") + .bind(event_id.as_str()) + .execute(store.pool()) + .await + .expect("forge stored classification"); + + assert!(matches!( + store.status_summary().await, + Err(RadrootsEventStoreError::StoredRawEventClassificationInconsistent { + event_id: actual, + }) if actual == event_id + )); + } + + #[tokio::test] async fn database_guards_reject_derived_envelope_mutation() { let store = RadrootsEventStore::open_memory().await.expect("open"); let event = signed_event(KIND_POST, 9, Vec::new(), "corruption target");