lib

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

commit f4a352183041e288c605fe4d840d19f1131af94a
parent c47ca80391953813005cb658dd6617640154c99b
Author: triesap <tyson@radroots.org>
Date:   Tue, 30 Jun 2026 23:52:39 +0000

tests: harden SDK root trade guards

- broaden removed root trade alias detection
- guard RadrootsClient against trade shortcut methods
- allow internal trade status error identifiers
- prove the SDK source-boundary lane

Diffstat:
Mcrates/sdk/tests/source_boundary.rs | 156+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 156 insertions(+), 0 deletions(-)

diff --git a/crates/sdk/tests/source_boundary.rs b/crates/sdk/tests/source_boundary.rs @@ -78,6 +78,14 @@ const FORBIDDEN_SDK_README_CONCEPTS: &[ForbiddenSdkConcept] = &[ }, ]; +const FORBIDDEN_SDK_ROOT_TRADE_ALIAS_NAMES: &[&str] = &[ + "trade_buyer", + "trade_seller", + "trade_status", + "trade_resync", + "trade_validation", +]; + const REQUIRED_SDK_README_CONCEPTS: &[&str] = &[ "RadrootsClient::builder()", "sdk.trades()", @@ -442,6 +450,70 @@ fn sdk_readme_documents_current_public_product_surface() { } #[test] +fn sdk_sources_do_not_reintroduce_root_trade_alias_surface() { + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + + for path in sdk_root_alias_guard_files(manifest_dir) { + let source = read_source(path.as_path()); + let relative_path = relative_manifest_path(manifest_dir, path.as_path()); + let findings = root_trade_alias_findings(relative_path.as_str(), source.as_str()); + assert!( + findings.is_empty(), + "SDK root trade aliases are forbidden:\n{}", + findings.join("\n") + ); + } +} + +#[test] +fn radroots_client_does_not_expose_root_trade_alias_methods() { + let source = read_source( + Path::new(env!("CARGO_MANIFEST_DIR")) + .join("src/runtime.rs") + .as_path(), + ); + let client_impl = impl_block(source.as_str(), "impl RadrootsClient {"); + let findings = root_trade_alias_findings("src/runtime.rs RadrootsClient impl", client_impl); + + assert!( + findings.is_empty(), + "RadrootsClient must expose grouped product handles instead of root trade aliases:\n{}", + findings.join("\n") + ); +} + +#[test] +fn root_trade_alias_scanner_preserves_internal_status_identifiers() { + let allowed_source = r#" + let code = "trade_status_limit_invalid"; + let error = RadrootsSdkError::trade_status_limit_invalid(0, 1, 100); + async fn dvm_validation_receipt_ingest_commits_pending_trade_status() {} + "#; + assert!( + root_trade_alias_findings("allowed_fixture.rs", allowed_source).is_empty(), + "internal status identifiers must remain allowed when they are not root alias calls or definitions" + ); + + let forbidden_source = r#" + impl RadrootsClient { + pub async fn trade_status(&self) {} + } + async fn workflow(sdk: RadrootsClient) { + sdk.trade_resync (request).await; + RadrootsClient::trade_buyer(&sdk); + } + "#; + let findings = root_trade_alias_findings("forbidden_fixture.rs", forbidden_source); + + for alias in ["trade_status", "trade_resync", "trade_buyer"] { + assert!( + findings.iter().any(|finding| finding.contains(alias)), + "root trade alias scanner must reject `{alias}`" + ); + } +} + +#[test] fn farm_runtime_stays_on_product_runtime_boundary() { product_runtime_file_stays_on_boundary("src/farms_runtime.rs"); } @@ -1009,6 +1081,23 @@ fn product_runtime_file_stays_on_boundary(relative_path: &str) { } } +fn sdk_root_alias_guard_files(manifest_dir: &Path) -> Vec<PathBuf> { + let mut paths = vec![manifest_dir.join("README")]; + + for relative_root in ["src", "examples", "tests"] { + let root = manifest_dir.join(relative_root); + if root.exists() { + paths.extend(rust_source_files(root.as_path())); + } + } + + paths.retain(|path| { + path.file_name().and_then(|file_name| file_name.to_str()) != Some("source_boundary.rs") + }); + paths.sort(); + paths +} + fn read_source(path: &Path) -> String { fs::read_to_string(path) .unwrap_or_else(|error| panic!("failed to read source {}: {error}", path.display())) @@ -1023,6 +1112,73 @@ fn contains_forbidden_concept(source: &str, pattern: &str) -> bool { }) } +fn root_trade_alias_findings(relative_path: &str, source: &str) -> Vec<String> { + let mut findings = Vec::new(); + + for alias in FORBIDDEN_SDK_ROOT_TRADE_ALIAS_NAMES { + for (index, _) in source.match_indices(alias) { + let before = source[..index].chars().next_back(); + let after_index = index + alias.len(); + let after = source[after_index..].chars().next(); + + if before.is_some_and(is_rust_identifier_character) + || after.is_some_and(is_rust_identifier_character) + { + continue; + } + + if source[after_index..] + .chars() + .find(|character| !character.is_whitespace()) + != Some('(') + { + continue; + } + + let prefix = source[..index].trim_end(); + let reason = if prefix.ends_with('.') { + "root client method call" + } else if prefix.ends_with("::") { + "root client associated function call" + } else if prefix_ends_with_keyword(prefix, "fn") { + "function or method definition" + } else { + continue; + }; + + findings.push(format!( + "{relative_path}:{} uses `{alias}` as a {reason}", + line_number(source, index) + )); + } + } + + findings +} + +fn prefix_ends_with_keyword(source: &str, keyword: &str) -> bool { + source.ends_with(keyword) + && source[..source.len() - keyword.len()] + .chars() + .next_back() + .is_none_or(|character| !is_rust_identifier_character(character)) +} + +fn line_number(source: &str, index: usize) -> usize { + source[..index] + .bytes() + .filter(|byte| *byte == b'\n') + .count() + + 1 +} + +fn relative_manifest_path(manifest_dir: &Path, path: &Path) -> String { + path.strip_prefix(manifest_dir) + .unwrap_or(path) + .display() + .to_string() +} + fn function_source<'source>(source: &'source str, function_name: &str) -> &'source str { let signature = format!("async fn {function_name}"); let start = source