lib

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

commit e27df066f628a1583b053c4c195ca3463c8dc1f0
parent 961fd6b18e61cba6d4ed4be7b8576b5dcfecc4db
Author: triesap <tyson@radroots.org>
Date:   Tue, 28 Jul 2026 06:44:36 +0000

event_store: cover projection wrapper boundaries

- reject inconsistent stored-event classification combinations
- exercise valid and visible wrapper ownership transitions
- cover projection cursor, ticket, and diagnostic boundaries
- preserve production AST hashes while improving governed coverage

Diffstat:
Mcrates/event_store/src/model.rs | 100+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/event_store/src/model/food_availability_projection_v1.rs | 33+++++++++++++++++++++++++++++++++
2 files changed, 133 insertions(+), 0 deletions(-)

diff --git a/crates/event_store/src/model.rs b/crates/event_store/src/model.rs @@ -808,6 +808,106 @@ mod tests { } #[test] + fn stored_event_wrappers_and_projection_authority_cover_typed_boundaries() { + let raw = RadrootsStoredRawEvent { + seq: 1, + event_id: "a".repeat(64), + pubkey: "b".repeat(64), + created_at: 1, + kind: 10_001, + tags_json: "[]".to_owned(), + content: String::new(), + sig: "c".repeat(128), + raw_json: "{}".to_owned(), + admission_status: RadrootsEventAdmissionStatus::Admitted, + contract_id: None, + event_class: StoredEventClass::Replaceable, + valid_stream_eligible: true, + inserted_at_ms: 1, + updated_at_ms: 1, + }; + + let mut invalid = raw.clone(); + invalid.admission_status = RadrootsEventAdmissionStatus::Unsupported; + assert!(RadrootsStoredValidEvent::try_from_raw(invalid).is_err()); + invalid = raw.clone(); + invalid.event_class = StoredEventClass::Regular; + assert!(RadrootsStoredValidEvent::try_from_raw(invalid).is_err()); + invalid = raw.clone(); + invalid.kind = 20_001; + invalid.event_class = StoredEventClass::Ephemeral; + assert!(RadrootsStoredValidEvent::try_from_raw(invalid).is_err()); + invalid = raw.clone(); + invalid.valid_stream_eligible = false; + assert!(RadrootsStoredValidEvent::try_from_raw(invalid).is_err()); + + let valid = RadrootsStoredValidEvent::try_from_raw(raw.clone()).expect("valid event"); + assert_eq!(valid.raw_event(), &raw); + assert_eq!(valid.clone().into_raw_event(), raw); + let visible = RadrootsStoredVisibleEvent::new(valid.clone()); + assert_eq!(visible.valid_event(), &valid); + assert_eq!(visible.clone().into_valid_event(), valid); + let raw_head = RadrootsStoredRawEventHead { + coordinate_type: StoredEventClass::Replaceable, + kind: 10_001, + pubkey: "b".repeat(64), + d_tag: None, + event_id: "a".repeat(64), + created_at: 1, + updated_at_ms: 1, + }; + let head = RadrootsStoredVisibleEventHead::new(raw_head.clone(), visible.clone()); + assert_eq!(head.raw_head(), &raw_head); + assert_eq!(head.event(), &visible); + + let source_generation = RadrootsEventStoreSourceGeneration::from_bytes([0x42; 32]); + assert!(matches!( + RadrootsProjectionCursor::new("", 1, source_generation, 0, 1), + Err(RadrootsEventStoreError::InvalidProjectionId) + )); + assert!(matches!( + RadrootsProjectionCursor::new("fixture", 0, source_generation, 0, 1), + Err(RadrootsEventStoreError::InvalidProjectionVersion { value: 0, .. }) + )); + assert!(matches!( + RadrootsProjectionCursor::new("fixture", 1, source_generation, -1, 1), + Err(RadrootsEventStoreError::InvalidProjectionCursor { value: -1, .. }) + )); + let cursor = RadrootsProjectionCursor::new("fixture", 2, source_generation, 7, 9) + .expect("projection cursor"); + assert_eq!(cursor.projection_id(), "fixture"); + assert_eq!(cursor.projection_version(), 2); + assert_eq!(cursor.source_generation(), source_generation); + assert_eq!(cursor.last_event_seq(), 7); + assert_eq!(cursor.updated_at_ms(), 9); + + let ticket = RadrootsProjectionRebuildTicket { + projection_id: "fixture".to_owned(), + target_projection_version: 3, + target_source_generation: source_generation, + target_raw_high_water_seq: 11, + prior: RadrootsProjectionRebuildPrior::Cursor { + source_generation: Some(source_generation), + source_revision: 1, + projection_version: 2, + last_event_seq: 7, + updated_at_ms: 9, + }, + }; + assert_eq!(ticket.projection_id(), "fixture"); + assert_eq!(ticket.target_projection_version(), 3); + assert_eq!(ticket.target_source_generation(), source_generation); + assert_eq!(ticket.target_raw_high_water_seq(), 11); + assert!(matches!( + ticket.prior(), + RadrootsProjectionRebuildPrior::Cursor { + source_revision: 1, + .. + } + )); + } + + #[test] fn head_decisions_and_tag_metadata_names_cover_all_variants() { let coordinate = RadrootsEventHeadCoordinate::Addressable { kind: 30_023, diff --git a/crates/event_store/src/model/food_availability_projection_v1.rs b/crates/event_store/src/model/food_availability_projection_v1.rs @@ -493,6 +493,11 @@ mod tests { Some("active") ); assert_eq!( + RadrootsFoodAvailabilityStatusFilterV1::from(RadrootsFoodAvailabilityStatus::Active) + .storage_value(), + Some("active") + ); + assert_eq!( RadrootsFoodAvailabilityStatusFilterV1::from(RadrootsFoodAvailabilityStatus::Sold) .storage_value(), Some("sold") @@ -534,5 +539,33 @@ mod tests { ), Err(RadrootsEventStoreError::FoodAvailabilityProjectionDrift { .. }) )); + + let clean = RadrootsStoredFoodAvailabilityImageV1 { + image_index: 0, + raw_tag: vec!["image".to_owned()], + url: None, + dimensions: None, + blossom_sha256: None, + diagnostics: Vec::new(), + }; + let image_level_count = RadrootsStoredFoodAvailabilityImageV1 { + diagnostics: vec![RadrootsFoodAvailabilityImageDiagnostic::CountExceeded], + ..clean.clone() + }; + assert!(validate_projection_diagnostics(&[], &[image_level_count]).is_err()); + + let maximum_clean = vec![clean.clone(); RADROOTS_FOOD_IMAGE_MAX_COUNT]; + validate_projection_diagnostics( + &[RadrootsFoodAvailabilityImageDiagnostic::CountExceeded], + &maximum_clean, + ) + .expect("coherent count diagnostic"); + assert!( + validate_projection_diagnostics( + &[RadrootsFoodAvailabilityImageDiagnostic::DimensionsMissing], + &[clean], + ) + .is_err() + ); } }