lib

Core libraries for Radroots
git clone https://radroots.dev/git/lib.git
Log | Files | Refs | README

commit f451d26904e4a4a4d59ea9df244541b67b26f9ff
parent e9d27715b40ec1b719d0f2e8531928a12ba3b7d7
Author: triesap <tyson@radroots.org>
Date:   Tue,  7 Jul 2026 08:33:50 +0000

transport: reject custom Reticulum preview targets

Diffstat:
Mcrates/sdk/src/transport.rs | 14+++++++++++++-
Mcrates/sdk/tests/unit/transport_tests.rs | 15+++++++++++++++
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()),