commit c9de1f9b7c550928f364cb53773e74ba4156e96e
parent 854e2423de13c95be43a8abdbc5b7a9f3182e904
Author: triesap <tyson@radroots.org>
Date: Wed, 15 Jul 2026 00:25:24 +0000
contract: add runtime contract v1 root
- add the runtime contract crate with operation, envelope, error, and transaction descriptors
- expose the runtime contract through the public SDK surface
- align dto_bindgen dependencies on crates.io 0.1.0
- validate SDK contract checks, workspace tests, no-default check, and clippy lanes
Diffstat:
7 files changed, 49 insertions(+), 4 deletions(-)
diff --git a/crates/sdk/Cargo.toml b/crates/sdk/Cargo.toml
@@ -13,8 +13,18 @@ readme = "README"
[features]
default = ["std", "serde", "serde_json", "identity-models"]
-std = ["radroots_event/std", "radroots_event_codec/std", "radroots_trade/std"]
-serde = ["dep:serde", "radroots_event/serde", "radroots_trade/serde"]
+std = [
+ "radroots_event/std",
+ "radroots_event_codec/std",
+ "radroots_runtime_contract_v1/std",
+ "radroots_trade/std",
+]
+serde = [
+ "dep:serde",
+ "radroots_event/serde",
+ "radroots_runtime_contract_v1/serde",
+ "radroots_trade/serde",
+]
serde_json = [
"dep:serde_json",
"serde",
@@ -131,6 +141,7 @@ radroots_transport_publish_protocol = { workspace = true, optional = true, defau
radroots_transport_nostr = { workspace = true, optional = true, default-features = false }
radroots_transport_reticulum = { workspace = true, optional = true, default-features = false }
radroots_runtime_paths = { workspace = true, optional = true, default-features = false }
+radroots_runtime_contract_v1 = { workspace = true, default-features = false }
radroots_trade = { workspace = true, default-features = false }
radroots_identity = { workspace = true, optional = true, default-features = false }
radroots_nostr = { workspace = true, optional = true, default-features = false }
diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs
@@ -56,6 +56,8 @@ pub mod transport;
#[cfg(feature = "runtime")]
mod workflow_runtime;
+pub use radroots_runtime_contract_v1 as runtime_contract_v1;
+
#[cfg(feature = "runtime")]
pub use crate::dvm_runtime::{
DVM_TRADE_TRANSITION_PROOF_REQUEST_CONTRACT_ID,
diff --git a/crates/sdk/tests/identity_public_api.rs b/crates/sdk/tests/identity_public_api.rs
@@ -10,7 +10,7 @@ fn identity_models_are_public_through_identity_module() {
};
assert_eq!(DEFAULT_IDENTITY_PATH, "default.json");
- assert!(RADROOTS_USERNAME_MIN_LEN <= RADROOTS_USERNAME_MAX_LEN);
+ const { assert!(RADROOTS_USERNAME_MIN_LEN <= RADROOTS_USERNAME_MAX_LEN) };
assert!(RADROOTS_USERNAME_REGEX.contains("[a-z0-9._-]"));
let normalized = radroots_username_normalize(" Field_User ").expect("normalized username");
diff --git a/crates/sdk/tests/runtime_contract_public_api.rs b/crates/sdk/tests/runtime_contract_public_api.rs
@@ -0,0 +1,26 @@
+use radroots_sdk::runtime_contract_v1::{
+ RuntimeOperationIdV1, TransportKindV1, operation_descriptor, validate_runtime_contract_v1,
+};
+
+#[test]
+fn runtime_contract_v1_is_public_through_sdk_surface() {
+ validate_runtime_contract_v1().expect("runtime contract validates");
+
+ let descriptor = operation_descriptor(RuntimeOperationIdV1::TransportDeliveryRetry)
+ .expect("delivery retry descriptor");
+
+ assert!(
+ descriptor
+ .transport_capability
+ .includes_transport(TransportKindV1::Nostr)
+ );
+ assert!(
+ descriptor
+ .transport_capability
+ .includes_transport(TransportKindV1::Reticulum)
+ );
+ assert!(matches!(
+ TransportKindV1::parse("reticulum"),
+ Ok(TransportKindV1::Reticulum)
+ ));
+}
diff --git a/crates/sdk/tests/source_boundary.rs b/crates/sdk/tests/source_boundary.rs
@@ -2312,7 +2312,10 @@ fn sdk_transport_sources_keep_reticulum_preview_push_boundary() {
"src/adapters/radrootsd.rs",
] {
let source = read_source(manifest_dir.join(relative_path).as_path());
- for line in removed_reticulum_preview_endpoint_lines(source.as_str()) {
+ if let Some(line) = removed_reticulum_preview_endpoint_lines(source.as_str())
+ .into_iter()
+ .next()
+ {
panic!(
"{relative_path}:{line} contains removed Reticulum preview endpoint `reticulum:preview`"
);
diff --git a/tools/sdk_xtask_import/Cargo.toml b/tools/sdk_xtask_import/Cargo.toml
@@ -22,6 +22,7 @@ radroots_event_bindings = { path = "../../crates/event_bindings" }
radroots_event_index = { workspace = true, features = ["dto-bindgen"] }
radroots_identity_bindings = { path = "../../crates/identity_bindings" }
radroots_replica_schema_bindings = { path = "../../crates/replica_schema_bindings" }
+radroots_runtime_contract_v1 = { path = "../../crates/runtime_contract_v1" }
radroots_trade_bindings = { path = "../../crates/trade_bindings" }
flate2 = "1"
serde_json = "1"
diff --git a/tools/sdk_xtask_import/src/contracts.rs b/tools/sdk_xtask_import/src/contracts.rs
@@ -104,6 +104,8 @@ struct SdkArtifacts {
}
pub fn validate_sdk_contracts(root: &Path) -> Result<(), String> {
+ radroots_runtime_contract_v1::validate_runtime_contract_v1()
+ .map_err(|error| error.to_string())?;
let exports = load_contract_dir::<ExportContract>(&root.join("contracts").join("exports"))?;
let packages = load_contract_dir::<PackageContract>(&root.join("contracts").join("packages"))?;
if exports.is_empty() {