From 5dfeb7fbe00a123f69419030256afb166d6575bc Mon Sep 17 00:00:00 2001 From: npub1qyvc0c5kl4gqv2fd97fsk46tu378sqgy35vc83rvgfwne90sel7s0ed67d <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@sprout-oss.stage.blox.sqprod.co> Date: Wed, 24 Jun 2026 19:22:28 -0400 Subject: [PATCH] test(e2e): use private channel for cross-author search isolation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cross-author isolation test was vacuously failing on BOTH backends: it created an `open` channel, which is searchable by anyone by design (get_accessible_channel_ids unions member channels with ALL open channels), so the outsider legitimately found the author's message. Switch the test to create_private_test_channel. In a private channel the creator is bootstrapped as a member (so the author still finds their own post — the non-vacuous control), while the outsider is not a member and gets zero hits. This makes the test a true visibility-widening guard, backend-independent by construction. Adds create_private_test_channel / create_channel_with_visibility helpers; create_test_channel now delegates to the open variant (no behavior change for existing callers). Co-authored-by: Tyler Longwell Signed-off-by: Tyler Longwell --- .../tests/e2e_nostr_interop.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/crates/buzz-test-client/tests/e2e_nostr_interop.rs b/crates/buzz-test-client/tests/e2e_nostr_interop.rs index 9d0c275e8..008e4c1ce 100644 --- a/crates/buzz-test-client/tests/e2e_nostr_interop.rs +++ b/crates/buzz-test-client/tests/e2e_nostr_interop.rs @@ -44,6 +44,17 @@ fn sub_id(name: &str) -> String { /// Create a real channel in the DB via REST so the relay accepts events for it. async fn create_test_channel(keys: &Keys) -> String { + create_channel_with_visibility(keys, "open").await +} + +/// Like `create_test_channel` but creates a `private` (invite-only, non-searchable +/// by non-members) channel. Used by the cross-author search-isolation test, where +/// an *open* channel would be visible to outsiders by design. +async fn create_private_test_channel(keys: &Keys) -> String { + create_channel_with_visibility(keys, "private").await +} + +async fn create_channel_with_visibility(keys: &Keys, visibility: &str) -> String { let client = reqwest::Client::new(); let pubkey_hex = keys.public_key().to_hex(); let channel_uuid = uuid::Uuid::new_v4(); @@ -54,7 +65,7 @@ async fn create_test_channel(keys: &Keys) -> String { Tag::parse(["h", &channel_uuid.to_string()]).unwrap(), Tag::parse(["name", &channel_name]).unwrap(), Tag::parse(["channel_type", "stream"]).unwrap(), - Tag::parse(["visibility", "open"]).unwrap(), + Tag::parse(["visibility", visibility]).unwrap(), ]) .sign_with_keys(keys) .unwrap(); @@ -1107,8 +1118,10 @@ async fn test_nip50_search_cross_author_isolation() { let author = Keys::generate(); let outsider = Keys::generate(); - // Author A owns a private-by-default working channel and posts a token. - let channel = create_test_channel(&author).await; + // Author A owns a PRIVATE (invite-only) working channel and posts a token. + // Must be private: open channels are searchable by anyone by design, so the + // outsider would legitimately find the message and this test would be vacuous. + let channel = create_private_test_channel(&author).await; let unique_token = format!("isolation_{}", uuid::Uuid::new_v4().simple()); let content = format!("secret in A's channel {unique_token}");