sdk

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

commit c926ccad3662685142029431c48ef7b9b6013ed8
parent 3edb09c0088a5d37d496515ee7cbbe1aadb57904
Author: triesap <tyson@radroots.org>
Date:   Fri, 31 Jul 2026 06:25:21 +0000

transport: quarantine superseded package surface

- Exercise canonical transport target construction in SDK runtime boundary tests.
- Freeze the remaining SDK-local target and satisfaction mapping until exact Step 235 removal.
- Record out-of-scope CLI and daemon compatibility aliases as publication blockers through Step 305.
- Verify the standalone SDK with formatting, tests, architecture checks, and strict Clippy.

Diffstat:
Mcrates/sdk/tests/source_boundary.rs | 30++++++++++++++++++++++++++++++
Mcrates/sdk/tests/unit/sync_runtime_tests.rs | 8+++++---
Mcrates/sdk/tests/unit/transport_tests.rs | 24++++++++++++++++--------
Mdocs/implementation/DEVIATIONS.md | 1+
Mdocs/implementation/deviations.toml | 27+++++++++++++++++++++++++++
5 files changed, 79 insertions(+), 11 deletions(-)

diff --git a/crates/sdk/tests/source_boundary.rs b/crates/sdk/tests/source_boundary.rs @@ -141,6 +141,36 @@ fn active_sources_use_canonical_transport_type_names() { } #[test] +fn temporary_transport_mapping_is_publish_frozen_until_step_235() { + let manifest = manifest_dir(); + let cargo_manifest = read_source(&manifest.join("Cargo.toml")); + let transport = read_source(&manifest.join("src/transport.rs")); + let deviations = read_source(&manifest.join("../../docs/implementation/deviations.toml")); + + assert!(cargo_manifest.contains("publish = false")); + for required in [ + "pub enum SatisfactionPolicy", + "pub struct TargetSet", + "transport_satisfaction_policy", + ] { + assert!( + transport.contains(required), + "the bounded Step 235 migration inventory is missing `{required}`" + ); + } + for required in [ + "id = \"RCRV1-DEV-007\"", + "affected_steps = [\"122\", \"170\", \"235\", \"305\"]", + "SDK-local unpublished target-set and satisfaction-policy mapping only until Step 235", + ] { + assert!( + deviations.contains(required), + "the Step 235 final-removal record is missing `{required}`" + ); + } +} + +#[test] fn active_sources_do_not_describe_compatibility_paths() { for path in active_source_files() { let source = read_source(&path).to_lowercase(); diff --git a/crates/sdk/tests/unit/sync_runtime_tests.rs b/crates/sdk/tests/unit/sync_runtime_tests.rs @@ -1009,7 +1009,7 @@ async fn radrootsd_delivery_policy_rejects_non_accepted_satisfaction_before_daem #[cfg(feature = "radrootsd-execution")] #[test] fn radrootsd_outbox_target_conversion_rejects_reticulum_targets_before_behavior_loss() { - let target = Target::reticulum().expect("Reticulum target"); + let target = Target::new(TransportId::RETICULUM, "reticulum:local").expect("Reticulum target"); let record = RadrootsOutboxDeliveryTargetRecord { delivery_target_id: 1, delivery_plan_id: 1, @@ -1190,7 +1190,8 @@ async fn radrootsd_local_validation_errors_release_claim_before_daemon_publish() .expect("stored before"); assert!(!stored_before.event_store_ingested); assert_eq!(stored_before.event_store_ingested_at_ms, None); - let reticulum_target = Target::reticulum().expect("Reticulum target"); + let reticulum_target = + Target::new(TransportId::RETICULUM, "reticulum:local").expect("Reticulum target"); claimed.delivery_targets[0].transport_kind = *reticulum_target.kind(); claimed.delivery_targets[0].endpoint_uri = reticulum_target.uri().clone(); claimed.delivery_targets[0].endpoint_fingerprint = reticulum_target.fingerprint().clone(); @@ -1320,7 +1321,8 @@ async fn radrootsd_local_validation_failure_keeps_sibling_plan_ready_and_claimab .expect("stored before"); let ingested_before = stored_before.event_store_ingested; let ingested_at_before = stored_before.event_store_ingested_at_ms; - let reticulum_target = Target::reticulum().expect("Reticulum target"); + let reticulum_target = + Target::new(TransportId::RETICULUM, "reticulum:local").expect("Reticulum target"); claimed.delivery_targets[0].transport_kind = *reticulum_target.kind(); claimed.delivery_targets[0].endpoint_uri = reticulum_target.uri().clone(); claimed.delivery_targets[0].endpoint_fingerprint = reticulum_target.fingerprint().clone(); diff --git a/crates/sdk/tests/unit/transport_tests.rs b/crates/sdk/tests/unit/transport_tests.rs @@ -294,20 +294,28 @@ fn reticulum_agent_endpoint_rejects_non_agent_endpoint_families() { #[test] fn explicit_target_sets_reject_noncanonical_reticulum_endpoints() { - for invalid in [ - " reticulum:local".to_owned(), - "reticulum:local ".to_owned(), + for invalid in [" reticulum:local", "reticulum:local "] { + assert_eq!( + Target::new(TransportId::RETICULUM, invalid) + .expect_err("syntactically invalid transport target"), + RadrootsTransportError::InvalidTargetUri + ); + } + + for noncanonical in [ "RETICULUM:deferred-until-implemented".to_owned(), "reticulum:Preview-Unavailable".to_owned(), ["reticulum:", "pre", "view"].concat(), "reticulum:local-alt".to_owned(), "reticulum:custom".to_owned(), ] { - assert_eq!( - Target::new(TransportId::RETICULUM, invalid.as_str()) - .expect_err("invalid Reticulum target"), - RadrootsTransportError::InvalidTargetUri - ); + let target = Target::new(TransportId::RETICULUM, noncanonical.as_str()) + .expect("transport-neutral target"); + assert!(matches!( + TargetSet::transport_targets(vec![target]), + Err(RadrootsSdkError::InvalidRequest { ref message }) + if message == "Reticulum endpoint must be reticulum:local" + )); } } diff --git a/docs/implementation/DEVIATIONS.md b/docs/implementation/DEVIATIONS.md @@ -13,6 +13,7 @@ silently change `radroots.crates.release.v1`. | `RCRV1-DEV-002` | 249 | Pull only the facade scaffold forward to immediately after Step 014 in `sdk`; do not repeat it later. | | `RCRV1-DEV-005` | 013, 019-026, 226, 247, 249-268, 305 | Pin every Rust crate and internal Radroots dependency in `radrootslabs/sdk` to exactly `0.1.0-alpha` until further explicit authority. | | `RCRV1-DEV-006` | 073, 261-268 | Retire public event/trade codegen edges now and authenticate the predecessor TypeScript snapshots until their scheduled protocol/codec replacement. | +| `RCRV1-DEV-007` | 122, 170, 235, 305 | Remove the predecessor monolithic transport SPI now; quarantine publish-frozen runtime, SDK, CLI, and daemon consumer shims until their explicit removal gates. | ## Record template diff --git a/docs/implementation/deviations.toml b/docs/implementation/deviations.toml @@ -148,3 +148,30 @@ verification = [ unresolved_risk = "Event and trade TypeScript type surfaces remain intentionally frozen until their scheduled protocol/codec generator replacement in Steps 261-268." normative_architecture_change = false adr_required = false + +[[deviation]] +id = "RCRV1-DEV-007" +date = "2026-07-30" +status = "active" +approval = "All code-review recommendations and the full multi-RCLD implementation sequence were explicitly approved by the user." +affected_steps = ["122", "170", "235", "305"] +spec_anchors = [ + "docs/specs/radroots_crates_release_v1.md#9-radroots_transport", + "docs/specs/radroots_crates_release_v1.md#111-separate-source-and-sink-contracts", +] +source_evidence = [ + "Step 120 migrated canonical adapters and registries to independent EventSource and EventSink contracts.", + "Mixed runtime delivery workers still consume predecessor request and receipt models until their ordered RCLD 40 migration.", + "The standalone publish-frozen SDK still maps user-facing target and satisfaction models into predecessor outbox orchestration until Step 235.", + "oss/cli/src/runtime/{config,sync,transport}.rs and oss/radrootsd/src/core/transport_publish.rs still import the predecessor identity aliases and Reticulum target helpers; those standalone repositories are outside the approved crate-surface mutation scope.", +] +replacement_action = "Consume canonical transport identity and target types immediately; retain the SDK-local unpublished target-set and satisfaction-policy mapping only until Step 235, while documentation-hidden lib aliases/helpers required by out-of-scope CLI and daemon consumers remain publication-blocking until Step 305." +verification = [ + "SDK source-boundary tests reject every removed public predecessor transport name.", + "SDK release policy keeps publication disabled while the downstream mapping remains.", + "Step 235 is the exact fail-closed final-removal gate for SDK-local duplicate transport types.", + "Step 305 rejects publication until oss/cli and oss/radrootsd no longer require the documentation-hidden external-consumer aliases and Reticulum helpers.", +] +unresolved_risk = "Publish-frozen SDK, CLI, and daemon consumers retain bounded predecessor mappings; package-realistic publication remains blocked until their explicit removal gates." +normative_architecture_change = false +adr_required = false