sdk

Radroots SDK and bindings
git clone https://radroots.dev/git/sdk.git
Log | Files | Refs | README

commit 0d4ef63f34003da2c0c7872bd2aef0546a9041a6
parent fd8384aee348034e0c8ea17a868fe7f094770050
Author: triesap <tyson@radroots.org>
Date:   Mon, 27 Jul 2026 20:38:52 +0000

transport: align sdk with sealed models

- use transport target accessors instead of private fields
- retain target-set identity in SDK delivery receipts
- reconstruct governed receipts through the validated constructor
- expose read-only receipt accessors for existing consumers

Diffstat:
Mcrates/sdk/src/sync_runtime.rs | 10+++++-----
Mcrates/sdk/src/transport.rs | 43+++++++++++++++++++++++++++++--------------
Mcrates/sdk/src/workflow_runtime.rs | 12++++++------
3 files changed, 40 insertions(+), 25 deletions(-)

diff --git a/crates/sdk/src/sync_runtime.rs b/crates/sdk/src/sync_runtime.rs @@ -217,11 +217,11 @@ pub struct SyncTransportTargetSummary { impl SyncTransportTargetSummary { fn from_transport_target(target: &RadrootsTransportTarget) -> Self { Self { - transport_kind: target.kind.canonical_label(), - endpoint_uri: target.uri.as_str().to_owned(), - target_scope: target.scope.as_ref().map(|scope| scope.as_str().to_owned()), - target_label: target.label.as_ref().map(|label| label.as_str().to_owned()), - endpoint_fingerprint: target.fingerprint.as_str().to_owned(), + transport_kind: target.kind().canonical_label(), + endpoint_uri: target.uri().as_str().to_owned(), + target_scope: target.scope().map(|scope| scope.as_str().to_owned()), + target_label: target.label().map(|label| label.as_str().to_owned()), + endpoint_fingerprint: target.fingerprint().as_str().to_owned(), } } } diff --git a/crates/sdk/src/transport.rs b/crates/sdk/src/transport.rs @@ -297,8 +297,8 @@ impl TargetSet { pub fn nostr_relay_urls(&self) -> Vec<String> { self.targets .iter() - .filter(|target| target.kind == RadrootsTransportKind::Nostr) - .map(|target| target.uri.as_str().to_owned()) + .filter(|target| target.kind() == &RadrootsTransportKind::Nostr) + .map(|target| target.uri().as_str().to_owned()) .collect() } @@ -329,8 +329,8 @@ impl TargetSet { )); } for target in &targets { - if target.kind == RadrootsTransportKind::Reticulum - && target.uri.as_str() != RADROOTS_RETICULUM_ENDPOINT_URI + if target.kind() == &RadrootsTransportKind::Reticulum + && target.uri().as_str() != RADROOTS_RETICULUM_ENDPOINT_URI { return Err(RadrootsSdkError::InvalidRequest { message: format!( @@ -342,7 +342,7 @@ impl TargetSet { RadrootsTransportTargetSet::new(targets.clone())?; let canonical_targets = targets .iter() - .map(|target| target.fingerprint.to_string()) + .map(|target| target.fingerprint().to_string()) .collect::<BTreeSet<_>>() .into_iter() .collect(); @@ -714,19 +714,33 @@ fn reticulum_transport_status(profile_id: &str, endpoint_uri: &str) -> RadrootsT impl From<RadrootsTransportDeliveryReceipt> for TransportReceipt { fn from(value: RadrootsTransportDeliveryReceipt) -> Self { Self { - request_id: value.request_id, - target_receipts: value.target_receipts, + request_id: value.request_id().to_owned(), + target_set: value.target_set().clone(), + target_receipts: value.target_receipts().to_vec(), } } } #[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)] pub struct TransportReceipt { - pub request_id: String, - pub target_receipts: Vec<RadrootsTransportTargetReceipt>, + request_id: String, + target_set: RadrootsTransportTargetSet, + target_receipts: Vec<RadrootsTransportTargetReceipt>, } impl TransportReceipt { + pub fn request_id(&self) -> &str { + self.request_id.as_str() + } + + pub fn target_set(&self) -> &RadrootsTransportTargetSet { + &self.target_set + } + + pub fn target_receipts(&self) -> &[RadrootsTransportTargetReceipt] { + self.target_receipts.as_slice() + } + pub fn satisfied_target_count( &self, satisfaction_class: RadrootsTransportSatisfactionClass, @@ -738,11 +752,12 @@ impl TransportReceipt { } pub fn is_satisfied_by(&self, policy: &SatisfactionPolicy) -> Result<bool, RadrootsSdkError> { - Ok(RadrootsTransportDeliveryReceipt { - request_id: self.request_id.clone(), - target_receipts: self.target_receipts.clone(), - } - .is_satisfied_by(&policy.transport_satisfaction_policy()?)?) + let receipt = RadrootsTransportDeliveryReceipt::new( + self.request_id.clone(), + self.target_set.clone(), + self.target_receipts.clone(), + )?; + Ok(receipt.is_satisfied_by(&policy.transport_satisfaction_policy()?)?) } } diff --git a/crates/sdk/src/workflow_runtime.rs b/crates/sdk/src/workflow_runtime.rs @@ -395,7 +395,7 @@ fn reticulum_behavior_for_targets( ) -> RadrootsOutboxReticulumBehavior { if targets .iter() - .any(|target| target.kind == RadrootsTransportKind::Reticulum) + .any(|target| target.kind() == &RadrootsTransportKind::Reticulum) { outbox_reticulum_behavior(transport_profile) } else { @@ -998,11 +998,11 @@ fn runtime_request_digest( .iter() .map(|target| { serde_json::json!({ - "kind": target.kind.canonical_label(), - "uri": target.uri.as_str(), - "scope": target.scope.as_ref().map(|scope| scope.as_str()), - "label": target.label.as_ref().map(|label| label.as_str()), - "fingerprint": target.fingerprint.as_str() + "kind": target.kind().canonical_label(), + "uri": target.uri().as_str(), + "scope": target.scope().map(|scope| scope.as_str()), + "label": target.label().map(|label| label.as_str()), + "fingerprint": target.fingerprint().as_str() }) }) .collect::<Vec<_>>();