lib

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

commit f74e8272809e9b65863a8b69cda74fbf8f511b91
parent 561d56fde65e6e2817029fc005c959b73f3c38fd
Author: triesap <tyson@radroots.org>
Date:   Tue, 28 Jul 2026 10:29:03 +0000

event_store: cover stored food model boundaries

- drive storage from a real signed food projection
- reject an unrepresentable projected image index
- map invalid publication chronology into typed drift
- exercise the governed d-tag alias on stored food

Diffstat:
Mcrates/event_store/src/model/food_availability_projection_v1.rs | 8++++++++
Mcrates/event_store/src/store.rs | 63+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 71 insertions(+), 0 deletions(-)

diff --git a/crates/event_store/src/model/food_availability_projection_v1.rs b/crates/event_store/src/model/food_availability_projection_v1.rs @@ -183,6 +183,14 @@ impl RadrootsStoredFoodAvailabilityImageV1 { }) } + #[cfg(test)] + pub(crate) fn from_projection_for_test( + image_index: usize, + image: &RadrootsInboundFoodAvailabilityImage, + ) -> Result<Self, RadrootsEventStoreError> { + Self::from_projection(image_index, image) + } + pub const fn image_index(&self) -> u32 { self.image_index } diff --git a/crates/event_store/src/store.rs b/crates/event_store/src/store.rs @@ -7101,6 +7101,7 @@ CREATE TABLE aux.event_transport_observation (event_id TEXT);", .expect("food lookup") .expect("projected carrots"); assert_eq!(projected.event_id().as_str(), carrots.id_str()); + assert_eq!(projected.d_tag(), &carrot_id); assert_eq!(projected.title().as_str(), "Nantes Carrots"); assert_eq!(projected.summary().as_str(), "Fresh bunches"); assert_eq!(projected.price().amount(), "3"); @@ -7256,6 +7257,68 @@ CREATE TABLE aux.event_transport_observation (event_id TEXT);", assert_eq!(replacement_matches[0].event_id().as_str(), sold.id_str()); } + #[test] + fn stored_food_projection_rejects_unrepresentable_internal_boundaries() { + let event = food_availability_event( + 200, + "bounded-model-carrots", + "Bounded Model Carrots", + "Fresh model harvest", + "active", + vec![vec![ + "image".to_owned(), + "https://media.example/2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824.webp" + .to_owned(), + "800x600".to_owned(), + ]], + ); + let ingest = RadrootsEventIngest::new(event.clone(), 10_000); + let projection = match radroots_event_codec::food_availability::inbound::registry_v7::project_verified_food_availability_event_registry_v7( + ingest.verified_event(), + ) + .expect("food projection") + { + radroots_event_codec::food_availability::inbound::registry_v7::RadrootsFoodAvailabilityProjectionOutcome::Focused(projection) => projection, + _ => panic!("unexpected food projection outcome"), + }; + let image = projection.images().first().expect("projected image"); + assert!(matches!( + crate::RadrootsStoredFoodAvailabilityImageV1::from_projection_for_test( + usize::MAX, + image, + ), + Err(RadrootsEventStoreError::FoodAvailabilityProjectionDrift { ref reason }) + if reason.contains("image index exceeds") + )); + + let author = RadrootsPublicKey::parse(event.pubkey_str()).expect("author"); + let event_id = RadrootsEventId::parse(event.id_str()).expect("event id"); + assert!(matches!( + crate::RadrootsStoredFoodAvailabilityV1::from_projection( + RadrootsEventStoreSourceGeneration::from_bytes([0x55; 32]), + author.clone(), + event_id.clone(), + 1, + 99, + 1, + &projection, + ), + Err(RadrootsEventStoreError::FoodAvailabilityProjectionDrift { .. }) + )); + + let stored = crate::RadrootsStoredFoodAvailabilityV1::from_projection( + RadrootsEventStoreSourceGeneration::from_bytes([0x55; 32]), + author, + event_id, + 1, + 200, + 1, + &projection, + ) + .expect("bounded stored projection"); + assert_eq!(stored.d_tag().as_str(), "bounded-model-carrots"); + } + #[tokio::test] async fn food_availability_projection_guards_images_and_exhaustive_audit_detects_fts_drift() { let store = RadrootsEventStore::open_memory().await.expect("open");