commit 69aaf27ba95fd97a2dd431f22331218a05ecc0c0
parent 41acfb8af066a1f08e870eb43a09ffed8c428b22
Author: triesap <tyson@radroots.org>
Date: Tue, 28 Jul 2026 11:42:20 +0000
event_store: cover isolated storage boundaries
- format inbound foreign keys with one fallible write
- classify optional trade contracts through a closed predicate
- reject out-of-range authored timestamps before SQL writes
- cover malformed stored-head coordinate authority
Diffstat:
5 files changed, 90 insertions(+), 19 deletions(-)
diff --git a/contracts/event_store_production_sources.toml b/contracts/event_store_production_sources.toml
@@ -3,7 +3,7 @@ hash_algorithm = "rust_production_ast_sha256_v1"
[[sources]]
path = "crates/event_store/src/error.rs"
-sha256 = "e218754814e195a76fcdfa99c4c4abeaa3b045b4c799b56685ed8acfe5edb90b"
+sha256 = "4cced9506c8c0c78d7826460a3aba0a0466ab739974fa26de2f78b46f19d5d6b"
[[sources]]
path = "crates/event_store/src/lib.rs"
@@ -91,7 +91,7 @@ sha256 = "1a5569a1a29849db3eeebc92316aeea26db4b2dc58b7b7f297349fcb89b0ca34"
[[sources]]
path = "crates/event_store/src/store/post_core_extensions_v1.rs"
-sha256 = "4b12d5257e425ed1e15e20dec3558d1b02455f86b95342900db7d10286d6da00"
+sha256 = "03829790c0bdbd7dea13099b24f1f0edae2361e5e5f5eaf93d763bd7d018706b"
[[sources]]
path = "crates/event_store/src/store/post_core_extensions_v2.rs"
diff --git a/crates/event_store/src/error.rs b/crates/event_store/src/error.rs
@@ -107,23 +107,22 @@ pub struct RadrootsEventStoreCallerInboundForeignKeyV1 {
impl core::fmt::Display for RadrootsEventStoreCallerInboundForeignKeyV1 {
fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ let (parent_column_open, parent_column, parent_column_close) =
+ match self.parent_column.as_deref() {
+ Some(parent_column) => ("`", parent_column, "`"),
+ None => ("", "<implicit primary key>", ""),
+ };
write!(
formatter,
- "{}:{} on `{}` (`{}` -> `{}`.",
+ "{}:{} on `{}` (`{}` -> `{}`.{parent_column_open}{parent_column}{parent_column_close}, on update {}, on delete {}, match {})",
self.foreign_key_id,
self.foreign_key_sequence,
self.child_table,
self.child_column,
self.parent_table,
- )?;
- match self.parent_column.as_deref() {
- Some(parent_column) => write!(formatter, "`{parent_column}`")?,
- None => formatter.write_str("<implicit primary key>")?,
- }
- write!(
- formatter,
- ", on update {}, on delete {}, match {})",
- self.on_update, self.on_delete, self.match_clause,
+ self.on_update,
+ self.on_delete,
+ self.match_clause,
)
}
}
diff --git a/crates/event_store/src/store.rs b/crates/event_store/src/store.rs
@@ -25,7 +25,7 @@ use self::post_core_extensions_v1::{
};
#[cfg(test)]
use self::post_core_storage_v1::{
- i64_from_usize_for_test as i64_from_usize,
+ PostCoreStorageV1, TradeProjectionWrite, i64_from_usize_for_test as i64_from_usize,
register_protocol_post_extension_raw_authority_forge,
register_protocol_post_extension_schema_forge,
trade_mutation_kind_storage_value_for_test as trade_mutation_kind_storage_value,
@@ -6155,6 +6155,45 @@ CREATE TABLE aux.event_transport_observation (event_id TEXT);",
}
#[tokio::test]
+ async fn trade_projection_rejects_authored_timestamps_outside_sqlite_range() {
+ let store = RadrootsEventStore::open_memory().await.expect("open");
+ let canonical =
+ canonical_trade_mutation_content(proposal_envelope()).expect("canonical proposal");
+ let signed = signed_trade_mutation(&canonical);
+ let ingest = RadrootsEventIngest::new(signed, 2_250);
+ let mut mutation = canonical.envelope.clone();
+ mutation.authored_at_unix_s = u64::MAX;
+ let mut transaction = store
+ .begin_write_transaction()
+ .await
+ .expect("write transaction");
+ let mut storage = PostCoreStorageV1::new(&mut transaction);
+ let candidate_id = candidate_id_for_mutation(&mutation);
+ let proposal_mutation_id = proposal_mutation_id_for_mutation(&mutation);
+ let target_claim_mutation_id = target_claim_mutation_id_for_mutation(&mutation);
+ let write = TradeProjectionWrite::new(
+ ingest.event(),
+ 1,
+ &mutation,
+ &canonical.mutation_id,
+ candidate_id.as_ref(),
+ proposal_mutation_id.as_ref(),
+ target_claim_mutation_id.as_ref(),
+ "fixture-sha256",
+ ingest.observed_at_ms(),
+ seller_reservation_for_mutation(&mutation),
+ );
+
+ assert!(matches!(
+ storage.persist_trade_projection(write).await,
+ Err(RadrootsEventStoreError::UnsignedIntegerRange {
+ field: "authored_at_unix_s",
+ value: u64::MAX,
+ })
+ ));
+ }
+
+ #[tokio::test]
async fn ingest_rejects_governed_temp_shadow_before_owned_or_borrowed_mutation() {
let owned = RadrootsEventStore::open_memory()
.await
diff --git a/crates/event_store/src/store/post_core_extensions_v1.rs b/crates/event_store/src/store/post_core_extensions_v1.rs
@@ -18,10 +18,7 @@ pub(super) async fn apply_post_core_extensions_v1(
if let Some(stored_event_seq) = result.inserted_seq
&& result.receipt.valid_stream_eligible
{
- let is_trade_mutation = match &result.receipt.contract_id {
- Some(contract_id) => is_trade_mutation_contract_id(contract_id.as_str()),
- None => false,
- };
+ let is_trade_mutation = is_trade_mutation_contract(result.receipt.contract_id.as_deref());
if is_trade_mutation {
store_trade_mutation_event(storage, ingest, stored_event_seq).await?;
}
@@ -36,8 +33,11 @@ pub(super) async fn apply_post_core_extensions_v1(
Ok(())
}
-fn is_trade_mutation_contract_id(contract_id: &str) -> bool {
- RADROOTS_TRADE_MUTATION_CONTRACT_IDS.contains(&contract_id)
+fn is_trade_mutation_contract(contract_id: Option<&str>) -> bool {
+ match contract_id {
+ Some(contract_id) => RADROOTS_TRADE_MUTATION_CONTRACT_IDS.contains(&contract_id),
+ None => false,
+ }
}
async fn store_trade_mutation_event(
@@ -209,3 +209,17 @@ pub(super) fn seller_reservation_for_mutation_for_test(
pub(super) fn sha256_hex_for_test(bytes: &[u8]) -> String {
sha256_hex(bytes)
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn trade_mutation_contract_classification_is_closed() {
+ assert!(!is_trade_mutation_contract(None));
+ assert!(!is_trade_mutation_contract(Some("radroots.unknown.v1")));
+ for contract_id in RADROOTS_TRADE_MUTATION_CONTRACT_IDS {
+ assert!(is_trade_mutation_contract(Some(contract_id)));
+ }
+ }
+}
diff --git a/crates/event_store/src/store/protocol_storage_v1.rs b/crates/event_store/src/store/protocol_storage_v1.rs
@@ -430,4 +430,23 @@ mod tests {
}) if stored_event_id == event_id
));
}
+
+ #[tokio::test]
+ async fn stored_raw_head_rejects_an_unknown_coordinate_type() {
+ let store = crate::RadrootsEventStore::open_memory()
+ .await
+ .expect("open store");
+ let row = sqlx::query("SELECT 'unknown' AS raw_head_coordinate_type")
+ .fetch_one(store.pool())
+ .await
+ .expect("fixture row");
+
+ assert!(matches!(
+ stored_raw_head_from_joined_row(&row),
+ Err(RadrootsEventStoreError::InvalidStoredEnum {
+ field: "event_class",
+ value,
+ }) if value == "unknown"
+ ));
+ }
}