commit c5d49822d16a2653f2ec4f4e6253319f27a2dabb
parent 1b89ecc4e6ea92ff9f8f416b08db22502a7a5dde
Author: triesap <tyson@radroots.org>
Date: Mon, 13 Jul 2026 06:17:06 +0000
sdk: expose transport operation capabilities
- add operation capabilities to sync transport summaries
- re-export the SDK capability summary type
- assert Nostr delivery-only and Reticulum inert status JSON
- guard the status summary source boundary
Diffstat:
4 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/crates/sdk/src/lib.rs b/crates/sdk/src/lib.rs
@@ -221,7 +221,8 @@ pub use crate::sync_runtime::{
SYNC_PROJECTION_REFRESH_DEFAULT_LIMIT, SYNC_PROJECTION_REFRESH_MAX_LIMIT, SdkRelayAuthPolicy,
SyncEventStoreStatus, SyncOutboxStatus, SyncProjectionRefreshReceipt,
SyncProjectionRefreshRequest, SyncStatusReceipt, SyncStatusRequest, SyncStatusSource,
- SyncTransportProfileSummary, SyncTransportStatusSummary, SyncTransportTargetSummary,
+ SyncTransportOperationCapabilitiesSummary, SyncTransportProfileSummary,
+ SyncTransportStatusSummary, SyncTransportTargetSummary,
};
#[cfg(feature = "runtime")]
pub use crate::trade_storage::{
diff --git a/crates/sdk/src/sync_runtime.rs b/crates/sdk/src/sync_runtime.rs
@@ -233,10 +233,18 @@ pub struct SyncTransportStatusSummary {
pub configured: bool,
pub implementation: String,
pub usable_for_delivery: bool,
+ pub capabilities: SyncTransportOperationCapabilitiesSummary,
pub message: String,
}
#[cfg(feature = "runtime")]
+#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize)]
+pub struct SyncTransportOperationCapabilitiesSummary {
+ pub deliver: bool,
+ pub fetch: bool,
+}
+
+#[cfg(feature = "runtime")]
impl SyncTransportStatusSummary {
fn from_transport_status(status: RadrootsTransportStatus) -> Self {
Self {
@@ -246,6 +254,10 @@ impl SyncTransportStatusSummary {
configured: status.configured,
implementation: transport_implementation_label(status.implementation).to_owned(),
usable_for_delivery: status.usable_for_delivery,
+ capabilities: SyncTransportOperationCapabilitiesSummary {
+ deliver: status.capabilities.deliver,
+ fetch: status.capabilities.fetch,
+ },
message: status.message,
}
}
diff --git a/crates/sdk/tests/source_boundary.rs b/crates/sdk/tests/source_boundary.rs
@@ -2005,6 +2005,12 @@ fn sdk_sync_status_sources_reject_retired_relay_shaped_generic_fields() {
"pub configured: bool,",
"pub implementation: String,",
"pub usable_for_delivery: bool,",
+ "pub capabilities: SyncTransportOperationCapabilitiesSummary,",
+ "pub struct SyncTransportOperationCapabilitiesSummary",
+ "pub deliver: bool,",
+ "pub fetch: bool,",
+ "status.capabilities.deliver",
+ "status.capabilities.fetch",
"pub message: String,",
] {
assert!(
@@ -2018,6 +2024,7 @@ fn sdk_sync_status_sources_reject_retired_relay_shaped_generic_fields() {
"pub configured: bool,",
"pub implementation: String,",
"pub usable_for_delivery: bool,",
+ "pub capabilities: SyncTransportOperationCapabilitiesSummary,",
"pub message: String,",
] {
assert!(
@@ -2026,6 +2033,18 @@ fn sdk_sync_status_sources_reject_retired_relay_shaped_generic_fields() {
);
}
+ let operation_capabilities_summary = source_between(
+ sync_runtime.as_str(),
+ "pub struct SyncTransportOperationCapabilitiesSummary",
+ "\n}\n\n#[cfg(feature = \"runtime\")]\nimpl SyncTransportStatusSummary",
+ );
+ for required in ["pub deliver: bool,", "pub fetch: bool,"] {
+ assert!(
+ operation_capabilities_summary.contains(required),
+ "SDK sync transport capabilities must retain operation field witness `{required}`"
+ );
+ }
+
for forbidden in [
concat!("configured_nostr", "_relay", "_count"),
concat!("configured_nostr", "_relays"),
diff --git a/crates/sdk/tests/sync_runtime.rs b/crates/sdk/tests/sync_runtime.rs
@@ -776,6 +776,10 @@ async fn sync_status_empty_store_reports_canonical_sources_and_transport_targets
"configured": true,
"implementation": "real",
"usable_for_delivery": true,
+ "capabilities": {
+ "deliver": true,
+ "fetch": false
+ },
"message": "ready"
}]
}
@@ -834,12 +838,21 @@ async fn sync_status_reports_hybrid_transport_targets_and_statuses() {
status.implementation.as_str(),
status.configured,
status.usable_for_delivery,
+ status.capabilities.deliver,
+ status.capabilities.fetch,
)
})
.collect::<Vec<_>>(),
vec![
- ("nostr", "real", true, true),
- ("reticulum", "preview_unavailable", true, false)
+ ("nostr", "real", true, true, true, false),
+ (
+ "reticulum",
+ "preview_unavailable",
+ true,
+ false,
+ false,
+ false
+ )
]
);
}