diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-11 09:20:48 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2026-02-11 15:54:51 +0000 |
| commit | 15bf0d0b6befae6c81631c0e5d0dc2947dd3318a (patch) | |
| tree | 3d12d8b104c7a36ac8d2a7194da26fb432c95f23 /src | |
| parent | 459d33b6d7d3e5fdd55780670cd05d8141e670ac (diff) | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/bin/ngit/cli.rs | 2 | ||||
| -rw-r--r-- | src/bin/ngit/sub_commands/create.rs | 30 | ||||
| -rw-r--r-- | src/lib/client.rs | 20 | ||||
| -rw-r--r-- | src/lib/login/fresh.rs | 17 | ||||
| -rw-r--r-- | src/lib/login/user.rs | 2 |
5 files changed, 56 insertions, 15 deletions
diff --git a/src/bin/ngit/cli.rs b/src/bin/ngit/cli.rs index d2246d7..47f4b27 100644 --- a/src/bin/ngit/cli.rs +++ b/src/bin/ngit/cli.rs | |||
| @@ -53,7 +53,7 @@ ngit settings are managed through the git config. | |||
| 53 | Currently the only settings not reachable through standard commands relate to default hardcoded relays: | 53 | Currently the only settings not reachable through standard commands relate to default hardcoded relays: |
| 54 | 54 | ||
| 55 | - nostr.grasp-default-set - only used during `ngit init` | 55 | - nostr.grasp-default-set - only used during `ngit init` |
| 56 | - nostr.relay-default-set - must have at least 1 value, all events send to repo relays, user write and default relays | 56 | - nostr.relay-default-set - used for profile discovery and account bootstrapping |
| 57 | - nostr.relay-blaster-set - only used for repo announcement events | 57 | - nostr.relay-blaster-set - only used for repo announcement events |
| 58 | - nostr.relay-signer-fallback-set | 58 | - nostr.relay-signer-fallback-set |
| 59 | 59 | ||
diff --git a/src/bin/ngit/sub_commands/create.rs b/src/bin/ngit/sub_commands/create.rs index e0d89b5..1c2b8db 100644 --- a/src/bin/ngit/sub_commands/create.rs +++ b/src/bin/ngit/sub_commands/create.rs | |||
| @@ -16,6 +16,11 @@ pub struct SubCommandArgs { | |||
| 16 | #[arg(long, required = true)] | 16 | #[arg(long, required = true)] |
| 17 | pub name: String, | 17 | pub name: String, |
| 18 | 18 | ||
| 19 | /// Relay URLs for the new account's relay list (can be specified multiple | ||
| 20 | /// times). Defaults to the relay-default-set if not provided. | ||
| 21 | #[arg(long = "relay", value_parser, num_args = 1)] | ||
| 22 | pub relays: Vec<String>, | ||
| 23 | |||
| 19 | /// Don't publish metadata to relays (offline mode) | 24 | /// Don't publish metadata to relays (offline mode) |
| 20 | #[arg(long)] | 25 | #[arg(long)] |
| 21 | pub offline: bool, | 26 | pub offline: bool, |
| @@ -28,20 +33,31 @@ pub struct SubCommandArgs { | |||
| 28 | pub async fn launch(_cli: &Cli, args: &SubCommandArgs) -> Result<()> { | 33 | pub async fn launch(_cli: &Cli, args: &SubCommandArgs) -> Result<()> { |
| 29 | let git_repo = Repo::discover().ok(); | 34 | let git_repo = Repo::discover().ok(); |
| 30 | 35 | ||
| 36 | let params = Params::with_git_config_relay_defaults(&git_repo.as_ref()); | ||
| 37 | |||
| 38 | let relay_urls = if args.relays.is_empty() { | ||
| 39 | params.relay_default_set.clone() | ||
| 40 | } else { | ||
| 41 | args.relays.clone() | ||
| 42 | }; | ||
| 43 | |||
| 31 | let client = if args.offline { | 44 | let client = if args.offline { |
| 32 | None | 45 | None |
| 33 | } else { | 46 | } else { |
| 34 | Some(Client::new(Params::with_git_config_relay_defaults( | 47 | Some(Client::new(params)) |
| 35 | &git_repo.as_ref(), | ||
| 36 | ))) | ||
| 37 | }; | 48 | }; |
| 38 | 49 | ||
| 39 | let publish = !args.offline; | 50 | let publish = !args.offline; |
| 40 | 51 | ||
| 41 | let (_signer, public_key, _signer_info, keys) = | 52 | let (_signer, public_key, _signer_info, keys) = signup_non_interactive( |
| 42 | signup_non_interactive(args.name.clone(), client.as_ref(), args.local, publish) | 53 | args.name.clone(), |
| 43 | .await | 54 | client.as_ref(), |
| 44 | .context("failed to create account")?; | 55 | args.local, |
| 56 | publish, | ||
| 57 | relay_urls, | ||
| 58 | ) | ||
| 59 | .await | ||
| 60 | .context("failed to create account")?; | ||
| 45 | 61 | ||
| 46 | // Display the generated nsec prominently | 62 | // Display the generated nsec prominently |
| 47 | println!("\nā Account created successfully!"); | 63 | println!("\nā Account created successfully!"); |
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( | |||
| 1577 | }; | 1577 | }; |
| 1578 | 1578 | ||
| 1579 | let relays = { | 1579 | let relays = { |
| 1580 | let mut relays = fallback_relays; | 1580 | // Only use fallback relays for bootstrapping (no repo context). |
| 1581 | // When we have a repo coordinate, rely on repo relays and coordinate | ||
| 1582 | // hint relays instead of always merging in the default set. | ||
| 1583 | let mut relays = if trusted_maintainer_coordinate.is_none() { | ||
| 1584 | fallback_relays | ||
| 1585 | } else { | ||
| 1586 | HashSet::new() | ||
| 1587 | }; | ||
| 1581 | if let Some(repo_ref) = &repo_ref { | 1588 | if let Some(repo_ref) = &repo_ref { |
| 1582 | for r in repo_ref.relays.clone() { | 1589 | for r in repo_ref.relays.clone() { |
| 1583 | relays.insert(r); | 1590 | relays.insert(r); |
| @@ -1588,6 +1595,8 @@ async fn create_relays_request( | |||
| 1588 | relays.insert(r.clone()); | 1595 | relays.insert(r.clone()); |
| 1589 | } | 1596 | } |
| 1590 | } | 1597 | } |
| 1598 | // When bootstrapping with no repo context and no coordinate hints, | ||
| 1599 | // we need at least the fallback relays to discover the user profile. | ||
| 1591 | relays | 1600 | relays |
| 1592 | }; | 1601 | }; |
| 1593 | 1602 | ||
| @@ -2238,8 +2247,15 @@ pub async fn send_events( | |||
| 2238 | animate: bool, | 2247 | animate: bool, |
| 2239 | silent: bool, | 2248 | silent: bool, |
| 2240 | ) -> Result<()> { | 2249 | ) -> Result<()> { |
| 2250 | // Only include default relays as fallback when there are no repo relays | ||
| 2251 | // (bootstrapping case, e.g. new account signup). When repo relays exist, | ||
| 2252 | // trust the repo and user relay configuration. | ||
| 2241 | let fallback = [ | 2253 | let fallback = [ |
| 2242 | client.get_relay_default_set().clone(), | 2254 | if repo_read_relays.is_empty() && my_write_relays.is_empty() { |
| 2255 | client.get_relay_default_set().clone() | ||
| 2256 | } else { | ||
| 2257 | vec![] | ||
| 2258 | }, | ||
| 2243 | if events.iter().any(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) { | 2259 | if events.iter().any(|e| e.kind.eq(&Kind::GitRepoAnnouncement)) { |
| 2244 | client.get_blaster_relays().clone() | 2260 | client.get_blaster_relays().clone() |
| 2245 | } else { | 2261 | } 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( | |||
| 715 | #[cfg(not(test))] client: Option<&Client>, | 715 | #[cfg(not(test))] client: Option<&Client>, |
| 716 | save_local: bool, | 716 | save_local: bool, |
| 717 | publish: bool, | 717 | publish: bool, |
| 718 | relay_urls: Vec<String>, | ||
| 718 | ) -> Result<(Arc<dyn NostrSigner>, PublicKey, SignerInfo, Keys)> { | 719 | ) -> Result<(Arc<dyn NostrSigner>, PublicKey, SignerInfo, Keys)> { |
| 719 | // Generate new keypair | 720 | // Generate new keypair |
| 720 | let keys = nostr::Keys::generate(); | 721 | let keys = nostr::Keys::generate(); |
| @@ -783,10 +784,9 @@ pub async fn signup_non_interactive( | |||
| 783 | if let Some(client) = client { | 784 | if let Some(client) = client { |
| 784 | let profile = EventBuilder::metadata(&Metadata::new().name(name)).sign_with_keys(&keys)?; | 785 | let profile = EventBuilder::metadata(&Metadata::new().name(name)).sign_with_keys(&keys)?; |
| 785 | let relay_list = EventBuilder::relay_list( | 786 | let relay_list = EventBuilder::relay_list( |
| 786 | client | 787 | relay_urls |
| 787 | .get_relay_default_set() | ||
| 788 | .iter() | 788 | .iter() |
| 789 | .map(|s| (RelayUrl::parse(s).unwrap(), None)), | 789 | .filter_map(|s| RelayUrl::parse(s).ok().map(|url| (url, None))), |
| 790 | ) | 790 | ) |
| 791 | .sign_with_keys(&keys)?; | 791 | .sign_with_keys(&keys)?; |
| 792 | 792 | ||
| @@ -799,7 +799,7 @@ pub async fn signup_non_interactive( | |||
| 799 | client, | 799 | client, |
| 800 | git_repo_path, | 800 | git_repo_path, |
| 801 | vec![profile, relay_list], | 801 | vec![profile, relay_list], |
| 802 | client.get_relay_default_set().clone(), | 802 | relay_urls, |
| 803 | vec![], | 803 | vec![], |
| 804 | true, | 804 | true, |
| 805 | false, | 805 | false, |
| @@ -848,12 +848,19 @@ async fn signup( | |||
| 848 | } | 848 | } |
| 849 | } | 849 | } |
| 850 | 850 | ||
| 851 | // Call the non-interactive function | 851 | // Call the non-interactive function, using relay_default_set as the |
| 852 | // relay list for interactive signup | ||
| 853 | let relay_urls = if let Some(c) = client { | ||
| 854 | c.get_relay_default_set().clone() | ||
| 855 | } else { | ||
| 856 | vec![] | ||
| 857 | }; | ||
| 852 | let (signer, public_key, signer_info, _keys) = signup_non_interactive( | 858 | let (signer, public_key, signer_info, _keys) = signup_non_interactive( |
| 853 | name.clone(), | 859 | name.clone(), |
| 854 | client, | 860 | client, |
| 855 | false, // save_local = false (will be saved globally by caller) | 861 | false, // save_local = false (will be saved globally by caller) |
| 856 | true, // publish = true (always publish in interactive mode) | 862 | true, // publish = true (always publish in interactive mode) |
| 863 | relay_urls, | ||
| 857 | ) | 864 | ) |
| 858 | .await?; | 865 | .await?; |
| 859 | 866 | ||
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( | |||
| 113 | } | 113 | } |
| 114 | Ok(user_ref) | 114 | Ok(user_ref) |
| 115 | } else { | 115 | } else { |
| 116 | // No cached profile found. Fall back to fetching from default relays | ||
| 117 | // (bootstrapping). | ||
| 116 | let empty = UserRef { | 118 | let empty = UserRef { |
| 117 | public_key: public_key.to_owned(), | 119 | public_key: public_key.to_owned(), |
| 118 | metadata: extract_user_metadata(public_key, &[])?, | 120 | metadata: extract_user_metadata(public_key, &[])?, |