From 15bf0d0b6befae6c81631c0e5d0dc2947dd3318a Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Wed, 11 Feb 2026 09:20:48 +0000 Subject: feat: use fallback relays for bootstrapping only - Add --relay flag to 'ngit account create' allowing users to specify relay URLs (repeatable). Defaults to relay-default-set when not provided. - Remove fallback relays from fetch when repo context exists (repo coordinate provided). Only use them for bootstrapping (profile discovery with no repo context). - Remove fallback relays from publish when repo or user relays exist. Only use them when neither is available (e.g. new account signup). - Update --customize help text to reflect new relay-default-set behavior. --- src/lib/client.rs | 20 ++++++++++++++++++-- src/lib/login/fresh.rs | 17 ++++++++++++----- src/lib/login/user.rs | 2 ++ 3 files changed, 32 insertions(+), 7 deletions(-) (limited to 'src/lib') diff --git a/src/lib/client.rs b/src/lib/client.rs index 9c49653..89fcaf7 100644 --- a/src/lib/client.rs +++ b/src/lib/client.rs @@ -1577,7 +1577,14 @@ async fn create_relays_request( }; let relays = { - let mut relays = fallback_relays; + // Only use fallback relays for bootstrapping (no repo context). + // When we have a repo coordinate, rely on repo relays and coordinate + // hint relays instead of always merging in the default set. + let mut relays = if trusted_maintainer_coordinate.is_none() { + fallback_relays + } else { + HashSet::new() + }; if let Some(repo_ref) = &repo_ref { for r in repo_ref.relays.clone() { relays.insert(r); @@ -1588,6 +1595,8 @@ async fn create_relays_request( relays.insert(r.clone()); } } + // When bootstrapping with no repo context and no coordinate hints, + // we need at least the fallback relays to discover the user profile. relays }; @@ -2238,8 +2247,15 @@ pub async fn send_events( animate: bool, silent: bool, ) -> Result<()> { + // Only include default relays as fallback when there are no repo relays + // (bootstrapping case, e.g. new account signup). When repo relays exist, + // trust the repo and user relay configuration. let fallback = [ - client.get_relay_default_set().clone(), + if repo_read_relays.is_empty() && my_write_relays.is_empty() { + client.get_relay_default_set().clone() + } else { + vec![] + }, if events.iter().any(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) { client.get_blaster_relays().clone() } else { diff --git a/src/lib/login/fresh.rs b/src/lib/login/fresh.rs index 886b0e4..8e49085 100644 --- a/src/lib/login/fresh.rs +++ b/src/lib/login/fresh.rs @@ -715,6 +715,7 @@ pub async fn signup_non_interactive( #[cfg(not(test))] client: Option<&Client>, save_local: bool, publish: bool, + relay_urls: Vec, ) -> Result<(Arc, PublicKey, SignerInfo, Keys)> { // Generate new keypair let keys = nostr::Keys::generate(); @@ -783,10 +784,9 @@ pub async fn signup_non_interactive( if let Some(client) = client { let profile = EventBuilder::metadata(&Metadata::new().name(name)).sign_with_keys(&keys)?; let relay_list = EventBuilder::relay_list( - client - .get_relay_default_set() + relay_urls .iter() - .map(|s| (RelayUrl::parse(s).unwrap(), None)), + .filter_map(|s| RelayUrl::parse(s).ok().map(|url| (url, None))), ) .sign_with_keys(&keys)?; @@ -799,7 +799,7 @@ pub async fn signup_non_interactive( client, git_repo_path, vec![profile, relay_list], - client.get_relay_default_set().clone(), + relay_urls, vec![], true, false, @@ -848,12 +848,19 @@ async fn signup( } } - // Call the non-interactive function + // Call the non-interactive function, using relay_default_set as the + // relay list for interactive signup + let relay_urls = if let Some(c) = client { + c.get_relay_default_set().clone() + } else { + vec![] + }; let (signer, public_key, signer_info, _keys) = signup_non_interactive( name.clone(), client, false, // save_local = false (will be saved globally by caller) true, // publish = true (always publish in interactive mode) + relay_urls, ) .await?; diff --git a/src/lib/login/user.rs b/src/lib/login/user.rs index 0b702ef..b273363 100644 --- a/src/lib/login/user.rs +++ b/src/lib/login/user.rs @@ -113,6 +113,8 @@ pub async fn get_user_details( } Ok(user_ref) } else { + // No cached profile found. Fall back to fetching from default relays + // (bootstrapping). let empty = UserRef { public_key: public_key.to_owned(), metadata: extract_user_metadata(public_key, &[])?, -- cgit v1.2.3