diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-11-05 08:31:24 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-11-05 08:31:24 +0000 |
| commit | c2183f156a767c1443c7ae62954fe8192e349ceb (patch) | |
| tree | cbbcbd41113a1d96898106b43ea11c9bf65399ca /grasp-audit/src/specs | |
| parent | 64e607dd67f3777aa596596d74ee16e1bf9f4f27 (diff) | |
feat(grasp-audit): implement test_accept_valid_repo_announcement
- Fix Tags iteration error (use .iter() method)
- Test validates GRASP-01 requirement: accept repo announcements listing service
- Verifies clone and relays tags contain service URL
- Tested against ngit-relay on port 18081
- Test passes successfully
Diffstat (limited to 'grasp-audit/src/specs')
| -rw-r--r-- | grasp-audit/src/specs/grasp01_nostr_relay.rs | 89 | ||||
| -rw-r--r-- | grasp-audit/src/specs/mod.rs | 2 |
2 files changed, 77 insertions, 14 deletions
diff --git a/grasp-audit/src/specs/grasp01_nostr_relay.rs b/grasp-audit/src/specs/grasp01_nostr_relay.rs index 1d1de79..a81132d 100644 --- a/grasp-audit/src/specs/grasp01_nostr_relay.rs +++ b/grasp-audit/src/specs/grasp01_nostr_relay.rs | |||
| @@ -64,20 +64,81 @@ impl Grasp01NostrRelayTests { | |||
| 64 | "Accept valid repository announcements with service in clone and relays tags", | 64 | "Accept valid repository announcements with service in clone and relays tags", |
| 65 | ) | 65 | ) |
| 66 | .run(|| async { | 66 | .run(|| async { |
| 67 | // TODO: Implementation | 67 | // Get relay URL from client |
| 68 | // 1. Get service URL from client config | 68 | let relay_url = client.client().relays().await |
| 69 | // 2. Create kind 30617 event with: | 69 | .keys() |
| 70 | // - d tag: "test-repo-{timestamp}" | 70 | .next() |
| 71 | // - name tag: "Test Repository" | 71 | .ok_or("No relay connected")? |
| 72 | // - description tag: "Test repository for GRASP-01 compliance" | 72 | .to_string(); |
| 73 | // - clone tag: "{service_url}/{npub}/test-repo.git" | ||
| 74 | // - relays tag: "{service_ws_url}" | ||
| 75 | // 3. Send event to relay | ||
| 76 | // 4. Verify OK response (not rejected) | ||
| 77 | // 5. Query back with filter on kind 30617, author, d tag | ||
| 78 | // 6. Verify event is stored and matches what we sent | ||
| 79 | 73 | ||
| 80 | Err("Not implemented yet".to_string()) | 74 | // Convert WebSocket URL to HTTP URL for clone tag |
| 75 | let http_url = relay_url | ||
| 76 | .replace("ws://", "http://") | ||
| 77 | .replace("wss://", "https://"); | ||
| 78 | |||
| 79 | // Create unique repository identifier | ||
| 80 | let timestamp = Timestamp::now().as_u64(); | ||
| 81 | let repo_id = format!("test-repo-{}", timestamp); | ||
| 82 | |||
| 83 | // Get npub for clone URL | ||
| 84 | let npub = client.public_key().to_bech32() | ||
| 85 | .map_err(|e| format!("Failed to convert pubkey to npub: {}", e))?; | ||
| 86 | |||
| 87 | // Build kind 30617 repository announcement | ||
| 88 | let event = client.event_builder(Kind::GitRepoAnnouncement, "") | ||
| 89 | .tag(Tag::identifier(&repo_id)) | ||
| 90 | .tag(Tag::custom(TagKind::Custom("name".into()), vec!["GRASP-01 Test Repository"])) | ||
| 91 | .tag(Tag::custom(TagKind::Custom("description".into()), vec!["Test repository for GRASP-01 compliance testing"])) | ||
| 92 | .tag(Tag::custom(TagKind::Custom("clone".into()), vec![format!("{}/{}/{}.git", http_url, npub, repo_id)])) | ||
| 93 | .tag(Tag::custom(TagKind::Custom("relays".into()), vec![relay_url.clone()])) | ||
| 94 | .build(client.keys()) | ||
| 95 | .map_err(|e| format!("Failed to build event: {}", e))?; | ||
| 96 | |||
| 97 | // Send the event | ||
| 98 | let event_id = client.send_event(event.clone()).await | ||
| 99 | .map_err(|e| format!("Failed to send event: {}", e))?; | ||
| 100 | |||
| 101 | // Query back to verify it was accepted and stored | ||
| 102 | let filter = Filter::new() | ||
| 103 | .kind(Kind::GitRepoAnnouncement) | ||
| 104 | .author(client.public_key()) | ||
| 105 | .identifier(&repo_id); | ||
| 106 | |||
| 107 | let events = client.query(filter).await | ||
| 108 | .map_err(|e| format!("Failed to query events: {}", e))?; | ||
| 109 | |||
| 110 | // Verify we got the event back | ||
| 111 | if events.is_empty() { | ||
| 112 | return Err("Event was not stored in relay (possibly rejected)".to_string()); | ||
| 113 | } | ||
| 114 | |||
| 115 | // Verify it's the same event | ||
| 116 | let stored_event = events.iter() | ||
| 117 | .find(|e| e.id == event_id) | ||
| 118 | .ok_or("Stored event ID doesn't match sent event")?; | ||
| 119 | |||
| 120 | // Verify key tags are present | ||
| 121 | let has_clone_tag = stored_event.tags.iter() | ||
| 122 | .any(|t| { | ||
| 123 | t.kind() == TagKind::Custom("clone".into()) && | ||
| 124 | t.content().map(|c| c.contains(&http_url)).unwrap_or(false) | ||
| 125 | }); | ||
| 126 | |||
| 127 | let has_relays_tag = stored_event.tags.iter() | ||
| 128 | .any(|t| { | ||
| 129 | t.kind() == TagKind::Custom("relays".into()) && | ||
| 130 | t.content() == Some(&relay_url) | ||
| 131 | }); | ||
| 132 | |||
| 133 | if !has_clone_tag { | ||
| 134 | return Err(format!("Stored event missing clone tag with service URL ({})", http_url)); | ||
| 135 | } | ||
| 136 | |||
| 137 | if !has_relays_tag { | ||
| 138 | return Err(format!("Stored event missing relays tag with service URL ({})", relay_url)); | ||
| 139 | } | ||
| 140 | |||
| 141 | Ok(()) | ||
| 81 | }) | 142 | }) |
| 82 | .await | 143 | .await |
| 83 | } | 144 | } |
| @@ -564,7 +625,7 @@ mod tests { | |||
| 564 | #[ignore] // Requires running relay | 625 | #[ignore] // Requires running relay |
| 565 | async fn test_grasp01_nostr_relay_against_relay() { | 626 | async fn test_grasp01_nostr_relay_against_relay() { |
| 566 | let config = AuditConfig::ci(); | 627 | let config = AuditConfig::ci(); |
| 567 | let client = AuditClient::new("ws://localhost:8081", config) | 628 | let client = AuditClient::new("ws://localhost:18081", config) |
| 568 | .await | 629 | .await |
| 569 | .expect("Failed to connect to relay"); | 630 | .expect("Failed to connect to relay"); |
| 570 | 631 | ||
diff --git a/grasp-audit/src/specs/mod.rs b/grasp-audit/src/specs/mod.rs index 451ea1f..834bf9e 100644 --- a/grasp-audit/src/specs/mod.rs +++ b/grasp-audit/src/specs/mod.rs | |||
| @@ -1,5 +1,7 @@ | |||
| 1 | //! Test specifications | 1 | //! Test specifications |
| 2 | 2 | ||
| 3 | pub mod grasp01_nostr_relay; | ||
| 3 | pub mod nip01_smoke; | 4 | pub mod nip01_smoke; |
| 4 | 5 | ||
| 6 | pub use grasp01_nostr_relay::Grasp01NostrRelayTests; | ||
| 5 | pub use nip01_smoke::Nip01SmokeTests; | 7 | pub use nip01_smoke::Nip01SmokeTests; |