commit b4765d78c6edfa261cbf0aa19af9156abec98834
parent c685656cd9604417e9ce965770fa66740e595283
Author: triesap <tyson@radroots.org>
Date: Tue, 7 Jul 2026 04:29:34 +0000
transport: remove publish mirror config
- Remove derived publish and relay runtime config mirrors in favor of direct transport profile state.
- Treat local-only and Reticulum preview profiles as non-networked publish states.
- Rename publish_transport output and validation surfaces to transport_profile.
- Delete the orphaned relay command source and validate focused CLI transport tests.
Diffstat:
23 files changed, 246 insertions(+), 478 deletions(-)
diff --git a/src/cli/relay.rs b/src/cli/relay.rs
@@ -1,12 +0,0 @@
-use clap::{Args, Subcommand};
-
-#[derive(Debug, Clone, Args)]
-pub struct RelayArgs {
- #[command(subcommand)]
- pub command: RelayCommand,
-}
-
-#[derive(Debug, Clone, Copy, Subcommand)]
-pub enum RelayCommand {
- List,
-}
diff --git a/src/main.rs b/src/main.rs
@@ -372,7 +372,7 @@ fn validate_request_contract(
config: &RuntimeConfig,
) -> Result<(), OperationAdapterError> {
validate_pre_runtime_request_contract(request)?;
- validate_publish_transport_contract(request, config)?;
+ validate_transport_profile_contract(request, config)?;
validate_signer_mode_contract(request, config)?;
validate_network_contract(request, config)?;
Ok(())
@@ -407,7 +407,7 @@ fn validate_signer_mode_contract(
) -> Result<(), OperationAdapterError> {
let spec = request.spec();
if matches!(config.signer.backend, SignerBackend::Myc)
- && requires_local_signer_mode_for_publish_transport(spec.operation_id, config)
+ && requires_local_signer_mode_for_transport_profile(spec.operation_id, config)
{
return Err(OperationAdapterError::SignerModeDeferred {
operation_id: spec.operation_id.to_owned(),
@@ -468,7 +468,7 @@ fn validate_network_contract(
}
}
-fn requires_local_signer_mode_for_publish_transport(
+fn requires_local_signer_mode_for_transport_profile(
operation_id: &str,
config: &RuntimeConfig,
) -> bool {
@@ -477,19 +477,19 @@ fn requires_local_signer_mode_for_publish_transport(
}
fn requires_pre_runtime_transport_target(operation_id: &str) -> bool {
- !is_publish_transport_routed_operation(operation_id)
+ !is_transport_profile_routed_operation(operation_id)
}
fn allows_offline_local_mutation(operation_id: &str) -> bool {
matches!(operation_id, "listing.publish")
}
-fn validate_publish_transport_contract(
+fn validate_transport_profile_contract(
request: &TargetOperationRequest,
config: &RuntimeConfig,
) -> Result<(), OperationAdapterError> {
let spec = request.spec();
- if !is_publish_transport_routed_operation(spec.operation_id) {
+ if !is_transport_profile_routed_operation(spec.operation_id) {
return Ok(());
}
if request.context().dry_run
@@ -529,7 +529,7 @@ fn validate_publish_transport_contract(
Ok(())
}
-fn is_publish_transport_routed_operation(operation_id: &str) -> bool {
+fn is_transport_profile_routed_operation(operation_id: &str) -> bool {
matches!(
operation_id,
"farm.publish"
diff --git a/src/ops/exec/basket.rs b/src/ops/exec/basket.rs
@@ -1333,9 +1333,8 @@ mod tests {
use crate::runtime::account;
use crate::runtime::config::{
AccountConfig, AccountSecretContractConfig, HyfConfig, IdentityConfig, InteractionConfig,
- LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig,
- PublishConfig, PublishTransport, PublishTransportSource, RelayConfig, RelayConfigSource,
- RelayPublishPolicy, RpcConfig, RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
+ LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig, RpcConfig,
+ RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
};
const LISTING_ADDR: &str = "30402:1111111111111111111111111111111111111111111111111111111111111111:AAAAAAAAAAAAAAAAAAAAAg";
@@ -1907,16 +1906,6 @@ mod tests {
backend: SignerBackend::Local,
},
transport: crate::runtime::config::TransportConfig::local_only(),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: Vec::new(),
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Defaults,
- },
local: LocalConfig {
root: data.join("apps/cli/replica"),
replica_db_path: data.join("apps/cli/replica/replica.sqlite"),
diff --git a/src/ops/exec/core.rs b/src/ops/exec/core.rs
@@ -27,7 +27,7 @@ use crate::runtime::account::{
remove_account, resolve_account_resolution, resolve_account_selector, secret_backend_status,
select_account, snapshot, unresolved_account_reason,
};
-use crate::runtime::config::{PublishTransport, RuntimeConfig, SignerBackend};
+use crate::runtime::config::{RuntimeConfig, SignerBackend, TransportProfileKind};
use crate::runtime::logging::LoggingState;
use crate::runtime::sdk::CliSdkAdapterError;
use crate::runtime::signer::resolve_signer_status;
@@ -794,22 +794,22 @@ fn publish_runtime_view(
signed_write_required: bool,
account: &AccountResolution,
) -> PublishRuntimeView {
- let relay_ready = !config.relay.urls.is_empty();
- let source = config.publish.source.as_str().to_owned();
+ let relay_ready = !config.transport.nostr_relay_urls.is_empty();
+ let source = config.transport.source.as_str().to_owned();
let relay = PublishRelayRuntimeView {
ready: relay_ready,
- count: config.relay.urls.len(),
- source: config.relay.source.as_str().to_owned(),
+ count: config.transport.nostr_relay_urls.len(),
+ source: config.transport.source.as_str().to_owned(),
};
- match config.publish.transport {
- PublishTransport::Nostr => {
+ match config.transport.profile {
+ TransportProfileKind::Nostr => {
let (state, executable, reason) =
nostr_publish_readiness(config, relay_ready, signed_write_required, account);
PublishRuntimeView {
- transport: config.publish.transport.as_str().to_owned(),
+ transport: config.transport.profile.as_str().to_owned(),
source,
- transport_family: config.publish.transport.transport_family().to_owned(),
+ transport_family: config.transport.profile.transport_family().to_owned(),
state: state.to_owned(),
executable,
reason: reason.clone(),
@@ -818,17 +818,17 @@ fn publish_runtime_view(
provider: PublishProviderRuntimeView {
provider_runtime_id: "nostr".to_owned(),
state: state.to_owned(),
- source: config.relay.source.as_str().to_owned(),
+ source: config.transport.source.as_str().to_owned(),
reason,
},
}
}
- PublishTransport::Proxy => {
+ TransportProfileKind::Proxy => {
let (state, executable, reason) = proxy_publish_readiness(config);
PublishRuntimeView {
- transport: config.publish.transport.as_str().to_owned(),
+ transport: config.transport.profile.as_str().to_owned(),
source,
- transport_family: config.publish.transport.transport_family().to_owned(),
+ transport_family: config.transport.profile.transport_family().to_owned(),
state: state.to_owned(),
executable,
reason: reason.clone(),
@@ -842,6 +842,42 @@ fn publish_runtime_view(
},
}
}
+ TransportProfileKind::LocalOnly => PublishRuntimeView {
+ transport: config.transport.profile.as_str().to_owned(),
+ source,
+ transport_family: config.transport.profile.transport_family().to_owned(),
+ state: "local_only".to_owned(),
+ executable: false,
+ reason: Some(
+ "local_only transport profile does not perform network publish".to_owned(),
+ ),
+ signed_write_required,
+ relay,
+ provider: PublishProviderRuntimeView {
+ provider_runtime_id: "local_only".to_owned(),
+ state: "local_only".to_owned(),
+ source: config.transport.source.as_str().to_owned(),
+ reason: Some("local_only transport profile writes only to local state".to_owned()),
+ },
+ },
+ TransportProfileKind::ReticulumPreview => PublishRuntimeView {
+ transport: config.transport.profile.as_str().to_owned(),
+ source,
+ transport_family: config.transport.profile.transport_family().to_owned(),
+ state: "preview_unavailable".to_owned(),
+ executable: false,
+ reason: Some(
+ "reticulum preview transport does not perform MVP network delivery".to_owned(),
+ ),
+ signed_write_required,
+ relay,
+ provider: PublishProviderRuntimeView {
+ provider_runtime_id: "reticulum_preview".to_owned(),
+ state: "preview_unavailable".to_owned(),
+ source: config.transport.source.as_str().to_owned(),
+ reason: Some("reticulum preview is non-networked in the MVP".to_owned()),
+ },
+ },
}
}
@@ -900,7 +936,9 @@ fn nostr_publish_readiness(
}
fn proxy_publish_readiness(config: &RuntimeConfig) -> (&'static str, bool, Option<String>) {
- if config.publish.proxy.token_file.is_none() && config.publish.proxy.token_secret_id.is_none() {
+ if config.transport.proxy.token_file.is_none()
+ && config.transport.proxy.token_secret_id.is_none()
+ {
return (
"unconfigured",
false,
@@ -1072,9 +1110,9 @@ fn publish_recovery_actions(
}
let mut actions = Vec::new();
- match config.publish.transport {
- PublishTransport::Nostr => {
- if config.relay.urls.is_empty() {
+ match config.transport.profile {
+ TransportProfileKind::Nostr => {
+ if config.transport.nostr_relay_urls.is_empty() {
push_unique(
&mut actions,
"radroots transport profile set --kind nostr --nostr-relay wss://relay.example.com",
@@ -1092,7 +1130,7 @@ fn publish_recovery_actions(
}
}
}
- PublishTransport::Proxy => {
+ TransportProfileKind::Proxy => {
if self::proxy_token_configured(config) {
if publish.signed_write_required
&& matches!(config.signer.backend, SignerBackend::Myc)
@@ -1106,12 +1144,24 @@ fn publish_recovery_actions(
);
}
}
+ TransportProfileKind::LocalOnly => {
+ push_unique(
+ &mut actions,
+ "radroots transport profile set --kind nostr --nostr-relay wss://relay.example.com",
+ );
+ }
+ TransportProfileKind::ReticulumPreview => {
+ push_unique(
+ &mut actions,
+ "radroots transport profile set --kind nostr --nostr-relay wss://relay.example.com",
+ );
+ }
}
actions
}
fn proxy_token_configured(config: &RuntimeConfig) -> bool {
- config.publish.proxy.token_file.is_some() || config.publish.proxy.token_secret_id.is_some()
+ config.transport.proxy.token_file.is_some() || config.transport.proxy.token_secret_id.is_some()
}
fn push_unique(actions: &mut Vec<String>, action: impl Into<String>) {
@@ -1200,9 +1250,8 @@ mod tests {
};
use crate::runtime::config::{
AccountConfig, AccountSecretContractConfig, HyfConfig, IdentityConfig, InteractionConfig,
- LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig,
- PublishConfig, PublishTransport, PublishTransportSource, RelayConfig, RelayConfigSource,
- RelayPublishPolicy, RpcConfig, RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
+ LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig, RpcConfig,
+ RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
};
use crate::runtime::logging::LoggingState;
@@ -1448,16 +1497,6 @@ mod tests {
backend: SignerBackend::Local,
},
transport: crate::runtime::config::TransportConfig::local_only(),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: Vec::new(),
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Defaults,
- },
local: LocalConfig {
root: data.join("apps/cli/replica"),
replica_db_path: data.join("apps/cli/replica/replica.sqlite"),
diff --git a/src/ops/exec/farm.rs b/src/ops/exec/farm.rs
@@ -16,7 +16,7 @@ use crate::ops::{
OperationResult, OperationResultData, OperationService,
};
use crate::runtime::RuntimeError;
-use crate::runtime::config::{PublishTransport, RuntimeConfig};
+use crate::runtime::config::{RuntimeConfig, TransportProfileKind};
use crate::view::runtime::{CommandDisposition, FarmPublishView};
pub struct FarmOperationService<'a> {
@@ -232,7 +232,7 @@ impl OperationService<FarmPublishRequest> for FarmOperationService<'_> {
request.operation_id(),
));
}
- if matches!(self.config.publish.transport, PublishTransport::Nostr) {
+ if matches!(self.config.transport.profile, TransportProfileKind::Nostr) {
require_relay_target(&request, self.config)?;
}
@@ -358,7 +358,7 @@ fn require_relay_target<P>(
where
P: OperationRequestPayload,
{
- if !config.relay.urls.is_empty() {
+ if !config.transport.nostr_relay_urls.is_empty() {
return Ok(());
}
@@ -596,9 +596,8 @@ mod tests {
};
use crate::runtime::config::{
AccountConfig, AccountSecretContractConfig, HyfConfig, IdentityConfig, InteractionConfig,
- LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig,
- PublishConfig, PublishTransport, PublishTransportSource, RelayConfig, RelayConfigSource,
- RelayPublishPolicy, RpcConfig, RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
+ LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig, RpcConfig,
+ RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
};
use crate::view::runtime::{
FarmPrivateExactLocationView, FarmPrivateLocationCandidateView, FarmPrivateLocationView,
@@ -877,16 +876,6 @@ mod tests {
backend: SignerBackend::Local,
},
transport: crate::runtime::config::TransportConfig::local_only(),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: Vec::new(),
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Defaults,
- },
local: LocalConfig {
root: data.join("apps/cli/replica"),
replica_db_path: data.join("apps/cli/replica/replica.sqlite"),
diff --git a/src/ops/exec/listing.rs b/src/ops/exec/listing.rs
@@ -473,9 +473,8 @@ mod tests {
};
use crate::runtime::config::{
AccountConfig, AccountSecretContractConfig, HyfConfig, IdentityConfig, InteractionConfig,
- LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig,
- PublishConfig, PublishTransport, PublishTransportSource, RelayConfig, RelayConfigSource,
- RelayPublishPolicy, RpcConfig, RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
+ LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig, RpcConfig,
+ RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
};
#[test]
@@ -607,16 +606,6 @@ mod tests {
backend: SignerBackend::Local,
},
transport: crate::runtime::config::TransportConfig::local_only(),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: Vec::new(),
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Defaults,
- },
local: LocalConfig {
root: data.join("apps/cli/replica"),
replica_db_path: data.join("apps/cli/replica/replica.sqlite"),
diff --git a/src/ops/exec/market.rs b/src/ops/exec/market.rs
@@ -253,9 +253,8 @@ mod tests {
};
use crate::runtime::config::{
AccountConfig, AccountSecretContractConfig, HyfConfig, IdentityConfig, InteractionConfig,
- LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig,
- PublishConfig, PublishTransport, PublishTransportSource, RelayConfig, RelayConfigSource,
- RelayPublishPolicy, RpcConfig, RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
+ LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig, RpcConfig,
+ RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
};
use crate::view::runtime::{
FindPriceView, FindQuantityView, FindResultProvenanceView, FindResultView, FindView,
@@ -311,7 +310,7 @@ mod tests {
let dir = tempdir().expect("tempdir");
let mut config = sample_config(dir.path());
config.output.dry_run = true;
- config.relay.urls = vec!["wss://relay.example.com".to_owned()];
+ config.transport.nostr_relay_urls = vec!["wss://relay.example.com".to_owned()];
crate::runtime::store::init(&config).expect("store init");
let service = OperationAdapter::new(MarketOperationService::new(&config));
@@ -671,16 +670,6 @@ mod tests {
backend: SignerBackend::Local,
},
transport: crate::runtime::config::TransportConfig::local_only(),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: Vec::new(),
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Defaults,
- },
local: LocalConfig {
root: data.join("apps/cli/replica"),
replica_db_path: data.join("apps/cli/replica/replica.sqlite"),
diff --git a/src/ops/exec/runtime.rs b/src/ops/exec/runtime.rs
@@ -341,9 +341,8 @@ mod tests {
};
use crate::runtime::config::{
AccountConfig, AccountSecretContractConfig, HyfConfig, IdentityConfig, InteractionConfig,
- LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig,
- PublishConfig, PublishTransport, PublishTransportSource, RelayConfig, RelayConfigSource,
- RelayPublishPolicy, RpcConfig, RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
+ LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig, RpcConfig,
+ RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
};
#[test]
@@ -475,16 +474,6 @@ mod tests {
transport: crate::runtime::config::TransportConfig::from_nostr_relay_urls(
relays.clone(),
),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: relays,
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Defaults,
- },
local: LocalConfig {
root: data.join("apps/cli/replica"),
replica_db_path: data.join("apps/cli/replica/replica.sqlite"),
diff --git a/src/ops/exec/trade.rs b/src/ops/exec/trade.rs
@@ -1267,9 +1267,8 @@ mod tests {
};
use crate::runtime::config::{
AccountConfig, AccountSecretContractConfig, HyfConfig, IdentityConfig, InteractionConfig,
- LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig,
- PublishConfig, PublishTransport, PublishTransportSource, RelayConfig, RelayConfigSource,
- RelayPublishPolicy, RpcConfig, RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
+ LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig, RpcConfig,
+ RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
};
use crate::view::runtime::OrderDecisionView;
@@ -1683,7 +1682,7 @@ mod tests {
fn order_event_list_requires_seller_account_with_account_action() {
let dir = tempdir().expect("tempdir");
let mut config = sample_config(dir.path());
- config.relay.urls = vec!["ws://127.0.0.1:9".to_owned()];
+ config.transport.nostr_relay_urls = vec!["ws://127.0.0.1:9".to_owned()];
let service = OperationAdapter::new(TradeOperationService::new(&config));
let context = OperationContext::default();
let request = OperationRequest::new(context.clone(), TradeEventListRequest::default())
@@ -1813,16 +1812,6 @@ mod tests {
backend: SignerBackend::Local,
},
transport: crate::runtime::config::TransportConfig::local_only(),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: Vec::new(),
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Defaults,
- },
local: LocalConfig {
root: data.join("apps/cli/replica"),
replica_db_path: data.join("apps/cli/replica/replica.sqlite"),
diff --git a/src/out/terminal/renderers/common.rs b/src/out/terminal/renderers/common.rs
@@ -239,7 +239,7 @@ fn add_terminal_display_fields(
if let Some(state) = terminal_state(display) {
push_field(document, "State", terminal_status_label(state));
}
- if let Some(mode) = terminal_publish_transport(display) {
+ if let Some(mode) = terminal_transport_profile(display) {
push_field(document, "Transport", transport_label(mode));
}
if let Some(state) = terminal_publish_state(display) {
@@ -282,10 +282,10 @@ fn terminal_state(result: &Value) -> Option<&str> {
string_path(result, &["state"])
}
-fn terminal_publish_transport(result: &Value) -> Option<&str> {
+fn terminal_transport_profile(result: &Value) -> Option<&str> {
string_path(result, &["publish", "mode"])
.or_else(|| string_path(result, &["checks", "publish", "mode"]))
- .or_else(|| string_path(result, &["publish_transport"]))
+ .or_else(|| string_path(result, &["transport_profile"]))
}
fn terminal_publish_state(result: &Value) -> Option<&str> {
diff --git a/src/out/terminal/renderers/farm.rs b/src/out/terminal/renderers/farm.rs
@@ -154,7 +154,7 @@ fn farm_readiness_document(envelope: &OutputEnvelope, result: &Value) -> Termina
&["listing_defaults_state"],
);
common::push_path_field(&mut document, "Publish", result, &["publish_state"]);
- if let Some(mode) = common::string(result, &["publish_transport"]) {
+ if let Some(mode) = common::string(result, &["transport_profile"]) {
common::push_field(&mut document, "Transport", transport_label(mode.as_str()));
}
common::push_bool_field(&mut document, "Executable", result, &["publish_executable"]);
diff --git a/src/out/terminal/renderers/listing.rs b/src/out/terminal/renderers/listing.rs
@@ -224,7 +224,7 @@ fn listing_publish_document(envelope: &OutputEnvelope, result: &Value) -> Termin
result,
&[
&["publish", "mode"],
- &["publish_transport"],
+ &["transport_profile"],
&["transport"],
&["source"],
],
diff --git a/src/registry/mod.rs b/src/registry/mod.rs
@@ -235,7 +235,7 @@ pub fn requires_local_signer_mode(operation_id: &str) -> bool {
)
}
-pub fn requires_nostr_publish_transport(operation_id: &str) -> bool {
+pub fn requires_nostr_transport_profile(operation_id: &str) -> bool {
matches!(
operation_id,
"sync.push"
@@ -270,7 +270,7 @@ mod tests {
use super::{
ApprovalPolicy, NetworkRequirement, OPERATION_REGISTRY, OperationRole, RiskLevel,
get_operation, network_requirement, requires_local_signer_mode,
- requires_nostr_publish_transport,
+ requires_nostr_transport_profile,
};
const EXPECTED_OPERATION_IDS: &[&str] = &[
@@ -625,7 +625,7 @@ mod tests {
fn registry_nostr_publish_requirements_are_explicit() {
let publish = OPERATION_REGISTRY
.iter()
- .filter(|operation| requires_nostr_publish_transport(operation.operation_id))
+ .filter(|operation| requires_nostr_transport_profile(operation.operation_id))
.map(|operation| operation.operation_id)
.collect::<BTreeSet<_>>();
let expected = [
diff --git a/src/runtime/config.rs b/src/runtime/config.rs
@@ -198,6 +198,15 @@ impl TransportProfileKind {
Self::Proxy => "proxy",
}
}
+
+ pub fn transport_family(self) -> &'static str {
+ match self {
+ Self::LocalOnly => "local",
+ Self::Nostr => "nostr",
+ Self::ReticulumPreview => "reticulum",
+ Self::Proxy => "proxy",
+ }
+ }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@@ -268,56 +277,6 @@ impl TransportConfig {
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum PublishTransport {
- Nostr,
- Proxy,
-}
-
-impl PublishTransport {
- pub fn as_str(self) -> &'static str {
- match self {
- Self::Nostr => "nostr",
- Self::Proxy => "proxy",
- }
- }
-
- pub fn transport_family(self) -> &'static str {
- match self {
- Self::Nostr => "nostr",
- Self::Proxy => "proxy",
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum PublishTransportSource {
- Flags,
- Environment,
- UserConfig,
- WorkspaceConfig,
- Defaults,
-}
-
-impl PublishTransportSource {
- pub fn as_str(self) -> &'static str {
- match self {
- Self::Flags => "cli flags · transport profile",
- Self::Environment => "environment · transport profile",
- Self::UserConfig => "user config · transport profile",
- Self::WorkspaceConfig => "workspace config · transport profile",
- Self::Defaults => "defaults · transport profile",
- }
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct PublishConfig {
- pub transport: PublishTransport,
- pub source: PublishTransportSource,
- pub proxy: ProxyTransportConfig,
-}
-
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ProxyTransportConfig {
pub url: String,
@@ -335,47 +294,6 @@ impl Default for ProxyTransportConfig {
}
}
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum RelayPublishPolicy {
- Any,
-}
-
-impl RelayPublishPolicy {
- pub fn as_str(self) -> &'static str {
- match self {
- Self::Any => "any",
- }
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub enum RelayConfigSource {
- Flags,
- Environment,
- UserConfig,
- WorkspaceConfig,
- Defaults,
-}
-
-impl RelayConfigSource {
- pub fn as_str(self) -> &'static str {
- match self {
- Self::Flags => "cli flags · local first",
- Self::Environment => "environment · local first",
- Self::UserConfig => "user config · local first",
- Self::WorkspaceConfig => "workspace config · local first",
- Self::Defaults => "defaults · local first",
- }
- }
-}
-
-#[derive(Debug, Clone, PartialEq, Eq)]
-pub struct RelayConfig {
- pub urls: Vec<String>,
- pub publish_policy: RelayPublishPolicy,
- pub source: RelayConfigSource,
-}
-
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct LocalConfig {
pub root: PathBuf,
@@ -530,8 +448,6 @@ pub struct RuntimeConfig {
pub identity: IdentityConfig,
pub signer: SignerConfig,
pub transport: TransportConfig,
- pub publish: PublishConfig,
- pub relay: RelayConfig,
pub local: LocalConfig,
pub myc: MycConfig,
pub hyf: HyfConfig,
@@ -875,9 +791,7 @@ impl RuntimeConfig {
app_config.as_ref(),
workspace_config.as_ref(),
)?,
- transport: transport.clone(),
- publish: publish_config_from_transport(&transport),
- relay: relay_config_from_transport(&transport),
+ transport,
local: LocalConfig {
root: paths.app_data_root.join(DEFAULT_LOCAL_STATE_DIR),
replica_db_path: paths
@@ -1195,41 +1109,6 @@ fn resolve_transport_proxy_file(
})
}
-fn publish_config_from_transport(transport: &TransportConfig) -> PublishConfig {
- PublishConfig {
- transport: match transport.profile {
- TransportProfileKind::Proxy => PublishTransport::Proxy,
- TransportProfileKind::LocalOnly
- | TransportProfileKind::Nostr
- | TransportProfileKind::ReticulumPreview => PublishTransport::Nostr,
- },
- source: match transport.source {
- TransportConfigSource::Environment => PublishTransportSource::Environment,
- TransportConfigSource::UserConfig => PublishTransportSource::UserConfig,
- TransportConfigSource::WorkspaceConfig => PublishTransportSource::WorkspaceConfig,
- TransportConfigSource::Defaults => PublishTransportSource::Defaults,
- },
- proxy: transport.proxy.clone(),
- }
-}
-
-fn relay_config_from_transport(transport: &TransportConfig) -> RelayConfig {
- RelayConfig {
- urls: if matches!(transport.profile, TransportProfileKind::Nostr) {
- transport.nostr_relay_urls.clone()
- } else {
- Vec::new()
- },
- publish_policy: RelayPublishPolicy::Any,
- source: match transport.source {
- TransportConfigSource::Environment => RelayConfigSource::Environment,
- TransportConfigSource::UserConfig => RelayConfigSource::UserConfig,
- TransportConfigSource::WorkspaceConfig => RelayConfigSource::WorkspaceConfig,
- TransportConfigSource::Defaults => RelayConfigSource::Defaults,
- },
- }
-}
-
fn resolve_rhi_config(
env: &dyn Environment,
env_file: &EnvFileValues,
@@ -2046,8 +1925,7 @@ mod tests {
CapabilityBindingSource, CapabilityBindingTargetKind, DEFAULT_HYF_EXECUTABLE,
DEFAULT_LOG_FILTER, DEFAULT_MYC_STATUS_TIMEOUT_MS, DEFAULT_RPC_URL, EnvFileValues,
Environment, HyfConfig, INFERENCE_HYF_STDIO_CAPABILITY, InteractionConfig, OutputConfig,
- OutputFormat, PathsConfig, PublishConfig, PublishTransport, PublishTransportSource,
- RelayConfigSource, RelayPublishPolicy, RuntimeConfig, SignerBackend, TransportConfigSource,
+ OutputFormat, PathsConfig, RuntimeConfig, SignerBackend, TransportConfigSource,
TransportProfileKind, Verbosity, parse_env_file_values,
};
use crate::cli::global::{RuntimeInvocationArgs, RuntimeOutputFormatArg};
@@ -2282,19 +2160,13 @@ mod tests {
TransportConfigSource::Environment
);
assert_eq!(
- resolved.publish,
- PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Environment,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- }
+ resolved.transport.nostr_relay_urls,
+ vec!["wss://relay.one".to_owned(), "wss://relay.two".to_owned()]
);
assert_eq!(
- resolved.relay.urls,
- vec!["wss://relay.one".to_owned(), "wss://relay.two".to_owned()]
+ resolved.transport.source,
+ TransportConfigSource::Environment
);
- assert_eq!(resolved.relay.source, RelayConfigSource::Environment);
- assert_eq!(resolved.relay.publish_policy, RelayPublishPolicy::Any);
assert_eq!(resolved.myc.executable, PathBuf::from("bin/myc-cli"));
assert_eq!(resolved.myc.status_timeout_ms, 2500);
assert_eq!(
@@ -2392,18 +2264,13 @@ mod tests {
TransportConfigSource::Environment
);
assert_eq!(
- resolved.publish,
- PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Environment,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- }
+ resolved.transport.nostr_relay_urls,
+ vec!["wss://relay.one".to_owned(), "wss://relay.two".to_owned()]
);
assert_eq!(
- resolved.relay.urls,
- vec!["wss://relay.one".to_owned(), "wss://relay.two".to_owned()]
+ resolved.transport.source,
+ TransportConfigSource::Environment
);
- assert_eq!(resolved.relay.source, RelayConfigSource::Environment);
assert_eq!(resolved.myc.executable, PathBuf::from("bin/myc"));
assert_eq!(resolved.myc.status_timeout_ms, 3500);
assert_eq!(
@@ -2471,8 +2338,8 @@ mod tests {
RadrootsSecretBackend::HostVault(RadrootsHostVaultPolicy::desktop())
);
assert_eq!(resolved.signer.backend, SignerBackend::Local);
- assert_eq!(resolved.publish.transport, PublishTransport::Nostr);
- assert_eq!(resolved.relay.urls, Vec::<String>::new());
+ assert_eq!(resolved.transport.profile, TransportProfileKind::Nostr);
+ assert_eq!(resolved.transport.nostr_relay_urls, Vec::<String>::new());
assert_eq!(resolved.myc.executable, PathBuf::from("myc"));
assert_eq!(
resolved.myc.status_timeout_ms,
@@ -2796,15 +2663,13 @@ RADROOTS_CLI_HYF_EXECUTABLE=bin/hyfd
TransportConfigSource::Environment
);
assert_eq!(
- resolved.publish,
- PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Environment,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- }
+ resolved.transport.nostr_relay_urls,
+ vec!["wss://relay.env-file".to_owned()]
+ );
+ assert_eq!(
+ resolved.transport.source,
+ TransportConfigSource::Environment
);
- assert_eq!(resolved.relay.urls, vec!["wss://relay.env-file".to_owned()]);
- assert_eq!(resolved.relay.source, RelayConfigSource::Environment);
assert_eq!(resolved.myc.executable, PathBuf::from("bin/myc"));
assert_eq!(resolved.myc.status_timeout_ms, 4500);
assert_eq!(
@@ -2947,14 +2812,13 @@ RADROOTS_CLI_LOGGING_STDOUT=true
assert_eq!(resolved.transport.profile, TransportProfileKind::Nostr);
assert_eq!(resolved.transport.source, TransportConfigSource::UserConfig);
assert_eq!(
- resolved.relay.urls,
+ resolved.transport.nostr_relay_urls,
vec![
"wss://relay.user".to_owned(),
"wss://relay.workspace".to_owned()
]
);
- assert_eq!(resolved.relay.source, RelayConfigSource::UserConfig);
- assert_eq!(resolved.relay.publish_policy, RelayPublishPolicy::Any);
+ assert_eq!(resolved.transport.source, TransportConfigSource::UserConfig);
}
#[test]
@@ -2994,36 +2858,6 @@ RADROOTS_CLI_LOGGING_STDOUT=true
resolved.transport.source,
TransportConfigSource::Environment
);
- assert_eq!(
- resolved.publish,
- PublishConfig {
- transport: PublishTransport::Proxy,
- source: PublishTransportSource::Environment,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- }
- );
-
- let env = repo_local_env(
- workspace_root.clone(),
- repo_local_root.clone(),
- user_home.clone(),
- BTreeMap::from([(
- "RADROOTS_CLI_TRANSPORT_PROFILE".to_owned(),
- "proxy".to_owned(),
- )]),
- );
- let resolved =
- RuntimeConfig::resolve_with_env_file(&runtime_args(), &env, &EnvFileValues::default())
- .expect("resolve environment publish transport");
- assert_eq!(
- resolved.publish,
- PublishConfig {
- transport: PublishTransport::Proxy,
- source: PublishTransportSource::Environment,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- }
- );
-
let env = repo_local_env(
workspace_root.clone(),
repo_local_root.clone(),
@@ -3035,15 +2869,6 @@ RADROOTS_CLI_LOGGING_STDOUT=true
.expect("resolve user transport profile");
assert_eq!(resolved.transport.profile, TransportProfileKind::Nostr);
assert_eq!(resolved.transport.source, TransportConfigSource::UserConfig);
- assert_eq!(
- resolved.publish,
- PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::UserConfig,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- }
- );
-
fs::remove_file(app_config_dir.join("config.toml")).expect("remove user config");
let env = repo_local_env(
workspace_root.clone(),
@@ -3059,15 +2884,6 @@ RADROOTS_CLI_LOGGING_STDOUT=true
resolved.transport.source,
TransportConfigSource::WorkspaceConfig
);
- assert_eq!(
- resolved.publish,
- PublishConfig {
- transport: PublishTransport::Proxy,
- source: PublishTransportSource::WorkspaceConfig,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- }
- );
-
fs::remove_file(repo_local_root.join("config.toml")).expect("remove workspace config");
let env = repo_local_env(workspace_root, repo_local_root, user_home, BTreeMap::new());
let resolved =
@@ -3075,14 +2891,6 @@ RADROOTS_CLI_LOGGING_STDOUT=true
.expect("resolve default transport profile");
assert_eq!(resolved.transport.profile, TransportProfileKind::LocalOnly);
assert_eq!(resolved.transport.source, TransportConfigSource::Defaults);
- assert_eq!(
- resolved.publish,
- PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- }
- );
}
#[test]
@@ -3503,7 +3311,10 @@ target = "workflow-default"
let config = RuntimeConfig::resolve_with_env_file(&args, &env, &EnvFileValues::default())
.expect("valid relay url");
- assert_eq!(config.relay.urls, vec!["ws://[::1]:443/relay"]);
+ assert_eq!(
+ config.transport.nostr_relay_urls,
+ vec!["ws://[::1]:443/relay"]
+ );
}
#[test]
diff --git a/src/runtime/farm.rs b/src/runtime/farm.rs
@@ -27,7 +27,7 @@ use crate::cli::global::{
};
use crate::runtime::RuntimeError;
use crate::runtime::account::{self, AccountRecordView};
-use crate::runtime::config::{PublishTransport, RuntimeConfig, SignerBackend};
+use crate::runtime::config::{RuntimeConfig, SignerBackend, TransportProfileKind};
use crate::runtime::farm_config::{
self, FarmConfigDocument, FarmConfigScope, FarmConfigSelection, FarmListingDefaults,
FarmMissingField, FarmPublicationStatus, ResolvedFarmConfig, SUPPORTED_FARM_CONFIG_VERSION,
@@ -474,7 +474,7 @@ pub fn status(
config_valid: false,
account_state: "not_checked".to_owned(),
listing_defaults_state: "missing".to_owned(),
- publish_transport: config.publish.transport.as_str().to_owned(),
+ transport_profile: config.transport.profile.as_str().to_owned(),
publish_state: "not_checked".to_owned(),
publish_executable: false,
publish_reason: None,
@@ -538,7 +538,7 @@ pub fn status(
config_valid: true,
account_state: account_state.to_owned(),
listing_defaults_state: listing_defaults_state.to_owned(),
- publish_transport: config.publish.transport.as_str().to_owned(),
+ transport_profile: config.transport.profile.as_str().to_owned(),
publish_state: publish.state.to_owned(),
publish_executable: publish.executable,
publish_reason: publish.reason,
@@ -621,7 +621,9 @@ fn relay_farm_publish_readiness(
config: &RuntimeConfig,
account: &AccountRecordView,
) -> FarmPublishReadiness {
- if matches!(config.publish.transport, PublishTransport::Nostr) && config.relay.urls.is_empty() {
+ if matches!(config.transport.profile, TransportProfileKind::Nostr)
+ && config.transport.nostr_relay_urls.is_empty()
+ {
return FarmPublishReadiness {
state: "unconfigured",
executable: false,
@@ -1152,7 +1154,7 @@ fn sdk_enqueued_publish_view(
deduplicated: matches!(enqueue.state, SdkMutationState::AlreadyQueued),
target_relays: push_event
.map(sdk_push_target_relays)
- .unwrap_or_else(|| config.relay.urls.clone()),
+ .unwrap_or_else(|| config.transport.nostr_relay_urls.clone()),
connected_relays: push_event
.map(sdk_push_connected_relays)
.unwrap_or_default(),
diff --git a/src/runtime/find.rs b/src/runtime/find.rs
@@ -51,7 +51,7 @@ pub fn search(config: &RuntimeConfig, args: &FindQueryArgs) -> Result<FindView,
source: FIND_SOURCE.to_owned(),
query,
count: 0,
- relay_count: config.relay.urls.len(),
+ relay_count: config.transport.nostr_relay_urls.len(),
replica_db: config.local.replica_db_path.display().to_string(),
freshness: missing_freshness(),
results: Vec::new(),
@@ -71,7 +71,7 @@ pub fn search(config: &RuntimeConfig, args: &FindQueryArgs) -> Result<FindView,
.map(|rewrite| rewrite.query_terms.clone())
.unwrap_or_else(|| normalize_query_terms(args.query.clone()));
let rows = db.trade_product_search(effective_query_terms.as_slice())?;
- let relay_count = config.relay.urls.len();
+ let relay_count = config.transport.nostr_relay_urls.len();
let result_provenance = FindResultProvenanceView {
origin: "local_replica.trade_product".to_owned(),
freshness: freshness.display.clone(),
@@ -159,7 +159,7 @@ pub fn search(config: &RuntimeConfig, args: &FindQueryArgs) -> Result<FindView,
}
fn refresh_market_if_needed(config: &RuntimeConfig) -> Result<(), RuntimeError> {
- if config.output.dry_run || config.relay.urls.is_empty() {
+ if config.output.dry_run || config.transport.nostr_relay_urls.is_empty() {
return Ok(());
}
let executor = SqliteExecutor::open(&config.local.replica_db_path)?;
diff --git a/src/runtime/listing.rs b/src/runtime/listing.rs
@@ -1616,7 +1616,7 @@ pub fn get(
let provenance = FindResultProvenanceView {
origin: "local_replica.trade_product".to_owned(),
freshness: freshness.display.clone(),
- relay_count: config.relay.urls.len(),
+ relay_count: config.transport.nostr_relay_urls.len(),
};
if !config.local.replica_db_path.exists() {
@@ -1724,7 +1724,7 @@ pub fn get(
fn refresh_market_listing_if_needed(config: &RuntimeConfig) -> Result<(), RuntimeError> {
if !config.local.replica_db_path.exists()
|| config.output.dry_run
- || config.relay.urls.is_empty()
+ || config.transport.nostr_relay_urls.is_empty()
{
return Ok(());
}
@@ -1902,7 +1902,7 @@ fn sdk_enqueued_publish_view(
let reason = sdk_publish_reason(args, push_event);
let target_relays = push_event
.map(sdk_push_target_relays)
- .unwrap_or_else(|| config.relay.urls.clone());
+ .unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
let connected_relays = push_event
.map(sdk_push_connected_relays)
.unwrap_or_default();
diff --git a/src/runtime/order.rs b/src/runtime/order.rs
@@ -1164,7 +1164,7 @@ pub fn event_list(
config: &RuntimeConfig,
order_id: Option<&str>,
) -> Result<OrderEventListView, RuntimeError> {
- if config.relay.urls.is_empty() {
+ if config.transport.nostr_relay_urls.is_empty() {
return Ok(order_event_list_unconfigured(
None,
ORDER_ACTOR_CONTEXT_NETWORK_ONLY,
@@ -1181,16 +1181,20 @@ pub fn event_list(
None,
ORDER_ACTOR_CONTEXT_NETWORK_ONLY,
"trade event list requires a selected seller account".to_owned(),
- config.relay.urls.clone(),
+ config.transport.nostr_relay_urls.clone(),
vec!["radroots account create".to_owned()],
));
}
};
let seller_pubkey = actor_context.seller_pubkey;
let filter = order_request_filter(seller_pubkey.as_str(), order_id)?;
- let receipt =
- fetch_relay_events_via_shared_transport(&config.relay.urls, now_unix_ms(), 1_000, filter)
- .map_err(order_relay_fetch_error)?;
+ let receipt = fetch_relay_events_via_shared_transport(
+ &config.transport.nostr_relay_urls,
+ now_unix_ms(),
+ 1_000,
+ filter,
+ )
+ .map_err(order_relay_fetch_error)?;
if receipt.connected_relays.is_empty() && !receipt.failed_relays.is_empty() {
return Ok(order_event_list_unavailable(
seller_pubkey,
@@ -1588,7 +1592,7 @@ fn sdk_trade_decision_outcome_view(
view.prev_event_id = Some(plan.request_event_id.to_string());
view.event_id = Some(plan.expected_event_id.to_string());
view.event_kind = Some(KIND_ORDER_DECISION);
- view.target_relays = config.relay.urls.clone();
+ view.target_relays = config.transport.nostr_relay_urls.clone();
view.reason = Some(format!(
"dry run requested; seller trade {} publication skipped",
args.decision.command()
@@ -1630,7 +1634,7 @@ fn sdk_trade_revision_outcome_view(
})
.collect();
view.economics = Some(revision.economics);
- view.target_relays = config.relay.urls.clone();
+ view.target_relays = config.transport.nostr_relay_urls.clone();
view.reason =
Some("dry run requested; seller revision proposal publication skipped".to_owned());
view.actions = vec![format!("radroots trade status get {}", status.order_id)];
@@ -1665,7 +1669,7 @@ fn sdk_trade_revision_decision_outcome_view(
view.prev_event_id = Some(plan.previous_event_id.to_string());
view.event_id = Some(plan.expected_event_id.to_string());
view.event_kind = Some(KIND_ORDER_REVISION_DECISION);
- view.target_relays = config.relay.urls.clone();
+ view.target_relays = config.transport.nostr_relay_urls.clone();
view.reason = Some(format!(
"dry run requested; buyer revision {} publication skipped",
args.decision.command()
@@ -1696,7 +1700,7 @@ fn sdk_trade_cancellation_outcome_view(
view.prev_event_id = Some(plan.previous_event_id.to_string());
view.event_id = Some(plan.expected_event_id.to_string());
view.event_kind = Some(KIND_ORDER_CANCELLATION);
- view.target_relays = config.relay.urls.clone();
+ view.target_relays = config.transport.nostr_relay_urls.clone();
view.reason =
Some("dry run requested; buyer trade cancellation publication skipped".to_owned());
view.actions = vec![format!("radroots trade status get {}", status.order_id)];
@@ -1920,7 +1924,7 @@ fn order_decision_base_view(
event_kind: None,
inventory: None,
dry_run,
- target_relays: config.relay.urls.clone(),
+ target_relays: config.transport.nostr_relay_urls.clone(),
connected_relays: Vec::new(),
acknowledged_relays: Vec::new(),
failed_relays: Vec::new(),
@@ -1960,7 +1964,7 @@ fn order_revision_base_view(
economics: None,
inventory: None,
dry_run,
- target_relays: config.relay.urls.clone(),
+ target_relays: config.transport.nostr_relay_urls.clone(),
connected_relays: Vec::new(),
acknowledged_relays: Vec::new(),
failed_relays: Vec::new(),
@@ -2001,7 +2005,7 @@ fn order_revision_decision_base_view(
economics: None,
inventory: None,
dry_run,
- target_relays: config.relay.urls.clone(),
+ target_relays: config.transport.nostr_relay_urls.clone(),
connected_relays: Vec::new(),
acknowledged_relays: Vec::new(),
failed_relays: Vec::new(),
@@ -2038,7 +2042,7 @@ fn order_cancellation_base_view(
event_kind: None,
cancellation_reason: Some(args.reason.clone()),
dry_run,
- target_relays: config.relay.urls.clone(),
+ target_relays: config.transport.nostr_relay_urls.clone(),
connected_relays: Vec::new(),
acknowledged_relays: Vec::new(),
failed_relays: Vec::new(),
@@ -2406,7 +2410,7 @@ fn sdk_enqueued_order_decision_view(
view.event_kind = Some(KIND_ORDER_DECISION);
view.target_relays = push_event
.map(sdk_push_target_relays)
- .unwrap_or_else(|| config.relay.urls.clone());
+ .unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
view.connected_relays = push_event
.map(sdk_push_connected_relays)
.unwrap_or_default();
@@ -2515,7 +2519,7 @@ fn sdk_enqueued_order_revision_view(
view.event_kind = Some(KIND_ORDER_REVISION_PROPOSAL);
view.target_relays = push_event
.map(sdk_push_target_relays)
- .unwrap_or_else(|| config.relay.urls.clone());
+ .unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
view.connected_relays = push_event
.map(sdk_push_connected_relays)
.unwrap_or_default();
@@ -2558,7 +2562,7 @@ fn sdk_enqueued_order_revision_decision_view(
}
view.target_relays = push_event
.map(sdk_push_target_relays)
- .unwrap_or_else(|| config.relay.urls.clone());
+ .unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
view.connected_relays = push_event
.map(sdk_push_connected_relays)
.unwrap_or_default();
@@ -2595,7 +2599,7 @@ fn sdk_enqueued_order_cancellation_view(
view.event_kind = Some(KIND_ORDER_CANCELLATION);
view.target_relays = push_event
.map(sdk_push_target_relays)
- .unwrap_or_else(|| config.relay.urls.clone());
+ .unwrap_or_else(|| config.transport.nostr_relay_urls.clone());
view.connected_relays = push_event
.map(sdk_push_connected_relays)
.unwrap_or_default();
@@ -4477,7 +4481,7 @@ fn order_rebind_existing_request_check(
config: &RuntimeConfig,
loaded: &LoadedOrderDraft,
) -> Result<OrderRebindExistingRequestCheck, RuntimeError> {
- if config.relay.urls.is_empty() {
+ if config.transport.nostr_relay_urls.is_empty() {
return Ok(OrderRebindExistingRequestCheck {
state: "skipped_no_relays".to_owned(),
event_ids: Vec::new(),
@@ -4488,9 +4492,13 @@ fn order_rebind_existing_request_check(
loaded.document.order.seller_pubkey.as_str(),
Some(loaded.document.order.order_id.as_str()),
)?;
- let receipt =
- fetch_relay_events_via_shared_transport(&config.relay.urls, now_unix_ms(), 1_000, filter)
- .map_err(order_relay_fetch_error)?;
+ let receipt = fetch_relay_events_via_shared_transport(
+ &config.transport.nostr_relay_urls,
+ now_unix_ms(),
+ 1_000,
+ filter,
+ )
+ .map_err(order_relay_fetch_error)?;
let mut event_ids = receipt
.events
.iter()
@@ -4901,9 +4909,13 @@ fn sdk_trade_submit_outcome_view(
outcome: TradeMutationOutcome<TradeSubmitPlan, TradeSubmitReceipt>,
) -> OrderSubmitView {
match outcome {
- TradeMutationOutcome::DryRun { plan } => {
- order_submit_dry_run_view(config, loaded, args, plan, config.relay.urls.clone())
- }
+ TradeMutationOutcome::DryRun { plan } => order_submit_dry_run_view(
+ config,
+ loaded,
+ args,
+ plan,
+ config.transport.nostr_relay_urls.clone(),
+ ),
TradeMutationOutcome::Enqueued { receipt } => {
sdk_enqueued_order_submit_view(config, loaded, args, receipt, None)
}
@@ -4943,7 +4955,7 @@ fn sdk_enqueued_order_submit_view(
deduplicated: matches!(enqueue.state, SdkMutationState::AlreadyQueued),
target_relays: push_event
.map(sdk_push_target_relays)
- .unwrap_or_else(|| config.relay.urls.clone()),
+ .unwrap_or_else(|| config.transport.nostr_relay_urls.clone()),
connected_relays: push_event
.map(sdk_push_connected_relays)
.unwrap_or_default(),
diff --git a/src/runtime/provider.rs b/src/runtime/provider.rs
@@ -2,7 +2,7 @@
use crate::runtime::config::{
CapabilityBindingInspection, CapabilityBindingInspectionState, INFERENCE_HYF_STDIO_CAPABILITY,
};
-use crate::runtime::config::{PublishTransport, RuntimeConfig};
+use crate::runtime::config::{RuntimeConfig, TransportProfileKind};
#[cfg(test)]
use crate::runtime::hyf;
use crate::view::runtime::PublishRuntimeView;
@@ -21,7 +21,7 @@ pub enum ProviderProvenance {
DirectConfig,
#[cfg(test)]
Disabled,
- PublishTransport,
+ TransportProfile,
#[cfg(test)]
Unavailable,
}
@@ -37,7 +37,7 @@ impl ProviderProvenance {
Self::DirectConfig => "direct_config",
#[cfg(test)]
Self::Disabled => "disabled",
- Self::PublishTransport => "publish_transport",
+ Self::TransportProfile => "transport_profile",
#[cfg(test)]
Self::Unavailable => "unavailable",
}
@@ -95,23 +95,33 @@ pub fn resolve_write_plane_provider(
config: &RuntimeConfig,
publish: &PublishRuntimeView,
) -> WritePlaneProviderView {
- let (provider_runtime_id, binding_model, detail) = match config.publish.transport {
- PublishTransport::Nostr => (
+ let (provider_runtime_id, binding_model, detail) = match config.transport.profile {
+ TransportProfileKind::Nostr => (
"nostr",
"nostr_transport",
"Nostr transport profile is selected; readiness is reported under publish",
),
- PublishTransport::Proxy => (
+ TransportProfileKind::Proxy => (
"proxy",
"proxy_transport",
"proxy transport profile is selected; readiness is reported under publish",
),
+ TransportProfileKind::LocalOnly => (
+ "local_only",
+ "local_transport",
+ "local_only transport profile does not provide network publish",
+ ),
+ TransportProfileKind::ReticulumPreview => (
+ "reticulum_preview",
+ "reticulum_preview",
+ "reticulum preview transport is non-networked in the MVP",
+ ),
};
WritePlaneProviderView {
provider_runtime_id: provider_runtime_id.to_owned(),
binding_model: binding_model.to_owned(),
state: publish.state.clone(),
- provenance: ProviderProvenance::PublishTransport.as_str().to_owned(),
+ provenance: ProviderProvenance::TransportProfile.as_str().to_owned(),
source: publish.source.clone(),
target_kind: None,
target: None,
@@ -260,9 +270,7 @@ mod tests {
AccountConfig, AccountSecretContractConfig, CapabilityBindingConfig,
CapabilityBindingSource, CapabilityBindingTargetKind, HyfConfig, IdentityConfig,
InteractionConfig, LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat,
- PathsConfig, PublishConfig, PublishTransport, PublishTransportSource, RelayConfig,
- RelayConfigSource, RelayPublishPolicy, RpcConfig, RuntimeConfig, SignerBackend,
- SignerConfig, Verbosity,
+ PathsConfig, RpcConfig, RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
};
use crate::view::runtime::{
PublishProviderRuntimeView, PublishRelayRuntimeView, PublishRuntimeView,
@@ -327,16 +335,6 @@ mod tests {
backend: SignerBackend::Local,
},
transport: crate::runtime::config::TransportConfig::local_only(),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: Vec::new(),
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Defaults,
- },
local: LocalConfig {
root: PathBuf::from("/tmp/local"),
replica_db_path: PathBuf::from("/tmp/local/replica.sqlite"),
@@ -368,22 +366,22 @@ mod tests {
reason: Option<&str>,
) -> PublishRuntimeView {
PublishRuntimeView {
- transport: config.publish.transport.as_str().to_owned(),
- source: config.publish.source.as_str().to_owned(),
- transport_family: config.publish.transport.transport_family().to_owned(),
+ transport: config.transport.profile.as_str().to_owned(),
+ source: config.transport.source.as_str().to_owned(),
+ transport_family: config.transport.profile.transport_family().to_owned(),
state: state.to_owned(),
executable: state == "ready",
reason: reason.map(str::to_owned),
signed_write_required: true,
relay: PublishRelayRuntimeView {
- ready: !config.relay.urls.is_empty(),
- count: config.relay.urls.len(),
- source: config.relay.source.as_str().to_owned(),
+ ready: !config.transport.nostr_relay_urls.is_empty(),
+ count: config.transport.nostr_relay_urls.len(),
+ source: config.transport.source.as_str().to_owned(),
},
provider: PublishProviderRuntimeView {
- provider_runtime_id: config.publish.transport.as_str().to_owned(),
+ provider_runtime_id: config.transport.profile.as_str().to_owned(),
state: state.to_owned(),
- source: config.publish.source.as_str().to_owned(),
+ source: config.transport.source.as_str().to_owned(),
reason: reason.map(str::to_owned),
},
}
@@ -403,7 +401,7 @@ mod tests {
assert_eq!(view.state, "unconfigured");
assert_eq!(
view.provenance,
- ProviderProvenance::PublishTransport.as_str()
+ ProviderProvenance::TransportProfile.as_str()
);
assert!(view.target.is_none());
assert!(view.detail.contains("configured Nostr relay"));
diff --git a/src/runtime/sdk.rs b/src/runtime/sdk.rs
@@ -718,9 +718,8 @@ mod tests {
use super::*;
use crate::runtime::config::{
AccountConfig, AccountSecretContractConfig, HyfConfig, IdentityConfig, InteractionConfig,
- LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig,
- PublishConfig, PublishTransport, PublishTransportSource, RelayConfig, RelayConfigSource,
- RelayPublishPolicy, RhiConfig, RpcConfig, SignerBackend, SignerConfig, Verbosity,
+ LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig, RhiConfig,
+ RpcConfig, SignerBackend, SignerConfig, Verbosity,
};
struct DirectRrRsDependency {
@@ -2235,16 +2234,6 @@ mod tests {
transport: crate::runtime::config::TransportConfig::from_nostr_relay_urls(
relays.clone(),
),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: relays,
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Flags,
- },
local: LocalConfig {
root: data.join("apps/cli/replica"),
replica_db_path: data.join("apps/cli/replica/replica.sqlite"),
diff --git a/src/runtime/sync.rs b/src/runtime/sync.rs
@@ -223,7 +223,7 @@ where
let mut view = empty_action_from_snapshot(snapshot, "pull");
view.state = "ready".to_owned();
view.reason = Some("dry run requested; relay fetch skipped".to_owned());
- view.target_relays = config.relay.urls.clone();
+ view.target_relays = config.transport.nostr_relay_urls.clone();
view.fetched_count = Some(0);
view.ingested_count = Some(0);
view.publishable_count = None;
@@ -237,7 +237,7 @@ where
}
let started_at = unix_now();
- let receipt = match fetcher(&config.relay.urls, scope.filter()) {
+ let receipt = match fetcher(&config.transport.nostr_relay_urls, scope.filter()) {
Ok(receipt) if receipt.connected_relays.is_empty() && !receipt.failed_relays.is_empty() => {
let target_relays = receipt.target_relays;
let failed_relays = relay_failures(receipt.failed_relays);
@@ -249,7 +249,7 @@ where
&executor,
&sync_record_from_failure(
scope,
- &config.relay.urls,
+ &config.transport.nostr_relay_urls,
target_relays.clone(),
failed_relays.clone(),
started_at,
@@ -274,8 +274,8 @@ where
&executor,
&sync_record_from_failure(
scope,
- &config.relay.urls,
- config.relay.urls.clone(),
+ &config.transport.nostr_relay_urls,
+ config.transport.nostr_relay_urls.clone(),
Vec::new(),
started_at,
failure_reason.clone(),
@@ -285,7 +285,7 @@ where
view.state = "unavailable".to_owned();
view.reason = Some(failure_reason);
view.reason_code = Some("relay_fetch_failed".to_owned());
- view.target_relays = config.relay.urls.clone();
+ view.target_relays = config.transport.nostr_relay_urls.clone();
view.freshness = freshness_for_scope_from_executor(config, &executor, scope)?;
return Ok(view);
}
@@ -296,7 +296,13 @@ where
let ingest = ingest_events(&executor, &receipt, scope)?;
record_sync_run(
&executor,
- &sync_record_from_ingest(scope, &config.relay.urls, &receipt, &ingest, started_at)?,
+ &sync_record_from_ingest(
+ scope,
+ &config.transport.nostr_relay_urls,
+ &receipt,
+ &ingest,
+ started_at,
+ )?,
)?;
let failed_relays = relay_failures(receipt.failed_relays);
let failed_count = ingest.failed_count + failed_relays.len();
@@ -311,8 +317,8 @@ where
source: INGEST_SOURCE.to_owned(),
local_root: config.local.root.display().to_string(),
replica_db: "ready".to_owned(),
- relay_count: config.relay.urls.len(),
- publish_policy: config.relay.publish_policy.as_str().to_owned(),
+ relay_count: config.transport.nostr_relay_urls.len(),
+ publish_policy: "any".to_owned(),
freshness,
queue: derived_projection_sync_queue(queue.expected_count, queue.pending_count),
target_relays: receipt.target_relays,
@@ -423,7 +429,7 @@ fn sdk_sync_status_view(config: &RuntimeConfig, receipt: SyncStatusReceipt) -> S
local_root: config.local.root.display().to_string(),
replica_db: "derived_projection_not_checked".to_owned(),
relay_count,
- publish_policy: config.relay.publish_policy.as_str().to_owned(),
+ publish_policy: "any".to_owned(),
freshness: sdk_sync_freshness(&receipt),
queue: sdk_sync_queue(&receipt),
reason: None,
@@ -521,8 +527,8 @@ fn sdk_push_action_view(
source: SDK_PUSH_SOURCE.to_owned(),
local_root: config.local.root.display().to_string(),
replica_db: "derived_projection_not_checked".to_owned(),
- relay_count: config.relay.urls.len(),
- publish_policy: config.relay.publish_policy.as_str().to_owned(),
+ relay_count: config.transport.nostr_relay_urls.len(),
+ publish_policy: "any".to_owned(),
freshness,
queue,
target_relays,
@@ -737,8 +743,8 @@ fn inspect_sync(config: &RuntimeConfig) -> Result<SyncSnapshot, RuntimeError> {
source: SYNC_SOURCE.to_owned(),
local_root: config.local.root.display().to_string(),
replica_db: "missing".to_owned(),
- relay_count: config.relay.urls.len(),
- publish_policy: config.relay.publish_policy.as_str().to_owned(),
+ relay_count: config.transport.nostr_relay_urls.len(),
+ publish_policy: "any".to_owned(),
freshness: missing_freshness(),
queue: derived_projection_sync_queue(0, 0),
reason: Some("local replica database is not initialized".to_owned()),
@@ -751,8 +757,8 @@ fn inspect_sync(config: &RuntimeConfig) -> Result<SyncSnapshot, RuntimeError> {
let queue = radroots_replica_sync_status(&executor)?;
let freshness =
freshness_for_scope_from_executor(config, &executor, RelayIngestScope::SyncPull)?;
- let relay_count = config.relay.urls.len();
- let publish_policy = config.relay.publish_policy.as_str().to_owned();
+ let relay_count = config.transport.nostr_relay_urls.len();
+ let publish_policy = "any".to_owned();
let mut actions = Vec::new();
if relay_count == 0 {
@@ -820,7 +826,7 @@ pub(crate) fn relay_provenance_relays_for_scope(
let executor = SqliteExecutor::open(&config.local.replica_db_path)?;
migrations::run_all_up(&executor)?;
ensure_sync_run_table(&executor)?;
- let current_fingerprint = relay_set_fingerprint(&config.relay.urls);
+ let current_fingerprint = relay_set_fingerprint(&config.transport.nostr_relay_urls);
let Some(run) = latest_sync_run(&executor, scope)? else {
return Ok(Vec::new());
};
@@ -842,7 +848,7 @@ pub(crate) fn freshness_for_scope_from_executor(
let now = unix_now();
let age_seconds = last_event_at.map(|last_event_at| now.saturating_sub(last_event_at));
ensure_sync_run_table(executor)?;
- let current_fingerprint = relay_set_fingerprint(&config.relay.urls);
+ let current_fingerprint = relay_set_fingerprint(&config.transport.nostr_relay_urls);
let latest = latest_sync_run(executor, scope)?;
let current = latest
.as_ref()
@@ -1465,9 +1471,8 @@ mod tests {
use crate::cli::global::{FindQueryArgs, RecordLookupArgs};
use crate::runtime::config::{
AccountConfig, AccountSecretContractConfig, HyfConfig, IdentityConfig, InteractionConfig,
- LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig,
- PublishConfig, PublishTransport, PublishTransportSource, RelayConfig, RelayConfigSource,
- RelayPublishPolicy, RpcConfig, RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
+ LocalConfig, LoggingConfig, MycConfig, OutputConfig, OutputFormat, PathsConfig, RpcConfig,
+ RuntimeConfig, SignerBackend, SignerConfig, Verbosity,
};
const FARM_D_TAG: &str = "AAAAAAAAAAAAAAAAAAAAAA";
@@ -2348,16 +2353,6 @@ mod tests {
transport: crate::runtime::config::TransportConfig::from_nostr_relay_urls(
relays.clone(),
),
- publish: PublishConfig {
- transport: PublishTransport::Nostr,
- source: PublishTransportSource::Defaults,
- proxy: crate::runtime::config::ProxyTransportConfig::default(),
- },
- relay: RelayConfig {
- urls: relays,
- publish_policy: RelayPublishPolicy::Any,
- source: RelayConfigSource::Defaults,
- },
local: LocalConfig {
root: data.join("apps/cli/replica"),
replica_db_path: data.join("apps/cli/replica/replica.sqlite"),
diff --git a/src/view/runtime.rs b/src/view/runtime.rs
@@ -903,7 +903,7 @@ pub struct FarmStatusView {
pub config_valid: bool,
pub account_state: String,
pub listing_defaults_state: String,
- pub publish_transport: String,
+ pub transport_profile: String,
pub publish_state: String,
pub publish_executable: bool,
#[serde(skip_serializing_if = "Option::is_none")]
@@ -2810,7 +2810,7 @@ pub struct SellMutationView {
#[serde(default)]
pub deduplicated: bool,
#[serde(skip_serializing_if = "Option::is_none")]
- pub publish_transport: Option<String>,
+ pub transport_profile: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub job_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
diff --git a/tests/target_cli.rs b/tests/target_cli.rs
@@ -1728,7 +1728,7 @@ fn farm_readiness_check_reports_mode_specific_publish_gates() {
} else {
&relay_value["result"]
};
- assert_eq!(relay_detail["publish_transport"], "nostr");
+ assert_eq!(relay_detail["transport_profile"], "nostr");
assert_eq!(relay_detail["publish_state"], "unconfigured");
assert_eq!(relay_detail["publish_executable"], false);
assert_eq!(
@@ -1762,7 +1762,7 @@ signer_session_ref = "session_test"
assert!(output.status.success());
assert_eq!(proxy_value["operation_id"], "farm.readiness.check");
- assert_contains(&proxy_value["result"]["publish_transport"], "proxy");
+ assert_contains(&proxy_value["result"]["transport_profile"], "proxy");
assert_eq!(proxy_value["result"]["publish_state"], "ready");
assert_eq!(proxy_value["result"]["publish_executable"], true);
assert_eq!(proxy_value["result"]["reason"], Value::Null);
@@ -3750,7 +3750,7 @@ fn order_status_get_invalid_order_id_uses_sdk_error_contract() {
}
#[test]
-fn removed_publish_transport_flag_is_rejected() {
+fn removed_transport_profile_flag_is_rejected() {
let sandbox = RadrootsCliSandbox::new();
let output = sandbox
.command()