upleb.uk

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

summaryrefslogtreecommitdiff
path: root/grasp-audit/src/fixtures.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2026-02-12 12:57:44 +0000
committerDanConwayDev <DanConwayDev@protonmail.com>2026-02-12 12:57:44 +0000
commitdcaaa0c44c46f963929ab0baa91f63759ec702dc (patch)
tree1808621ff43eb01acaabe091033672d347bfbf67 /grasp-audit/src/fixtures.rs
parent3fd6ce4149d567c67009b0332ca76c0cd6f51055 (diff)
refactor(grasp-audit): split ValidRepo into Sent/Served, add tolerant purgatory
- Rename ValidRepo to ValidRepoSent (announcement sent, may be in purgatory) - Add ValidRepoServed (announcement queryable after git data pushed) - Add send_event_and_note_purgatory() for tolerant purgatory detection - Update fixtures to use tolerant method instead of strict assertion - Update event_acceptance_policy tests to use ValidRepoServed This enables tests to pass regardless of purgatory implementation status while still having explicit purgatory tests that verify the behavior.
Diffstat (limited to 'grasp-audit/src/fixtures.rs')
-rw-r--r--grasp-audit/src/fixtures.rs139
1 files changed, 81 insertions, 58 deletions
diff --git a/grasp-audit/src/fixtures.rs b/grasp-audit/src/fixtures.rs
index e1a5320..2c53bf0 100644
--- a/grasp-audit/src/fixtures.rs
+++ b/grasp-audit/src/fixtures.rs
@@ -47,7 +47,7 @@
47//! let ctx = TestContext::new(&client); 47//! let ctx = TestContext::new(&client);
48//! 48//!
49//! // Request a fixture - behavior depends on mode 49//! // Request a fixture - behavior depends on mode
50//! let repo = ctx.get_fixture(FixtureKind::ValidRepo).await?; 50//! let repo = ctx.get_fixture(FixtureKind::ValidRepoSent).await?;
51//! # Ok(()) 51//! # Ok(())
52//! # } 52//! # }
53//! ``` 53//! ```
@@ -109,11 +109,11 @@ pub const PR_TEST_COMMIT_HASH: &str = "5d40fb1555a0c28bf4d650515a73aaa54d4d9bfb"
109/// 109///
110/// ## Fixture Dependencies 110/// ## Fixture Dependencies
111/// 111///
112/// Several fixtures depend on `ValidRepo` - they all use the SAME repo_id 112/// Several fixtures depend on `ValidRepoSent` - they all use the SAME repo_id
113/// within a single TestContext instance to ensure proper fixture relationships: 113/// within a single TestContext instance to ensure proper fixture relationships:
114/// - `RepoState` → uses ValidRepo's repo_id 114/// - `RepoState` → uses ValidRepoSent's repo_id
115/// - `MaintainerAnnouncement` + `MaintainerState` → uses ValidRepo's repo_id 115/// - `MaintainerAnnouncement` + `MaintainerState` → uses ValidRepoSent's repo_id
116/// - `RecursiveMaintainerRepoAndState` → uses ValidRepo's repo_id 116/// - `RecursiveMaintainerRepoAndState` → uses ValidRepoSent's repo_id
117/// 117///
118/// This enables testing recursive maintainer authorization chains where multiple 118/// This enables testing recursive maintainer authorization chains where multiple
119/// parties publish announcements and state events for the same repository. 119/// parties publish announcements and state events for the same repository.
@@ -122,10 +122,16 @@ pub enum FixtureKind {
122 /// Basic repository announcement (kind 30617) 122 /// Basic repository announcement (kind 30617)
123 /// - Signed by owner keys (`client.keys()`) 123 /// - Signed by owner keys (`client.keys()`)
124 /// - Lists `client.maintainer_pubkey_hex()` in maintainers tag 124 /// - Lists `client.maintainer_pubkey_hex()` in maintainers tag
125 ValidRepo, 125 ValidRepoSent,
126
127 /// Repository announcement that is queryable from the relay (served, not in purgatory)
128 /// - Depends on OwnerStateDataPushed (git data pushed, announcement promoted)
129 /// - Returns the same event as ValidRepoSent (now queryable)
130 /// - Use this for tests that need to query the announcement back from the relay
131 ValidRepoServed,
126 132
127 /// Repository with one issue (kind 1621) 133 /// Repository with one issue (kind 1621)
128 /// - Requires ValidRepo (reuses same repo_id) 134 /// - Requires ValidRepoSent (reuses same repo_id)
129 RepoWithIssue, 135 RepoWithIssue,
130 136
131 /// Repository with issue and comment (kind 1111) 137 /// Repository with issue and comment (kind 1111)
@@ -133,14 +139,14 @@ pub enum FixtureKind {
133 RepoWithComment, 139 RepoWithComment,
134 140
135 /// Repository state announcement (kind 30618) for owner 141 /// Repository state announcement (kind 30618) for owner
136 /// - Requires ValidRepo (uses same repo_id) 142 /// - Requires ValidRepoSent (uses same repo_id)
137 /// - Signed by owner keys (`client.keys()`) 143 /// - Signed by owner keys (`client.keys()`)
138 /// - Points to DETERMINISTIC_COMMIT_HASH 144 /// - Points to DETERMINISTIC_COMMIT_HASH
139 /// - Timestamp: 10 seconds in the past 145 /// - Timestamp: 10 seconds in the past
140 RepoState, 146 RepoState,
141 147
142 /// PR (Pull Request) event for the SAME repo_id as ValidRepo 148 /// PR (Pull Request) event for the SAME repo_id as ValidRepoSent
143 /// - Requires ValidRepo (uses same repo_id) 149 /// - Requires ValidRepoSent (uses same repo_id)
144 /// - Signed by `client.pr_author_keys()` 150 /// - Signed by `client.pr_author_keys()`
145 /// - Kind 1618 (NIP-34 PR) 151 /// - Kind 1618 (NIP-34 PR)
146 /// - Includes `a` tag referencing the repo 152 /// - Includes `a` tag referencing the repo
@@ -153,7 +159,7 @@ pub enum FixtureKind {
153 /// This is a "Generated" stage fixture - the event is created but not published. 159 /// This is a "Generated" stage fixture - the event is created but not published.
154 /// Useful for tests that need the PR event ID before the event exists on the relay. 160 /// Useful for tests that need the PR event ID before the event exists on the relay.
155 /// 161 ///
156 /// - Requires ValidRepo (uses same repo_id) 162 /// - Requires ValidRepoSent (uses same repo_id)
157 /// - Signed by `client.pr_author_keys()` 163 /// - Signed by `client.pr_author_keys()`
158 /// - Kind 1618 (NIP-34 PR) 164 /// - Kind 1618 (NIP-34 PR)
159 /// - Includes `c` tag pointing to PR_TEST_COMMIT_HASH 165 /// - Includes `c` tag pointing to PR_TEST_COMMIT_HASH
@@ -187,7 +193,7 @@ pub enum FixtureKind {
187 /// (the "wrong" commit), but no PR event exists yet on the relay. 193 /// (the "wrong" commit), but no PR event exists yet on the relay.
188 /// 194 ///
189 /// Server state after this fixture: 195 /// Server state after this fixture:
190 /// - ValidRepo announcement on relay 196 /// - ValidRepoSent announcement on relay
191 /// - refs/nostr/<pr-event-id> exists on git server with wrong commit 197 /// - refs/nostr/<pr-event-id> exists on git server with wrong commit
192 /// - PR event is NOT on relay (but returned for tests to publish later) 198 /// - PR event is NOT on relay (but returned for tests to publish later)
193 /// 199 ///
@@ -203,7 +209,7 @@ pub enum FixtureKind {
203 /// then the PR event was published (which may trigger cleanup). 209 /// then the PR event was published (which may trigger cleanup).
204 /// 210 ///
205 /// Server state after this fixture: 211 /// Server state after this fixture:
206 /// - ValidRepo announcement on relay 212 /// - ValidRepoSent announcement on relay
207 /// - PR event is on relay 213 /// - PR event is on relay
208 /// - refs/nostr/<pr-event-id> may have been cleaned up (that's what tests verify) 214 /// - refs/nostr/<pr-event-id> may have been cleaned up (that's what tests verify)
209 /// 215 ///
@@ -221,7 +227,7 @@ pub enum FixtureKind {
221 /// 4. **DataPushed**: Clones repo, creates deterministic commit, pushes to relay 227 /// 4. **DataPushed**: Clones repo, creates deterministic commit, pushes to relay
222 /// 5. **Verified**: Confirms event is served by relay 228 /// 5. **Verified**: Confirms event is served by relay
223 /// 229 ///
224 /// - Requires ValidRepo (uses same repo_id) 230 /// - Requires ValidRepoSent (uses same repo_id)
225 /// - State event signed by owner keys (`client.keys()`) 231 /// - State event signed by owner keys (`client.keys()`)
226 /// - Points to DETERMINISTIC_COMMIT_HASH 232 /// - Points to DETERMINISTIC_COMMIT_HASH
227 /// - Git push verified to succeed (state matches pushed commit) 233 /// - Git push verified to succeed (state matches pushed commit)
@@ -252,7 +258,7 @@ pub enum FixtureKind {
252 /// not the owner's announcement, so this tests the recursive maintainer traversal. 258 /// not the owner's announcement, so this tests the recursive maintainer traversal.
253 /// 259 ///
254 /// This fixture represents the complete flow for testing recursive maintainer push authorization: 260 /// This fixture represents the complete flow for testing recursive maintainer push authorization:
255 /// 1. **Generated**: (MaintainerStateDataPushed dependency includes ValidRepo + OwnerStateDataPushed) 261 /// 1. **Generated**: (MaintainerStateDataPushed dependency includes ValidRepoSent + OwnerStateDataPushed)
256 /// Creates MaintainerAnnouncement + RecursiveMaintainerState 262 /// Creates MaintainerAnnouncement + RecursiveMaintainerState
257 /// 2. **Sent**: Sends events to relay (returns OK, accepted but 'purgatory:...' message) 263 /// 2. **Sent**: Sends events to relay (returns OK, accepted but 'purgatory:...' message)
258 /// 3. **Verify Not Served**: Confirms event is not served by relays 264 /// 3. **Verify Not Served**: Confirms event is not served by relays
@@ -276,16 +282,19 @@ impl FixtureKind {
276 pub fn dependencies(&self) -> Vec<FixtureKind> { 282 pub fn dependencies(&self) -> Vec<FixtureKind> {
277 match self { 283 match self {
278 // Base fixtures - no dependencies 284 // Base fixtures - no dependencies
279 Self::ValidRepo => vec![], 285 Self::ValidRepoSent => vec![],
286
287 // ValidRepoServed depends on OwnerStateDataPushed (announcement promoted after git push)
288 Self::ValidRepoServed => vec![Self::OwnerStateDataPushed],
280 289
281 // Fixtures that depend on ValidRepo 290 // Fixtures that depend on ValidRepoServed (need queryable announcement)
282 Self::RepoWithIssue => vec![Self::ValidRepo], 291 Self::RepoWithIssue => vec![Self::ValidRepoServed],
283 Self::RepoState => vec![Self::ValidRepo], 292 Self::RepoState => vec![Self::ValidRepoSent],
284 Self::PREvent => vec![Self::ValidRepo], 293 Self::PREvent => vec![Self::ValidRepoSent],
285 Self::PREventGenerated => vec![Self::ValidRepo], 294 Self::PREventGenerated => vec![Self::ValidRepoSent],
286 Self::PRWrongCommitPushedBeforeEvent => vec![Self::PREventGenerated], 295 Self::PRWrongCommitPushedBeforeEvent => vec![Self::PREventGenerated],
287 Self::PREventSentAfterWrongPush => vec![Self::PRWrongCommitPushedBeforeEvent], 296 Self::PREventSentAfterWrongPush => vec![Self::PRWrongCommitPushedBeforeEvent],
288 Self::OwnerStateDataPushed => vec![Self::ValidRepo], 297 Self::OwnerStateDataPushed => vec![Self::ValidRepoSent],
289 298
290 // Fixtures that depend on RepoWithIssue 299 // Fixtures that depend on RepoWithIssue
291 Self::RepoWithComment => vec![Self::RepoWithIssue], 300 Self::RepoWithComment => vec![Self::RepoWithIssue],
@@ -323,6 +332,8 @@ impl FixtureKind {
323 Self::PREventSentAfterWrongPush => true, 332 Self::PREventSentAfterWrongPush => true,
324 // HeadSetToDevelopBranch sends its state event internally 333 // HeadSetToDevelopBranch sends its state event internally
325 Self::HeadSetToDevelopBranch => true, 334 Self::HeadSetToDevelopBranch => true,
335 // ValidRepoServed doesn't send anything itself, just returns cached event
336 Self::ValidRepoServed => true,
326 // All other fixtures return a single event for the caller to send 337 // All other fixtures return a single event for the caller to send
327 _ => false, 338 _ => false,
328 } 339 }
@@ -373,7 +384,7 @@ impl From<AuditMode> for ContextMode {
373/// let ctx = TestContext::new(&client); 384/// let ctx = TestContext::new(&client);
374/// 385///
375/// // Get a repository fixture - will be reused by subsequent TestContexts 386/// // Get a repository fixture - will be reused by subsequent TestContexts
376/// let repo = ctx.get_fixture(FixtureKind::ValidRepo).await?; 387/// let repo = ctx.get_fixture(FixtureKind::ValidRepoSent).await?;
377/// 388///
378/// // For cargo test (isolated fixtures) 389/// // For cargo test (isolated fixtures)
379/// let config = AuditConfig::isolated(); 390/// let config = AuditConfig::isolated();
@@ -381,7 +392,7 @@ impl From<AuditMode> for ContextMode {
381/// let ctx = TestContext::new(&client); 392/// let ctx = TestContext::new(&client);
382/// 393///
383/// // Get a repository fixture - fresh for this TestContext only 394/// // Get a repository fixture - fresh for this TestContext only
384/// let repo = ctx.get_fixture(FixtureKind::ValidRepo).await?; 395/// let repo = ctx.get_fixture(FixtureKind::ValidRepoSent).await?;
385/// # Ok(()) 396/// # Ok(())
386/// # } 397/// # }
387/// ``` 398/// ```
@@ -436,7 +447,7 @@ impl<'a> TestContext<'a> {
436 /// ```no_run 447 /// ```no_run
437 /// # use grasp_audit::*; 448 /// # use grasp_audit::*;
438 /// # async fn example(ctx: &TestContext<'_>) -> anyhow::Result<()> { 449 /// # async fn example(ctx: &TestContext<'_>) -> anyhow::Result<()> {
439 /// let repo = ctx.get_fixture(FixtureKind::ValidRepo).await?; 450 /// let repo = ctx.get_fixture(FixtureKind::ValidRepoSent).await?;
440 /// # Ok(()) 451 /// # Ok(())
441 /// # } 452 /// # }
442 /// ``` 453 /// ```
@@ -517,7 +528,7 @@ impl<'a> TestContext<'a> {
517 /// ```no_run 528 /// ```no_run
518 /// # use grasp_audit::*; 529 /// # use grasp_audit::*;
519 /// # async fn example(ctx: &TestContext<'_>) -> anyhow::Result<()> { 530 /// # async fn example(ctx: &TestContext<'_>) -> anyhow::Result<()> {
520 /// // This ensures ValidRepo exists first, then creates RepoState 531 /// // This ensures ValidRepoSent exists first, then creates RepoState
521 /// let state = ctx.ensure_fixture(FixtureKind::RepoState).await?; 532 /// let state = ctx.ensure_fixture(FixtureKind::RepoState).await?;
522 /// # Ok(()) 533 /// # Ok(())
523 /// # } 534 /// # }
@@ -625,10 +636,10 @@ impl<'a> TestContext<'a> {
625 /// already-cached dependencies. 636 /// already-cached dependencies.
626 async fn build_fixture_inner(&self, kind: FixtureKind) -> Result<Event> { 637 async fn build_fixture_inner(&self, kind: FixtureKind) -> Result<Event> {
627 match kind { 638 match kind {
628 FixtureKind::ValidRepo => { 639 FixtureKind::ValidRepoSent => {
629 // ValidRepo has no dependencies - create a new repo announcement 640 // ValidRepoSent has no dependencies - create a new repo announcement
630 let test_name = format!( 641 let test_name = format!(
631 "fixture-ValidRepo-{}", 642 "fixture-ValidRepoSent-{}",
632 &uuid::Uuid::new_v4().to_string()[..8] 643 &uuid::Uuid::new_v4().to_string()[..8]
633 ); 644 );
634 645
@@ -638,9 +649,15 @@ impl<'a> TestContext<'a> {
638 .with_context(|| format!("create_repo_announcement failed for {}", test_name)) 649 .with_context(|| format!("create_repo_announcement failed for {}", test_name))
639 } 650 }
640 651
652 FixtureKind::ValidRepoServed => {
653 // OwnerStateDataPushed is already ensured as a dependency.
654 // The announcement is now promoted (served). Return the cached ValidRepoSent event.
655 self.get_cached_dependency(FixtureKind::ValidRepoSent)
656 }
657
641 FixtureKind::RepoWithIssue => { 658 FixtureKind::RepoWithIssue => {
642 // ValidRepo is ensured by ensure_fixture before this is called 659 // ValidRepoServed is ensured by ensure_fixture before this is called
643 let repo = self.get_cached_dependency(FixtureKind::ValidRepo)?; 660 let repo = self.get_cached_dependency(FixtureKind::ValidRepoServed)?;
644 661
645 // Build issue referencing it - caller will send it 662 // Build issue referencing it - caller will send it
646 self.client 663 self.client
@@ -658,8 +675,8 @@ impl<'a> TestContext<'a> {
658 FixtureKind::RepoState => { 675 FixtureKind::RepoState => {
659 use nostr_sdk::prelude::*; 676 use nostr_sdk::prelude::*;
660 677
661 // ValidRepo is ensured by ensure_fixture before this is called 678 // ValidRepoSent is ensured by ensure_fixture before this is called
662 let repo = self.get_cached_dependency(FixtureKind::ValidRepo)?; 679 let repo = self.get_cached_dependency(FixtureKind::ValidRepoSent)?;
663 680
664 // Extract repo_id from repo announcement 681 // Extract repo_id from repo announcement
665 let repo_id = repo 682 let repo_id = repo
@@ -695,15 +712,15 @@ impl<'a> TestContext<'a> {
695 FixtureKind::PREvent => { 712 FixtureKind::PREvent => {
696 use nostr_sdk::prelude::*; 713 use nostr_sdk::prelude::*;
697 714
698 // ValidRepo is ensured by ensure_fixture before this is called 715 // ValidRepoSent is ensured by ensure_fixture before this is called
699 let repo = self.get_cached_dependency(FixtureKind::ValidRepo)?; 716 let repo = self.get_cached_dependency(FixtureKind::ValidRepoSent)?;
700 717
701 let repo_id = repo 718 let repo_id = repo
702 .tags 719 .tags
703 .iter() 720 .iter()
704 .find(|t| t.kind() == TagKind::d()) 721 .find(|t| t.kind() == TagKind::d())
705 .and_then(|t| t.content()) 722 .and_then(|t| t.content())
706 .ok_or_else(|| anyhow::anyhow!("Missing repo_id in ValidRepo fixture"))? 723 .ok_or_else(|| anyhow::anyhow!("Missing repo_id in ValidRepoSent fixture"))?
707 .to_string(); 724 .to_string();
708 725
709 // Create PR event 1 second in the past 726 // Create PR event 1 second in the past
@@ -738,15 +755,15 @@ impl<'a> TestContext<'a> {
738 // This fixture is for "Generated" stage only 755 // This fixture is for "Generated" stage only
739 use nostr_sdk::prelude::*; 756 use nostr_sdk::prelude::*;
740 757
741 // ValidRepo is ensured by ensure_fixture before this is called 758 // ValidRepoSent is ensured by ensure_fixture before this is called
742 let repo = self.get_cached_dependency(FixtureKind::ValidRepo)?; 759 let repo = self.get_cached_dependency(FixtureKind::ValidRepoSent)?;
743 760
744 let repo_id = repo 761 let repo_id = repo
745 .tags 762 .tags
746 .iter() 763 .iter()
747 .find(|t| t.kind() == TagKind::d()) 764 .find(|t| t.kind() == TagKind::d())
748 .and_then(|t| t.content()) 765 .and_then(|t| t.content())
749 .ok_or_else(|| anyhow::anyhow!("Missing repo_id in ValidRepo fixture"))? 766 .ok_or_else(|| anyhow::anyhow!("Missing repo_id in ValidRepoSent fixture"))?
750 .to_string(); 767 .to_string();
751 768
752 // Create PR event 1 second in the past 769 // Create PR event 1 second in the past
@@ -873,9 +890,9 @@ impl<'a> TestContext<'a> {
873 use nostr_sdk::prelude::*; 890 use nostr_sdk::prelude::*;
874 891
875 // ============================================================ 892 // ============================================================
876 // Stage 1: ValidRepo is ensured by ensure_fixture before this is called 893 // Stage 1: ValidRepoSent is ensured by ensure_fixture before this is called
877 // ============================================================ 894 // ============================================================
878 let repo = self.get_cached_dependency(FixtureKind::ValidRepo)?; 895 let repo = self.get_cached_dependency(FixtureKind::ValidRepoSent)?;
879 let repo_id = self.extract_repo_id(&repo)?; 896 let repo_id = self.extract_repo_id(&repo)?;
880 897
881 // Build state event 898 // Build state event
@@ -901,9 +918,11 @@ impl<'a> TestContext<'a> {
901 // ============================================================ 918 // ============================================================
902 // Stage 2 & 3: Send to Relay, get Accepted response and Verify its Not Served 919 // Stage 2 & 3: Send to Relay, get Accepted response and Verify its Not Served
903 // ============================================================ 920 // ============================================================
904 self.client 921 let (_, _in_purgatory) = self
905 .send_event_expect_purgatory_not_served(state_event.clone()) 922 .client
923 .send_event_and_note_purgatory(state_event.clone())
906 .await?; 924 .await?;
925 // Note: We don't fail if purgatory wasn't observed - the fixture proceeds regardless
907 926
908 // ============================================================ 927 // ============================================================
909 // Stage 4: DataPushed - Clone repo, create commit, push 928 // Stage 4: DataPushed - Clone repo, create commit, push
@@ -1048,8 +1067,8 @@ impl<'a> TestContext<'a> {
1048 // Extract repo_id from owner's state event (same d-tag structure) 1067 // Extract repo_id from owner's state event (same d-tag structure)
1049 let repo_id = self.extract_repo_id(&owner_state)?; 1068 let repo_id = self.extract_repo_id(&owner_state)?;
1050 1069
1051 // Get the repo (ValidRepo, also cached) for the owner's npub 1070 // Get the repo (ValidRepoSent, also cached) for the owner's npub
1052 let repo = self.get_cached_dependency(FixtureKind::ValidRepo)?; 1071 let repo = self.get_cached_dependency(FixtureKind::ValidRepoSent)?;
1053 1072
1054 // Build maintainer's state event (state event ONLY - no announcement) 1073 // Build maintainer's state event (state event ONLY - no announcement)
1055 let base_time = Timestamp::now().as_secs(); 1074 let base_time = Timestamp::now().as_secs();
@@ -1074,9 +1093,11 @@ impl<'a> TestContext<'a> {
1074 // ============================================================ 1093 // ============================================================
1075 // Stage 2 & 3: Send to Relay, get Accepted response and Verify its Not Served 1094 // Stage 2 & 3: Send to Relay, get Accepted response and Verify its Not Served
1076 // ============================================================ 1095 // ============================================================
1077 self.client 1096 let (_, _in_purgatory) = self
1078 .send_event_expect_purgatory_not_served(maintainer_state_event.clone()) 1097 .client
1098 .send_event_and_note_purgatory(maintainer_state_event.clone())
1079 .await?; 1099 .await?;
1100 // Note: We don't fail if purgatory wasn't observed - the fixture proceeds regardless
1080 1101
1081 // ============================================================ 1102 // ============================================================
1082 // Stage 4: DataPushed - Clone repo, create maintainer commit, push 1103 // Stage 4: DataPushed - Clone repo, create maintainer commit, push
@@ -1194,7 +1215,7 @@ impl<'a> TestContext<'a> {
1194 /// recursive maintainer force-pushes their commit on top. 1215 /// recursive maintainer force-pushes their commit on top.
1195 /// 1216 ///
1196 /// This handles all stages of the fixture: 1217 /// This handles all stages of the fixture:
1197 /// 1. **Generated**: (MaintainerStateDataPushed dependency includes ValidRepo + OwnerStateDataPushed) 1218 /// 1. **Generated**: (MaintainerStateDataPushed dependency includes ValidRepoSent + OwnerStateDataPushed)
1198 /// Creates MaintainerAnnouncement + RecursiveMaintainerState 1219 /// Creates MaintainerAnnouncement + RecursiveMaintainerState
1199 /// 2. **Sent**: Sends events to relay (returns OK, accepted but 'purgatory:...' message) 1220 /// 2. **Sent**: Sends events to relay (returns OK, accepted but 'purgatory:...' message)
1200 /// 3. **Verify Not Served**: Confirms event is not served by relays 1221 /// 3. **Verify Not Served**: Confirms event is not served by relays
@@ -1215,8 +1236,8 @@ impl<'a> TestContext<'a> {
1215 // Extract repo_id from maintainer's state event (same d-tag structure) 1236 // Extract repo_id from maintainer's state event (same d-tag structure)
1216 let repo_id = self.extract_repo_id(&maintainer_state)?; 1237 let repo_id = self.extract_repo_id(&maintainer_state)?;
1217 1238
1218 // Get the repo (ValidRepo, also cached) for the owner's npub 1239 // Get the repo (ValidRepoSent, also cached) for the owner's npub
1219 let repo = self.get_cached_dependency(FixtureKind::ValidRepo)?; 1240 let repo = self.get_cached_dependency(FixtureKind::ValidRepoSent)?;
1220 1241
1221 // ============================================================ 1242 // ============================================================
1222 // Stage 1 (continued): Generate MaintainerAnnouncement and RecursiveMaintainerState 1243 // Stage 1 (continued): Generate MaintainerAnnouncement and RecursiveMaintainerState
@@ -1249,9 +1270,11 @@ impl<'a> TestContext<'a> {
1249 // ============================================================ 1270 // ============================================================
1250 // Stage 2 & 3: Send to Relay, get Accepted response and Verify its Not Served 1271 // Stage 2 & 3: Send to Relay, get Accepted response and Verify its Not Served
1251 // ============================================================ 1272 // ============================================================
1252 self.client 1273 let (_, _in_purgatory) = self
1253 .send_event_expect_purgatory_not_served(recursive_maintainer_state_event.clone()) 1274 .client
1275 .send_event_and_note_purgatory(recursive_maintainer_state_event.clone())
1254 .await?; 1276 .await?;
1277 // Note: We don't fail if purgatory wasn't observed - the fixture proceeds regardless
1255 1278
1256 // ============================================================ 1279 // ============================================================
1257 // Stage 4: DataPushed - Clone repo, create recursive maintainer commit, push 1280 // Stage 4: DataPushed - Clone repo, create recursive maintainer commit, push
@@ -1428,7 +1451,7 @@ impl<'a> TestContext<'a> {
1428 /// 3. A wrong commit is pushed to refs/nostr/<pr-event-id> 1451 /// 3. A wrong commit is pushed to refs/nostr/<pr-event-id>
1429 /// 1452 ///
1430 /// Server state after: 1453 /// Server state after:
1431 /// - ValidRepo announcement on relay 1454 /// - ValidRepoSent announcement on relay
1432 /// - refs/nostr/<pr-event-id> on git server pointing to DETERMINISTIC_COMMIT_HASH (wrong) 1455 /// - refs/nostr/<pr-event-id> on git server pointing to DETERMINISTIC_COMMIT_HASH (wrong)
1433 /// - NO PR event on relay 1456 /// - NO PR event on relay
1434 /// 1457 ///
@@ -1440,8 +1463,8 @@ impl<'a> TestContext<'a> {
1440 let pr_event = self.get_cached_dependency(FixtureKind::PREventGenerated)?; 1463 let pr_event = self.get_cached_dependency(FixtureKind::PREventGenerated)?;
1441 let pr_event_id = pr_event.id.to_hex(); 1464 let pr_event_id = pr_event.id.to_hex();
1442 1465
1443 // Get the ValidRepo to extract repo info 1466 // Get the ValidRepoSent to extract repo info
1444 let repo = self.get_cached_dependency(FixtureKind::ValidRepo)?; 1467 let repo = self.get_cached_dependency(FixtureKind::ValidRepoSent)?;
1445 let repo_id = self.extract_repo_id(&repo)?; 1468 let repo_id = self.extract_repo_id(&repo)?;
1446 1469
1447 // Get relay domain for cloning 1470 // Get relay domain for cloning
@@ -1520,7 +1543,7 @@ impl<'a> TestContext<'a> {
1520 /// 1543 ///
1521 /// This fixture builds on PRWrongCommitPushedBeforeEvent by sending the PR event. 1544 /// This fixture builds on PRWrongCommitPushedBeforeEvent by sending the PR event.
1522 /// After this fixture, the relay has: 1545 /// After this fixture, the relay has:
1523 /// - ValidRepo announcement 1546 /// - ValidRepoSent announcement
1524 /// - PR event 1547 /// - PR event
1525 /// - refs/nostr/<pr-event-id> may have been cleaned up (that's what tests verify) 1548 /// - refs/nostr/<pr-event-id> may have been cleaned up (that's what tests verify)
1526 /// 1549 ///
@@ -2040,10 +2063,10 @@ mod tests {
2040 use std::collections::HashSet; 2063 use std::collections::HashSet;
2041 2064
2042 let mut set = HashSet::new(); 2065 let mut set = HashSet::new();
2043 set.insert(FixtureKind::ValidRepo); 2066 set.insert(FixtureKind::ValidRepoSent);
2044 set.insert(FixtureKind::RepoWithIssue); 2067 set.insert(FixtureKind::RepoWithIssue);
2045 2068
2046 assert!(set.contains(&FixtureKind::ValidRepo)); 2069 assert!(set.contains(&FixtureKind::ValidRepoSent));
2047 assert!(!set.contains(&FixtureKind::RepoWithComment)); 2070 assert!(!set.contains(&FixtureKind::RepoWithComment));
2048 } 2071 }
2049 2072