commit 40524c7348e8df6ccb854e64485aedbb1e80cfc6
parent 0a12dcf67290ae49285f4a46991b4e2a479382bf
Author: triesap <tyson@radroots.org>
Date: Tue, 7 Jul 2026 22:26:34 +0000
transport: reject proxy explicit publish targets
- Add a typed protocol error for canonical proxy explicit targets.
- Reject proxy transport targets during shared request validation.
- Preserve Reticulum preview validation while blocking daemon proxy targets.
- Extend protocol tests for the canonical proxy rejection path.
Diffstat:
1 file changed, 22 insertions(+), 0 deletions(-)
diff --git a/crates/transport_publish_protocol/src/lib.rs b/crates/transport_publish_protocol/src/lib.rs
@@ -48,6 +48,9 @@ pub enum TransportPublishProtocolError {
InvalidReticulumPreviewEndpoint {
index: usize,
},
+ ExplicitProxyTarget {
+ index: usize,
+ },
TargetLimitExceeded {
max: usize,
actual: usize,
@@ -90,6 +93,10 @@ impl fmt::Display for TransportPublishProtocolError {
f,
"transport target {index} Reticulum preview endpoint must be {RADROOTS_RETICULUM_PREVIEW_ENDPOINT_URI}"
),
+ Self::ExplicitProxyTarget { index } => write!(
+ f,
+ "transport target {index} proxy is an SDK delegation target and cannot be used as a daemon explicit target"
+ ),
Self::TargetLimitExceeded { max, actual } => {
write!(f, "transport target count {actual} exceeds limit {max}")
}
@@ -184,6 +191,9 @@ impl TransportPublishTarget {
}
let transport_kind = RadrootsTransportKind::parse_canonical(self.transport_kind.as_str())
.map_err(|error| transport_kind_error(error, index))?;
+ if transport_kind == RadrootsTransportKind::Proxy {
+ return Err(TransportPublishProtocolError::ExplicitProxyTarget { index });
+ }
if self.endpoint_uri.trim().is_empty() {
return Err(TransportPublishProtocolError::EmptyEndpointUri { index });
}
@@ -839,6 +849,18 @@ mod tests {
Err(TransportPublishProtocolError::InvalidTransportKind { index: 0 })
);
+ let mut explicit_proxy_target = request.clone();
+ explicit_proxy_target.target_policy =
+ TransportPublishTargetPolicy::explicit_targets(vec![TransportPublishTarget {
+ transport_kind: "proxy".to_owned(),
+ endpoint_uri: "radrootsd-proxy:publish".to_owned(),
+ preview_behavior: None,
+ }]);
+ assert_eq!(
+ explicit_proxy_target.validate(1),
+ Err(TransportPublishProtocolError::ExplicitProxyTarget { index: 0 })
+ );
+
let mut empty_key = request.clone();
empty_key.idempotency_key = Some(" ".to_owned());
assert_eq!(