sdk

Radroots SDK and bindings
git clone https://radroots.dev/git/sdk.git
Log | Files | Refs | README

commit 7c0177cd5b2261e2e5bea054907aa6147d52aae7
parent 2452accade2358dc65a38fb22f654d2eab60fd2e
Author: triesap <tyson@radroots.org>
Date:   Mon, 27 Jul 2026 08:05:57 +0000

facade: align package manifest and module root

- Create the non-publishable radroots package at its final sdk-owned identity.
- Reserve the approved feature and eleven-module public vocabularies.
- Avoid temporary edges from the public facade to private migration packages.
- Guard metadata and surface boundaries with package and repository checks.

Diffstat:
MCargo.toml | 1+
Acrates/radroots/Cargo.toml | 26++++++++++++++++++++++++++
Acrates/radroots/README.md | 11+++++++++++
Acrates/radroots/src/client.rs | 1+
Acrates/radroots/src/event.rs | 1+
Acrates/radroots/src/farm.rs | 1+
Acrates/radroots/src/identity.rs | 1+
Acrates/radroots/src/knowledge.rs | 1+
Acrates/radroots/src/lib.rs | 19+++++++++++++++++++
Acrates/radroots/src/listing.rs | 1+
Acrates/radroots/src/signing.rs | 1+
Acrates/radroots/src/storage.rs | 1+
Acrates/radroots/src/sync.rs | 1+
Acrates/radroots/src/trade.rs | 1+
Acrates/radroots/src/transport.rs | 1+
Acrates/radroots/tests/public_surface.rs | 7+++++++
Mtools/xtask/src/check.rs | 157+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 files changed, 232 insertions(+), 0 deletions(-)

diff --git a/Cargo.toml b/Cargo.toml @@ -9,6 +9,7 @@ members = [ "crates/replica_schema_bindings", "crates/replica_sync_wasm", "crates/runtime_contract_v1", + "crates/radroots", "crates/sdk", "crates/sql_wasm_runtime", "crates/trade_bindings", diff --git a/crates/radroots/Cargo.toml b/crates/radroots/Cargo.toml @@ -0,0 +1,26 @@ +[package] +name = "radroots" +description = "Curated ordinary-user Rust facade for Radroots" +version.workspace = true +edition.workspace = true +rust-version.workspace = true +license.workspace = true +repository.workspace = true +homepage.workspace = true +readme = "README.md" +publish = false + +[lib] +name = "radroots" +path = "src/lib.rs" + +[features] +default = ["client"] +client = [] +native = ["client"] +nostr = ["client"] +nip46 = ["nostr"] +radrootsd = ["client"] +geonames = ["client"] +knowledge = ["client"] +full = ["native", "nostr", "nip46", "radrootsd", "geonames", "knowledge"] diff --git a/crates/radroots/README.md b/crates/radroots/README.md @@ -0,0 +1,11 @@ +# radroots + +`radroots` is the curated ordinary-user Rust facade for Radroots. This initial +non-publishable scaffold reserves the final package identity, public module +vocabulary, and feature vocabulary while the lower release-v1 packages are +being established. + +The facade intentionally contains no temporary dependency on private +migration crates. Its final builders, safe defaults, curated re-exports, and +dependency forwarding are implemented and qualified in the owned facade +checkpoints before publication is enabled. diff --git a/crates/radroots/src/client.rs b/crates/radroots/src/client.rs @@ -0,0 +1 @@ +//! Curated client construction and operation entry points. diff --git a/crates/radroots/src/event.rs b/crates/radroots/src/event.rs @@ -0,0 +1 @@ +//! Curated event authoring and inspection entry points. diff --git a/crates/radroots/src/farm.rs b/crates/radroots/src/farm.rs @@ -0,0 +1 @@ +//! Curated farm-domain entry points. diff --git a/crates/radroots/src/identity.rs b/crates/radroots/src/identity.rs @@ -0,0 +1 @@ +//! Curated public identity entry points. diff --git a/crates/radroots/src/knowledge.rs b/crates/radroots/src/knowledge.rs @@ -0,0 +1 @@ +//! Curated knowledge-domain entry points. diff --git a/crates/radroots/src/lib.rs b/crates/radroots/src/lib.rs @@ -0,0 +1,19 @@ +#![forbid(unsafe_code)] +#![warn(missing_docs)] + +//! Curated ordinary-user entry point for Radroots. +//! +//! This non-publishable scaffold reserves the final module and feature +//! vocabulary without exposing private migration packages. + +pub mod client; +pub mod event; +pub mod farm; +pub mod identity; +pub mod knowledge; +pub mod listing; +pub mod signing; +pub mod storage; +pub mod sync; +pub mod trade; +pub mod transport; diff --git a/crates/radroots/src/listing.rs b/crates/radroots/src/listing.rs @@ -0,0 +1 @@ +//! Curated listing-domain entry points. diff --git a/crates/radroots/src/signing.rs b/crates/radroots/src/signing.rs @@ -0,0 +1 @@ +//! Curated signing entry points. diff --git a/crates/radroots/src/storage.rs b/crates/radroots/src/storage.rs @@ -0,0 +1 @@ +//! Curated storage entry points. diff --git a/crates/radroots/src/sync.rs b/crates/radroots/src/sync.rs @@ -0,0 +1 @@ +//! Curated synchronization entry points. diff --git a/crates/radroots/src/trade.rs b/crates/radroots/src/trade.rs @@ -0,0 +1 @@ +//! Curated trade-domain entry points. diff --git a/crates/radroots/src/transport.rs b/crates/radroots/src/transport.rs @@ -0,0 +1 @@ +//! Curated transport entry points. diff --git a/crates/radroots/tests/public_surface.rs b/crates/radroots/tests/public_surface.rs @@ -0,0 +1,7 @@ +#[test] +fn approved_module_skeleton_is_public() { + #[allow(unused_imports)] + use radroots::{ + client, event, farm, identity, knowledge, listing, signing, storage, sync, trade, transport, + }; +} diff --git a/tools/xtask/src/check.rs b/tools/xtask/src/check.rs @@ -30,6 +30,30 @@ const PACKAGE_HOMEPAGE: &str = "https://radroots.org"; const PACKAGE_REPOSITORY_URL: &str = "git+https://github.com/radrootslabs/sdk.git"; const PUBLISH_ACCESS: &str = "public"; const ALLOWED_RETICULUM_PREVIEW_PACKAGE: &str = "radroots-transport-reticulum"; +const RADROOTS_FACADE_MODULES: [&str; 11] = [ + "client", + "event", + "farm", + "identity", + "knowledge", + "listing", + "signing", + "storage", + "sync", + "trade", + "transport", +]; +const RADROOTS_FACADE_FEATURES: [&str; 9] = [ + "client", + "default", + "full", + "geonames", + "knowledge", + "native", + "nip46", + "nostr", + "radrootsd", +]; #[derive(Debug, Deserialize)] struct PnpmPackEntry { @@ -119,6 +143,7 @@ pub fn check() -> Result<(), String> { let root = workspace_root()?; crate::architecture::validate(&root)?; check_publication_policy(&root)?; + check_radroots_facade_scaffold(&root)?; validate_sdk_contracts(&root)?; check_sdk_feature_matrix(&root)?; check_forbidden_packages(&root)?; @@ -131,6 +156,138 @@ pub fn check() -> Result<(), String> { Ok(()) } +fn check_radroots_facade_scaffold(root: &Path) -> Result<(), String> { + let manifest_path = root.join("crates/radroots/Cargo.toml"); + let manifest_raw = fs::read_to_string(&manifest_path) + .map_err(|error| format!("failed to read {}: {error}", manifest_path.display()))?; + let manifest = manifest_raw + .parse::<toml::Value>() + .map_err(|error| format!("failed to parse {}: {error}", manifest_path.display()))?; + let package = manifest + .get("package") + .and_then(toml::Value::as_table) + .ok_or_else(|| "crates/radroots/Cargo.toml must define [package]".to_owned())?; + for (field, expected) in [ + ("name", "radroots"), + ( + "description", + "Curated ordinary-user Rust facade for Radroots", + ), + ("readme", "README.md"), + ] { + if package.get(field).and_then(toml::Value::as_str) != Some(expected) { + return Err(format!( + "crates/radroots/Cargo.toml package.{field} must be {expected}" + )); + } + } + if package.get("publish").and_then(toml::Value::as_bool) != Some(false) { + return Err("radroots facade must remain publish = false during the scaffold".to_owned()); + } + for field in [ + "version", + "edition", + "rust-version", + "license", + "repository", + "homepage", + ] { + let inherited = package + .get(field) + .and_then(toml::Value::as_table) + .and_then(|value| value.get("workspace")) + .and_then(toml::Value::as_bool); + if inherited != Some(true) { + return Err(format!( + "crates/radroots/Cargo.toml package.{field} must inherit workspace metadata" + )); + } + } + let library = manifest + .get("lib") + .and_then(toml::Value::as_table) + .ok_or_else(|| "crates/radroots/Cargo.toml must define [lib]".to_owned())?; + if library.get("name").and_then(toml::Value::as_str) != Some("radroots") + || library.get("path").and_then(toml::Value::as_str) != Some("src/lib.rs") + { + return Err("radroots facade [lib] must use name radroots and path src/lib.rs".to_owned()); + } + for dependency_table in ["dependencies", "dev-dependencies", "build-dependencies"] { + if manifest + .get(dependency_table) + .and_then(toml::Value::as_table) + .is_some_and(|dependencies| !dependencies.is_empty()) + { + return Err(format!( + "radroots scaffold must not depend on private migration packages through [{dependency_table}]" + )); + } + } + + let features = manifest + .get("features") + .and_then(toml::Value::as_table) + .ok_or_else(|| "crates/radroots/Cargo.toml must define [features]".to_owned())?; + let actual_features = features.keys().map(String::as_str).collect::<BTreeSet<_>>(); + let expected_features = RADROOTS_FACADE_FEATURES + .into_iter() + .collect::<BTreeSet<_>>(); + if actual_features != expected_features { + return Err(format!( + "radroots facade features must be exactly {}; found {}", + expected_features.into_iter().collect::<Vec<_>>().join(", "), + actual_features.into_iter().collect::<Vec<_>>().join(", ") + )); + } + let defaults = features + .get("default") + .and_then(toml::Value::as_array) + .ok_or_else(|| "radroots facade default feature must be an array".to_owned())?; + if defaults.len() != 1 || defaults[0].as_str() != Some("client") { + return Err("radroots facade default feature must be exactly client".to_owned()); + } + + let source_path = root.join("crates/radroots/src/lib.rs"); + let source = fs::read_to_string(&source_path) + .map_err(|error| format!("failed to read {}: {error}", source_path.display()))?; + let actual_modules = source + .lines() + .filter_map(|line| { + line.trim() + .strip_prefix("pub mod ") + .and_then(|module| module.strip_suffix(';')) + }) + .collect::<BTreeSet<_>>(); + let expected_modules = RADROOTS_FACADE_MODULES.into_iter().collect::<BTreeSet<_>>(); + if actual_modules != expected_modules { + return Err(format!( + "radroots facade modules must be exactly {}; found {}", + expected_modules.into_iter().collect::<Vec<_>>().join(", "), + actual_modules.into_iter().collect::<Vec<_>>().join(", ") + )); + } + if source.contains("pub mod sdk") || source.contains("pub use radroots_sdk") { + return Err( + "radroots facade must not expose an sdk namespace or broad SDK re-export".to_owned(), + ); + } + for module in RADROOTS_FACADE_MODULES { + if !root + .join("crates/radroots/src") + .join(format!("{module}.rs")) + .is_file() + { + return Err(format!( + "radroots facade module file {module}.rs is missing" + )); + } + } + if !root.join("crates/radroots/README.md").is_file() { + return Err("radroots facade README.md is missing".to_owned()); + } + Ok(()) +} + fn check_publication_policy(root: &Path) -> Result<(), String> { let policy_path = root.join("contracts/releases/publication.toml"); let raw = fs::read_to_string(&policy_path)