radrootsd

JSON-RPC bridge for Radroots event publishing
git clone https://radroots.dev/git/radrootsd.git
Log | Files | Refs | README | LICENSE

commit 17de947e1b9ae44d2d0de2ce19498530d3e89fe7
parent 8714874e201b1f9449fbd5a2664163056980d39c
Author: triesap <tyson@radroots.org>
Date:   Tue,  7 Jul 2026 08:33:50 +0000

transport: reject custom Reticulum preview publish targets

Diffstat:
Msrc/core/transport_publish.rs | 38++++++++++++++++++++++++++++++++++----
1 file changed, 34 insertions(+), 4 deletions(-)

diff --git a/src/core/transport_publish.rs b/src/core/transport_publish.rs @@ -2077,10 +2077,7 @@ mod tests { TransportPublishEventRequest { event, target_policy: TransportPublishTargetPolicy::explicit_targets(vec![ - TransportPublishTarget::reticulum_preview( - "reticulum:preview-unavailable", - behavior, - ), + TransportPublishTarget::reticulum_preview(behavior), ]), delivery_policy: TransportPublishDeliveryPolicy::Any, idempotency_key: None, @@ -2920,6 +2917,39 @@ mod tests { } #[tokio::test] + async fn publish_event_rejects_noncanonical_reticulum_preview_endpoint_before_recording_job() { + let identity = RadrootsIdentity::generate(); + let (proxy, adapter) = transport_publish(TransportPublishConfig::default()); + let principal = + explicit_target_principal(&proxy, identity.public_key_hex(), PublishJobVisibility::Own); + let mut request = reticulum_publish_request( + signed_event(&identity, "{}"), + TransportPublishPreviewBehavior::RejectDeliveryAttempts, + ); + request.target_policy = + TransportPublishTargetPolicy::explicit_targets(vec![TransportPublishTarget { + transport_kind: "reticulum".to_owned(), + endpoint_uri: "reticulum:preview-unavailable-alt".to_owned(), + preview_behavior: Some(TransportPublishPreviewBehavior::RejectDeliveryAttempts), + }]); + + let err = proxy + .publish_event(&principal, request) + .await + .expect_err("noncanonical Reticulum endpoint"); + + assert!(matches!(err, TransportPublishError::InvalidSignedEvent(_))); + assert!(adapter.captured_raw_events().is_empty()); + assert!( + proxy + .store + .list_jobs_for_principal(&principal, 10) + .expect("jobs") + .is_empty() + ); + } + + #[tokio::test] async fn publish_event_records_unsafe_request_relay_rejection() { let identity = RadrootsIdentity::generate(); let (proxy, adapter) = transport_publish(TransportPublishConfig::default());