commit b65f714457dd6eff1d6cb00b3828fc0c2aa12760
parent 52e1cfff74b8d7720d5bac84bc2367cc8c5edee4
Author: triesap <tyson@radroots.org>
Date: Tue, 7 Jul 2026 08:33:50 +0000
transport: reject custom Reticulum preview targets
Diffstat:
2 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/crates/sdk/src/transport.rs b/crates/sdk/src/transport.rs
@@ -16,6 +16,7 @@ pub use radroots_transport::{
};
pub const SDK_TRANSPORT_TARGET_MAX_COUNT: usize = 20;
+const RETICULUM_PREVIEW_ENDPOINT_URI: &str = "reticulum:preview-unavailable";
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize)]
#[serde(rename_all = "snake_case")]
@@ -234,6 +235,17 @@ impl TargetSet {
targets.len(),
));
}
+ for target in &targets {
+ if target.kind == RadrootsTransportKind::Reticulum
+ && target.uri.as_str() != RETICULUM_PREVIEW_ENDPOINT_URI
+ {
+ return Err(RadrootsSdkError::InvalidRequest {
+ message: format!(
+ "Reticulum preview endpoint must be {RETICULUM_PREVIEW_ENDPOINT_URI}"
+ ),
+ });
+ }
+ }
let canonical_targets = targets
.iter()
.map(|target| {
@@ -296,7 +308,7 @@ pub struct ReticulumPreviewProfile {
impl ReticulumPreviewProfile {
pub fn preview_unavailable() -> Self {
Self {
- endpoint_uri: "reticulum:preview-unavailable".to_owned(),
+ endpoint_uri: RETICULUM_PREVIEW_ENDPOINT_URI.to_owned(),
behavior: ReticulumPreviewBehavior::RejectDeliveryAttempts,
}
}
diff --git a/crates/sdk/tests/unit/transport_tests.rs b/crates/sdk/tests/unit/transport_tests.rs
@@ -3,6 +3,7 @@ use super::{
ReticulumPreviewProfile, SatisfactionPolicy, TargetPolicy, TargetSet, TransportProfile,
};
use crate::{RadrootsSdkError, SDK_TRANSPORT_TARGET_MAX_COUNT};
+use radroots_transport::{RadrootsTransportKind, RadrootsTransportTarget};
#[path = "../support/serializer_failure.rs"]
mod serializer_failure;
@@ -197,6 +198,20 @@ fn reticulum_preview_profile_uses_canonical_endpoint_and_behavior_names() {
}
#[test]
+fn explicit_target_sets_reject_noncanonical_reticulum_preview_endpoints() {
+ let err = TargetSet::transport_targets(vec![
+ RadrootsTransportTarget::new(
+ RadrootsTransportKind::Reticulum,
+ "reticulum:preview-unavailable-alt",
+ )
+ .expect("target"),
+ ])
+ .expect_err("noncanonical Reticulum endpoint");
+
+ assert!(matches!(err, RadrootsSdkError::InvalidRequest { .. }));
+}
+
+#[test]
fn normalized_relays_reject_empty_and_over_limit_sets() {
assert!(matches!(
TargetSet::from_normalized_nostr_relays(Vec::new()),