commit 58fd4bb48ef0dd29fa3171d45607ce29f339b8e2
parent 06c70ab56c883f22a30ac6f2137a5197583efefa
Author: triesap <tyson@radroots.org>
Date: Thu, 30 Jul 2026 23:04:03 +0000
transport: migrate workspace consumers
- Consume canonical transport identities, targets, and final sink contracts.
- Route Nostr outbox publication through the final delivery request and receipt model.
- Keep Reticulum preview policy private to its adapter-owned contract constants.
- Update source boundaries, runtime tests, and the exact alpha dependency lock.
Diffstat:
9 files changed, 143 insertions(+), 117 deletions(-)
diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs
@@ -193,9 +193,9 @@ pub use crate::trade_runtime::{
#[cfg(feature = "runtime")]
pub use crate::transport::{
MeshScopeId, MultiTargetProfile, NostrProfile, NostrRelayUrlPolicy, PublishMode,
- RadrootsTransportDeliveryReceipt, RadrootsTransportDeliveryTargetStatus, RadrootsTransportKind,
+ RadrootsTransportDeliveryReceipt, RadrootsTransportDeliveryTargetStatus,
RadrootsTransportOutcome, RadrootsTransportSatisfactionClass, RadrootsTransportTargetReceipt,
RadrootsdExecutionAuth, RadrootsdExecutionProfile, ReticulumAgentEndpoint, ReticulumBehavior,
ReticulumProfile, SDK_TRANSPORT_TARGET_MAX_COUNT, SatisfactionPolicy, TargetPolicy, TargetSet,
- TransportProfile, TransportReceipt,
+ TransportId, TransportProfile, TransportReceipt,
};
diff --git a/crates/sdk/src/sync_runtime.rs b/crates/sdk/src/sync_runtime.rs
@@ -34,13 +34,12 @@ use radroots_protocol::radrootsd::transport_publish::v5::{
#[cfg(feature = "runtime")]
use radroots_trade::reducer::{RADROOTS_TRADE_REDUCER_CONTRACT_ID, RADROOTS_TRADE_REDUCER_VERSION};
#[cfg(all(feature = "runtime", feature = "radrootsd-execution"))]
-use radroots_transport::RadrootsTransportTargetFingerprint;
+use radroots_transport::target::TargetFingerprint;
#[cfg(feature = "runtime")]
use radroots_transport::{
- RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE, RadrootsTransportCapabilityAvailability,
- RadrootsTransportCapabilityMaturity, RadrootsTransportImplementationState,
- RadrootsTransportKind, RadrootsTransportOutcomeKind, RadrootsTransportStatus,
- RadrootsTransportTarget,
+ RadrootsTransportCapabilityAvailability, RadrootsTransportCapabilityMaturity,
+ RadrootsTransportImplementationState, RadrootsTransportOutcomeKind, RadrootsTransportStatus,
+ Target, TransportId,
};
#[cfg(all(feature = "runtime", feature = "radrootsd-execution"))]
use radroots_transport::{RadrootsTransportSatisfactionClass, RadrootsTransportSatisfactionPolicy};
@@ -51,6 +50,7 @@ use radroots_transport_nostr::{
RadrootsOutboxPublishPolicy, RadrootsOutboxPublishReceipt, RadrootsOutboxPublishTargetReceipt,
RadrootsRelayOutcomeKind, publish_claimed_outbox_event_with_transport,
};
+use radroots_transport_reticulum::RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE;
#[cfg(feature = "runtime")]
use sha2::{Digest, Sha256};
@@ -214,7 +214,7 @@ pub struct SyncTransportTargetSummary {
#[cfg(feature = "runtime")]
impl SyncTransportTargetSummary {
- fn from_transport_target(target: &RadrootsTransportTarget) -> Self {
+ fn from_transport_target(target: &Target) -> Self {
Self {
transport_kind: target.kind().canonical_label(),
endpoint_uri: target.uri().as_str().to_owned(),
@@ -279,6 +279,7 @@ fn transport_implementation_label(state: RadrootsTransportImplementationState) -
#[cfg(feature = "runtime")]
fn transport_maturity_label(maturity: RadrootsTransportCapabilityMaturity) -> &'static str {
match maturity {
+ RadrootsTransportCapabilityMaturity::Experimental => "experimental",
RadrootsTransportCapabilityMaturity::Preview => "preview",
RadrootsTransportCapabilityMaturity::Stable => "stable",
}
@@ -816,7 +817,7 @@ impl<'sdk> SyncClient<'sdk> {
request: PushOutboxRequest,
) -> Result<PushOutboxReceipt, RadrootsSdkError>
where
- T: radroots_transport::RadrootsTransport + ?Sized,
+ T: radroots_transport::EventSink + ?Sized,
{
request.validate()?;
let recovery_now_ms = sdk_now_ms(self.sdk)?;
@@ -1313,7 +1314,7 @@ async fn radrootsd_delivery_policy(
fn radrootsd_delivery_policy_from_remaining(
ready_target_count: usize,
required_remaining: usize,
- required_remaining_targets: Option<&[RadrootsTransportTargetFingerprint]>,
+ required_remaining_targets: Option<&[TargetFingerprint]>,
satisfaction_policy: &RadrootsTransportSatisfactionPolicy,
) -> Result<TransportPublishDeliveryPolicy, RadrootsSdkError> {
reject_non_accepted_radrootsd_satisfaction(satisfaction_policy)?;
@@ -1373,7 +1374,7 @@ fn radrootsd_delivery_policy_from_remaining(
fn radrootsd_required_remaining_targets(
satisfaction_policy: &RadrootsTransportSatisfactionPolicy,
active_targets: &[&RadrootsOutboxDeliveryTargetRecord],
-) -> Result<Option<Vec<RadrootsTransportTargetFingerprint>>, RadrootsSdkError> {
+) -> Result<Option<Vec<TargetFingerprint>>, RadrootsSdkError> {
let RadrootsTransportSatisfactionPolicy::RequiredTargets { class, targets } =
satisfaction_policy
else {
@@ -1535,7 +1536,7 @@ fn radrootsd_transport_publish_target_policy(
fn transport_publish_target_from_outbox_target(
target: &RadrootsOutboxDeliveryTargetRecord,
) -> Result<TransportPublishTarget, RadrootsSdkError> {
- if target.transport_kind != RadrootsTransportKind::Nostr {
+ if target.transport_kind != TransportId::NOSTR {
return Err(RadrootsSdkError::InvalidRequest {
message: format!(
"radrootsd execution explicit targets are Nostr-only and cannot publish {} target {}",
@@ -1930,7 +1931,7 @@ fn push_receipt_event_id(value: &str, field: &str) -> Result<EventId, RadrootsSd
#[cfg(feature = "runtime")]
fn push_target_receipt(target: RadrootsOutboxPublishTargetReceipt) -> PushOutboxTargetReceipt {
PushOutboxTargetReceipt {
- transport_kind: RadrootsTransportKind::Nostr.canonical_label(),
+ transport_kind: TransportId::NOSTR.canonical_label(),
endpoint_uri: target.endpoint_uri,
target_scope: target.target_scope,
target_label: target.target_label,
diff --git a/crates/sdk/src/transport.rs b/crates/sdk/src/transport.rs
@@ -1,18 +1,22 @@
use crate::RadrootsSdkError;
+use radroots_transport::target::{TargetFingerprint, TargetScope, TargetSet as TransportTargetSet};
use radroots_transport::{
- RADROOTS_RETICULUM_ENDPOINT_URI, RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE,
RadrootsTransportCapabilityAvailability, RadrootsTransportCapabilityMaturity,
- RadrootsTransportImplementationState, RadrootsTransportMeshScopeId,
- RadrootsTransportSatisfactionPolicy, RadrootsTransportStatus, RadrootsTransportTarget,
- RadrootsTransportTargetFingerprint, RadrootsTransportTargetSet,
+ RadrootsTransportImplementationState, RadrootsTransportSatisfactionPolicy,
+ RadrootsTransportStatus, Target,
};
use radroots_transport_nostr::{RadrootsRelayUrlPolicy, RelayUrl};
+use radroots_transport_reticulum::{
+ RADROOTS_RETICULUM_ENDPOINT_URI, RADROOTS_RETICULUM_SCOPE_ID,
+ RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE,
+};
use serde::ser::{SerializeStruct, Serializer};
use std::collections::BTreeSet;
pub use radroots_transport::{
- RadrootsTransportDeliveryReceipt, RadrootsTransportDeliveryTargetStatus, RadrootsTransportKind,
+ RadrootsTransportDeliveryReceipt, RadrootsTransportDeliveryTargetStatus,
RadrootsTransportOutcome, RadrootsTransportSatisfactionClass, RadrootsTransportTargetReceipt,
+ TransportId,
};
pub const SDK_TRANSPORT_TARGET_MAX_COUNT: usize = 20;
@@ -43,10 +47,10 @@ pub enum SatisfactionPolicy {
threshold: u16,
},
RequiredAcceptedTargets {
- target_fingerprints: Vec<RadrootsTransportTargetFingerprint>,
+ target_fingerprints: Vec<TargetFingerprint>,
},
RequiredDeliveredTargets {
- target_fingerprints: Vec<RadrootsTransportTargetFingerprint>,
+ target_fingerprints: Vec<TargetFingerprint>,
},
}
@@ -127,14 +131,14 @@ fn validate_satisfaction_threshold(threshold: u16) -> Result<(), RadrootsSdkErro
fn required_target_fingerprints<I, S>(
targets: I,
-) -> Result<Vec<RadrootsTransportTargetFingerprint>, RadrootsSdkError>
+) -> Result<Vec<TargetFingerprint>, RadrootsSdkError>
where
I: IntoIterator<Item = S>,
S: AsRef<str>,
{
let fingerprints = targets
.into_iter()
- .map(|target| RadrootsTransportTargetFingerprint::parse(target.as_ref()))
+ .map(|target| TargetFingerprint::parse(target.as_ref()))
.collect::<Result<Vec<_>, _>>()?;
RadrootsTransportSatisfactionPolicy::required_targets(
RadrootsTransportSatisfactionClass::Accepted,
@@ -233,29 +237,29 @@ impl serde::Serialize for TargetPolicy {
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
#[serde(transparent)]
-pub struct MeshScopeId(RadrootsTransportMeshScopeId);
+pub struct MeshScopeId(TargetScope);
impl MeshScopeId {
pub fn parse(raw: impl AsRef<str>) -> Result<Self, RadrootsSdkError> {
- Ok(Self(RadrootsTransportMeshScopeId::parse(raw)?))
+ Ok(Self(TargetScope::parse(raw)?))
}
pub fn local_reticulum() -> Self {
- Self(RadrootsTransportMeshScopeId::local_reticulum())
+ Self(TargetScope::parse(RADROOTS_RETICULUM_SCOPE_ID).expect("Reticulum scope"))
}
pub fn as_str(&self) -> &str {
self.0.as_str()
}
- pub(crate) fn transport_scope(&self) -> RadrootsTransportMeshScopeId {
+ pub(crate) fn transport_scope(&self) -> TargetScope {
self.0.clone()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TargetSet {
- targets: Vec<RadrootsTransportTarget>,
+ targets: Vec<Target>,
canonical_targets: Vec<String>,
}
@@ -271,18 +275,16 @@ impl TargetSet {
let mut targets = Vec::new();
for relay in relays {
let normalized = normalized_nostr_relay_url(relay.as_ref(), policy)?;
- targets.push(RadrootsTransportTarget::nostr_relay(normalized)?);
+ targets.push(Target::new(TransportId::NOSTR, normalized)?);
}
Self::from_transport_targets(targets)
}
- pub fn transport_targets(
- targets: Vec<RadrootsTransportTarget>,
- ) -> Result<Self, RadrootsSdkError> {
+ pub fn transport_targets(targets: Vec<Target>) -> Result<Self, RadrootsSdkError> {
Self::from_transport_targets(targets)
}
- pub fn targets(&self) -> &[RadrootsTransportTarget] {
+ pub fn targets(&self) -> &[Target] {
self.targets.as_slice()
}
@@ -290,19 +292,19 @@ impl TargetSet {
self.canonical_targets.as_slice()
}
- pub fn transport_target_set(&self) -> Result<RadrootsTransportTargetSet, RadrootsSdkError> {
- Ok(RadrootsTransportTargetSet::new(self.targets.clone())?)
+ pub fn transport_target_set(&self) -> Result<TransportTargetSet, RadrootsSdkError> {
+ Ok(TransportTargetSet::new(self.targets.clone())?)
}
pub fn nostr_relay_urls(&self) -> Vec<String> {
self.targets
.iter()
- .filter(|target| target.kind() == &RadrootsTransportKind::Nostr)
+ .filter(|target| target.kind() == &TransportId::NOSTR)
.map(|target| target.uri().as_str().to_owned())
.collect()
}
- pub fn into_targets(self) -> Vec<RadrootsTransportTarget> {
+ pub fn into_targets(self) -> Vec<Target> {
self.targets
}
@@ -314,9 +316,7 @@ impl TargetSet {
self.targets.is_empty()
}
- fn from_transport_targets(
- targets: Vec<RadrootsTransportTarget>,
- ) -> Result<Self, RadrootsSdkError> {
+ fn from_transport_targets(targets: Vec<Target>) -> Result<Self, RadrootsSdkError> {
if targets.is_empty() {
return Err(RadrootsSdkError::empty_transport_targets(
"sdk transport target set",
@@ -329,7 +329,7 @@ impl TargetSet {
));
}
for target in &targets {
- if target.kind() == &RadrootsTransportKind::Reticulum
+ if target.kind() == &TransportId::RETICULUM
&& target.uri().as_str() != RADROOTS_RETICULUM_ENDPOINT_URI
{
return Err(RadrootsSdkError::InvalidRequest {
@@ -339,7 +339,7 @@ impl TargetSet {
});
}
}
- RadrootsTransportTargetSet::new(targets.clone())?;
+ TransportTargetSet::new(targets.clone())?;
let canonical_targets = targets
.iter()
.map(|target| target.fingerprint().to_string())
@@ -440,10 +440,11 @@ impl ReticulumProfile {
}
pub fn target_set(&self) -> Result<TargetSet, RadrootsSdkError> {
- if self.endpoint_uri.as_str() != radroots_transport::RADROOTS_RETICULUM_ENDPOINT_URI {
+ if self.endpoint_uri.as_str() != RADROOTS_RETICULUM_ENDPOINT_URI {
return Err(radroots_transport::RadrootsTransportError::InvalidTargetUri.into());
}
- TargetSet::transport_targets(vec![RadrootsTransportTarget::reticulum_with_metadata(
+ TargetSet::transport_targets(vec![Target::new_with_metadata(
+ TransportId::RETICULUM,
self.endpoint_uri.as_str(),
Some(self.scope.transport_scope()),
None,
@@ -639,9 +640,7 @@ impl TransportProfile {
}
}
- pub(crate) fn configured_transport_targets(
- &self,
- ) -> Result<Vec<RadrootsTransportTarget>, RadrootsSdkError> {
+ pub(crate) fn configured_transport_targets(&self) -> Result<Vec<Target>, RadrootsSdkError> {
Ok(self
.target_set()?
.map(TargetSet::into_targets)
@@ -652,7 +651,7 @@ impl TransportProfile {
match self {
Self::LocalOnly => vec![
RadrootsTransportStatus::new(
- RadrootsTransportKind::Local,
+ TransportId::LOCAL,
true,
RadrootsTransportImplementationState::Real,
false,
@@ -688,7 +687,7 @@ impl TransportProfile {
fn nostr_transport_status(profile_id: &str) -> RadrootsTransportStatus {
RadrootsTransportStatus::new(
- RadrootsTransportKind::Nostr,
+ TransportId::NOSTR,
true,
RadrootsTransportImplementationState::Real,
true,
@@ -699,7 +698,7 @@ fn nostr_transport_status(profile_id: &str) -> RadrootsTransportStatus {
fn reticulum_transport_status(profile_id: &str, endpoint_uri: &str) -> RadrootsTransportStatus {
RadrootsTransportStatus::new(
- RadrootsTransportKind::Reticulum,
+ TransportId::RETICULUM,
true,
RadrootsTransportImplementationState::Real,
false,
@@ -724,7 +723,7 @@ impl From<RadrootsTransportDeliveryReceipt> for TransportReceipt {
#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
pub struct TransportReceipt {
request_id: String,
- target_set: RadrootsTransportTargetSet,
+ target_set: TransportTargetSet,
target_receipts: Vec<RadrootsTransportTargetReceipt>,
}
@@ -733,7 +732,7 @@ impl TransportReceipt {
self.request_id.as_str()
}
- pub fn target_set(&self) -> &RadrootsTransportTargetSet {
+ pub fn target_set(&self) -> &TransportTargetSet {
&self.target_set
}
diff --git a/crates/sdk/src/workflow_runtime.rs b/crates/sdk/src/workflow_runtime.rs
@@ -23,9 +23,8 @@ use radroots_signing::{
Actor, SignRequest, Signer,
request::{CancellationPolicy, SignPolicy},
};
-use radroots_transport::{
- RADROOTS_RETICULUM_ENDPOINT_URI, RadrootsTransportKind, RadrootsTransportTarget,
-};
+use radroots_transport::{Target, TransportId};
+use radroots_transport_reticulum::RADROOTS_RETICULUM_ENDPOINT_URI;
use sha2::{Digest, Sha256};
use sqlx::Row;
@@ -221,7 +220,7 @@ async fn enqueue_signed_workflow_event(
})?;
ensure_runtime_operation_can_commit(&mut tx, request, &idempotency_key).await?;
let local_import_observation = RadrootsTransportObservation::new(
- RadrootsTransportKind::Local,
+ TransportId::LOCAL,
SDK_LOCAL_EVENT_ENDPOINT_URI,
RadrootsTransportObservationType::LocalImport,
observed_at_ms,
@@ -300,7 +299,7 @@ async fn enqueue_signed_trade_workflow_event(
})?;
ensure_runtime_operation_can_commit(&mut tx, request, &idempotency_key).await?;
let local_import_observation = RadrootsTransportObservation::new(
- RadrootsTransportKind::Local,
+ TransportId::LOCAL,
SDK_LOCAL_EVENT_ENDPOINT_URI,
RadrootsTransportObservationType::LocalImport,
observed_at_ms,
@@ -411,13 +410,12 @@ fn resolved_delivery_plan(
)
}
TargetPolicy::MeshScope(scope) => {
- let target_set = TargetSet::transport_targets(vec![
- RadrootsTransportTarget::reticulum_with_metadata(
- RADROOTS_RETICULUM_ENDPOINT_URI,
- Some(scope.transport_scope()),
- None,
- )?,
- ])?;
+ let target_set = TargetSet::transport_targets(vec![Target::new_with_metadata(
+ TransportId::RETICULUM,
+ RADROOTS_RETICULUM_ENDPOINT_URI,
+ Some(scope.transport_scope()),
+ None,
+ )?])?;
delivery_plan_from_targets(
"mesh_scope",
target_set.into_targets(),
@@ -430,7 +428,7 @@ fn resolved_delivery_plan(
fn delivery_plan_from_targets(
transport_profile_id: impl Into<String>,
- targets: Vec<RadrootsTransportTarget>,
+ targets: Vec<Target>,
satisfaction_policy: &SatisfactionPolicy,
reticulum_behavior: RadrootsOutboxReticulumBehavior,
) -> Result<SdkResolvedDeliveryPlan, RadrootsSdkError> {
@@ -446,11 +444,11 @@ fn delivery_plan_from_targets(
fn reticulum_behavior_for_targets(
transport_profile: &TransportProfile,
- targets: &[RadrootsTransportTarget],
+ targets: &[Target],
) -> RadrootsOutboxReticulumBehavior {
if targets
.iter()
- .any(|target| target.kind() == &RadrootsTransportKind::Reticulum)
+ .any(|target| target.kind() == &TransportId::RETICULUM)
{
outbox_reticulum_behavior(transport_profile)
} else {
diff --git a/crates/sdk/tests/source_boundary.rs b/crates/sdk/tests/source_boundary.rs
@@ -113,6 +113,34 @@ fn active_sources_do_not_import_retired_listing_contracts() {
}
#[test]
+fn active_sources_use_canonical_transport_type_names() {
+ for path in active_source_files() {
+ let source = read_source(&path);
+ for retired in [
+ "RadrootsTransportKind",
+ "RadrootsTransportMeshScopeId",
+ "RadrootsTransportTarget",
+ "RadrootsTransportTargetFingerprint",
+ "RadrootsTransportTargetLabel",
+ "RadrootsTransportTargetSet",
+ ] {
+ let restores_identifier = source.match_indices(retired).any(|(index, _)| {
+ let before = source[..index].chars().next_back();
+ let after = source[index + retired.len()..].chars().next();
+ before.is_none_or(|character| !(character.is_alphanumeric() || character == '_'))
+ && after
+ .is_none_or(|character| !(character.is_alphanumeric() || character == '_'))
+ });
+ assert!(
+ !restores_identifier,
+ "{} must use the canonical transport type instead of `{retired}`",
+ path.display()
+ );
+ }
+ }
+}
+
+#[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/sync_runtime.rs b/crates/sdk/tests/sync_runtime.rs
@@ -31,15 +31,14 @@ use radroots_sdk::{
StorageStatusRequest, SyncStatusRequest, SyncStatusSource, TargetPolicy, TransportProfile,
};
use radroots_signing::{Actor, actor::ActorSource};
-use radroots_transport::{
- RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE, RadrootsTransportMeshScopeId,
- RadrootsTransportSatisfactionPolicy, RadrootsTransportTarget, RadrootsTransportTargetLabel,
-};
+use radroots_transport::target::{TargetLabel, TargetScope};
+use radroots_transport::{RadrootsTransportSatisfactionPolicy, Target, TransportId};
use radroots_transport_nostr::{
RadrootsMockRelayPublishAdapter, RadrootsNostrTransport, RadrootsRelayOutcome,
RadrootsRelayPublishAdapter, RadrootsRelayPublishRelayReceipt, RadrootsRelayPublishRequest,
RadrootsRelayTransportError,
};
+use radroots_transport_reticulum::RADROOTS_RETICULUM_UNAVAILABLE_MESSAGE;
#[cfg(feature = "radrootsd-execution")]
use std::io::{Read, Write};
#[cfg(feature = "radrootsd-execution")]
@@ -602,11 +601,12 @@ fn scoped_duplicate_relay_delivery_plan(
)
}
-fn scoped_nostr_target(relay: &str, scope: &str, label: &str) -> RadrootsTransportTarget {
- RadrootsTransportTarget::nostr_relay_with_metadata(
+fn scoped_nostr_target(relay: &str, scope: &str, label: &str) -> Target {
+ Target::new_with_metadata(
+ TransportId::NOSTR,
relay,
- Some(RadrootsTransportMeshScopeId::parse(scope).expect("target scope")),
- Some(RadrootsTransportTargetLabel::parse(label).expect("target label")),
+ Some(TargetScope::parse(scope).expect("target scope")),
+ Some(TargetLabel::parse(label).expect("target label")),
)
.expect("scoped Nostr target")
}
@@ -1746,7 +1746,7 @@ async fn product_push_outbox_uses_radrootsd_execution_transport_with_daemon_reso
assert_eq!(pre_push_targets.len(), 1);
assert_eq!(
pre_push_targets[0].transport_kind,
- radroots_sdk::RadrootsTransportKind::Nostr
+ radroots_sdk::TransportId::NOSTR
);
assert_eq!(
pre_push_targets[0].status,
@@ -2753,7 +2753,7 @@ async fn push_outbox_with_transport_scopes_duplicate_endpoint_sibling_plans() {
1,
radroots_transport::RadrootsTransportSatisfactionPolicy::all_accepted(),
vec![
- radroots_transport::RadrootsTransportTarget::nostr_relay(RELAY_A)
+ radroots_transport::Target::new(TransportId::NOSTR, RELAY_A)
.expect("second target"),
],
),
diff --git a/crates/sdk/tests/unit/adapters_radrootsd_tests.rs b/crates/sdk/tests/unit/adapters_radrootsd_tests.rs
@@ -10,7 +10,7 @@ use radroots_protocol::radrootsd::transport_publish::v5::{
TargetOutcome as TransportPublishTargetOutcome, TargetPolicy as TransportPublishTargetPolicy,
TargetSource as TransportPublishTargetSource,
};
-use radroots_transport::RADROOTS_RETICULUM_ENDPOINT_URI;
+use radroots_transport_reticulum::RADROOTS_RETICULUM_ENDPOINT_URI;
use std::io::{Read, Write};
use std::net::TcpListener;
use std::thread::JoinHandle;
diff --git a/crates/sdk/tests/unit/sync_runtime_tests.rs b/crates/sdk/tests/unit/sync_runtime_tests.rs
@@ -51,10 +51,8 @@ use radroots_signing::{
Actor, Error as SigningError, SignReceipt, SignRequest, Signer, SignerStatus,
actor::ActorSource, error::Kind as SigningErrorKind, signer::BoxFuture as SigningFuture,
};
-use radroots_transport::{
- RadrootsTransportDeliveryTargetStatus, RadrootsTransportMeshScopeId, RadrootsTransportTarget,
- RadrootsTransportTargetLabel,
-};
+use radroots_transport::target::{TargetLabel, TargetScope};
+use radroots_transport::{RadrootsTransportDeliveryTargetStatus, Target, TransportId};
#[cfg(feature = "radrootsd-execution")]
use radroots_transport::{RadrootsTransportSatisfactionClass, RadrootsTransportSatisfactionPolicy};
use radroots_transport_nostr::{
@@ -233,7 +231,7 @@ async fn claimed_uningested_radrootsd_event_with_satisfaction(
.expect("sdk");
let draft = radrootsd_frozen_draft(d_tag);
let radrootsd_target =
- RadrootsTransportTarget::nostr_relay("wss://relay.example.com").expect("Nostr target");
+ Target::new(TransportId::NOSTR, "wss://relay.example.com").expect("Nostr target");
let enqueue = sdk
._outbox
.enqueue_operation(
@@ -313,12 +311,12 @@ fn assert_no_transport_publish_request(listener: &TcpListener) {
fn delivery_target_record(
delivery_target_id: i64,
delivery_plan_id: i64,
- target: &RadrootsTransportTarget,
+ target: &Target,
) -> RadrootsOutboxDeliveryTargetRecord {
RadrootsOutboxDeliveryTargetRecord {
delivery_target_id,
delivery_plan_id,
- transport_kind: target.kind().clone(),
+ transport_kind: *target.kind(),
endpoint_uri: target.uri().clone(),
target_scope: target.scope().cloned(),
target_label: target.label().cloned(),
@@ -869,12 +867,12 @@ async fn radrootsd_push_empty_queue_and_private_helpers_are_deterministic() {
.expect("any-target radrootsd policy"),
TransportPublishDeliveryPolicy::Any
);
- let first_required = RadrootsTransportTarget::nostr_relay("wss://required-a.example.com")
+ let first_required = Target::new(TransportId::NOSTR, "wss://required-a.example.com")
.expect("first required target");
- let second_required = RadrootsTransportTarget::nostr_relay("wss://required-b.example.com")
+ let second_required = Target::new(TransportId::NOSTR, "wss://required-b.example.com")
.expect("second required target");
- let optional = RadrootsTransportTarget::nostr_relay("wss://optional.example.com")
- .expect("optional target");
+ let optional =
+ Target::new(TransportId::NOSTR, "wss://optional.example.com").expect("optional target");
let policy = RadrootsTransportSatisfactionPolicy::required_targets(
RadrootsTransportSatisfactionClass::Accepted,
vec![
@@ -1011,11 +1009,11 @@ 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 = RadrootsTransportTarget::reticulum().expect("Reticulum target");
+ let target = Target::reticulum().expect("Reticulum target");
let record = RadrootsOutboxDeliveryTargetRecord {
delivery_target_id: 1,
delivery_plan_id: 1,
- transport_kind: target.kind().clone(),
+ transport_kind: *target.kind(),
endpoint_uri: target.uri().clone(),
target_scope: target.scope().cloned(),
target_label: target.label().cloned(),
@@ -1043,10 +1041,11 @@ fn radrootsd_outbox_target_conversion_rejects_reticulum_targets_before_behavior_
#[cfg(feature = "radrootsd-execution")]
#[test]
fn radrootsd_outbox_target_conversion_preserves_nostr_scope_and_label() {
- let target = RadrootsTransportTarget::nostr_relay_with_metadata(
+ let target = Target::new_with_metadata(
+ TransportId::NOSTR,
"wss://relay.example.com",
- Some(RadrootsTransportMeshScopeId::parse("farm.local").expect("scope")),
- Some(RadrootsTransportTargetLabel::parse("Farm relay").expect("label")),
+ Some(TargetScope::parse("farm.local").expect("scope")),
+ Some(TargetLabel::parse("Farm relay").expect("label")),
)
.expect("scoped Nostr target");
let record = delivery_target_record(1, 1, &target);
@@ -1191,8 +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 = RadrootsTransportTarget::reticulum().expect("Reticulum target");
- claimed.delivery_targets[0].transport_kind = reticulum_target.kind().clone();
+ let reticulum_target = Target::reticulum().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();
let sync = sdk.sync();
@@ -1259,7 +1258,7 @@ async fn radrootsd_local_validation_failure_keeps_sibling_plan_ready_and_claimab
1,
RadrootsTransportSatisfactionPolicy::all_accepted(),
vec![
- RadrootsTransportTarget::nostr_relay("wss://active.example.com")
+ Target::new(TransportId::NOSTR, "wss://active.example.com")
.expect("active target"),
],
),
@@ -1283,7 +1282,7 @@ async fn radrootsd_local_validation_failure_keeps_sibling_plan_ready_and_claimab
1,
RadrootsTransportSatisfactionPolicy::all_accepted(),
vec![
- RadrootsTransportTarget::nostr_relay("wss://sibling.example.com")
+ Target::new(TransportId::NOSTR, "wss://sibling.example.com")
.expect("sibling target"),
],
),
@@ -1321,8 +1320,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 = RadrootsTransportTarget::reticulum().expect("Reticulum target");
- claimed.delivery_targets[0].transport_kind = reticulum_target.kind().clone();
+ let reticulum_target = Target::reticulum().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();
let sync = sdk.sync();
@@ -1526,16 +1525,18 @@ async fn radrootsd_completion_matches_duplicate_endpoint_targets_by_scope() {
let signed_event = RadrootsdFixtureSigner::new()
.sign_frozen_draft(&draft)
.expect("signed event");
- let farm_a = RadrootsTransportTarget::nostr_relay_with_metadata(
+ let farm_a = Target::new_with_metadata(
+ TransportId::NOSTR,
"wss://relay.example.com",
- Some(RadrootsTransportMeshScopeId::parse("farm.a").expect("farm a scope")),
- Some(RadrootsTransportTargetLabel::parse("Farm A").expect("farm a label")),
+ Some(TargetScope::parse("farm.a").expect("farm a scope")),
+ Some(TargetLabel::parse("Farm A").expect("farm a label")),
)
.expect("farm a target");
- let farm_b = RadrootsTransportTarget::nostr_relay_with_metadata(
+ let farm_b = Target::new_with_metadata(
+ TransportId::NOSTR,
"wss://relay.example.com",
- Some(RadrootsTransportMeshScopeId::parse("farm.b").expect("farm b scope")),
- Some(RadrootsTransportTargetLabel::parse("Farm B").expect("farm b label")),
+ Some(TargetScope::parse("farm.b").expect("farm b scope")),
+ Some(TargetLabel::parse("Farm B").expect("farm b label")),
)
.expect("farm b target");
let enqueue = sdk
@@ -1736,10 +1737,11 @@ impl OutboxPublishReceiptFixture for RadrootsOutboxPublishReceipt {
.push(RadrootsOutboxPublishTargetReceipt {
delivery_target_id: 10,
endpoint_uri: "wss://relay.example.com".to_owned(),
- endpoint_fingerprint: RadrootsTransportTarget::nostr_relay_with_metadata(
+ endpoint_fingerprint: Target::new_with_metadata(
+ TransportId::NOSTR,
"wss://relay.example.com",
- Some(RadrootsTransportMeshScopeId::parse("farm.local").expect("scope")),
- Some(RadrootsTransportTargetLabel::parse("Farm relay").expect("label")),
+ Some(TargetScope::parse("farm.local").expect("scope")),
+ Some(TargetLabel::parse("Farm relay").expect("label")),
)
.expect("target")
.fingerprint()
diff --git a/crates/sdk/tests/unit/transport_tests.rs b/crates/sdk/tests/unit/transport_tests.rs
@@ -4,10 +4,8 @@ use super::{
TransportProfile,
};
use crate::{RadrootsSdkError, SDK_TRANSPORT_TARGET_MAX_COUNT};
-use radroots_transport::{
- RADROOTS_RETICULUM_ENDPOINT_URI, RadrootsTransportError, RadrootsTransportKind,
- RadrootsTransportTarget,
-};
+use radroots_transport::{RadrootsTransportError, Target, TransportId};
+use radroots_transport_reticulum::RADROOTS_RETICULUM_ENDPOINT_URI;
use crate::serializer_failure::assert_struct_serialize_error_paths;
@@ -208,10 +206,10 @@ fn target_sets_reject_duplicate_transport_fingerprints() {
if message == "transport target set contains duplicate fingerprints"
));
- 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 first =
+ Target::new(TransportId::NOSTR, "wss://relay-a.example.com/path").expect("first target");
+ let second =
+ Target::new(TransportId::NOSTR, "WSS://RELAY-A.EXAMPLE.COM/path").expect("second target");
let duplicate_targets =
TargetSet::transport_targets(vec![first, second]).expect_err("duplicate targets");
@@ -306,7 +304,7 @@ fn explicit_target_sets_reject_noncanonical_reticulum_endpoints() {
"reticulum:custom".to_owned(),
] {
assert_eq!(
- RadrootsTransportTarget::new(RadrootsTransportKind::Reticulum, invalid.as_str())
+ Target::new(TransportId::RETICULUM, invalid.as_str())
.expect_err("invalid Reticulum target"),
RadrootsTransportError::InvalidTargetUri
);