upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-02-11 09:20:48 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-02-11 15:54:51 +0000
commit15bf0d0b6befae6c81631c0e5d0dc2947dd3318a (patch)
tree3d12d8b104c7a36ac8d2a7194da26fb432c95f23
parent459d33b6d7d3e5fdd55780670cd05d8141e670ac (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.
-rw-r--r--src/bin/ngit/cli.rs2
-rw-r--r--src/bin/ngit/sub_commands/create.rs30
-rw-r--r--src/lib/client.rs20
-rw-r--r--src/lib/login/fresh.rs17
-rw-r--r--src/lib/login/user.rs2
-rw-r--r--tests/ngit_init.rs140
-rw-r--r--tests/ngit_send.rs167
7 files changed, 315 insertions, 63 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.
53Currently the only settings not reachable through standard commands relate to default hardcoded relays: 53Currently 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 {
28pub async fn launch(_cli: &Cli, args: &SubCommandArgs) -> Result<()> { 33pub 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, &[])?,
diff --git a/tests/ngit_init.rs b/tests/ngit_init.rs
index 5483315..f70bc2e 100644
--- a/tests/ngit_init.rs
+++ b/tests/ngit_init.rs
@@ -337,7 +337,21 @@ mod state_b_coordinate_only {
337 ), 337 ),
338 Relay::new(8052, None, None), 338 Relay::new(8052, None, None),
339 Relay::new(8053, None, None), 339 Relay::new(8053, None, None),
340 Relay::new(8055, None, None), 340 Relay::new(
341 8055,
342 None,
343 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
344 relay.respond_events(
345 client_id,
346 &subscription_id,
347 &vec![
348 generate_test_key_1_metadata_event("fred"),
349 generate_test_key_1_relay_list_event(),
350 ],
351 )?;
352 Ok(())
353 }),
354 ),
341 Relay::new(8056, None, None), 355 Relay::new(8056, None, None),
342 ); 356 );
343 357
@@ -420,7 +434,21 @@ mod state_b_coordinate_only {
420 ), 434 ),
421 Relay::new(8052, None, None), 435 Relay::new(8052, None, None),
422 Relay::new(8053, None, None), 436 Relay::new(8053, None, None),
423 Relay::new(8055, None, None), 437 Relay::new(
438 8055,
439 None,
440 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
441 relay.respond_events(
442 client_id,
443 &subscription_id,
444 &vec![
445 generate_test_key_1_metadata_event("fred"),
446 generate_test_key_1_relay_list_event(),
447 ],
448 )?;
449 Ok(())
450 }),
451 ),
424 Relay::new(8056, None, None), 452 Relay::new(8056, None, None),
425 ); 453 );
426 454
@@ -537,7 +565,22 @@ mod state_c_my_announcement {
537 ), 565 ),
538 Relay::new(8052, None, None), 566 Relay::new(8052, None, None),
539 Relay::new(8053, None, None), 567 Relay::new(8053, None, None),
540 Relay::new(8055, None, None), 568 Relay::new(
569 8055,
570 None,
571 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
572 relay.respond_events(
573 client_id,
574 &subscription_id,
575 &vec![
576 generate_test_key_1_metadata_event("fred"),
577 generate_test_key_1_relay_list_event(),
578 generate_repo_ref_event(),
579 ],
580 )?;
581 Ok(())
582 }),
583 ),
541 Relay::new(8056, None, None), 584 Relay::new(8056, None, None),
542 ); 585 );
543 586
@@ -595,7 +638,22 @@ mod state_c_my_announcement {
595 ), 638 ),
596 Relay::new(8052, None, None), 639 Relay::new(8052, None, None),
597 Relay::new(8053, None, None), 640 Relay::new(8053, None, None),
598 Relay::new(8055, None, None), 641 Relay::new(
642 8055,
643 None,
644 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
645 relay.respond_events(
646 client_id,
647 &subscription_id,
648 &vec![
649 generate_test_key_1_metadata_event("fred"),
650 generate_test_key_1_relay_list_event(),
651 generate_repo_ref_event(),
652 ],
653 )?;
654 Ok(())
655 }),
656 ),
599 Relay::new(8056, None, None), 657 Relay::new(8056, None, None),
600 ); 658 );
601 659
@@ -657,7 +715,22 @@ mod state_c_my_announcement {
657 ), 715 ),
658 Relay::new(8052, None, None), 716 Relay::new(8052, None, None),
659 Relay::new(8053, None, None), 717 Relay::new(8053, None, None),
660 Relay::new(8055, None, None), 718 Relay::new(
719 8055,
720 None,
721 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
722 relay.respond_events(
723 client_id,
724 &subscription_id,
725 &vec![
726 generate_test_key_1_metadata_event("fred"),
727 generate_test_key_1_relay_list_event(),
728 generate_repo_ref_event(),
729 ],
730 )?;
731 Ok(())
732 }),
733 ),
661 Relay::new(8056, None, None), 734 Relay::new(8056, None, None),
662 ); 735 );
663 736
@@ -836,7 +909,24 @@ mod state_d_co_maintainer {
836 ), 909 ),
837 Relay::new(8052, None, None), 910 Relay::new(8052, None, None),
838 Relay::new(8053, None, None), 911 Relay::new(8053, None, None),
839 Relay::new(8055, None, None), 912 Relay::new(
913 8055,
914 None,
915 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
916 relay.respond_events(
917 client_id,
918 &subscription_id,
919 &vec![
920 generate_test_key_1_metadata_event("fred"),
921 generate_test_key_1_relay_list_event(),
922 generate_test_key_2_metadata_event("carole"),
923 generate_test_key_2_relay_list_event(),
924 generate_repo_ref_event_as_key_2_listing_key_1(),
925 ],
926 )?;
927 Ok(())
928 }),
929 ),
840 Relay::new(8056, None, None), 930 Relay::new(8056, None, None),
841 ); 931 );
842 932
@@ -1021,7 +1111,24 @@ mod state_e_not_listed {
1021 ), 1111 ),
1022 Relay::new(8052, None, None), 1112 Relay::new(8052, None, None),
1023 Relay::new(8053, None, None), 1113 Relay::new(8053, None, None),
1024 Relay::new(8055, None, None), 1114 Relay::new(
1115 8055,
1116 None,
1117 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1118 relay.respond_events(
1119 client_id,
1120 &subscription_id,
1121 &vec![
1122 generate_test_key_1_metadata_event("fred"),
1123 generate_test_key_1_relay_list_event(),
1124 generate_test_key_2_metadata_event("carole"),
1125 generate_test_key_2_relay_list_event(),
1126 generate_repo_ref_event_as_key_2_not_listing_key_1(),
1127 ],
1128 )?;
1129 Ok(())
1130 }),
1131 ),
1025 Relay::new(8056, None, None), 1132 Relay::new(8056, None, None),
1026 ); 1133 );
1027 1134
@@ -1104,7 +1211,24 @@ mod state_e_not_listed {
1104 ), 1211 ),
1105 Relay::new(8052, None, None), 1212 Relay::new(8052, None, None),
1106 Relay::new(8053, None, None), 1213 Relay::new(8053, None, None),
1107 Relay::new(8055, None, None), 1214 Relay::new(
1215 8055,
1216 None,
1217 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
1218 relay.respond_events(
1219 client_id,
1220 &subscription_id,
1221 &vec![
1222 generate_test_key_1_metadata_event("fred"),
1223 generate_test_key_1_relay_list_event(),
1224 generate_test_key_2_metadata_event("carole"),
1225 generate_test_key_2_relay_list_event(),
1226 generate_repo_ref_event_as_key_2_not_listing_key_1(),
1227 ],
1228 )?;
1229 Ok(())
1230 }),
1231 ),
1108 Relay::new(8056, None, None), 1232 Relay::new(8056, None, None),
1109 ); 1233 );
1110 1234
diff --git a/tests/ngit_send.rs b/tests/ngit_send.rs
index 7946aef..7170f84 100644
--- a/tests/ngit_send.rs
+++ b/tests/ngit_send.rs
@@ -56,6 +56,29 @@ mod when_commits_behind_ask_to_proceed {
56 )) 56 ))
57 } 57 }
58 58
59 fn create_relay_55() -> Result<Relay<'static>> {
60 Ok(Relay::new(
61 8055,
62 None,
63 Some(&|relay, client_id, subscription_id, _| -> Result<()> {
64 relay.respond_events(
65 client_id,
66 &subscription_id,
67 &vec![
68 generate_repo_ref_event(),
69 generate_test_key_1_metadata_event("fred"),
70 generate_test_key_1_relay_list_event(),
71 ],
72 )?;
73 Ok(())
74 }),
75 ))
76 }
77
78 fn create_relay_56() -> Result<Relay<'static>> {
79 Ok(Relay::new(8056, None, None))
80 }
81
59 fn expect_confirm_prompt(p: &'_ mut CliTester) -> Result<CliTesterConfirmPrompt<'_>> { 82 fn expect_confirm_prompt(p: &'_ mut CliTester) -> Result<CliTesterConfirmPrompt<'_>> {
60 p.expect("fetching updates...\r\n")?; 83 p.expect("fetching updates...\r\n")?;
61 p.expect_eventually("\r\n")?; // may be 'no updates' or some updates 84 p.expect_eventually("\r\n")?; // may be 'no updates' or some updates
@@ -73,17 +96,25 @@ mod when_commits_behind_ask_to_proceed {
73 async fn asked_with_default_no() -> Result<()> { 96 async fn asked_with_default_no() -> Result<()> {
74 let test_repo = prep_test_repo()?; 97 let test_repo = prep_test_repo()?;
75 let mut r51 = create_relay_51()?; 98 let mut r51 = create_relay_51()?;
99 let mut r55 = create_relay_55()?;
100 let mut r56 = create_relay_56()?;
76 // // check relay had the right number of events 101 // // check relay had the right number of events
77 let cli_tester_handle = std::thread::spawn(move || -> Result<()> { 102 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
78 let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]); 103 let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]);
79 expect_confirm_prompt(&mut p)?; 104 expect_confirm_prompt(&mut p)?;
80 p.exit()?; 105 p.exit()?;
81 relay::shutdown_relay(8051)?; 106 for p in [51, 55, 56] {
107 relay::shutdown_relay(8000 + p)?;
108 }
82 Ok(()) 109 Ok(())
83 }); 110 });
84 111
85 // launch relay 112 // launch relay
86 r51.listen_until_close().await?; 113 let _ = join!(
114 r51.listen_until_close(),
115 r55.listen_until_close(),
116 r56.listen_until_close(),
117 );
87 cli_tester_handle.join().unwrap()?; 118 cli_tester_handle.join().unwrap()?;
88 Ok(()) 119 Ok(())
89 } 120 }
@@ -93,16 +124,24 @@ mod when_commits_behind_ask_to_proceed {
93 async fn when_response_is_false_aborts() -> Result<()> { 124 async fn when_response_is_false_aborts() -> Result<()> {
94 let test_repo = prep_test_repo()?; 125 let test_repo = prep_test_repo()?;
95 let mut r51 = create_relay_51()?; 126 let mut r51 = create_relay_51()?;
127 let mut r55 = create_relay_55()?;
128 let mut r56 = create_relay_56()?;
96 let cli_tester_handle = std::thread::spawn(move || -> Result<()> { 129 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
97 let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]); 130 let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]);
98 expect_confirm_prompt(&mut p)?.succeeds_with(Some(false))?; 131 expect_confirm_prompt(&mut p)?.succeeds_with(Some(false))?;
99 p.expect_end_with("Error: aborting so commits can be rebased\r\n")?; 132 p.expect_end_with("Error: aborting so commits can be rebased\r\n")?;
100 relay::shutdown_relay(8051)?; 133 for p in [51, 55, 56] {
134 relay::shutdown_relay(8000 + p)?;
135 }
101 Ok(()) 136 Ok(())
102 }); 137 });
103 138
104 // launch relay 139 // launch relay
105 r51.listen_until_close().await?; 140 let _ = join!(
141 r51.listen_until_close(),
142 r55.listen_until_close(),
143 r56.listen_until_close(),
144 );
106 cli_tester_handle.join().unwrap()?; 145 cli_tester_handle.join().unwrap()?;
107 Ok(()) 146 Ok(())
108 } 147 }
@@ -112,17 +151,25 @@ mod when_commits_behind_ask_to_proceed {
112 async fn when_response_is_true_proceeds() -> Result<()> { 151 async fn when_response_is_true_proceeds() -> Result<()> {
113 let test_repo = prep_test_repo()?; 152 let test_repo = prep_test_repo()?;
114 let mut r51 = create_relay_51()?; 153 let mut r51 = create_relay_51()?;
154 let mut r55 = create_relay_55()?;
155 let mut r56 = create_relay_56()?;
115 let cli_tester_handle = std::thread::spawn(move || -> Result<()> { 156 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
116 let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]); 157 let mut p = CliTester::new_from_dir(&test_repo.dir, ["-i", "send", "HEAD~2"]);
117 expect_confirm_prompt(&mut p)?.succeeds_with(Some(true))?; 158 expect_confirm_prompt(&mut p)?.succeeds_with(Some(true))?;
118 p.expect("? include cover letter")?; 159 p.expect("? include cover letter")?;
119 p.exit()?; 160 p.exit()?;
120 relay::shutdown_relay(8051)?; 161 for p in [51, 55, 56] {
162 relay::shutdown_relay(8000 + p)?;
163 }
121 Ok(()) 164 Ok(())
122 }); 165 });
123 166
124 // launch relay 167 // launch relay
125 r51.listen_until_close().await?; 168 let _ = join!(
169 r51.listen_until_close(),
170 r55.listen_until_close(),
171 r56.listen_until_close(),
172 );
126 cli_tester_handle.join().unwrap()?; 173 cli_tester_handle.join().unwrap()?;
127 Ok(()) 174 Ok(())
128 } 175 }
@@ -245,7 +292,11 @@ async fn prep_run_create_proposal(
245 relay.respond_events( 292 relay.respond_events(
246 client_id, 293 client_id,
247 &subscription_id, 294 &subscription_id,
248 &vec![generate_repo_ref_event()], 295 &vec![
296 generate_repo_ref_event(),
297 generate_test_key_1_metadata_event("fred"),
298 generate_test_key_1_relay_list_event(),
299 ],
249 )?; 300 )?;
250 Ok(()) 301 Ok(())
251 }), 302 }),
@@ -319,13 +370,11 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
319 370
320 #[tokio::test] 371 #[tokio::test]
321 #[serial] 372 #[serial]
322 async fn only_1_cover_letter_event_sent_to_fallback_relays() -> Result<()> { 373 async fn no_events_sent_to_fallback_relays() -> Result<()> {
323 let (r51, r52, _, _, _) = prep_run_create_proposal(true).await?; 374 let (r51, r52, _, _, _) = prep_run_create_proposal(true).await?;
375 // Fallback relays should not receive events when repo relays exist
324 for relay in [&r51, &r52] { 376 for relay in [&r51, &r52] {
325 assert_eq!( 377 assert_eq!(relay.events.len(), 0);
326 relay.events.iter().filter(|e| is_cover_letter(e)).count(),
327 1,
328 );
329 } 378 }
330 Ok(()) 379 Ok(())
331 } 380 }
@@ -333,8 +382,9 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
333 #[tokio::test] 382 #[tokio::test]
334 #[serial] 383 #[serial]
335 async fn only_2_patch_kind_events_sent_to_each_relay() -> Result<()> { 384 async fn only_2_patch_kind_events_sent_to_each_relay() -> Result<()> {
336 let (r51, r52, r53, r55, r56) = prep_run_create_proposal(true).await?; 385 let (_, _, r53, r55, r56) = prep_run_create_proposal(true).await?;
337 for relay in [&r51, &r52, &r53, &r55, &r56] { 386 // Only user and repo relays should receive patches, not fallback relays
387 for relay in [&r53, &r55, &r56] {
338 assert_eq!(relay.events.iter().filter(|e| is_patch(e)).count(), 2,); 388 assert_eq!(relay.events.iter().filter(|e| is_patch(e)).count(), 2,);
339 } 389 }
340 Ok(()) 390 Ok(())
@@ -832,7 +882,11 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
832 relay.respond_events( 882 relay.respond_events(
833 client_id, 883 client_id,
834 &subscription_id, 884 &subscription_id,
835 &vec![generate_repo_ref_event()], 885 &vec![
886 generate_repo_ref_event(),
887 generate_test_key_1_metadata_event("fred"),
888 generate_test_key_1_relay_list_event(),
889 ],
836 )?; 890 )?;
837 Ok(()) 891 Ok(())
838 }), 892 }),
@@ -848,10 +902,8 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
848 &mut p, 902 &mut p,
849 vec![ 903 vec![
850 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), 904 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""),
851 (" [my-relay] ws://localhost:8053", true, ""),
852 (" [repo-relay] ws://localhost:8056", true, ""), 905 (" [repo-relay] ws://localhost:8056", true, ""),
853 (" [default] ws://localhost:8051", true, ""), 906 (" [my-relay] ws://localhost:8053", true, ""),
854 (" [default] ws://localhost:8052", true, ""),
855 ], 907 ],
856 3, 908 3,
857 )?; 909 )?;
@@ -912,7 +964,11 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
912 relay.respond_events( 964 relay.respond_events(
913 client_id, 965 client_id,
914 &subscription_id, 966 &subscription_id,
915 &vec![generate_repo_ref_event()], 967 &vec![
968 generate_repo_ref_event(),
969 generate_test_key_1_metadata_event("fred"),
970 generate_test_key_1_relay_list_event(),
971 ],
916 )?; 972 )?;
917 Ok(()) 973 Ok(())
918 }), 974 }),
@@ -986,7 +1042,11 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
986 relay.respond_events( 1042 relay.respond_events(
987 client_id, 1043 client_id,
988 &subscription_id, 1044 &subscription_id,
989 &vec![generate_repo_ref_event()], 1045 &vec![
1046 generate_repo_ref_event(),
1047 generate_test_key_1_metadata_event("fred"),
1048 generate_test_key_1_relay_list_event(),
1049 ],
990 )?; 1050 )?;
991 Ok(()) 1051 Ok(())
992 }), 1052 }),
@@ -1009,14 +1069,12 @@ mod when_cover_letter_details_specified_with_range_of_head_2_sends_cover_letter_
1009 &mut p, 1069 &mut p,
1010 vec![ 1070 vec![
1011 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), 1071 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""),
1012 (" [my-relay] ws://localhost:8053", true, ""),
1013 ( 1072 (
1014 " [repo-relay] ws://localhost:8056", 1073 " [repo-relay] ws://localhost:8056",
1015 false, 1074 false,
1016 "error: Payment Required", 1075 "error: Payment Required",
1017 ), 1076 ),
1018 (" [default] ws://localhost:8051", true, ""), 1077 (" [my-relay] ws://localhost:8053", true, ""),
1019 (" [default] ws://localhost:8052", true, ""),
1020 ], 1078 ],
1021 3, 1079 3,
1022 )?; 1080 )?;
@@ -1080,7 +1138,11 @@ mod when_no_cover_letter_flag_set_with_range_of_head_2_sends_2_patches_without_c
1080 relay.respond_events( 1138 relay.respond_events(
1081 client_id, 1139 client_id,
1082 &subscription_id, 1140 &subscription_id,
1083 &vec![generate_repo_ref_event()], 1141 &vec![
1142 generate_repo_ref_event(),
1143 generate_test_key_1_metadata_event("fred"),
1144 generate_test_key_1_relay_list_event(),
1145 ],
1084 )?; 1146 )?;
1085 Ok(()) 1147 Ok(())
1086 }), 1148 }),
@@ -1097,10 +1159,8 @@ mod when_no_cover_letter_flag_set_with_range_of_head_2_sends_2_patches_without_c
1097 &mut p, 1159 &mut p,
1098 vec![ 1160 vec![
1099 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), 1161 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""),
1100 (" [my-relay] ws://localhost:8053", true, ""),
1101 (" [repo-relay] ws://localhost:8056", true, ""), 1162 (" [repo-relay] ws://localhost:8056", true, ""),
1102 (" [default] ws://localhost:8051", true, ""), 1163 (" [my-relay] ws://localhost:8053", true, ""),
1103 (" [default] ws://localhost:8052", true, ""),
1104 ], 1164 ],
1105 2, 1165 2,
1106 )?; 1166 )?;
@@ -1303,7 +1363,11 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main {
1303 relay.respond_events( 1363 relay.respond_events(
1304 client_id, 1364 client_id,
1305 &subscription_id, 1365 &subscription_id,
1306 &vec![generate_repo_ref_event()], 1366 &vec![
1367 generate_repo_ref_event(),
1368 generate_test_key_1_metadata_event("fred"),
1369 generate_test_key_1_relay_list_event(),
1370 ],
1307 )?; 1371 )?;
1308 Ok(()) 1372 Ok(())
1309 }), 1373 }),
@@ -1366,7 +1430,11 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main {
1366 relay.respond_events( 1430 relay.respond_events(
1367 client_id, 1431 client_id,
1368 &subscription_id, 1432 &subscription_id,
1369 &vec![generate_repo_ref_event()], 1433 &vec![
1434 generate_repo_ref_event(),
1435 generate_test_key_1_metadata_event("fred"),
1436 generate_test_key_1_relay_list_event(),
1437 ],
1370 )?; 1438 )?;
1371 Ok(()) 1439 Ok(())
1372 }), 1440 }),
@@ -1382,10 +1450,8 @@ mod when_range_ommited_prompts_for_selection_defaulting_ahead_of_main {
1382 &mut p, 1450 &mut p,
1383 vec![ 1451 vec![
1384 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), 1452 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""),
1385 (" [my-relay] ws://localhost:8053", true, ""),
1386 (" [repo-relay] ws://localhost:8056", true, ""), 1453 (" [repo-relay] ws://localhost:8056", true, ""),
1387 (" [default] ws://localhost:8051", true, ""), 1454 (" [my-relay] ws://localhost:8053", true, ""),
1388 (" [default] ws://localhost:8052", true, ""),
1389 ], 1455 ],
1390 2, 1456 2,
1391 )?; 1457 )?;
@@ -1504,7 +1570,12 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let
1504 relay.respond_events( 1570 relay.respond_events(
1505 client_id, 1571 client_id,
1506 &subscription_id, 1572 &subscription_id,
1507 &vec![generate_repo_ref_event(), get_pretend_proposal_root_event()], 1573 &vec![
1574 generate_repo_ref_event(),
1575 get_pretend_proposal_root_event(),
1576 generate_test_key_1_metadata_event("fred"),
1577 generate_test_key_1_relay_list_event(),
1578 ],
1508 )?; 1579 )?;
1509 Ok(()) 1580 Ok(())
1510 }), 1581 }),
@@ -1567,7 +1638,12 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let
1567 relay.respond_events( 1638 relay.respond_events(
1568 client_id, 1639 client_id,
1569 &subscription_id, 1640 &subscription_id,
1570 &vec![generate_repo_ref_event(), get_pretend_proposal_root_event()], 1641 &vec![
1642 generate_repo_ref_event(),
1643 get_pretend_proposal_root_event(),
1644 generate_test_key_1_metadata_event("fred"),
1645 generate_test_key_1_relay_list_event(),
1646 ],
1571 )?; 1647 )?;
1572 Ok(()) 1648 Ok(())
1573 }), 1649 }),
@@ -1583,10 +1659,8 @@ mod root_proposal_specified_using_in_reply_to_with_range_of_head_2_and_cover_let
1583 &mut p, 1659 &mut p,
1584 vec![ 1660 vec![
1585 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""), 1661 (" [my-relay] [repo-relay] ws://localhost:8055", true, ""),
1586 (" [my-relay] ws://localhost:8053", true, ""),
1587 (" [repo-relay] ws://localhost:8056", true, ""), 1662 (" [repo-relay] ws://localhost:8056", true, ""),
1588 (" [default] ws://localhost:8051", true, ""), 1663 (" [my-relay] ws://localhost:8053", true, ""),
1589 (" [default] ws://localhost:8052", true, ""),
1590 ], 1664 ],
1591 3, 1665 3,
1592 )?; 1666 )?;
@@ -1765,7 +1839,12 @@ mod in_reply_to_mentions_issue {
1765 relay.respond_events( 1839 relay.respond_events(
1766 client_id, 1840 client_id,
1767 &subscription_id, 1841 &subscription_id,
1768 &vec![generate_repo_ref_event(), get_pretend_issue_event()], 1842 &vec![
1843 generate_repo_ref_event(),
1844 get_pretend_issue_event(),
1845 generate_test_key_1_metadata_event("fred"),
1846 generate_test_key_1_relay_list_event(),
1847 ],
1769 )?; 1848 )?;
1770 Ok(()) 1849 Ok(())
1771 }), 1850 }),
@@ -1885,7 +1964,11 @@ mod in_reply_to_mentions_npub_and_nprofile_which_get_mentioned_in_proposal_root
1885 relay.respond_events( 1964 relay.respond_events(
1886 client_id, 1965 client_id,
1887 &subscription_id, 1966 &subscription_id,
1888 &vec![generate_repo_ref_event()], 1967 &vec![
1968 generate_repo_ref_event(),
1969 generate_test_key_1_metadata_event("fred"),
1970 generate_test_key_1_relay_list_event(),
1971 ],
1889 )?; 1972 )?;
1890 Ok(()) 1973 Ok(())
1891 }), 1974 }),
@@ -2037,7 +2120,11 @@ mod non_interactive_validation {
2037 relay.respond_events( 2120 relay.respond_events(
2038 client_id, 2121 client_id,
2039 &subscription_id, 2122 &subscription_id,
2040 &vec![generate_repo_ref_event()], 2123 &vec![
2124 generate_repo_ref_event(),
2125 generate_test_key_1_metadata_event("fred"),
2126 generate_test_key_1_relay_list_event(),
2127 ],
2041 )?; 2128 )?;
2042 Ok(()) 2129 Ok(())
2043 }), 2130 }),