radrootsd

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

commit 6cd7c92bc95e2c3b42749b98798ffff89909a177
parent 10c59915a365e89e5e2bae8efd5a549c4d818a96
Author: triesap <tyson@radroots.org>
Date:   Wed,  5 Aug 2026 14:48:08 +0000

refactor: adopt canonical transport delivery policy

- pin daemon dependencies to the final authored-operations lib revision
- remove duplicate satisfaction policy state from the relay adapter
- preserve exact V5 target, SSRF, idempotency, and persistence behavior
- qualify locked checks, tests, Clippy, docs, and package payloads

Diffstat:
MCargo.lock | 22++++++++++++----------
MCargo.toml | 16++++++++--------
Msrc/core/transport_publish.rs | 56+++++---------------------------------------------------
Msrc/transport/relay_publish.rs | 11-----------
Mtests/source_boundary.rs | 45++++-----------------------------------------
5 files changed, 29 insertions(+), 121 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock @@ -1604,7 +1604,7 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "radroots_blossom" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ "mediatype", "serde", @@ -1616,7 +1616,7 @@ dependencies = [ [[package]] name = "radroots_core" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ "rust_decimal", "serde", @@ -1625,7 +1625,7 @@ dependencies = [ [[package]] name = "radroots_event" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ "hex", "jiff-tzdb", @@ -1643,8 +1643,9 @@ dependencies = [ [[package]] name = "radroots_event_codec" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ + "hex", "radroots_blossom", "radroots_core", "radroots_event", @@ -1653,12 +1654,13 @@ dependencies = [ "secp256k1", "serde", "serde_json", + "sha2", ] [[package]] name = "radroots_identity" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ "k256", "serde", @@ -1668,7 +1670,7 @@ dependencies = [ [[package]] name = "radroots_nostr" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ "nostr", "radroots_event", @@ -1682,7 +1684,7 @@ dependencies = [ [[package]] name = "radroots_protocol" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ "serde", ] @@ -1690,7 +1692,7 @@ dependencies = [ [[package]] name = "radroots_secrets" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ "chacha20poly1305", "zeroize", @@ -1699,7 +1701,7 @@ dependencies = [ [[package]] name = "radroots_transport" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ "radroots_event", "radroots_identity", @@ -1710,7 +1712,7 @@ dependencies = [ [[package]] name = "radroots_transport_nostr" version = "0.1.0-alpha" -source = "git+https://github.com/radrootslabs/lib.git?rev=74f5c91cbc80248df1f51f644004daaf8ae8e9be#74f5c91cbc80248df1f51f644004daaf8ae8e9be" +source = "git+https://github.com/radrootslabs/lib.git?rev=691b3c844bb8824fd16b2ff4fb37b8c09bac208d#691b3c844bb8824fd16b2ff4fb37b8c09bac208d" dependencies = [ "async-wsocket", "nostr-relay-pool", diff --git a/Cargo.toml b/Cargo.toml @@ -11,14 +11,14 @@ description = "Radroots local runtime daemon for storage, sync, and relay publis resolver = "3" [workspace.dependencies] -radroots_event = { git = "https://github.com/radrootslabs/lib.git", rev = "74f5c91cbc80248df1f51f644004daaf8ae8e9be", version = "=0.1.0-alpha" } -radroots_event_codec = { git = "https://github.com/radrootslabs/lib.git", rev = "74f5c91cbc80248df1f51f644004daaf8ae8e9be", version = "=0.1.0-alpha" } -radroots_identity = { git = "https://github.com/radrootslabs/lib.git", rev = "74f5c91cbc80248df1f51f644004daaf8ae8e9be", version = "=0.1.0-alpha" } -radroots_nostr = { git = "https://github.com/radrootslabs/lib.git", rev = "74f5c91cbc80248df1f51f644004daaf8ae8e9be", version = "=0.1.0-alpha" } -radroots_protocol = { git = "https://github.com/radrootslabs/lib.git", rev = "74f5c91cbc80248df1f51f644004daaf8ae8e9be", version = "=0.1.0-alpha", default-features = false } -radroots_secrets = { git = "https://github.com/radrootslabs/lib.git", rev = "74f5c91cbc80248df1f51f644004daaf8ae8e9be", version = "=0.1.0-alpha", default-features = false } -radroots_transport_nostr = { git = "https://github.com/radrootslabs/lib.git", rev = "74f5c91cbc80248df1f51f644004daaf8ae8e9be", version = "=0.1.0-alpha", default-features = false } -radroots_transport = { git = "https://github.com/radrootslabs/lib.git", rev = "74f5c91cbc80248df1f51f644004daaf8ae8e9be", version = "=0.1.0-alpha", default-features = false } +radroots_event = { git = "https://github.com/radrootslabs/lib.git", rev = "691b3c844bb8824fd16b2ff4fb37b8c09bac208d", version = "=0.1.0-alpha" } +radroots_event_codec = { git = "https://github.com/radrootslabs/lib.git", rev = "691b3c844bb8824fd16b2ff4fb37b8c09bac208d", version = "=0.1.0-alpha" } +radroots_identity = { git = "https://github.com/radrootslabs/lib.git", rev = "691b3c844bb8824fd16b2ff4fb37b8c09bac208d", version = "=0.1.0-alpha" } +radroots_nostr = { git = "https://github.com/radrootslabs/lib.git", rev = "691b3c844bb8824fd16b2ff4fb37b8c09bac208d", version = "=0.1.0-alpha" } +radroots_protocol = { git = "https://github.com/radrootslabs/lib.git", rev = "691b3c844bb8824fd16b2ff4fb37b8c09bac208d", version = "=0.1.0-alpha", default-features = false } +radroots_secrets = { git = "https://github.com/radrootslabs/lib.git", rev = "691b3c844bb8824fd16b2ff4fb37b8c09bac208d", version = "=0.1.0-alpha", default-features = false } +radroots_transport_nostr = { git = "https://github.com/radrootslabs/lib.git", rev = "691b3c844bb8824fd16b2ff4fb37b8c09bac208d", version = "=0.1.0-alpha", default-features = false } +radroots_transport = { git = "https://github.com/radrootslabs/lib.git", rev = "691b3c844bb8824fd16b2ff4fb37b8c09bac208d", version = "=0.1.0-alpha", default-features = false } [lints.rust] unexpected_cfgs = { level = "warn", check-cfg = ['cfg(coverage_nightly)'] } diff --git a/src/core/transport_publish.rs b/src/core/transport_publish.rs @@ -27,8 +27,7 @@ use radroots_protocol::radrootsd::transport_publish::v5::{ TargetSource, }; use radroots_transport::{ - RadrootsTransportSatisfactionClass, RadrootsTransportSatisfactionPolicy, - Target as TransportTarget, TransportId, + Error as TransportError, Target as TransportTarget, TransportId, target::{TargetFingerprint, TargetLabel, TargetScope}, }; use serde::{Deserialize, Serialize}; @@ -616,15 +615,9 @@ impl TransportPublish { .collect(), ) .map_err(|error| TransportPublishError::Relay(error.to_string()))?; - let satisfaction_policy = satisfaction_policy_from_delivery_policy( - &delivery_policy, - target_count, - resolution.targets.as_slice(), - )?; let publish_relays = target_set.relays().to_vec(); let publish_request = - RadrootsRelayPublishRequest::new(signed_event, target_set, current_unix_millis()) - .with_satisfaction_policy(satisfaction_policy); + RadrootsRelayPublishRequest::new(signed_event, target_set, current_unix_millis()); let started = Instant::now(); let publish_timeout = Duration::from_millis(timeout_ms); let receipts = @@ -2852,14 +2845,14 @@ fn transport_target_from_outcome_parts( endpoint_uri: &str, scope: Option<TargetScope>, label: Option<TargetLabel>, -) -> Result<TransportTarget, radroots_transport::RadrootsTransportError> { +) -> Result<TransportTarget, TransportError> { match transport_kind { TransportId::NOSTR => { TransportTarget::nostr_relay_with_metadata(endpoint_uri, scope, label) } TransportId::RETICULUM => { if endpoint_uri != RADROOTS_RETICULUM_ENDPOINT_URI { - return Err(radroots_transport::RadrootsTransportError::InvalidTargetUri); + return Err(TransportError::InvalidTargetUri); } let scope = match scope { Some(scope) => scope, @@ -2873,7 +2866,7 @@ fn transport_target_from_outcome_parts( ) } TransportId::LOCAL => TransportTarget::local_with_metadata(endpoint_uri, scope, label), - _ => Err(radroots_transport::RadrootsTransportError::InvalidTargetUri), + _ => Err(TransportError::InvalidTargetUri), } } @@ -2914,45 +2907,6 @@ fn required_outcomes_for_policy<'a>( .collect() } -fn satisfaction_policy_from_delivery_policy( - delivery_policy: &DeliveryPolicy, - target_count: usize, - nostr_targets: &[ResolvedPublishRelay], -) -> Result<RadrootsTransportSatisfactionPolicy, TransportPublishError> { - match delivery_policy { - DeliveryPolicy::Any => Ok(RadrootsTransportSatisfactionPolicy::any_accepted()), - DeliveryPolicy::All => Ok(RadrootsTransportSatisfactionPolicy::all_accepted()), - DeliveryPolicy::Quorum { quorum } => { - let required = (*quorum).min(target_count).min(nostr_targets.len()).max(1); - Ok(RadrootsTransportSatisfactionPolicy::quorum_accepted( - u16::try_from(required).unwrap_or(u16::MAX), - )) - } - DeliveryPolicy::RequiredTargets { targets } => { - let nostr_required_targets = targets - .iter() - .filter_map(|required| { - nostr_targets.iter().find_map(|target| { - target - .fingerprint() - .ok() - .filter(|fingerprint| fingerprint.as_str() == required.as_str()) - }) - }) - .collect::<Vec<_>>(); - if nostr_required_targets.is_empty() { - Ok(RadrootsTransportSatisfactionPolicy::no_wait()) - } else { - Ok(RadrootsTransportSatisfactionPolicy::required_targets( - RadrootsTransportSatisfactionClass::Accepted, - nostr_required_targets, - ) - .map_err(|error| TransportPublishError::Transport(error.to_string()))?) - } - } - } -} - fn delivery_status( delivery_policy: &DeliveryPolicy, target_count: usize, diff --git a/src/transport/relay_publish.rs b/src/transport/relay_publish.rs @@ -11,7 +11,6 @@ use std::sync::{Arc, Mutex}; use nostr::JsonUtil; use radroots_event::SignedEvent; -use radroots_transport::RadrootsTransportSatisfactionPolicy; use crate::host_nostr::DaemonNostrClient; @@ -89,7 +88,6 @@ impl RelayTargetSet { pub(crate) struct RelayPublishRequest { signed_event: SignedEvent, targets: RelayTargetSet, - satisfaction_policy: RadrootsTransportSatisfactionPolicy, now_ms: i64, } @@ -98,18 +96,9 @@ impl RelayPublishRequest { Self { signed_event, targets, - satisfaction_policy: RadrootsTransportSatisfactionPolicy::all_accepted(), now_ms, } } - - pub(crate) fn with_satisfaction_policy( - mut self, - satisfaction_policy: RadrootsTransportSatisfactionPolicy, - ) -> Self { - self.satisfaction_policy = satisfaction_policy; - self - } } #[derive(Clone, Copy, Debug, Eq, PartialEq)] diff --git a/tests/source_boundary.rs b/tests/source_boundary.rs @@ -198,7 +198,7 @@ fn transport_publish_sources_reject_removed_protocol_identifiers() { } assert!( manifest_source.contains( - "radroots_transport_nostr = { git = \"https://github.com/radrootslabs/lib.git\", rev = \"74f5c91cbc80248df1f51f644004daaf8ae8e9be\", version = \"=0.1.0-alpha\"" + "radroots_transport_nostr = { git = \"https://github.com/radrootslabs/lib.git\", rev = \"691b3c844bb8824fd16b2ff4fb37b8c09bac208d\", version = \"=0.1.0-alpha\"" ), "Cargo.toml must pin radroots_transport_nostr to the approved Lib revision and exact version" ); @@ -401,32 +401,10 @@ fn transport_publish_required_targets_stay_fingerprint_exact() { ); } - let satisfaction_arm = source_window( - daemon_source.as_str(), - "DeliveryPolicy::RequiredTargets { targets } => {", - "fn delivery_status(", + assert!( + !daemon_source.contains("SatisfactionPolicy"), + "daemon V5 delivery policy must not be duplicated in the transport adapter" ); - for required in [ - "let nostr_required_targets = targets", - "target\n .fingerprint()", - "filter(|fingerprint| fingerprint.as_str() == required.as_str())", - "RadrootsTransportSatisfactionPolicy::required_targets(", - ] { - assert!( - satisfaction_arm.contains(required), - "daemon RequiredTargets resolution arm must retain exact fingerprint witness `{required}`" - ); - } - for forbidden in [ - "RadrootsTransportSatisfactionPolicy::all_accepted()", - "RadrootsTransportSatisfactionPolicy::any_accepted()", - "RadrootsTransportSatisfactionPolicy::quorum_accepted(", - ] { - assert!( - !satisfaction_arm.contains(forbidden), - "daemon RequiredTargets resolution arm must not lower to count policy `{forbidden}`" - ); - } use radroots_protocol::radrootsd::transport_publish::v5::{DeliveryPolicy, TargetFingerprint}; let target = TargetFingerprint::parse("a".repeat(64)).expect("fingerprint"); @@ -619,21 +597,6 @@ fn is_doc_surface(path: &Path) -> bool { ) } -fn source_window<'source>( - source: &'source str, - start_marker: &str, - end_marker: &str, -) -> &'source str { - let start = source - .find(start_marker) - .unwrap_or_else(|| panic!("source must contain start marker `{start_marker}`")); - let end = source[start..] - .find(end_marker) - .map(|index| start + index) - .unwrap_or_else(|| panic!("source must contain end marker `{end_marker}`")); - &source[start..end] -} - fn contains_forbidden_concept(source: &str, pattern: &str) -> bool { if !pattern.chars().all(is_rust_identifier_character) { return source.contains(pattern);