commit ef668a1744c2a08fcb48fcb597d81af36febca9f
parent 8418646d0a621227d5528c234ba121bec179f31e
Author: triesap <tyson@radroots.org>
Date: Mon, 3 Aug 2026 20:03:22 +0000
myc: validate packaged nip46 interoperability
- exercise the canonical final client against the Myc server through a mocked relay
- remove every hidden NIP-46 migration-prelude and temporary alias reference
- retain external-client auth, permission, signing, crypto, restart, and revocation coverage
- add request-specific timeout diagnostics for package interoperability failures
Diffstat:
11 files changed, 432 insertions(+), 555 deletions(-)
diff --git a/src/app/backend.rs b/src/app/backend.rs
@@ -13,10 +13,7 @@ use crate::signer::prelude::{
RadrootsNostrSignerSignOutput, RadrootsNostrSignerWorkflowId,
};
use nostr::{PublicKey, RelayUrl, UnsignedEvent};
-use radroots_nostr_connect::prelude::{
- RadrootsNostrConnectMethod, RadrootsNostrConnectPermissions, RadrootsNostrConnectRequest,
- RadrootsNostrConnectRequestMessage,
-};
+use radroots_nostr_connect::{Method, Request, message::RequestMessage, permission::Permissions};
use crate::app::MycSignerContext;
use crate::error::MycError;
@@ -143,7 +140,7 @@ impl RadrootsNostrSignerBackend for MycSignerBackend {
fn evaluate_connect_request(
&self,
client_public_key: PublicKey,
- request: RadrootsNostrConnectRequest,
+ request: Request,
) -> Result<RadrootsNostrSignerConnectEvaluation, RadrootsNostrSignerError> {
self.manager()?
.evaluate_connect_request(client_public_key, request)
@@ -159,7 +156,7 @@ impl RadrootsNostrSignerBackend for MycSignerBackend {
fn set_granted_permissions(
&self,
connection_id: &RadrootsNostrSignerConnectionId,
- granted_permissions: RadrootsNostrConnectPermissions,
+ granted_permissions: Permissions,
) -> Result<RadrootsNostrSignerConnectionRecord, RadrootsNostrSignerError> {
self.manager()?
.set_granted_permissions(connection_id, granted_permissions)
@@ -168,7 +165,7 @@ impl RadrootsNostrSignerBackend for MycSignerBackend {
fn approve_connection(
&self,
connection_id: &RadrootsNostrSignerConnectionId,
- granted_permissions: RadrootsNostrConnectPermissions,
+ granted_permissions: Permissions,
) -> Result<RadrootsNostrSignerConnectionRecord, RadrootsNostrSignerError> {
self.manager()?
.approve_connection(connection_id, granted_permissions)
@@ -210,7 +207,7 @@ impl RadrootsNostrSignerBackend for MycSignerBackend {
fn set_pending_request(
&self,
connection_id: &RadrootsNostrSignerConnectionId,
- request_message: RadrootsNostrConnectRequestMessage,
+ request_message: RequestMessage,
) -> Result<RadrootsNostrSignerConnectionRecord, RadrootsNostrSignerError> {
self.manager()?
.set_pending_request(connection_id, request_message)
@@ -296,7 +293,7 @@ impl RadrootsNostrSignerBackend for MycSignerBackend {
fn evaluate_request(
&self,
connection_id: &RadrootsNostrSignerConnectionId,
- request_message: RadrootsNostrConnectRequestMessage,
+ request_message: RequestMessage,
) -> Result<RadrootsNostrSignerRequestEvaluation, RadrootsNostrSignerError> {
self.manager()?
.evaluate_request(connection_id, request_message)
@@ -314,7 +311,7 @@ impl RadrootsNostrSignerBackend for MycSignerBackend {
&self,
connection_id: &RadrootsNostrSignerConnectionId,
request_id: &str,
- method: RadrootsNostrConnectMethod,
+ method: Method,
decision: RadrootsNostrSignerRequestDecision,
message: Option<String>,
) -> Result<RadrootsNostrSignerRequestAuditRecord, RadrootsNostrSignerError> {
diff --git a/src/cli.rs b/src/cli.rs
@@ -7,7 +7,7 @@ use crate::signer::prelude::{
RadrootsNostrSignerConnectionRecord, RadrootsNostrSignerRequestAuditRecord,
};
use clap::{Args, Parser, Subcommand, ValueEnum};
-use radroots_nostr_connect::prelude::RadrootsNostrConnectPermissions;
+use radroots_nostr_connect::permission::Permissions;
use serde::Serialize;
use zeroize::Zeroizing;
@@ -716,7 +716,7 @@ fn granted_permissions_for_approval(
connections: &[RadrootsNostrSignerConnectionRecord],
connection_id: &RadrootsNostrSignerConnectionId,
grants: &[String],
-) -> Result<RadrootsNostrConnectPermissions, MycError> {
+) -> Result<Permissions, MycError> {
if !grants.is_empty() {
return policy.validate_operator_grants(parse_permission_values(grants)?);
}
@@ -1055,7 +1055,7 @@ mod tests {
use crate::signer::prelude::RadrootsNostrSignerConnectionDraft;
use clap::Parser;
use nostr::Timestamp;
- use radroots_nostr_connect::prelude::RadrootsNostrConnectRequest;
+ use radroots_nostr_connect::Request;
use serde_json::json;
use crate::audit::{MycOperationAuditKind, MycOperationAuditOutcome, MycOperationAuditRecord};
@@ -1144,10 +1144,7 @@ mod tests {
let request_evaluation = manager
.evaluate_request(
&connection.connection_id,
- radroots_nostr_connect::prelude::RadrootsNostrConnectRequestMessage::new(
- "request-1",
- RadrootsNostrConnectRequest::Ping,
- ),
+ radroots_nostr_connect::message::RequestMessage::new("request-1", Request::Ping),
)
.expect("record audit");
runtime.record_operation_audit(&MycOperationAuditRecord::new(
@@ -1192,9 +1189,9 @@ mod tests {
let denied = manager
.evaluate_request(
&connection.connection_id,
- radroots_nostr_connect::prelude::RadrootsNostrConnectRequestMessage::new(
+ radroots_nostr_connect::message::RequestMessage::new(
"request-1",
- RadrootsNostrConnectRequest::SignEvent(
+ Request::SignEvent(
radroots_nostr_connect::message::UnsignedEvent::from_json(
&json!({
"pubkey": runtime.user_identity().public_key().to_hex(),
@@ -1216,10 +1213,7 @@ mod tests {
let challenged_eval = manager
.evaluate_request(
&challenged.connection_id,
- radroots_nostr_connect::prelude::RadrootsNostrConnectRequestMessage::new(
- "request-2",
- RadrootsNostrConnectRequest::Ping,
- ),
+ radroots_nostr_connect::message::RequestMessage::new("request-2", Request::Ping),
)
.expect("challenged request");
diff --git a/src/config.rs b/src/config.rs
@@ -7,7 +7,7 @@ use crate::nostr_contract::RadrootsNostrRelayUrl;
use crate::paths::{RadrootsPathResolver, RadrootsRuntimePathPolicyContract};
use crate::signer::prelude::RadrootsNostrSignerApprovalRequirement;
use nostr::PublicKey;
-use radroots_nostr_connect::prelude::RadrootsNostrConnectPermissions;
+use radroots_nostr_connect::permission::Permissions;
use serde::{Deserialize, Serialize};
use tracing_subscriber::EnvFilter;
@@ -188,7 +188,7 @@ pub struct MycPolicyConfig {
pub connection_approval: MycConnectionApproval,
pub trusted_client_pubkeys: Vec<String>,
pub denied_client_pubkeys: Vec<String>,
- pub permission_ceiling: RadrootsNostrConnectPermissions,
+ pub permission_ceiling: Permissions,
pub allowed_sign_event_kinds: Vec<u16>,
pub auth_url: Option<String>,
pub auth_pending_ttl_secs: u64,
@@ -308,7 +308,7 @@ impl Default for MycPolicyConfig {
connection_approval: MycConnectionApproval::ExplicitUser,
trusted_client_pubkeys: Vec::new(),
denied_client_pubkeys: Vec::new(),
- permission_ceiling: RadrootsNostrConnectPermissions::default(),
+ permission_ceiling: Permissions::default(),
allowed_sign_event_kinds: Vec::new(),
auth_url: None,
auth_pending_ttl_secs: 900,
@@ -1553,12 +1553,10 @@ fn parse_permissions_env(
value: &str,
path: &Path,
line_number: usize,
-) -> Result<RadrootsNostrConnectPermissions, MycError> {
- value
- .parse::<RadrootsNostrConnectPermissions>()
- .map_err(|error| {
- config_parse_error(path, line_number, format!("{key} parse error: {error}"))
- })
+) -> Result<Permissions, MycError> {
+ value.parse::<Permissions>().map_err(|error| {
+ config_parse_error(path, line_number, format!("{key} parse error: {error}"))
+ })
}
fn parse_u16_list_env(
diff --git a/src/control.rs b/src/control.rs
@@ -6,10 +6,7 @@ use crate::signer::prelude::{
RadrootsNostrSignerPublishTransition, RadrootsNostrSignerPublishWorkflowRecord,
RadrootsNostrSignerRequestId, RadrootsNostrSignerWorkflowId,
};
-use radroots_nostr_connect::prelude::{
- RadrootsNostrConnectPermission, RadrootsNostrConnectPermissions, RadrootsNostrConnectRequest,
- RadrootsNostrConnectResponse, RadrootsNostrConnectUri,
-};
+use radroots_nostr_connect::{Permission, Request, Response, permission::Permissions, uri::Uri};
use serde::Serialize;
use crate::app::MycRuntime;
@@ -78,9 +75,9 @@ pub async fn accept_client_uri(
));
}
- let client_uri = match RadrootsNostrConnectUri::parse(uri)? {
- RadrootsNostrConnectUri::Client(client_uri) => client_uri,
- RadrootsNostrConnectUri::Bunker(_) => {
+ let client_uri = match Uri::parse(uri)? {
+ Uri::Client(client_uri) => client_uri,
+ Uri::Bunker(_) => {
return Err(MycError::InvalidOperation(
"connect accept requires a nostrconnect:// client URI".to_owned(),
));
@@ -91,7 +88,7 @@ pub async fn accept_client_uri(
MycError::InvalidOperation("NIP-46 client public key conversion failed".to_owned())
})?;
- let request = RadrootsNostrConnectRequest::Connect {
+ let request = Request::Connect {
remote_signer_public_key: runtime.signer_identity().public_identity().public_key(),
secret: Some(client_uri.secret().to_owned()),
requested_permissions: client_uri.metadata().requested_permissions().clone(),
@@ -160,7 +157,7 @@ pub async fn accept_client_uri(
let event = handler.build_response_event(
client_public_key,
response_request_id.clone(),
- RadrootsNostrConnectResponse::ConnectSecretEcho(client_uri.secret().to_owned()),
+ Response::ConnectSecretEcho(client_uri.secret().to_owned()),
)?;
let client_relays = client_uri
.relays()
@@ -310,9 +307,7 @@ pub async fn accept_client_uri(
})
}
-pub fn parse_permission_values(
- values: &[String],
-) -> Result<RadrootsNostrConnectPermissions, MycError> {
+pub fn parse_permission_values(values: &[String]) -> Result<Permissions, MycError> {
let mut permissions = Vec::new();
for value in values {
for fragment in value.split(',') {
@@ -320,7 +315,7 @@ pub fn parse_permission_values(
if trimmed.is_empty() {
continue;
}
- permissions.push(RadrootsNostrConnectPermission::from_str(trimmed)?);
+ permissions.push(Permission::from_str(trimmed)?);
}
}
permissions.sort();
diff --git a/src/discovery.rs b/src/discovery.rs
@@ -10,7 +10,7 @@ use crate::nostr_contract::{
radroots_nostr_metadata_has_fields, radroots_nostr_tag_first_value,
};
use crate::signer::prelude::RadrootsNostrSignerRequestId;
-use radroots_nostr_connect::prelude::RadrootsNostrConnectUri;
+use radroots_nostr_connect::uri::Uri;
use serde::{Deserialize, Serialize};
use tokio::task::JoinSet;
@@ -2102,7 +2102,7 @@ fn render_nostrconnect_url(
serializer.append_pair("relay", relay.as_str());
}
let bunker_uri = format!("bunker://{signer_public_key}?{}", serializer.finish());
- let bunker_uri = RadrootsNostrConnectUri::parse(&bunker_uri)?.to_string();
+ let bunker_uri = Uri::parse(&bunker_uri)?.to_string();
let encoded_bunker_uri: String =
url::form_urlencoded::byte_serialize(bunker_uri.as_bytes()).collect();
let rendered = template.replace("<nostrconnect>", &encoded_bunker_uri);
diff --git a/src/error.rs b/src/error.rs
@@ -6,7 +6,7 @@ use crate::host_identity::IdentityError;
use crate::nostr_contract::RadrootsNostrError;
use crate::signer::prelude::RadrootsNostrSignerError;
use crate::sql::error::SqlError;
-use radroots_nostr_connect::prelude::RadrootsNostrConnectError;
+use radroots_nostr_connect::Error as NostrConnectError;
use thiserror::Error;
use crate::config::MycTransportDeliveryPolicy;
@@ -280,7 +280,7 @@ pub enum MycError {
#[error(transparent)]
Nostr(#[from] RadrootsNostrError),
#[error(transparent)]
- NostrConnect(#[from] RadrootsNostrConnectError),
+ NostrConnect(#[from] NostrConnectError),
#[error(transparent)]
SignerState(#[from] RadrootsNostrSignerError),
#[error(transparent)]
diff --git a/src/operability/mod.rs b/src/operability/mod.rs
@@ -1788,7 +1788,7 @@ mod tests {
.record_request(
&connection.connection_id,
"req-live-metrics",
- radroots_nostr_connect::prelude::RadrootsNostrConnectMethod::Ping,
+ radroots_nostr_connect::Method::Ping,
RadrootsNostrSignerRequestDecision::Allowed,
None,
)
diff --git a/src/policy.rs b/src/policy.rs
@@ -8,9 +8,8 @@ use crate::signer::prelude::{
RadrootsNostrSignerNip46ConnectDecision, RadrootsNostrSignerNip46Policy,
};
use nostr::PublicKey;
-use radroots_nostr_connect::prelude::{
- RadrootsNostrConnectMethod, RadrootsNostrConnectPermission, RadrootsNostrConnectPermissions,
- RadrootsNostrConnectRequest, RadrootsNostrConnectRequestMessage,
+use radroots_nostr_connect::{
+ Method, Permission, Request, message::RequestMessage, permission::Permissions,
};
use crate::config::{MycConnectionApproval, MycPolicyConfig};
@@ -28,7 +27,7 @@ pub struct MycPolicyContext {
default_connect_decision: MycConnectDecision,
trusted_client_pubkeys: BTreeSet<String>,
denied_client_pubkeys: BTreeSet<String>,
- permission_ceiling: RadrootsNostrConnectPermissions,
+ permission_ceiling: Permissions,
allowed_sign_event_kinds: BTreeSet<u16>,
auth_url: Option<String>,
auth_pending_ttl_secs: u64,
@@ -116,29 +115,24 @@ impl MycPolicyContext {
})
}
- pub fn auto_granted_permissions(
- &self,
- requested_permissions: &RadrootsNostrConnectPermissions,
- ) -> RadrootsNostrConnectPermissions {
+ pub fn auto_granted_permissions(&self, requested_permissions: &Permissions) -> Permissions {
self.filtered_requested_permissions(requested_permissions)
}
pub fn filtered_requested_permissions(
&self,
- requested_permissions: &RadrootsNostrConnectPermissions,
- ) -> RadrootsNostrConnectPermissions {
+ requested_permissions: &Permissions,
+ ) -> Permissions {
let mut filtered = Vec::new();
for permission in requested_permissions.as_slice() {
- if permission.method == RadrootsNostrConnectMethod::SignEvent
+ if permission.method == Method::SignEvent
&& permission.parameter.is_none()
&& !self.allowed_sign_event_kinds.is_empty()
{
for kind in &self.allowed_sign_event_kinds {
- let candidate = RadrootsNostrConnectPermission::with_parameter(
- RadrootsNostrConnectMethod::SignEvent,
- format!("kind:{kind}"),
- );
+ let candidate =
+ Permission::with_parameter(Method::SignEvent, format!("kind:{kind}"));
if self.permission_within_policy(&candidate) {
filtered.push(candidate);
}
@@ -156,8 +150,8 @@ impl MycPolicyContext {
pub fn validate_operator_grants(
&self,
- granted_permissions: RadrootsNostrConnectPermissions,
- ) -> Result<RadrootsNostrConnectPermissions, MycError> {
+ granted_permissions: Permissions,
+ ) -> Result<Permissions, MycError> {
let granted_permissions = normalize_permissions(granted_permissions);
let invalid_permissions = granted_permissions
.as_slice()
@@ -180,7 +174,7 @@ impl MycPolicyContext {
&self,
backend: &B,
connection: &RadrootsNostrSignerConnectionRecord,
- request_message: &RadrootsNostrConnectRequestMessage,
+ request_message: &RequestMessage,
) -> Result<Option<String>, MycError> {
if self.client_is_denied(&connection.client_public_key) {
return Ok(Some("client public key denied by policy".to_owned()));
@@ -253,10 +247,8 @@ impl MycPolicyContext {
.contains(&client_public_key.to_hex())
}
- fn permission_within_policy(&self, permission: &RadrootsNostrConnectPermission) -> bool {
- if permission.method == RadrootsNostrConnectMethod::SignEvent
- && !self.allowed_sign_event_kinds.is_empty()
- {
+ fn permission_within_policy(&self, permission: &Permission) -> bool {
+ if permission.method == Method::SignEvent && !self.allowed_sign_event_kinds.is_empty() {
let Some(kind) = permission
.parameter
.as_deref()
@@ -279,10 +271,10 @@ impl MycPolicyContext {
.any(|ceiling| permission_within_ceiling(permission, ceiling))
}
- fn request_denied_reason(&self, request: &RadrootsNostrConnectRequest) -> Option<String> {
+ fn request_denied_reason(&self, request: &Request) -> Option<String> {
if self.permission_ceiling.is_empty()
&& (self.allowed_sign_event_kinds.is_empty()
- || !matches!(request, RadrootsNostrConnectRequest::SignEvent(_)))
+ || !matches!(request, Request::SignEvent(_)))
{
return None;
}
@@ -301,7 +293,7 @@ impl MycPolicyContext {
fn request_uses_automatic_auth(
&self,
connection: &RadrootsNostrSignerConnectionRecord,
- request: &RadrootsNostrConnectRequest,
+ request: &Request,
) -> bool {
self.automatic_auth_enabled_for_connection(connection) && request_requires_auth(request)
}
@@ -309,7 +301,7 @@ impl MycPolicyContext {
fn should_require_fresh_auth(
&self,
connection: &RadrootsNostrSignerConnectionRecord,
- request: &RadrootsNostrConnectRequest,
+ request: &Request,
) -> bool {
if !self.request_uses_automatic_auth(connection, request) {
return false;
@@ -460,17 +452,11 @@ impl<B: RadrootsNostrSignerBackend> RadrootsNostrSignerNip46Policy<B> for MycPol
self.approval_requirement_for_client(client_public_key)
}
- fn filtered_requested_permissions(
- &self,
- requested_permissions: &RadrootsNostrConnectPermissions,
- ) -> RadrootsNostrConnectPermissions {
+ fn filtered_requested_permissions(&self, requested_permissions: &Permissions) -> Permissions {
self.filtered_requested_permissions(requested_permissions)
}
- fn auto_granted_permissions(
- &self,
- requested_permissions: &RadrootsNostrConnectPermissions,
- ) -> RadrootsNostrConnectPermissions {
+ fn auto_granted_permissions(&self, requested_permissions: &Permissions) -> Permissions {
self.auto_granted_permissions(requested_permissions)
}
@@ -478,7 +464,7 @@ impl<B: RadrootsNostrSignerBackend> RadrootsNostrSignerNip46Policy<B> for MycPol
&self,
backend: &B,
connection: &RadrootsNostrSignerConnectionRecord,
- request_message: &RadrootsNostrConnectRequestMessage,
+ request_message: &RequestMessage,
) -> Result<Option<String>, crate::signer::prelude::RadrootsNostrSignerError> {
self.prepare_request(backend, connection, request_message)
.map_err(myc_policy_signer_error)
@@ -513,9 +499,7 @@ impl MycPolicyRateLimiter {
}
}
-fn normalize_permissions(
- permissions: RadrootsNostrConnectPermissions,
-) -> RadrootsNostrConnectPermissions {
+fn normalize_permissions(permissions: Permissions) -> Permissions {
let mut permissions = permissions.into_vec();
permissions.sort();
permissions.dedup();
@@ -546,46 +530,27 @@ fn normalize_public_key_hex(value: &str) -> Result<String, MycError> {
Ok(public_key.to_hex())
}
-fn required_permission_for_request(
- request: &RadrootsNostrConnectRequest,
-) -> Option<RadrootsNostrConnectPermission> {
+fn required_permission_for_request(request: &Request) -> Option<Permission> {
match request {
- RadrootsNostrConnectRequest::Connect { .. }
- | RadrootsNostrConnectRequest::GetPublicKey
- | RadrootsNostrConnectRequest::GetSessionCapability
- | RadrootsNostrConnectRequest::Ping
- | RadrootsNostrConnectRequest::Logout => None,
- RadrootsNostrConnectRequest::SignEvent(unsigned_event) => {
- Some(RadrootsNostrConnectPermission::with_parameter(
- RadrootsNostrConnectMethod::SignEvent,
- format!("kind:{}", unsigned_event.kind()),
- ))
- }
- RadrootsNostrConnectRequest::Nip04Encrypt { .. } => Some(
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip04Encrypt),
- ),
- RadrootsNostrConnectRequest::Nip04Decrypt { .. } => Some(
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip04Decrypt),
- ),
- RadrootsNostrConnectRequest::Nip44Encrypt { .. } => Some(
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip44Encrypt),
- ),
- RadrootsNostrConnectRequest::Nip44Decrypt { .. } => Some(
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip44Decrypt),
- ),
- RadrootsNostrConnectRequest::SwitchRelays => Some(RadrootsNostrConnectPermission::new(
- RadrootsNostrConnectMethod::SwitchRelays,
+ Request::Connect { .. }
+ | Request::GetPublicKey
+ | Request::GetSessionCapability
+ | Request::Ping
+ | Request::Logout => None,
+ Request::SignEvent(unsigned_event) => Some(Permission::with_parameter(
+ Method::SignEvent,
+ format!("kind:{}", unsigned_event.kind()),
)),
- RadrootsNostrConnectRequest::Custom { method, .. } => {
- Some(RadrootsNostrConnectPermission::new(method.clone()))
- }
+ Request::Nip04Encrypt { .. } => Some(Permission::new(Method::Nip04Encrypt)),
+ Request::Nip04Decrypt { .. } => Some(Permission::new(Method::Nip04Decrypt)),
+ Request::Nip44Encrypt { .. } => Some(Permission::new(Method::Nip44Encrypt)),
+ Request::Nip44Decrypt { .. } => Some(Permission::new(Method::Nip44Decrypt)),
+ Request::SwitchRelays => Some(Permission::new(Method::SwitchRelays)),
+ Request::Custom { method, .. } => Some(Permission::new(method.clone())),
}
}
-fn permission_within_ceiling(
- permission: &RadrootsNostrConnectPermission,
- ceiling: &RadrootsNostrConnectPermission,
-) -> bool {
+fn permission_within_ceiling(permission: &Permission, ceiling: &Permission) -> bool {
if permission.method != ceiling.method {
return false;
}
@@ -595,11 +560,11 @@ fn permission_within_ceiling(
permission.parameter.as_deref(),
ceiling.parameter.as_deref(),
) {
- (RadrootsNostrConnectMethod::SignEvent, _, None) => true,
- (RadrootsNostrConnectMethod::SignEvent, Some(parameter), Some(ceiling_parameter)) => {
+ (Method::SignEvent, _, None) => true,
+ (Method::SignEvent, Some(parameter), Some(ceiling_parameter)) => {
sign_event_parameter_eq(parameter, ceiling_parameter)
}
- (RadrootsNostrConnectMethod::SignEvent, None, Some(_)) => false,
+ (Method::SignEvent, None, Some(_)) => false,
(_, _, None) => true,
(_, Some(parameter), Some(ceiling_parameter)) => parameter == ceiling_parameter,
(_, None, Some(_)) => false,
@@ -618,14 +583,14 @@ fn parse_sign_event_kind_parameter(value: &str) -> Option<u16> {
.ok()
}
-fn request_requires_auth(request: &RadrootsNostrConnectRequest) -> bool {
+fn request_requires_auth(request: &Request) -> bool {
!matches!(
request,
- RadrootsNostrConnectRequest::Connect { .. }
- | RadrootsNostrConnectRequest::GetPublicKey
- | RadrootsNostrConnectRequest::GetSessionCapability
- | RadrootsNostrConnectRequest::Ping
- | RadrootsNostrConnectRequest::Logout
+ Request::Connect { .. }
+ | Request::GetPublicKey
+ | Request::GetSessionCapability
+ | Request::Ping
+ | Request::Logout
)
}
@@ -679,10 +644,8 @@ mod tests {
RadrootsNostrSignerManager,
};
use nostr::PublicKey;
- use radroots_nostr_connect::prelude::{
- RadrootsNostrConnectMethod, RadrootsNostrConnectPermission,
- RadrootsNostrConnectPermissions, RadrootsNostrConnectRequest,
- RadrootsNostrConnectRequestMessage,
+ use radroots_nostr_connect::{
+ Method, Permission, Request, message::RequestMessage, permission::Permissions,
};
use serde_json::json;
use std::thread;
@@ -729,11 +692,7 @@ mod tests {
.to_public(),
)
.with_requested_permissions(
- vec![RadrootsNostrConnectPermission::with_parameter(
- RadrootsNostrConnectMethod::SignEvent,
- "kind:1",
- )]
- .into(),
+ vec![Permission::with_parameter(Method::SignEvent, "kind:1")].into(),
)
.with_approval_requirement(RadrootsNostrSignerApprovalRequirement::NotRequired),
)
@@ -789,11 +748,8 @@ mod tests {
fn auto_granted_permissions_apply_policy_ceiling_and_kind_limits() {
let config = MycPolicyConfig {
permission_ceiling: vec![
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip04Encrypt),
- RadrootsNostrConnectPermission::with_parameter(
- RadrootsNostrConnectMethod::SignEvent,
- "kind:1",
- ),
+ Permission::new(Method::Nip04Encrypt),
+ Permission::with_parameter(Method::SignEvent, "kind:1"),
]
.into(),
allowed_sign_event_kinds: vec![1],
@@ -801,13 +757,10 @@ mod tests {
};
let policy = MycPolicyContext::from_config(&config).expect("policy");
- let requested_permissions: RadrootsNostrConnectPermissions = vec![
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip04Encrypt),
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::SignEvent),
- RadrootsNostrConnectPermission::with_parameter(
- RadrootsNostrConnectMethod::SignEvent,
- "kind:2",
- ),
+ let requested_permissions: Permissions = vec![
+ Permission::new(Method::Nip04Encrypt),
+ Permission::new(Method::SignEvent),
+ Permission::with_parameter(Method::SignEvent, "kind:2"),
]
.into();
let filtered = policy.auto_granted_permissions(&requested_permissions);
@@ -833,10 +786,7 @@ mod tests {
.prepare_request(
&backend,
&connection,
- &RadrootsNostrConnectRequestMessage::new(
- "request-1",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(2)),
- ),
+ &RequestMessage::new("request-1", Request::SignEvent(unsigned_event(2))),
)
.expect("prepare request");
@@ -849,20 +799,13 @@ mod tests {
#[test]
fn validate_operator_grants_rejects_out_of_policy_permissions() {
let config = MycPolicyConfig {
- permission_ceiling: RadrootsNostrConnectPermissions::from(vec![
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip04Encrypt),
- ]),
+ permission_ceiling: Permissions::from(vec![Permission::new(Method::Nip04Encrypt)]),
..MycPolicyConfig::default()
};
let policy = MycPolicyContext::from_config(&config).expect("policy");
let error = policy
- .validate_operator_grants(
- vec![RadrootsNostrConnectPermission::new(
- RadrootsNostrConnectMethod::Nip44Encrypt,
- )]
- .into(),
- )
+ .validate_operator_grants(vec![Permission::new(Method::Nip44Encrypt)].into())
.expect_err("grant outside ceiling");
assert!(
error
@@ -902,10 +845,7 @@ mod tests {
.prepare_request(
&backend,
&connection,
- &RadrootsNostrConnectRequestMessage::new(
- "request-1",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(1)),
- ),
+ &RequestMessage::new("request-1", Request::SignEvent(unsigned_event(1))),
)
.expect("prepare request");
@@ -952,7 +892,7 @@ mod tests {
.record_request(
&connection.connection_id,
"request-0",
- RadrootsNostrConnectMethod::SignEvent,
+ Method::SignEvent,
crate::signer::prelude::RadrootsNostrSignerRequestDecision::Allowed,
None,
)
@@ -967,10 +907,7 @@ mod tests {
.prepare_request(
&backend,
&connection,
- &RadrootsNostrConnectRequestMessage::new(
- "request-1",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(1)),
- ),
+ &RequestMessage::new("request-1", Request::SignEvent(unsigned_event(1))),
)
.expect("prepare request");
diff --git a/src/transport/nip46.rs b/src/transport/nip46.rs
@@ -13,10 +13,7 @@ use crate::signer::prelude::{
RadrootsNostrSignerRequestDecision, RadrootsNostrSignerRequestEvaluation,
RadrootsNostrSignerRequestId, RadrootsNostrSignerSessionLookup, RadrootsNostrSignerWorkflowId,
};
-use radroots_nostr_connect::prelude::{
- RADROOTS_NOSTR_CONNECT_RPC_KIND, RadrootsNostrConnectRequestMessage,
- RadrootsNostrConnectResponse,
-};
+use radroots_nostr_connect::{Response, message::RPC_KIND, message::RequestMessage};
use tokio::sync::broadcast;
use crate::app::MycSignerContext;
@@ -202,8 +199,8 @@ impl MycNip46Handler {
pub fn parse_request_event(
&self,
event: &RadrootsNostrEvent,
- ) -> Result<RadrootsNostrConnectRequestMessage, MycError> {
- if event.kind != RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND) {
+ ) -> Result<RequestMessage, MycError> {
+ if event.kind != RadrootsNostrKind::Custom(RPC_KIND) {
return Err(MycError::InvalidOperation(
"NIP-46 request event has the wrong kind".to_owned(),
));
@@ -232,7 +229,7 @@ impl MycNip46Handler {
&self,
client_public_key: RadrootsNostrPublicKey,
request_id: impl Into<String>,
- response: RadrootsNostrConnectResponse,
+ response: Response,
) -> Result<crate::nostr_contract::RadrootsNostrGenericEventBuilder, MycError> {
self.handler
.build_response_event(client_public_key, request_id, response)
@@ -242,11 +239,11 @@ impl MycNip46Handler {
pub(crate) fn handle_request(
&self,
client_public_key: RadrootsNostrPublicKey,
- request_message: RadrootsNostrConnectRequestMessage,
+ request_message: RequestMessage,
) -> Result<MycNip46HandledOutcome, MycError> {
if matches!(
&request_message.request,
- radroots_nostr_connect::prelude::RadrootsNostrConnectRequest::Logout
+ radroots_nostr_connect::Request::Logout
) {
return self.handle_logout_request(client_public_key, request_message);
}
@@ -258,26 +255,22 @@ impl MycNip46Handler {
fn handle_logout_request(
&self,
client_public_key: RadrootsNostrPublicKey,
- request_message: RadrootsNostrConnectRequestMessage,
+ request_message: RequestMessage,
) -> Result<MycNip46HandledOutcome, MycError> {
let manager = self.signer.load_signer_manager()?;
let connection = match manager.lookup_session(&client_public_key, None)? {
RadrootsNostrSignerSessionLookup::Connection(connection) => *connection,
RadrootsNostrSignerSessionLookup::None => {
- return Ok(MycNip46HandledOutcome::respond(
- RadrootsNostrConnectResponse::Error {
- result: None,
- error: "unauthorized".to_owned(),
- },
- ));
+ return Ok(MycNip46HandledOutcome::respond(Response::Error {
+ result: None,
+ error: "unauthorized".to_owned(),
+ }));
}
RadrootsNostrSignerSessionLookup::Ambiguous(_) => {
- return Ok(MycNip46HandledOutcome::respond(
- RadrootsNostrConnectResponse::Error {
- result: None,
- error: "ambiguous client sessions".to_owned(),
- },
- ));
+ return Ok(MycNip46HandledOutcome::respond(Response::Error {
+ result: None,
+ error: "ambiguous client sessions".to_owned(),
+ }));
}
};
if connection.status != RadrootsNostrSignerConnectionStatus::Active {
@@ -292,7 +285,7 @@ impl MycNip46Handler {
return Ok(MycNip46HandledOutcome::new(
RadrootsNostrSignerHandledRequest::respond_for_connection(
Some(connection.connection_id),
- RadrootsNostrConnectResponse::Error {
+ Response::Error {
result: None,
error: reason,
},
@@ -311,7 +304,7 @@ impl MycNip46Handler {
Ok(MycNip46HandledOutcome::new(
RadrootsNostrSignerHandledRequest::respond_for_connection(
Some(connection.connection_id),
- RadrootsNostrConnectResponse::LogoutAcknowledged,
+ Response::LogoutAcknowledged,
),
Some(audit),
))
@@ -321,8 +314,8 @@ impl MycNip46Handler {
fn handle_request_response(
&self,
client_public_key: RadrootsNostrPublicKey,
- request_message: RadrootsNostrConnectRequestMessage,
- ) -> Result<RadrootsNostrConnectResponse, MycError> {
+ request_message: RequestMessage,
+ ) -> Result<Response, MycError> {
match self.handle_request(client_public_key, request_message)? {
MycNip46HandledOutcome {
handled_request: RadrootsNostrSignerHandledRequest::Respond { response, .. },
@@ -339,7 +332,7 @@ impl MycNip46Handler {
pub(crate) fn handle_authorized_request_evaluation(
&self,
- request_message: RadrootsNostrConnectRequestMessage,
+ request_message: RequestMessage,
evaluation: RadrootsNostrSignerRequestEvaluation,
) -> Result<MycNip46HandledOutcome, MycError> {
self.handler
@@ -401,7 +394,7 @@ impl MycNip46Service {
continue;
};
let event = *event;
- if event.kind != RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND) {
+ if event.kind != RadrootsNostrKind::Custom(RPC_KIND) {
continue;
}
@@ -422,7 +415,7 @@ impl MycNip46Service {
Ok(handled_outcome) => handled_outcome,
Err(error) => {
tracing::warn!(error = %error, "failed to handle NIP-46 request");
- MycNip46HandledOutcome::respond(RadrootsNostrConnectResponse::Error {
+ MycNip46HandledOutcome::respond(Response::Error {
result: None,
error: error.to_string(),
})
@@ -441,10 +434,9 @@ impl MycNip46Service {
);
continue;
};
- let revoke_logout_connection =
- matches!(&response, RadrootsNostrConnectResponse::LogoutAcknowledged)
- .then(|| connection_id.clone())
- .flatten();
+ let revoke_logout_connection = matches!(&response, Response::LogoutAcknowledged)
+ .then(|| connection_id.clone())
+ .flatten();
let response_event =
self.handler
@@ -843,11 +835,9 @@ mod tests {
use nostr::nips::nip44::Version;
use nostr::{EventBuilder, Keys, PublicKey, SecretKey, Timestamp};
use radroots_nostr_connect::message::UnsignedEvent;
- use radroots_nostr_connect::prelude::{
- RADROOTS_NOSTR_CONNECT_RPC_KIND, RadrootsNostrConnectMethod,
- RadrootsNostrConnectPermission, RadrootsNostrConnectRequest,
- RadrootsNostrConnectRequestMessage, RadrootsNostrConnectResponse,
- RadrootsNostrConnectResponseEnvelope,
+ use radroots_nostr_connect::{
+ Method, Permission, Request, Response,
+ message::{RPC_KIND, RequestMessage, ResponseEnvelope},
};
use serde_json::json;
@@ -911,16 +901,13 @@ mod tests {
Keys::new(secret)
}
- fn request_event(
- handler: &MycNip46Handler,
- request: RadrootsNostrConnectRequestMessage,
- ) -> nostr::Event {
+ fn request_event(handler: &MycNip46Handler, request: RequestMessage) -> nostr::Event {
request_event_with_client_keys(handler, request, &client_keys())
}
fn request_event_with_client_keys(
handler: &MycNip46Handler,
- request: RadrootsNostrConnectRequestMessage,
+ request: RequestMessage,
client_keys: &Keys,
) -> nostr::Event {
let payload = serde_json::to_string(&request).expect("serialize request");
@@ -938,22 +925,16 @@ mod tests {
Version::V2,
)
.expect("encrypt");
- EventBuilder::new(
- radroots_nostr_kind(RADROOTS_NOSTR_CONNECT_RPC_KIND),
- ciphertext,
- )
- .tags(vec![RadrootsNostrTag::public_key(
- handler.signer.signer_identity().public_key(),
- )])
- .sign_with_keys(client_keys)
- .expect("sign request")
+ EventBuilder::new(radroots_nostr_kind(RPC_KIND), ciphertext)
+ .tags(vec![RadrootsNostrTag::public_key(
+ handler.signer.signer_identity().public_key(),
+ )])
+ .sign_with_keys(client_keys)
+ .expect("sign request")
}
- fn sign_event_permission(kind: u16) -> RadrootsNostrConnectPermission {
- RadrootsNostrConnectPermission::with_parameter(
- RadrootsNostrConnectMethod::SignEvent,
- format!("kind:{kind}"),
- )
+ fn sign_event_permission(kind: u16) -> Permission {
+ Permission::with_parameter(Method::SignEvent, format!("kind:{kind}"))
}
fn unsigned_event(pubkey: PublicKey, kind: u16, content: &str) -> UnsignedEvent {
@@ -973,14 +954,14 @@ mod tests {
fn connect_with_permissions(
handler: &MycNip46Handler,
runtime: &MycRuntime,
- requested_permissions: Vec<RadrootsNostrConnectPermission>,
+ requested_permissions: Vec<Permission>,
) {
handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1012,15 +993,14 @@ mod tests {
fn parse_and_build_nip46_envelopes_roundtrip() {
let runtime = runtime();
let handler = handler(&runtime);
- let request =
- RadrootsNostrConnectRequestMessage::new("req-1", RadrootsNostrConnectRequest::Ping);
+ let request = RequestMessage::new("req-1", Request::Ping);
let event = request_event(&handler, request.clone());
let parsed = handler.parse_request_event(&event).expect("parse request");
assert_eq!(parsed, request);
let response_builder = handler
- .build_response_event(event.pubkey, "req-1", RadrootsNostrConnectResponse::Pong)
+ .build_response_event(event.pubkey, "req-1", Response::Pong)
.expect("response builder");
let response_event = runtime
.signer_identity()
@@ -1032,14 +1012,10 @@ mod tests {
&response_event.content,
)
.expect("decrypt response");
- let envelope: RadrootsNostrConnectResponseEnvelope =
- serde_json::from_str(&decrypted).expect("parse envelope");
- let parsed = RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::Ping.method(),
- envelope,
- )
- .expect("parse response");
- assert_eq!(parsed, RadrootsNostrConnectResponse::Pong);
+ let envelope: ResponseEnvelope = serde_json::from_str(&decrypted).expect("parse envelope");
+ let parsed =
+ Response::from_envelope(&Request::Ping.method(), envelope).expect("parse response");
+ assert_eq!(parsed, Response::Pong);
}
#[test]
@@ -1059,9 +1035,9 @@ mod tests {
let response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1074,10 +1050,7 @@ mod tests {
)
.expect("connect response");
- assert_eq!(
- response,
- RadrootsNostrConnectResponse::ConnectSecretEcho("s3cr3t".to_owned())
- );
+ assert_eq!(response, Response::ConnectSecretEcho("s3cr3t".to_owned()));
let connections = runtime
.signer_manager()
.expect("manager")
@@ -1104,9 +1077,9 @@ mod tests {
let response = handler
.handle_request_response(
denied_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1121,7 +1094,7 @@ mod tests {
assert_eq!(
response,
- RadrootsNostrConnectResponse::Error {
+ Response::Error {
result: None,
error: "client public key denied by policy".to_owned(),
}
@@ -1144,9 +1117,9 @@ mod tests {
let first = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect-1",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1161,9 +1134,9 @@ mod tests {
let second = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect-2",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1176,10 +1149,7 @@ mod tests {
)
.expect("second connect response");
- assert_eq!(
- first,
- RadrootsNostrConnectResponse::ConnectSecretEcho("s3cr3t".to_owned())
- );
+ assert_eq!(first, Response::ConnectSecretEcho("s3cr3t".to_owned()));
assert_eq!(second, first);
}
@@ -1190,9 +1160,9 @@ mod tests {
let response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1204,10 +1174,7 @@ mod tests {
),
)
.expect("connect response");
- assert_eq!(
- response,
- RadrootsNostrConnectResponse::ConnectSecretEcho("s3cr3t".to_owned())
- );
+ assert_eq!(response, Response::ConnectSecretEcho("s3cr3t".to_owned()));
let connection = runtime
.signer_manager()
@@ -1226,9 +1193,9 @@ mod tests {
let ignored = handler
.handle_request(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect-reused",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1265,9 +1232,9 @@ mod tests {
let first = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect-1",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1279,14 +1246,14 @@ mod tests {
),
)
.expect("first connect response");
- assert_eq!(first, RadrootsNostrConnectResponse::ConnectAcknowledged);
+ assert_eq!(first, Response::ConnectAcknowledged);
let second = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect-2",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1300,7 +1267,7 @@ mod tests {
.expect("second connect response");
assert!(matches!(
second,
- RadrootsNostrConnectResponse::Error { error, .. }
+ Response::Error { error, .. }
if error.contains("connect attempts throttled by policy")
));
@@ -1316,9 +1283,9 @@ mod tests {
let third = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect-3",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1330,7 +1297,7 @@ mod tests {
),
)
.expect("third connect response");
- assert_eq!(third, RadrootsNostrConnectResponse::ConnectAcknowledged);
+ assert_eq!(third, Response::ConnectAcknowledged);
}
#[test]
@@ -1341,9 +1308,9 @@ mod tests {
let response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1356,7 +1323,7 @@ mod tests {
)
.expect("connect response");
- assert_eq!(response, RadrootsNostrConnectResponse::ConnectAcknowledged);
+ assert_eq!(response, Response::ConnectAcknowledged);
let connection = runtime
.signer_manager()
.expect("manager")
@@ -1384,15 +1351,12 @@ mod tests {
let pending_response = pending_handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
- "req-pending-logout",
- RadrootsNostrConnectRequest::Logout,
- ),
+ RequestMessage::new("req-pending-logout", Request::Logout),
)
.expect("pending logout response");
assert_eq!(
pending_response,
- RadrootsNostrConnectResponse::Error {
+ Response::Error {
result: None,
error: "connection is pending".to_owned(),
}
@@ -1404,16 +1368,10 @@ mod tests {
let active_response = active_handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
- "req-active-logout",
- RadrootsNostrConnectRequest::Logout,
- ),
+ RequestMessage::new("req-active-logout", Request::Logout),
)
.expect("active logout response");
- assert_eq!(
- active_response,
- RadrootsNostrConnectResponse::LogoutAcknowledged
- );
+ assert_eq!(active_response, Response::LogoutAcknowledged);
assert_eq!(
connection_for(&active_runtime, client_keys().public_key()).status,
RadrootsNostrSignerConnectionStatus::Active
@@ -1428,7 +1386,7 @@ mod tests {
let runtime = runtime_with_config(MycConnectionApproval::ExplicitUser, |config| {
config.policy.trusted_client_pubkeys = vec![trusted_client_keys.public_key().to_hex()];
config.policy.permission_ceiling = vec![
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip04Encrypt),
+ Permission::new(Method::Nip04Encrypt),
sign_event_permission(1),
]
.into();
@@ -1439,21 +1397,17 @@ mod tests {
let response = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
.public_key(),
secret: None,
requested_permissions: vec![
- RadrootsNostrConnectPermission::new(
- RadrootsNostrConnectMethod::Nip04Encrypt,
- ),
- RadrootsNostrConnectPermission::new(
- RadrootsNostrConnectMethod::SignEvent,
- ),
+ Permission::new(Method::Nip04Encrypt),
+ Permission::new(Method::SignEvent),
sign_event_permission(7),
]
.into(),
@@ -1463,7 +1417,7 @@ mod tests {
)
.expect("connect response");
- assert_eq!(response, RadrootsNostrConnectResponse::ConnectAcknowledged);
+ assert_eq!(response, Response::ConnectAcknowledged);
let connection = connection_for(&runtime, trusted_client_keys.public_key());
assert_eq!(
connection.granted_permissions().to_string(),
@@ -1492,9 +1446,9 @@ mod tests {
let _ = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1510,9 +1464,9 @@ mod tests {
let first = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign-1",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
runtime.user_identity().public_key(),
1,
"first",
@@ -1522,7 +1476,7 @@ mod tests {
.expect("first sign request");
assert_eq!(
first,
- RadrootsNostrConnectResponse::AuthUrl("https://auth.example/challenge".to_owned())
+ Response::AuthUrl("https://auth.example/challenge".to_owned())
);
let connection = connection_for(&runtime, trusted_client_keys.public_key());
@@ -1535,9 +1489,9 @@ mod tests {
let second = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign-2",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
runtime.user_identity().public_key(),
1,
"second",
@@ -1545,19 +1499,16 @@ mod tests {
),
)
.expect("second sign request");
- assert!(matches!(
- second,
- RadrootsNostrConnectResponse::SignedEvent(_)
- ));
+ assert!(matches!(second, Response::SignedEvent(_)));
std::thread::sleep(std::time::Duration::from_secs(2));
let third = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign-3",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
runtime.user_identity().public_key(),
1,
"third",
@@ -1567,7 +1518,7 @@ mod tests {
.expect("third sign request");
assert_eq!(
third,
- RadrootsNostrConnectResponse::AuthUrl("https://auth.example/challenge".to_owned())
+ Response::AuthUrl("https://auth.example/challenge".to_owned())
);
}
@@ -1588,9 +1539,9 @@ mod tests {
let _ = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1606,9 +1557,9 @@ mod tests {
let first = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign-1",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
runtime.user_identity().public_key(),
1,
"first",
@@ -1618,7 +1569,7 @@ mod tests {
.expect("first sign request");
assert_eq!(
first,
- RadrootsNostrConnectResponse::AuthUrl("https://auth.example/challenge".to_owned())
+ Response::AuthUrl("https://auth.example/challenge".to_owned())
);
let connection = connection_for(&runtime, trusted_client_keys.public_key());
@@ -1633,9 +1584,9 @@ mod tests {
let second = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign-2",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
runtime.user_identity().public_key(),
1,
"second",
@@ -1645,7 +1596,7 @@ mod tests {
.expect("second sign request");
assert_eq!(
second,
- RadrootsNostrConnectResponse::AuthUrl("https://auth.example/challenge".to_owned())
+ Response::AuthUrl("https://auth.example/challenge".to_owned())
);
}
@@ -1668,9 +1619,9 @@ mod tests {
let _ = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1686,9 +1637,9 @@ mod tests {
let first = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign-1",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
runtime.user_identity().public_key(),
1,
"first",
@@ -1698,7 +1649,7 @@ mod tests {
.expect("first sign request");
assert_eq!(
first,
- RadrootsNostrConnectResponse::AuthUrl("https://auth.example/challenge".to_owned())
+ Response::AuthUrl("https://auth.example/challenge".to_owned())
);
std::thread::sleep(std::time::Duration::from_secs(2));
@@ -1706,9 +1657,9 @@ mod tests {
let second = handler
.handle_request_response(
trusted_client_keys.public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign-2",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
runtime.user_identity().public_key(),
1,
"second",
@@ -1718,7 +1669,7 @@ mod tests {
.expect("second sign request");
assert!(matches!(
second,
- RadrootsNostrConnectResponse::Error { error, .. }
+ Response::Error { error, .. }
if error.contains("auth challenge issuance throttled by policy")
));
}
@@ -1730,18 +1681,15 @@ mod tests {
handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
.public_key(),
secret: None,
- requested_permissions: vec![RadrootsNostrConnectPermission::new(
- RadrootsNostrConnectMethod::SwitchRelays,
- )]
- .into(),
+ requested_permissions: vec![Permission::new(Method::SwitchRelays)].into(),
client_metadata: None,
},
),
@@ -1751,42 +1699,31 @@ mod tests {
let public_key = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
- "req-pubkey",
- RadrootsNostrConnectRequest::GetPublicKey,
- ),
+ RequestMessage::new("req-pubkey", Request::GetPublicKey),
)
.expect("get public key");
assert_eq!(
public_key,
- RadrootsNostrConnectResponse::UserPublicKey(
- runtime.user_identity().public_identity().public_key()
- )
+ Response::UserPublicKey(runtime.user_identity().public_identity().public_key())
);
let pong = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
- "req-ping",
- RadrootsNostrConnectRequest::Ping,
- ),
+ RequestMessage::new("req-ping", Request::Ping),
)
.expect("ping");
- assert_eq!(pong, RadrootsNostrConnectResponse::Pong);
+ assert_eq!(pong, Response::Pong);
let relays = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
- "req-switch",
- RadrootsNostrConnectRequest::SwitchRelays,
- ),
+ RequestMessage::new("req-switch", Request::SwitchRelays),
)
.expect("switch relays");
assert_eq!(
relays,
- RadrootsNostrConnectResponse::RelayList(
+ Response::RelayList(
runtime
.transport()
.expect("transport")
@@ -1802,16 +1739,13 @@ mod tests {
let capability = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
- "req-capability",
- RadrootsNostrConnectRequest::GetSessionCapability,
- ),
+ RequestMessage::new("req-capability", Request::GetSessionCapability),
)
.expect("get session capability");
assert_eq!(
capability,
- RadrootsNostrConnectResponse::RemoteSessionCapability(
- radroots_nostr_connect::prelude::RadrootsNostrConnectRemoteSessionCapability {
+ Response::RemoteSessionCapability(
+ radroots_nostr_connect::message::RemoteSessionCapability {
user_public_key: runtime.user_identity().public_identity().public_key(),
relays: runtime
.transport()
@@ -1823,10 +1757,7 @@ mod tests {
.expect("relay")
})
.collect(),
- permissions: vec![RadrootsNostrConnectPermission::new(
- RadrootsNostrConnectMethod::SwitchRelays,
- )]
- .into(),
+ permissions: vec![Permission::new(Method::SwitchRelays,)].into(),
},
)
);
@@ -1839,9 +1770,9 @@ mod tests {
handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: runtime
.signer_identity()
.public_identity()
@@ -1877,9 +1808,9 @@ mod tests {
let response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
runtime.user_identity().public_key(),
1,
"hello world",
@@ -1888,7 +1819,7 @@ mod tests {
)
.expect("sign event");
- let RadrootsNostrConnectResponse::SignedEvent(event) = response else {
+ let Response::SignedEvent(event) = response else {
panic!("unexpected sign_event response");
};
let event: nostr::Event = serde_json::from_str(&event.as_json()).expect("signed event");
@@ -1907,9 +1838,9 @@ mod tests {
let response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
runtime.user_identity().public_key(),
1,
"hello world",
@@ -1920,7 +1851,7 @@ mod tests {
assert_eq!(
response,
- RadrootsNostrConnectResponse::Error {
+ Response::Error {
result: None,
error: "unauthorized sign_event".to_owned(),
}
@@ -1936,9 +1867,9 @@ mod tests {
let response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-sign",
- RadrootsNostrConnectRequest::SignEvent(unsigned_event(
+ Request::SignEvent(unsigned_event(
client_keys().public_key(),
1,
"hello world",
@@ -1949,7 +1880,7 @@ mod tests {
assert_eq!(
response,
- RadrootsNostrConnectResponse::Error {
+ Response::Error {
result: None,
error: "sign_event pubkey does not match the managed user identity".to_owned(),
}
@@ -1964,17 +1895,17 @@ mod tests {
&handler,
&runtime,
vec![
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip04Encrypt),
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip04Decrypt),
+ Permission::new(Method::Nip04Encrypt),
+ Permission::new(Method::Nip04Decrypt),
],
);
let encrypt_response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-nip04-encrypt",
- RadrootsNostrConnectRequest::Nip04Encrypt {
+ Request::Nip04Encrypt {
public_key: radroots_nostr::key::public_key_from_nostr(
client_keys().public_key(),
)
@@ -1984,7 +1915,7 @@ mod tests {
),
)
.expect("nip04 encrypt");
- let RadrootsNostrConnectResponse::Nip04Encrypt(ciphertext) = encrypt_response else {
+ let Response::Nip04Encrypt(ciphertext) = encrypt_response else {
panic!("unexpected nip04 encrypt response");
};
assert_eq!(
@@ -2006,9 +1937,9 @@ mod tests {
let decrypt_response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-nip04-decrypt",
- RadrootsNostrConnectRequest::Nip04Decrypt {
+ Request::Nip04Decrypt {
public_key: radroots_nostr::key::public_key_from_nostr(
client_keys().public_key(),
)
@@ -2020,7 +1951,7 @@ mod tests {
.expect("nip04 decrypt");
assert_eq!(
decrypt_response,
- RadrootsNostrConnectResponse::Nip04Decrypt("hello to myc".to_owned())
+ Response::Nip04Decrypt("hello to myc".to_owned())
);
}
@@ -2032,17 +1963,17 @@ mod tests {
&handler,
&runtime,
vec![
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip44Encrypt),
- RadrootsNostrConnectPermission::new(RadrootsNostrConnectMethod::Nip44Decrypt),
+ Permission::new(Method::Nip44Encrypt),
+ Permission::new(Method::Nip44Decrypt),
],
);
let encrypt_response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-nip44-encrypt",
- RadrootsNostrConnectRequest::Nip44Encrypt {
+ Request::Nip44Encrypt {
public_key: radroots_nostr::key::public_key_from_nostr(
client_keys().public_key(),
)
@@ -2052,7 +1983,7 @@ mod tests {
),
)
.expect("nip44 encrypt");
- let RadrootsNostrConnectResponse::Nip44Encrypt(ciphertext) = encrypt_response else {
+ let Response::Nip44Encrypt(ciphertext) = encrypt_response else {
panic!("unexpected nip44 encrypt response");
};
assert_eq!(
@@ -2075,9 +2006,9 @@ mod tests {
let decrypt_response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-nip44-decrypt",
- RadrootsNostrConnectRequest::Nip44Decrypt {
+ Request::Nip44Decrypt {
public_key: radroots_nostr::key::public_key_from_nostr(
client_keys().public_key(),
)
@@ -2089,7 +2020,7 @@ mod tests {
.expect("nip44 decrypt");
assert_eq!(
decrypt_response,
- RadrootsNostrConnectResponse::Nip44Decrypt("hello to myc".to_owned())
+ Response::Nip44Decrypt("hello to myc".to_owned())
);
}
@@ -2100,17 +2031,15 @@ mod tests {
connect_with_permissions(
&handler,
&runtime,
- vec![RadrootsNostrConnectPermission::new(
- RadrootsNostrConnectMethod::Nip04Encrypt,
- )],
+ vec![Permission::new(Method::Nip04Encrypt)],
);
let response = handler
.handle_request_response(
client_keys().public_key(),
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"req-nip04-decrypt",
- RadrootsNostrConnectRequest::Nip04Decrypt {
+ Request::Nip04Decrypt {
public_key: radroots_nostr::key::public_key_from_nostr(
client_keys().public_key(),
)
@@ -2123,7 +2052,7 @@ mod tests {
assert_eq!(
response,
- RadrootsNostrConnectResponse::Error {
+ Response::Error {
result: None,
error: "unauthorized nip04_decrypt".to_owned(),
}
diff --git a/tests/discovery_cli.rs b/tests/discovery_cli.rs
@@ -14,7 +14,7 @@ use myc::nostr_contract::{
};
use nostr::filter::MatchEventOptions;
use nostr::{ClientMessage, Event, Filter, JsonUtil, PublicKey, RelayMessage, SubscriptionId};
-use radroots_nostr_connect::prelude::RadrootsNostrConnectUri;
+use radroots_nostr_connect::uri::Uri;
use serde_json::Value;
use tokio::net::{TcpListener, TcpStream};
use tokio::sync::{Mutex, Notify, mpsc, oneshot};
@@ -1169,7 +1169,7 @@ async fn discovery_diff_surfaces_relay_provenance_through_the_cli() -> TestResul
let mut bunker_query = url::form_urlencoded::Serializer::new(String::new());
bunker_query.append_pair("relay", relay_a.url());
bunker_query.append_pair("relay", relay_b.url());
- let bunker_uri = RadrootsNostrConnectUri::parse(&format!(
+ let bunker_uri = Uri::parse(&format!(
"bunker://{}?{}",
signer_identity.final_public_key(),
bunker_query.finish()
diff --git a/tests/nip46_e2e.rs b/tests/nip46_e2e.rs
@@ -36,10 +36,12 @@ use nostr::{
ClientMessage, Event, EventBuilder, Filter, JsonUtil, Keys, Kind, PublicKey, RelayMessage,
SecretKey, SubscriptionId, Tag, Timestamp, UnsignedEvent,
};
-use radroots_nostr_connect::prelude::{
- RADROOTS_NOSTR_CONNECT_RPC_KIND, RadrootsNostrConnectClientMetadata,
- RadrootsNostrConnectRequest, RadrootsNostrConnectRequestMessage, RadrootsNostrConnectResponse,
- RadrootsNostrConnectResponseEnvelope, RadrootsNostrConnectUri,
+use radroots_nostr_connect::{
+ Client, Request, Response,
+ client::{ClientEvent, EventOutcome, Target},
+ message::{RPC_KIND, RequestId, RequestMessage, ResponseEnvelope},
+ permission::Permissions,
+ uri::{ClientMetadata, RelayUrl as ConnectRelayUrl, Uri},
};
use tempfile::TempDir;
use tokio::net::{TcpListener, TcpStream};
@@ -76,7 +78,7 @@ fn connect_client_uri(
identity: &RadrootsIdentity,
relays: &[&str],
secret: &str,
- metadata: &RadrootsNostrConnectClientMetadata,
+ metadata: &ClientMetadata,
) -> TestResult<String> {
let mut query = url::form_urlencoded::Serializer::new(String::new());
for relay in relays {
@@ -100,11 +102,11 @@ fn connect_client_uri(
identity.final_public_key(),
query.finish()
);
- Ok(RadrootsNostrConnectUri::parse(&uri)?.to_string())
+ Ok(Uri::parse(&uri)?.to_string())
}
const RELAY_EVENT_TIMEOUT: Duration = Duration::from_secs(15);
-const EXTERNAL_RESPONSE_TIMEOUT: Duration = Duration::from_secs(15);
+const EXTERNAL_RESPONSE_TIMEOUT: Duration = Duration::from_secs(30);
const RUNTIME_STATE_TIMEOUT: Duration = Duration::from_secs(15);
const POLL_INTERVAL: Duration = Duration::from_millis(25);
@@ -603,7 +605,7 @@ fn connect_request_message(
request_id: &str,
signer_public_key: PublicKey,
secret: &str,
-) -> RadrootsNostrConnectRequestMessage {
+) -> RequestMessage {
connect_request_message_with_metadata(request_id, signer_public_key, secret, None)
}
@@ -611,11 +613,11 @@ fn connect_request_message_with_metadata(
request_id: &str,
signer_public_key: PublicKey,
secret: &str,
- client_metadata: Option<RadrootsNostrConnectClientMetadata>,
-) -> RadrootsNostrConnectRequestMessage {
- RadrootsNostrConnectRequestMessage::new(
+ client_metadata: Option<ClientMetadata>,
+) -> RequestMessage {
+ RequestMessage::new(
request_id,
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: connect_public_key(signer_public_key),
secret: Some(secret.to_owned()),
requested_permissions: Default::default(),
@@ -624,14 +626,14 @@ fn connect_request_message_with_metadata(
)
}
-fn ping_request_message(request_id: &str) -> RadrootsNostrConnectRequestMessage {
- RadrootsNostrConnectRequestMessage::new(request_id, RadrootsNostrConnectRequest::Ping)
+fn ping_request_message(request_id: &str) -> RequestMessage {
+ RequestMessage::new(request_id, Request::Ping)
}
fn build_request_event(
client_identity: &RadrootsIdentity,
signer_public_key: PublicKey,
- request_message: RadrootsNostrConnectRequestMessage,
+ request_message: RequestMessage,
created_at_unix: u64,
) -> Event {
build_request_event_with_recipient(
@@ -647,7 +649,7 @@ fn build_request_event_with_recipient(
client_identity: &RadrootsIdentity,
signer_public_key: PublicKey,
recipient_public_key: PublicKey,
- request_message: RadrootsNostrConnectRequestMessage,
+ request_message: RequestMessage,
created_at_unix: u64,
) -> Event {
let payload = serde_json::to_string(&request_message).expect("request payload");
@@ -674,7 +676,7 @@ fn build_request_event_payload(
Version::V2,
)
.expect("encrypt request");
- EventBuilder::new(Kind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND), ciphertext)
+ EventBuilder::new(Kind::Custom(RPC_KIND), ciphertext)
.tags([Tag::public_key(recipient_public_key)])
.custom_created_at(Timestamp::from(created_at_unix))
.sign_with_keys(client_identity.keys())
@@ -706,7 +708,7 @@ fn build_external_request_event(
Version::V2,
)
.expect("encrypt external request");
- EventBuilder::new(Kind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND), ciphertext)
+ EventBuilder::new(Kind::Custom(RPC_KIND), ciphertext)
.tags([Tag::public_key(signer_public_key)])
.custom_created_at(Timestamp::from(created_at_unix))
.sign_with_keys(client_identity.keys())
@@ -717,7 +719,7 @@ fn build_signer_noise_event(signer_identity: &MycActiveIdentity, created_at_unix
signer_identity
.sign_protocol_event_builder(
RadrootsNostrGenericEventBuilder::new(
- RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND),
+ RadrootsNostrKind::Custom(RPC_KIND),
"non-nip44-signer-noise",
)
.custom_created_at(Timestamp::from(created_at_unix)),
@@ -730,7 +732,7 @@ fn decrypt_response(
client_identity: &RadrootsIdentity,
signer_public_key: PublicKey,
response_event: &Event,
-) -> RadrootsNostrConnectResponseEnvelope {
+) -> ResponseEnvelope {
let plaintext = nip44::decrypt(
client_identity.keys().secret_key(),
&signer_public_key,
@@ -770,7 +772,13 @@ async fn wait_for_external_response(
sleep(POLL_INTERVAL).await;
}
})
- .await?
+ .await
+ .map_err(|_| {
+ std::io::Error::new(
+ std::io::ErrorKind::TimedOut,
+ format!("timed out waiting for NIP-46 response `{request_id}`"),
+ )
+ })?
}
async fn publish_external_request_and_wait_for_response(
@@ -800,6 +808,72 @@ async fn publish_external_request_and_wait_for_response(
.await
}
+#[tokio::test(flavor = "multi_thread", worker_threads = 4)]
+async fn packaged_final_client_interoperates_with_myc_server() -> TestResult<()> {
+ let relay = TestRelay::spawn().await?;
+ let test_runtime = MycTestRuntime::new(relay.url(), MycConnectionApproval::NotRequired);
+ let runtime = test_runtime.runtime.clone();
+ let signer_public_key = runtime.signer_identity().public_key();
+ let final_signer_public_key = connect_public_key(signer_public_key);
+ let target = Target::try_new(
+ final_signer_public_key,
+ vec![ConnectRelayUrl::parse(relay.url())?],
+ )?;
+ let client = Client::from_secret(
+ "3333333333333333333333333333333333333333333333333333333333333333",
+ target,
+ )?;
+
+ let (shutdown_tx, shutdown_rx) = oneshot::channel::<()>();
+ let service_runtime = runtime.clone();
+ let listener_task = tokio::spawn(async move {
+ service_runtime
+ .run_until(async {
+ let _ = shutdown_rx.await;
+ })
+ .await
+ });
+ relay.wait_for_subscription_count(1).await?;
+
+ let mut connect = client.prepare(
+ RequestId::parse("final-client-connect")?,
+ Request::Connect {
+ remote_signer_public_key: final_signer_public_key,
+ secret: None,
+ requested_permissions: Permissions::default(),
+ client_metadata: None,
+ },
+ )?;
+ let request = Event::from_json(connect.publication()?.as_json())?;
+ publish_event(relay.url(), &request).await?;
+ connect.mark_published()?;
+ let responses = relay
+ .wait_for_published_events_by_author(signer_public_key, 1)
+ .await?;
+ let response = ClientEvent::from_json(&responses[0].as_json())?;
+ assert_eq!(
+ connect.select(&response)?,
+ EventOutcome::Complete(Box::new(Response::ConnectAcknowledged))
+ );
+
+ let mut ping = client.prepare(RequestId::parse("final-client-ping")?, Request::Ping)?;
+ let request = Event::from_json(ping.publication()?.as_json())?;
+ publish_event(relay.url(), &request).await?;
+ ping.mark_published()?;
+ let responses = relay
+ .wait_for_published_events_by_author(signer_public_key, 2)
+ .await?;
+ let response = ClientEvent::from_json(&responses[1].as_json())?;
+ assert_eq!(
+ ping.select(&response)?,
+ EventOutcome::Complete(Box::new(Response::Pong))
+ );
+
+ let _ = shutdown_tx.send(());
+ listener_task.await??;
+ Ok(())
+}
+
fn register_external_client_session(
runtime: &MycRuntime,
client_public_key: PublicKey,
@@ -807,7 +881,7 @@ fn register_external_client_session(
permissions: &str,
) -> TestResult<()> {
let manager = runtime.signer_manager()?;
- let requested_permissions: radroots_nostr_connect::prelude::RadrootsNostrConnectPermissions =
+ let requested_permissions: radroots_nostr_connect::permission::Permissions =
if permissions.trim().is_empty() {
Default::default()
} else {
@@ -1000,8 +1074,8 @@ async fn live_listener_rejects_denied_clients_without_registering_connection() -
.await?;
let response = decrypt_response(&client_identity, signer_public_key, &response_events[0]);
assert_eq!(response.id, "denied-connect");
- let parsed = radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::Connect {
+ let parsed = radroots_nostr_connect::Response::from_envelope(
+ &Request::Connect {
remote_signer_public_key: connect_public_key(signer_public_key),
secret: Some("denied-secret".to_owned()),
requested_permissions: Default::default(),
@@ -1012,7 +1086,7 @@ async fn live_listener_rejects_denied_clients_without_registering_connection() -
)?;
assert_eq!(
parsed,
- radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::Error {
+ radroots_nostr_connect::Response::Error {
result: None,
error: "client public key denied by policy".to_owned(),
}
@@ -1083,13 +1157,10 @@ async fn live_listener_discards_malformed_and_replayed_request_events() -> TestR
);
publish_event(relay.url(), &invalid_request_id).await?;
- let malformed_ciphertext = EventBuilder::new(
- Kind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND),
- "not-nip44-ciphertext",
- )
- .tags([Tag::public_key(signer_public_key)])
- .custom_created_at(Timestamp::from(base_created_at + 3))
- .sign_with_keys(client_identity.keys())?;
+ let malformed_ciphertext = EventBuilder::new(Kind::Custom(RPC_KIND), "not-nip44-ciphertext")
+ .tags([Tag::public_key(signer_public_key)])
+ .custom_created_at(Timestamp::from(base_created_at + 3))
+ .sign_with_keys(client_identity.keys())?;
publish_event(relay.url(), &malformed_ciphertext).await?;
sleep(Duration::from_millis(200)).await;
@@ -1166,7 +1237,7 @@ async fn live_listener_enforces_signing_ceiling_and_switch_relay_permission() ->
});
relay.wait_for_subscription_count(1).await?;
- let connect_request = RadrootsNostrConnectRequest::Connect {
+ let connect_request = Request::Connect {
remote_signer_public_key: connect_public_key(signer_public_key),
secret: None,
requested_permissions: "get_public_key,sign_event:1,sign_event:7,switch_relays".parse()?,
@@ -1177,7 +1248,7 @@ async fn live_listener_enforces_signing_ceiling_and_switch_relay_permission() ->
&build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new("policy-connect", connect_request.clone()),
+ RequestMessage::new("policy-connect", connect_request.clone()),
base_created_at,
),
)
@@ -1185,14 +1256,11 @@ async fn live_listener_enforces_signing_ceiling_and_switch_relay_permission() ->
let responses = relay
.wait_for_published_events_by_author(signer_public_key, 1)
.await?;
- let connect_response = RadrootsNostrConnectResponse::from_envelope(
+ let connect_response = Response::from_envelope(
&connect_request.method(),
decrypt_response(&client_identity, signer_public_key, &responses[0]),
)?;
- assert_eq!(
- connect_response,
- RadrootsNostrConnectResponse::ConnectAcknowledged
- );
+ assert_eq!(connect_response, Response::ConnectAcknowledged);
let connection = runtime
.signer_manager()?
.list_connections()?
@@ -1204,16 +1272,13 @@ async fn live_listener_enforces_signing_ceiling_and_switch_relay_permission() ->
"get_public_key,sign_event:1,switch_relays"
);
- let get_public_key_request = RadrootsNostrConnectRequest::GetPublicKey;
+ let get_public_key_request = Request::GetPublicKey;
publish_event(
relay.url(),
&build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new(
- "policy-get-public-key",
- get_public_key_request.clone(),
- ),
+ RequestMessage::new("policy-get-public-key", get_public_key_request.clone()),
base_created_at + 1,
),
)
@@ -1223,26 +1288,23 @@ async fn live_listener_enforces_signing_ceiling_and_switch_relay_permission() ->
.await?;
assert_eq!(responses[1].pubkey, signer_public_key);
assert_eq!(
- RadrootsNostrConnectResponse::from_envelope(
+ Response::from_envelope(
&get_public_key_request.method(),
decrypt_response(&client_identity, signer_public_key, &responses[1]),
)?,
- RadrootsNostrConnectResponse::UserPublicKey(connect_public_key(user_public_key))
+ Response::UserPublicKey(connect_public_key(user_public_key))
);
let unsigned_event = |kind: u16, content: &str| {
connect_unsigned_event(user_public_key, base_created_at, kind, content)
};
- let allowed_sign_request = RadrootsNostrConnectRequest::SignEvent(unsigned_event(1, "allowed"));
+ let allowed_sign_request = Request::SignEvent(unsigned_event(1, "allowed"));
publish_event(
relay.url(),
&build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new(
- "policy-sign-allowed",
- allowed_sign_request.clone(),
- ),
+ RequestMessage::new("policy-sign-allowed", allowed_sign_request.clone()),
base_created_at + 2,
),
)
@@ -1250,27 +1312,24 @@ async fn live_listener_enforces_signing_ceiling_and_switch_relay_permission() ->
let responses = relay
.wait_for_published_events_by_author(signer_public_key, 3)
.await?;
- let allowed_response = RadrootsNostrConnectResponse::from_envelope(
+ let allowed_response = Response::from_envelope(
&allowed_sign_request.method(),
decrypt_response(&client_identity, signer_public_key, &responses[2]),
)?;
- let RadrootsNostrConnectResponse::SignedEvent(signed_event) = allowed_response else {
+ let Response::SignedEvent(signed_event) = allowed_response else {
panic!("expected signed event response");
};
let signed_event: Event = serde_json::from_str(&signed_event.as_json())?;
assert_eq!(signed_event.pubkey, user_public_key);
signed_event.verify()?;
- let denied_sign_request = RadrootsNostrConnectRequest::SignEvent(unsigned_event(7, "denied"));
+ let denied_sign_request = Request::SignEvent(unsigned_event(7, "denied"));
publish_event(
relay.url(),
&build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new(
- "policy-sign-denied",
- denied_sign_request.clone(),
- ),
+ RequestMessage::new("policy-sign-denied", denied_sign_request.clone()),
base_created_at + 3,
),
)
@@ -1279,21 +1338,21 @@ async fn live_listener_enforces_signing_ceiling_and_switch_relay_permission() ->
.wait_for_published_events_by_author(signer_public_key, 4)
.await?;
assert!(matches!(
- RadrootsNostrConnectResponse::from_envelope(
+ Response::from_envelope(
&denied_sign_request.method(),
decrypt_response(&client_identity, signer_public_key, &responses[3]),
)?,
- RadrootsNostrConnectResponse::Error { error, .. }
+ Response::Error { error, .. }
if error.contains("outside the configured policy ceiling")
));
- let switch_request = RadrootsNostrConnectRequest::SwitchRelays;
+ let switch_request = Request::SwitchRelays;
publish_event(
relay.url(),
&build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new("policy-switch", switch_request.clone()),
+ RequestMessage::new("policy-switch", switch_request.clone()),
base_created_at + 4,
),
)
@@ -1302,11 +1361,11 @@ async fn live_listener_enforces_signing_ceiling_and_switch_relay_permission() ->
.wait_for_published_events_by_author(signer_public_key, 5)
.await?;
assert_eq!(
- RadrootsNostrConnectResponse::from_envelope(
+ Response::from_envelope(
&switch_request.method(),
decrypt_response(&client_identity, signer_public_key, &responses[4]),
)?,
- RadrootsNostrConnectResponse::RelayList(vec![relay.url().parse()?])
+ Response::RelayList(vec![relay.url().parse()?])
);
let _ = shutdown_tx.send(());
@@ -1917,10 +1976,7 @@ async fn live_listener_acknowledges_logout_before_revoking_session() -> TestResu
let logout = build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new(
- "logout-request",
- RadrootsNostrConnectRequest::Logout,
- ),
+ RequestMessage::new("logout-request", Request::Logout),
base_created_at + 1,
);
publish_event(relay.url(), &logout).await?;
@@ -1928,14 +1984,8 @@ async fn live_listener_acknowledges_logout_before_revoking_session() -> TestResu
.wait_for_published_events_by_author(signer_public_key, 2)
.await?;
let logout_response = decrypt_response(&client_identity, signer_public_key, &responses[1]);
- let logout_response = RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::Logout.method(),
- logout_response,
- )?;
- assert_eq!(
- logout_response,
- RadrootsNostrConnectResponse::LogoutAcknowledged
- );
+ let logout_response = Response::from_envelope(&Request::Logout.method(), logout_response)?;
+ assert_eq!(logout_response, Response::LogoutAcknowledged);
wait_for_client_connection_status(
&runtime,
client_identity.public_key(),
@@ -1959,10 +2009,7 @@ async fn live_listener_acknowledges_logout_before_revoking_session() -> TestResu
let repeated_logout = build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new(
- "repeated-logout",
- RadrootsNostrConnectRequest::Logout,
- ),
+ RequestMessage::new("repeated-logout", Request::Logout),
base_created_at + 2,
);
publish_event(relay.url(), &repeated_logout).await?;
@@ -1971,13 +2018,11 @@ async fn live_listener_acknowledges_logout_before_revoking_session() -> TestResu
.await?;
let repeated_logout_response =
decrypt_response(&client_identity, signer_public_key, &responses[2]);
- let repeated_logout_response = RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::Logout.method(),
- repeated_logout_response,
- )?;
+ let repeated_logout_response =
+ Response::from_envelope(&Request::Logout.method(), repeated_logout_response)?;
assert_eq!(
repeated_logout_response,
- RadrootsNostrConnectResponse::Error {
+ Response::Error {
result: None,
error: "unauthorized".to_owned(),
}
@@ -1994,13 +2039,10 @@ async fn live_listener_acknowledges_logout_before_revoking_session() -> TestResu
.wait_for_published_events_by_author(signer_public_key, 4)
.await?;
let ping_response = decrypt_response(&client_identity, signer_public_key, &responses[3]);
- let ping_response = RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::Ping.method(),
- ping_response,
- )?;
+ let ping_response = Response::from_envelope(&Request::Ping.method(), ping_response)?;
assert_eq!(
ping_response,
- RadrootsNostrConnectResponse::Error {
+ Response::Error {
result: None,
error: "unauthorized".to_owned(),
}
@@ -2084,10 +2126,7 @@ async fn failed_logout_publish_is_retried_and_revoked_during_startup_recovery()
let logout = build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new(
- "recovery-logout",
- RadrootsNostrConnectRequest::Logout,
- ),
+ RequestMessage::new("recovery-logout", Request::Logout),
base_created_at + 1,
);
publish_event(relay.url(), &logout).await?;
@@ -2129,14 +2168,9 @@ async fn failed_logout_publish_is_retried_and_revoked_during_startup_recovery()
.wait_for_published_events_by_author(signer_public_key, 2)
.await?;
let recovered_response = decrypt_response(&client_identity, signer_public_key, &responses[1]);
- let recovered_response = RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::Logout.method(),
- recovered_response,
- )?;
- assert_eq!(
- recovered_response,
- RadrootsNostrConnectResponse::LogoutAcknowledged
- );
+ let recovered_response =
+ Response::from_envelope(&Request::Logout.method(), recovered_response)?;
+ assert_eq!(recovered_response, Response::LogoutAcknowledged);
let recovered_connection = restarted_runtime
.signer_manager()?
.find_connections_by_client_public_key(&client_identity.public_key())?
@@ -2181,7 +2215,7 @@ async fn published_logout_acknowledgement_is_finalized_without_republish_on_rest
.signer_identity()
.sign_protocol_event_builder(
RadrootsNostrGenericEventBuilder::new(
- RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND),
+ RadrootsNostrKind::Custom(RPC_KIND),
"published logout acknowledgement fixture",
),
"published logout acknowledgement fixture",
@@ -2286,7 +2320,7 @@ async fn live_listener_works_with_sqlite_signer_state_and_runtime_audit() -> Tes
relay.wait_for_subscription_count(1).await?;
- let client_metadata = RadrootsNostrConnectClientMetadata {
+ let client_metadata = ClientMetadata {
requested_permissions: "sign_event:1".parse()?,
name: Some(" SQLite Client ".to_owned()),
url: Some("https://client.example/".to_owned()),
@@ -2477,8 +2511,7 @@ async fn external_nostr_client_recovers_connect_response_after_restart() -> Test
.with_relays(vec![relay_url.clone()])
.with_approval_requirement(RadrootsNostrSignerApprovalRequirement::NotRequired),
)?;
- let response_envelope =
- RadrootsNostrConnectResponse::ConnectAcknowledged.into_envelope(connect_request_id)?;
+ let response_envelope = Response::ConnectAcknowledged.into_envelope(connect_request_id)?;
let response_payload = serde_json::to_string(&response_envelope)?;
let signer_identity =
identity("1111111111111111111111111111111111111111111111111111111111111111");
@@ -2490,7 +2523,7 @@ async fn external_nostr_client_recovers_connect_response_after_restart() -> Test
)?;
let response_event = runtime.signer_identity().sign_protocol_event_builder(
RadrootsNostrGenericEventBuilder::new(
- RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND),
+ RadrootsNostrKind::Custom(RPC_KIND),
response_ciphertext,
)
.tags(vec![RadrootsNostrTag::public_key(
@@ -2608,7 +2641,7 @@ async fn startup_recovery_republishes_queued_listener_connect_secret_job() -> Te
.signer_identity()
.sign_protocol_event_builder(
RadrootsNostrGenericEventBuilder::new(
- RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND),
+ RadrootsNostrKind::Custom(RPC_KIND),
"startup-recovery",
),
"startup recovery",
@@ -2707,7 +2740,7 @@ async fn startup_recovery_republishes_queued_connect_accept_job() -> TestResult<
.signer_identity()
.sign_protocol_event_builder(
RadrootsNostrGenericEventBuilder::new(
- RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND),
+ RadrootsNostrKind::Custom(RPC_KIND),
"startup-recovery-connect-accept",
),
"startup recovery connect accept",
@@ -2812,7 +2845,7 @@ async fn startup_recovery_republishes_queued_auth_replay_job() -> TestResult<()>
.signer_identity()
.sign_protocol_event_builder(
RadrootsNostrGenericEventBuilder::new(
- RadrootsNostrKind::Custom(RADROOTS_NOSTR_CONNECT_RPC_KIND),
+ RadrootsNostrKind::Custom(RPC_KIND),
"startup-recovery-auth-replay",
),
"startup recovery auth replay",
@@ -2921,9 +2954,9 @@ async fn trusted_client_reauths_after_authorized_ttl() -> TestResult<()> {
let connect_request = build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
"trusted-connect",
- RadrootsNostrConnectRequest::Connect {
+ Request::Connect {
remote_signer_public_key: connect_public_key(signer_public_key),
secret: None,
requested_permissions: "sign_event:1".parse().expect("requested permissions"),
@@ -2938,29 +2971,28 @@ async fn trusted_client_reauths_after_authorized_ttl() -> TestResult<()> {
.await?;
let connect_response =
decrypt_response(&client_identity, signer_public_key, &response_events[0]);
- let connect_parsed =
- radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::Connect {
- remote_signer_public_key: connect_public_key(signer_public_key),
- secret: None,
- requested_permissions: "sign_event:1".parse().expect("requested permissions"),
- client_metadata: None,
- }
- .method(),
- connect_response,
- )?;
+ let connect_parsed = radroots_nostr_connect::Response::from_envelope(
+ &Request::Connect {
+ remote_signer_public_key: connect_public_key(signer_public_key),
+ secret: None,
+ requested_permissions: "sign_event:1".parse().expect("requested permissions"),
+ client_metadata: None,
+ }
+ .method(),
+ connect_response,
+ )?;
assert_eq!(
connect_parsed,
- radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::ConnectAcknowledged
+ radroots_nostr_connect::Response::ConnectAcknowledged
);
let sign_request = |request_id: &str, created_at_unix| {
build_request_event(
&client_identity,
signer_public_key,
- RadrootsNostrConnectRequestMessage::new(
+ RequestMessage::new(
request_id,
- RadrootsNostrConnectRequest::SignEvent(connect_unsigned_event(
+ Request::SignEvent(connect_unsigned_event(
runtime.user_identity().public_key(),
created_at_unix,
1,
@@ -2980,8 +3012,8 @@ async fn trusted_client_reauths_after_authorized_ttl() -> TestResult<()> {
.wait_for_published_events_by_author(signer_public_key, 2)
.await?;
let first_auth = decrypt_response(&client_identity, signer_public_key, &response_events[1]);
- let first_auth = radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::SignEvent(connect_unsigned_event(
+ let first_auth = radroots_nostr_connect::Response::from_envelope(
+ &Request::SignEvent(connect_unsigned_event(
runtime.user_identity().public_key(),
Timestamp::from(1).as_secs(),
1,
@@ -2992,9 +3024,7 @@ async fn trusted_client_reauths_after_authorized_ttl() -> TestResult<()> {
)?;
assert_eq!(
first_auth,
- radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::AuthUrl(
- "https://auth.example/challenge".to_owned()
- )
+ radroots_nostr_connect::Response::AuthUrl("https://auth.example/challenge".to_owned())
);
let connection = runtime
@@ -3014,20 +3044,19 @@ async fn trusted_client_reauths_after_authorized_ttl() -> TestResult<()> {
.await?;
let replay_response =
decrypt_response(&client_identity, signer_public_key, &response_events[2]);
- let replay_parsed =
- radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::SignEvent(connect_unsigned_event(
- runtime.user_identity().public_key(),
- Timestamp::from(1).as_secs(),
- 1,
- "trusted-sign-1",
- ))
- .method(),
- replay_response,
- )?;
+ let replay_parsed = radroots_nostr_connect::Response::from_envelope(
+ &Request::SignEvent(connect_unsigned_event(
+ runtime.user_identity().public_key(),
+ Timestamp::from(1).as_secs(),
+ 1,
+ "trusted-sign-1",
+ ))
+ .method(),
+ replay_response,
+ )?;
assert!(matches!(
replay_parsed,
- radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::SignedEvent(_)
+ radroots_nostr_connect::Response::SignedEvent(_)
));
sleep(Duration::from_secs(2)).await;
@@ -3041,8 +3070,8 @@ async fn trusted_client_reauths_after_authorized_ttl() -> TestResult<()> {
.wait_for_published_events_by_author(signer_public_key, 4)
.await?;
let second_auth = decrypt_response(&client_identity, signer_public_key, &response_events[3]);
- let second_auth = radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::from_envelope(
- &RadrootsNostrConnectRequest::SignEvent(connect_unsigned_event(
+ let second_auth = radroots_nostr_connect::Response::from_envelope(
+ &Request::SignEvent(connect_unsigned_event(
runtime.user_identity().public_key(),
Timestamp::from(1).as_secs(),
1,
@@ -3053,9 +3082,7 @@ async fn trusted_client_reauths_after_authorized_ttl() -> TestResult<()> {
)?;
assert_eq!(
second_auth,
- radroots_nostr_connect::prelude::RadrootsNostrConnectResponse::AuthUrl(
- "https://auth.example/challenge".to_owned()
- )
+ radroots_nostr_connect::Response::AuthUrl("https://auth.example/challenge".to_owned())
);
let _ = shutdown_tx.send(());
@@ -3077,7 +3104,7 @@ async fn connect_accept_retries_without_consuming_secret_until_publish_succeeds(
.queue_publish_outcomes(signer_public_key, &[false, true])
.await;
- let client_metadata = RadrootsNostrConnectClientMetadata {
+ let client_metadata = ClientMetadata {
requested_permissions: Default::default(),
name: Some(" Connect Accept Client ".to_owned()),
url: Some("https://connect.example/".to_owned()),
@@ -3257,7 +3284,7 @@ async fn connect_accept_succeeds_with_any_delivery_policy_when_one_relay_acknowl
&client_identity,
&[relay_a.url(), relay_b.url()],
"delivery-any-secret",
- &RadrootsNostrConnectClientMetadata::default(),
+ &ClientMetadata::default(),
)?;
let accepted = control::accept_client_uri(&runtime, &client_uri).await?;
@@ -3328,7 +3355,7 @@ async fn connect_accept_rejects_when_quorum_delivery_policy_is_not_met() -> Test
&client_identity,
&[relay_a.url(), relay_b.url()],
"delivery-quorum-secret",
- &RadrootsNostrConnectClientMetadata::default(),
+ &ClientMetadata::default(),
)?;
let error = control::accept_client_uri(&runtime, &client_uri)