lib

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

commit 3fd537525d955a22053715c436481e991820ed50
parent aeb160c6db51ccaf3cd4c532b044c9c4e98c5a89
Author: triesap <tyson@radroots.org>
Date:   Thu, 30 Jul 2026 19:06:38 +0000

transport: complete package conformance coverage

- gate serialization assertions to the serde feature without losing core tests
- compile-check final root exports and reject adapter or runtime dependencies
- qualify no-default, std, serde, default, all-feature, and WASM matrices
- verify docs, doctests, API boundaries, dependencies, and workspace architecture

Diffstat:
Mcrates/transport/tests/delivery_contract.rs | 1+
Mcrates/transport/tests/package_boundary.rs | 51+++++++++++++++++++++++++++++++++++++++++++++++++++
Mcrates/transport/tests/source_contract.rs | 23+++++++++++++----------
3 files changed, 65 insertions(+), 10 deletions(-)

diff --git a/crates/transport/tests/delivery_contract.rs b/crates/transport/tests/delivery_contract.rs @@ -255,6 +255,7 @@ fn retryability_and_terminality_are_explicit_normalized_data() { } #[test] +#[cfg(feature = "serde")] fn serde_revalidates_policy_outcome_and_receipt_invariants() { let request = request(SatisfactionPolicy::new( SatisfactionClass::Accepted, diff --git a/crates/transport/tests/package_boundary.rs b/crates/transport/tests/package_boundary.rs @@ -2,6 +2,8 @@ use std::collections::BTreeSet; #[allow(unused_imports)] use radroots_transport::{ + DeliveryReceipt as _, DeliveryRequest as _, Error as _, EventSink as _, EventSource as _, + FetchPage as _, FetchRequest as _, Target as _, TargetSet as _, TransportId as _, capability as _, endpoint as _, error as _, outcome as _, policy as _, sink as _, source as _, target as _, }; @@ -10,6 +12,7 @@ const MANIFEST: &str = include_str!("../Cargo.toml"); const ROOT: &str = include_str!("../src/lib.rs"); const SOURCE: &str = include_str!("../src/source.rs"); const SINK: &str = include_str!("../src/sink.rs"); +const ID: &str = include_str!("../src/id.rs"); const LEGACY_TRANSPORT: &str = include_str!("../src/transport.rs"); #[test] @@ -91,6 +94,54 @@ fn source_and_sink_are_independent_dyn_compatible_host_spis() { assert!(LEGACY_TRANSPORT.contains("#[doc(hidden)]\npub trait RadrootsTransport: Send + Sync")); } +#[test] +fn public_api_excludes_adapter_runtime_storage_and_retry_authority() { + let dependency_keys = table_keys(MANIFEST, "[dependencies]"); + for forbidden in [ + "radroots_outbox", + "radroots_storage", + "radroots_transport_nostr", + "radroots_transport_reticulum", + "nostr-sdk", + "nostr_sdk", + "reqwest", + "sqlx", + "tokio", + ] { + assert!( + !dependency_keys.contains(forbidden), + "generic transport must not depend on `{forbidden}`" + ); + } + + assert!(ID.contains("pub struct TransportId(")); + assert!(!ID.contains("pub enum TransportId")); + for forbidden in [ + "RADROOTS_RETICULUM_", + "ReticulumDestination", + "RelayUrl", + "NostrRelay", + ] { + assert!( + !ROOT.contains(forbidden), + "generic transport root must not export adapter symbol `{forbidden}`" + ); + } + for source in [SOURCE, SINK] { + for forbidden in [ + "tokio::spawn", + "std::thread::spawn", + "retry_loop", + "fallback_transport", + ] { + assert!( + !source.contains(forbidden), + "transport SPI must not own runtime behavior `{forbidden}`" + ); + } + } +} + fn table_keys<'a>(source: &'a str, heading: &str) -> BTreeSet<&'a str> { let mut in_table = false; source diff --git a/crates/transport/tests/source_contract.rs b/crates/transport/tests/source_contract.rs @@ -120,16 +120,19 @@ fn page_preserves_cursor_provenance_and_partial_target_outcomes() { ); assert!(matches!(page.next_page(), NextPage::Cursor(cursor) if cursor.as_str() == "page-2")); - let encoded = serde_json::to_string(&page).expect("serialize page"); - assert!(!encoded.contains("admission")); - assert!(!encoded.contains("storage")); - assert_eq!( - serde_json::from_str::<FetchPage>(&encoded).expect("deserialize page"), - page - ); - let mut invalid_time = serde_json::to_value(&page).expect("page value"); - invalid_time["events"][0]["provenance"]["observed_at_unix_ms"] = 0.into(); - assert!(serde_json::from_value::<FetchPage>(invalid_time).is_err()); + #[cfg(feature = "serde")] + { + let encoded = serde_json::to_string(&page).expect("serialize page"); + assert!(!encoded.contains("admission")); + assert!(!encoded.contains("storage")); + assert_eq!( + serde_json::from_str::<FetchPage>(&encoded).expect("deserialize page"), + page + ); + let mut invalid_time = serde_json::to_value(&page).expect("page value"); + invalid_time["events"][0]["provenance"]["observed_at_unix_ms"] = 0.into(); + assert!(serde_json::from_value::<FetchPage>(invalid_time).is_err()); + } } #[test]