commit 99baec80e5b479e9c7c3a653e309ddfe3bc68914
parent 6a9cdfb1bda0181ab824967433cac737e3ceb79a
Author: triesap <tyson@radroots.org>
Date: Mon, 13 Jul 2026 07:11:05 +0000
sdk: use typed transport target constructors
Diffstat:
5 files changed, 50 insertions(+), 97 deletions(-)
diff --git a/crates/sdk/src/transport.rs b/crates/sdk/src/transport.rs
@@ -275,10 +275,7 @@ impl TargetSet {
let mut targets = Vec::new();
for relay in relays {
let normalized = normalized_nostr_relay_url(relay.as_ref(), policy)?;
- targets.push(RadrootsTransportTarget::new(
- RadrootsTransportKind::Nostr,
- normalized,
- )?);
+ targets.push(RadrootsTransportTarget::nostr_relay(normalized)?);
}
Self::from_transport_targets(targets)
}
@@ -457,12 +454,16 @@ impl ReticulumPreviewProfile {
}
pub fn target_set(&self) -> Result<TargetSet, RadrootsSdkError> {
- TargetSet::transport_targets(vec![RadrootsTransportTarget::new_with_metadata(
- RadrootsTransportKind::Reticulum,
- self.endpoint_uri.as_str(),
- Some(self.scope.transport_scope()),
- None,
- )?])
+ if self.endpoint_uri.as_str() != radroots_transport::RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI
+ {
+ return Err(radroots_transport::RadrootsTransportError::InvalidTargetUri.into());
+ }
+ TargetSet::transport_targets(vec![
+ RadrootsTransportTarget::reticulum_preview_with_metadata(
+ Some(self.scope.transport_scope()),
+ None,
+ )?,
+ ])
}
}
@@ -606,8 +607,7 @@ impl ProxyProfile {
}
pub(crate) fn target_set(&self) -> Result<TargetSet, RadrootsSdkError> {
- TargetSet::transport_targets(vec![RadrootsTransportTarget::new(
- RadrootsTransportKind::Proxy,
+ TargetSet::transport_targets(vec![RadrootsTransportTarget::proxy(
self.endpoint_url.as_str(),
)?])
}
diff --git a/crates/sdk/src/workflow_runtime.rs b/crates/sdk/src/workflow_runtime.rs
@@ -17,9 +17,7 @@ use radroots_outbox::{
RadrootsOutboxDeliveryPlanInput, RadrootsOutboxEnqueueStatus,
RadrootsOutboxReticulumPreviewBehavior, RadrootsOutboxSignedOperationInput,
};
-use radroots_transport::{
- RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI, RadrootsTransportKind, RadrootsTransportTarget,
-};
+use radroots_transport::{RadrootsTransportKind, RadrootsTransportTarget};
const SDK_LOCAL_EVENT_ENDPOINT_URI: &str = "local:sdk";
@@ -212,13 +210,12 @@ fn resolved_delivery_plan(
)
}
TargetPolicy::MeshScope(scope) => {
- let target_set =
- TargetSet::transport_targets(vec![RadrootsTransportTarget::new_with_metadata(
- RadrootsTransportKind::Reticulum,
- RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI,
+ let target_set = TargetSet::transport_targets(vec![
+ RadrootsTransportTarget::reticulum_preview_with_metadata(
Some(scope.transport_scope()),
None,
- )?])?;
+ )?,
+ ])?;
delivery_plan_from_targets(
"mesh_scope",
target_set.into_targets(),
diff --git a/crates/sdk/tests/sync_runtime.rs b/crates/sdk/tests/sync_runtime.rs
@@ -34,7 +34,7 @@ use radroots_sdk::{
StorageStatusRequest, SyncStatusRequest, SyncStatusSource, TargetPolicy, TransportProfile,
};
use radroots_transport::{
- RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE, RadrootsTransportKind, RadrootsTransportMeshScopeId,
+ RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE, RadrootsTransportMeshScopeId,
RadrootsTransportSatisfactionPolicy, RadrootsTransportTarget, RadrootsTransportTargetLabel,
};
use radroots_transport_nostr::{
@@ -627,8 +627,7 @@ fn scoped_duplicate_relay_delivery_plan(
}
fn scoped_nostr_target(relay: &str, scope: &str, label: &str) -> RadrootsTransportTarget {
- RadrootsTransportTarget::new_with_metadata(
- RadrootsTransportKind::Nostr,
+ RadrootsTransportTarget::nostr_relay_with_metadata(
relay,
Some(RadrootsTransportMeshScopeId::parse(scope).expect("target scope")),
Some(RadrootsTransportTargetLabel::parse(label).expect("target label")),
@@ -2744,11 +2743,8 @@ async fn push_outbox_with_transport_scopes_duplicate_endpoint_sibling_plans() {
1,
radroots_transport::RadrootsTransportSatisfactionPolicy::all_accepted(),
vec![
- radroots_transport::RadrootsTransportTarget::new(
- radroots_transport::RadrootsTransportKind::Nostr,
- RELAY_A,
- )
- .expect("second target"),
+ radroots_transport::RadrootsTransportTarget::nostr_relay(RELAY_A)
+ .expect("second target"),
],
),
true,
diff --git a/crates/sdk/tests/unit/sync_runtime_tests.rs b/crates/sdk/tests/unit/sync_runtime_tests.rs
@@ -45,15 +45,12 @@ use radroots_outbox::{
use radroots_outbox::{
RadrootsOutboxEventState, RadrootsOutboxEventStoreIngestReceipt, RadrootsOutboxStatusSummary,
};
-#[cfg(feature = "radrootsd-proxy")]
-use radroots_transport::{
- RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI, RadrootsTransportSatisfactionClass,
- RadrootsTransportSatisfactionPolicy,
-};
use radroots_transport::{
- RadrootsTransportDeliveryTargetStatus, RadrootsTransportKind, RadrootsTransportMeshScopeId,
- RadrootsTransportTarget, RadrootsTransportTargetLabel,
+ RadrootsTransportDeliveryTargetStatus, RadrootsTransportMeshScopeId, RadrootsTransportTarget,
+ RadrootsTransportTargetLabel,
};
+#[cfg(feature = "radrootsd-proxy")]
+use radroots_transport::{RadrootsTransportSatisfactionClass, RadrootsTransportSatisfactionPolicy};
use radroots_transport_nostr::{
RadrootsNostrTransport, RadrootsOutboxPublishReceipt, RadrootsOutboxPublishTargetReceipt,
RadrootsRelayOutcomeKind, RadrootsRelayPublishAdapter, RadrootsRelayPublishRelayReceipt,
@@ -220,8 +217,7 @@ async fn claimed_uningested_proxy_event_with_satisfaction(
.await
.expect("sdk");
let draft = proxy_frozen_draft(d_tag);
- let proxy_target = RadrootsTransportTarget::new(RadrootsTransportKind::Proxy, proxy_endpoint)
- .expect("proxy target");
+ let proxy_target = RadrootsTransportTarget::proxy(proxy_endpoint).expect("proxy target");
let enqueue = sdk
._outbox
.enqueue_operation(
@@ -858,15 +854,12 @@ async fn proxy_push_empty_queue_and_private_helpers_are_deterministic() {
.expect("any-target proxy policy"),
TransportPublishDeliveryPolicy::Any
);
- let first_required =
- RadrootsTransportTarget::new(RadrootsTransportKind::Nostr, "wss://required-a.example.com")
- .expect("first required target");
- let second_required =
- RadrootsTransportTarget::new(RadrootsTransportKind::Nostr, "wss://required-b.example.com")
- .expect("second required target");
- let optional =
- RadrootsTransportTarget::new(RadrootsTransportKind::Nostr, "wss://optional.example.com")
- .expect("optional target");
+ let first_required = RadrootsTransportTarget::nostr_relay("wss://required-a.example.com")
+ .expect("first required target");
+ let second_required = RadrootsTransportTarget::nostr_relay("wss://required-b.example.com")
+ .expect("second required target");
+ let optional = RadrootsTransportTarget::nostr_relay("wss://optional.example.com")
+ .expect("optional target");
let policy = RadrootsTransportSatisfactionPolicy::required_targets(
RadrootsTransportSatisfactionClass::Accepted,
vec![
@@ -989,11 +982,7 @@ async fn proxy_delivery_policy_rejects_non_accepted_satisfaction_before_daemon_p
#[cfg(feature = "radrootsd-proxy")]
#[test]
fn proxy_outbox_target_conversion_rejects_reticulum_targets_before_behavior_loss() {
- let target = RadrootsTransportTarget::new(
- RadrootsTransportKind::Reticulum,
- "reticulum:preview-unavailable",
- )
- .expect("Reticulum target");
+ let target = RadrootsTransportTarget::reticulum_preview().expect("Reticulum target");
let record = RadrootsOutboxDeliveryTargetRecord {
delivery_target_id: 1,
delivery_plan_id: 1,
@@ -1025,8 +1014,7 @@ fn proxy_outbox_target_conversion_rejects_reticulum_targets_before_behavior_loss
#[cfg(feature = "radrootsd-proxy")]
#[test]
fn proxy_outbox_target_conversion_preserves_nostr_scope_and_label() {
- let target = RadrootsTransportTarget::new_with_metadata(
- RadrootsTransportKind::Nostr,
+ let target = RadrootsTransportTarget::nostr_relay_with_metadata(
"wss://relay.example.com",
Some(RadrootsTransportMeshScopeId::parse("farm.local").expect("scope")),
Some(RadrootsTransportTargetLabel::parse("Farm relay").expect("label")),
@@ -1046,9 +1034,7 @@ fn proxy_outbox_target_conversion_preserves_nostr_scope_and_label() {
#[cfg(feature = "radrootsd-proxy")]
#[test]
fn proxy_outbox_target_conversion_rejects_proxy_targets_before_daemon_explicit_target() {
- let target =
- RadrootsTransportTarget::new(RadrootsTransportKind::Proxy, "http://127.0.0.1:8080/rpc")
- .expect("proxy target");
+ let target = RadrootsTransportTarget::proxy("http://127.0.0.1:8080/rpc").expect("proxy target");
let record = RadrootsOutboxDeliveryTargetRecord {
delivery_target_id: 1,
delivery_plan_id: 1,
@@ -1202,11 +1188,7 @@ async fn proxy_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 = RadrootsTransportTarget::new(
- RadrootsTransportKind::Reticulum,
- RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI,
- )
- .expect("Reticulum target");
+ let reticulum_target = RadrootsTransportTarget::reticulum_preview().expect("Reticulum target");
claimed.delivery_targets[0].transport_kind = reticulum_target.kind;
claimed.delivery_targets[0].endpoint_uri = reticulum_target.uri;
claimed.delivery_targets[0].endpoint_fingerprint = reticulum_target.fingerprint;
@@ -1274,11 +1256,8 @@ async fn proxy_local_validation_failure_keeps_sibling_plan_ready_and_claimable()
1,
RadrootsTransportSatisfactionPolicy::all_accepted(),
vec![
- RadrootsTransportTarget::new(
- RadrootsTransportKind::Nostr,
- "wss://active.example.com",
- )
- .expect("active target"),
+ RadrootsTransportTarget::nostr_relay("wss://active.example.com")
+ .expect("active target"),
],
),
true,
@@ -1301,11 +1280,8 @@ async fn proxy_local_validation_failure_keeps_sibling_plan_ready_and_claimable()
1,
RadrootsTransportSatisfactionPolicy::all_accepted(),
vec![
- RadrootsTransportTarget::new(
- RadrootsTransportKind::Nostr,
- "wss://sibling.example.com",
- )
- .expect("sibling target"),
+ RadrootsTransportTarget::nostr_relay("wss://sibling.example.com")
+ .expect("sibling target"),
],
),
true,
@@ -1342,11 +1318,7 @@ async fn proxy_local_validation_failure_keeps_sibling_plan_ready_and_claimable()
.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 = RadrootsTransportTarget::new(
- RadrootsTransportKind::Reticulum,
- RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI,
- )
- .expect("Reticulum target");
+ let reticulum_target = RadrootsTransportTarget::reticulum_preview().expect("Reticulum target");
claimed.delivery_targets[0].transport_kind = reticulum_target.kind;
claimed.delivery_targets[0].endpoint_uri = reticulum_target.uri;
claimed.delivery_targets[0].endpoint_fingerprint = reticulum_target.fingerprint;
@@ -1547,15 +1519,13 @@ async fn proxy_completion_matches_duplicate_endpoint_targets_by_scope() {
let signed_event = ProxyFixtureSigner::new()
.sign_frozen_draft(&draft)
.expect("signed event");
- let farm_a = RadrootsTransportTarget::new_with_metadata(
- RadrootsTransportKind::Nostr,
+ let farm_a = RadrootsTransportTarget::nostr_relay_with_metadata(
"wss://relay.example.com",
Some(RadrootsTransportMeshScopeId::parse("farm.a").expect("farm a scope")),
Some(RadrootsTransportTargetLabel::parse("Farm A").expect("farm a label")),
)
.expect("farm a target");
- let farm_b = RadrootsTransportTarget::new_with_metadata(
- RadrootsTransportKind::Nostr,
+ let farm_b = RadrootsTransportTarget::nostr_relay_with_metadata(
"wss://relay.example.com",
Some(RadrootsTransportMeshScopeId::parse("farm.b").expect("farm b scope")),
Some(RadrootsTransportTargetLabel::parse("Farm B").expect("farm b label")),
@@ -1763,8 +1733,7 @@ impl OutboxPublishReceiptFixture for RadrootsOutboxPublishReceipt {
.push(RadrootsOutboxPublishTargetReceipt {
delivery_target_id: 10,
endpoint_uri: "wss://relay.example.com".to_owned(),
- endpoint_fingerprint: RadrootsTransportTarget::new_with_metadata(
- RadrootsTransportKind::Nostr,
+ endpoint_fingerprint: RadrootsTransportTarget::nostr_relay_with_metadata(
"wss://relay.example.com",
Some(RadrootsTransportMeshScopeId::parse("farm.local").expect("scope")),
Some(RadrootsTransportTargetLabel::parse("Farm relay").expect("label")),
diff --git a/crates/sdk/tests/unit/transport_tests.rs b/crates/sdk/tests/unit/transport_tests.rs
@@ -211,16 +211,10 @@ fn target_sets_reject_duplicate_transport_fingerprints() {
if message == "transport target set contains duplicate fingerprints"
));
- let first = RadrootsTransportTarget::new(
- RadrootsTransportKind::Nostr,
- "wss://relay-a.example.com/path",
- )
- .expect("first target");
- let second = RadrootsTransportTarget::new(
- RadrootsTransportKind::Nostr,
- "WSS://RELAY-A.EXAMPLE.COM/path",
- )
- .expect("second target");
+ let first = RadrootsTransportTarget::nostr_relay("wss://relay-a.example.com/path")
+ .expect("first target");
+ let second = RadrootsTransportTarget::nostr_relay("WSS://RELAY-A.EXAMPLE.COM/path")
+ .expect("second target");
let duplicate_targets =
TargetSet::transport_targets(vec![first, second]).expect_err("duplicate targets");
@@ -345,12 +339,9 @@ fn explicit_target_sets_reject_noncanonical_reticulum_preview_endpoints() {
#[test]
fn explicit_target_sets_reject_mixed_proxy_delegate_targets() {
- let proxy =
- RadrootsTransportTarget::new(RadrootsTransportKind::Proxy, "http://127.0.0.1:8080/rpc")
- .expect("proxy target");
+ let proxy = RadrootsTransportTarget::proxy("http://127.0.0.1:8080/rpc").expect("proxy target");
let nostr =
- RadrootsTransportTarget::new(RadrootsTransportKind::Nostr, "wss://relay.example.com")
- .expect("Nostr target");
+ RadrootsTransportTarget::nostr_relay("wss://relay.example.com").expect("Nostr target");
let error = TargetSet::transport_targets(vec![proxy.clone(), nostr])
.expect_err("mixed proxy target set");