package_boundary.rs (12324B)
1 use std::collections::BTreeSet; 2 use std::fs; 3 use std::path::Path; 4 5 const MANIFEST: &str = include_str!("../Cargo.toml"); 6 const README: &str = include_str!("../README.md"); 7 const EXAMPLE: &str = include_str!("../examples/configure_transport.rs"); 8 const PUBLIC_API: &str = 9 include_str!("../../../contracts/api_baselines/radroots_transport_nostr.txt"); 10 const ROOT: &str = include_str!("../src/lib.rs"); 11 const ERROR: &str = include_str!("../src/error.rs"); 12 const PROFILE: &str = include_str!("../src/profile.rs"); 13 const SINK: &str = include_str!("../src/sink.rs"); 14 const SUBSCRIPTION: &str = include_str!("../src/subscription.rs"); 15 16 #[test] 17 fn manifest_and_root_match_the_governed_transport_boundary() { 18 for required in [ 19 "name = \"radroots_transport_nostr\"", 20 "version = \"0.1.0-alpha\"", 21 "publish = [\"crates-io\"]", 22 "[lib]\nname = \"radroots_transport_nostr\"", 23 ] { 24 assert!( 25 MANIFEST.contains(required), 26 "manifest is missing `{required}`" 27 ); 28 } 29 assert!(!MANIFEST.contains("[features]")); 30 assert_eq!( 31 radroots_dependency_keys(MANIFEST), 32 BTreeSet::from([ 33 "radroots_event_codec", 34 "radroots_nostr", 35 "radroots_protocol", 36 "radroots_transport", 37 ]) 38 ); 39 assert_eq!( 40 private_modules(ROOT), 41 BTreeSet::from([ 42 "auth", 43 "client", 44 "cursor", 45 "error", 46 "exact_delivery", 47 "profile", 48 "relay", 49 "sink", 50 "socket_write", 51 "source", 52 "source_ingress", 53 "source_wire", 54 "status", 55 "subscription" 56 ]) 57 ); 58 for export in [ 59 "pub use client::{Config, NostrTransport, ReconnectBackoff};", 60 "pub use cursor::RelayCursor;", 61 "pub use error::Error;", 62 "pub use profile::{", 63 "pub use relay::{RelayUrl, RelayUrlPolicy};", 64 "pub use sink::PreparedDelivery;", 65 ] { 66 assert!(ROOT.contains(export), "crate root is missing `{export}`"); 67 } 68 } 69 70 #[test] 71 fn documentation_example_and_reviewed_api_baseline_are_complete() { 72 for required in [ 73 "## Configure without connecting", 74 "## Public surface", 75 "## Relay and network security", 76 "## Fetch, live subscription, delivery, and outcome behavior", 77 "## Prepared delivery boundary", 78 "## Deadlines, cancellation, and commit points", 79 "## Serialization and diagnostics", 80 "## Features and runtime requirements", 81 "## Intended consumers", 82 "radroots_crates_release_v1.toml", 83 "examples/configure_transport.rs", 84 "contracts/api_baselines/radroots_transport_nostr.txt", 85 "Live subscriptions use the same explicit readable targets", 86 "exact indexed single-letter tag", 87 "Fetch reports `Complete` only after the exact subscription receives EOSE", 88 "Deadline expiry is `Cancelled`", 89 "exceeds the bounded inventory is `Partial`", 90 "inclusive `since` timestamp", 91 "permits at-least-once", 92 "same-second events in relay arrival order", 93 "never regresses the canonical target checkpoint", 94 "upstream auto-close deadline", 95 "adapter-owned worker", 96 "validates the exact request, writable\nrelay bindings, and signed-event conversion without reading a clock, polling\nstatus, or performing relay I/O", 97 "Executing a capability\nthrough a differently configured transport fails closed", 98 "let _forged = PreparedDelivery {", 99 "request: panic!(),", 100 "skipped: panic!(),", 101 "literal RFC1918 IPv4 or ULA IPv6 destinations", 102 "relay URLs and resolved addresses", 103 ] { 104 assert!(README.contains(required), "README is missing `{required}`"); 105 } 106 for required in [ 107 "Config::from_profile(", 108 "RelayEndpoint::new(", 109 "RelayProfile::explicit(", 110 "NostrTransport::new(config)", 111 "let source: &dyn EventSource", 112 "let subscriber: &dyn EventSubscriber", 113 "let sink: &dyn EventSink", 114 "drop(source.status())", 115 "let _ = subscriber", 116 "drop(sink.status())", 117 ] { 118 assert!( 119 EXAMPLE.contains(required), 120 "example is missing `{required}`" 121 ); 122 } 123 for required in [ 124 "pub struct radroots_transport_nostr::Config", 125 "pub struct radroots_transport_nostr::NostrTransport", 126 "pub struct radroots_transport_nostr::PreparedDelivery", 127 "pub enum radroots_transport_nostr::RelayAggregateState", 128 "pub struct radroots_transport_nostr::RelayProfile", 129 "pub fn radroots_transport_nostr::RelayEndpoint::new(", 130 "pub fn radroots_transport_nostr::RelayProfile::explicit<I>(", 131 "pub struct radroots_transport_nostr::RelayStatusReport", 132 "pub struct radroots_transport_nostr::RelayUrl(_)", 133 "pub enum radroots_transport_nostr::RelayUrlPolicy", 134 "pub enum radroots_transport_nostr::Error", 135 "impl radroots_transport::sink::EventSink for radroots_transport_nostr::NostrTransport", 136 "impl radroots_transport::source::EventSource for radroots_transport_nostr::NostrTransport", 137 "impl radroots_transport::source::EventSubscriber for radroots_transport_nostr::NostrTransport", 138 "NostrTransport::begin_authentication", 139 "NostrTransport::complete_authentication", 140 "NostrTransport::reject_authentication", 141 "NostrTransport::prepare_delivery", 142 "NostrTransport::execute_prepared_delivery", 143 ] { 144 assert!( 145 PUBLIC_API.contains(required), 146 "public API baseline is missing `{required}`" 147 ); 148 } 149 for forbidden in [ 150 "nostr_sdk", 151 "nostr_relay_pool", 152 "tokio::", 153 "radroots_storage", 154 "radroots_outbox", 155 "pub trait radroots_transport_nostr", 156 "impl core::clone::Clone for radroots_transport_nostr::PreparedDelivery", 157 "impl serde_core::ser::Serialize for radroots_transport_nostr::PreparedDelivery", 158 ] { 159 assert!( 160 !PUBLIC_API.contains(forbidden), 161 "reviewed public API baseline exposes `{forbidden}`" 162 ); 163 } 164 } 165 166 #[test] 167 fn public_errors_retain_no_network_or_dependency_owned_material() { 168 let declaration = ERROR 169 .split_once("pub enum Error {") 170 .expect("error declaration") 171 .1 172 .split_once("\n}") 173 .expect("error declaration end") 174 .0; 175 for forbidden in [ 176 "url:", 177 "address:", 178 "reason:", 179 "String", 180 "url::", 181 "nostr_sdk::", 182 "nostr_relay_pool::", 183 ] { 184 assert!( 185 !declaration.contains(forbidden), 186 "public error retains forbidden network material `{forbidden}`" 187 ); 188 } 189 } 190 191 #[test] 192 fn preparation_is_sealed_and_separated_from_execution_io() { 193 let prepare = SINK 194 .split_once("pub fn prepare_delivery(") 195 .expect("prepared delivery function") 196 .1 197 .split_once("pub fn execute_prepared_delivery(") 198 .expect("execution boundary") 199 .0; 200 for forbidden in [".await", "unix_time_ms", "self.status", ".publish("] { 201 assert!( 202 !prepare.contains(forbidden), 203 "delivery preparation contains I/O authority `{forbidden}`" 204 ); 205 } 206 for required in [ 207 "pub struct PreparedDelivery", 208 "#[must_use = \"prepared delivery must be durably bound before execution or deliberately discarded\"]", 209 "request: DeliveryRequest", 210 "event: ExactEvent", 211 "config: crate::Config", 212 "formatter.write_str(\"PreparedDelivery([redacted])\")", 213 "pub const fn request(&self) -> &DeliveryRequest", 214 ] { 215 assert!( 216 SINK.contains(required), 217 "prepared boundary is missing `{required}`" 218 ); 219 } 220 for forbidden in [ 221 "impl Clone for PreparedDelivery", 222 "derive(Clone", 223 "pub fn new(", 224 "pub request:", 225 "pub event:", 226 "pub config:", 227 ] { 228 assert!( 229 !prepare.contains(forbidden), 230 "prepared boundary exposes `{forbidden}`" 231 ); 232 } 233 } 234 235 #[test] 236 fn relay_profiles_have_no_implicit_destination_or_policy_constructor() { 237 for forbidden in [ 238 "DEFAULT_PUBLIC_RELAY", 239 "pub fn public", 240 "pub fn simulator", 241 "pub fn device", 242 ] { 243 assert!(!ROOT.contains(forbidden)); 244 assert!(!PROFILE.contains(forbidden)); 245 assert!(!PUBLIC_API.contains(forbidden)); 246 } 247 for required in [ 248 "pub fn new(", 249 "policy: RelayUrlPolicy", 250 "access: RelayAccess", 251 "IntoIterator<Item = RelayEndpoint>", 252 ".take(crate::client::MAX_RELAYS + 1)", 253 "Error::RelayProfilePolicyMismatch", 254 ] { 255 assert!( 256 PROFILE.contains(required), 257 "profile is missing `{required}`" 258 ); 259 } 260 } 261 262 fn radroots_dependency_keys(manifest: &str) -> BTreeSet<&str> { 263 dependency_keys(manifest) 264 .into_iter() 265 .filter(|key| key.starts_with("radroots_")) 266 .collect() 267 } 268 269 fn dependency_keys(manifest: &str) -> BTreeSet<&str> { 270 manifest 271 .split_once("[dependencies]") 272 .map(|(_, dependencies)| dependencies) 273 .unwrap_or_default() 274 .lines() 275 .skip(1) 276 .take_while(|line| !line.starts_with('[')) 277 .filter_map(|line| line.split_once('=').map(|(key, _)| key.trim())) 278 .filter(|key| !key.is_empty()) 279 .collect() 280 } 281 282 fn private_modules(root: &str) -> BTreeSet<&str> { 283 root.lines() 284 .filter_map(|line| line.trim().strip_prefix("mod ")) 285 .filter_map(|module| module.strip_suffix(';')) 286 .collect() 287 } 288 289 #[test] 290 fn adapter_owns_no_storage_outbox_or_orchestration_surface() { 291 for forbidden in [ 292 "radroots_event_store", 293 "radroots_outbox", 294 "radroots_storage", 295 "publish_claimed", 296 "fetch_and_ingest", 297 "projection_refresh", 298 "retry_schedule", 299 ] { 300 assert!(!MANIFEST.contains(forbidden)); 301 assert!(!ROOT.contains(forbidden)); 302 } 303 304 let source_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("src"); 305 let source_files = fs::read_dir(source_root) 306 .expect("source directory") 307 .map(|entry| { 308 entry 309 .expect("source entry") 310 .file_name() 311 .into_string() 312 .expect("utf-8 source name") 313 }) 314 .collect::<BTreeSet<_>>(); 315 assert_eq!( 316 source_files, 317 BTreeSet::from([ 318 "auth.rs".to_owned(), 319 "client.rs".to_owned(), 320 "cursor.rs".to_owned(), 321 "error.rs".to_owned(), 322 "exact_delivery.rs".to_owned(), 323 "lib.rs".to_owned(), 324 "profile.rs".to_owned(), 325 "relay.rs".to_owned(), 326 "sink.rs".to_owned(), 327 "socket_write.rs".to_owned(), 328 "socket_write_tests.rs".to_owned(), 329 "source.rs".to_owned(), 330 "source_budget.rs".to_owned(), 331 "source_ingress.rs".to_owned(), 332 "source_paging_tests.rs".to_owned(), 333 "source_window.rs".to_owned(), 334 "source_wire.rs".to_owned(), 335 "source_wire_tests.rs".to_owned(), 336 "status.rs".to_owned(), 337 "subscription.rs".to_owned(), 338 ]) 339 ); 340 341 for required in [ 342 "impl EventSubscriber for NostrTransport", 343 "SubscribeAutoCloseOptions::default()", 344 "ReqExitPolicy::WaitDurationAfterEOSE(query.timeout)", 345 "self.seen_event_ids.contains(event_id.as_str())", 346 "resume_cursors", 347 "let cursor_advances = self", 348 "self.terminate(SubscriptionEndReason::Cancelled)", 349 ] { 350 assert!( 351 SUBSCRIPTION.contains(required), 352 "subscription adapter is missing `{required}`" 353 ); 354 } 355 for forbidden in [ 356 "tokio::spawn", 357 "spawn_blocking", 358 "std::thread", 359 "process::", 360 "global_default", 361 ] { 362 assert!( 363 !SUBSCRIPTION.contains(forbidden), 364 "subscription adapter contains forbidden authority `{forbidden}`" 365 ); 366 } 367 }