From 57216c942f171db305135bcb6a4ede2d87e0be8a Mon Sep 17 00:00:00 2001 From: Luke Tornquist Date: Thu, 27 Aug 2026 16:07:00 -0400 Subject: [PATCH] test(db): use canonical channel roster fixtures (#6819) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Fix two PostgreSQL channel-roster test fixtures so they satisfy migration 0032's canonical kind-39002 fence before the channel/membership store extraction moves them. This is a test-only prerequisite in the issue #2 extraction stack. It emits the canonical four-field `p` tags with authoritative roles, keeps the stale-history mutation after insertion, and gives the colliding other-tenant fixture its own matching roster. ## Stack - Exact base: codex/issue-6-finish-replaceable-store at da018405cc83605362125c2d5e5a3f91492431ac ([#6777](https://github.com/block/buzz/pull/6777)) - Exact head: codex/issue-7-roster-test-fixtures at 21d1b265c133292e6707e766cd4204e6a43f08af - Structural tracker: TheSentinel454/buzz#2 - Domain issue: TheSentinel454/buzz#7 - Acceptance: TheSentinel454/buzz#17 and TheSentinel454/buzz#19 - Next: `codex/issue-7-channel-membership-store` ## Why separate The existing ignored tests are red against a freshly migrated current `main`: migration 0032 rejects their legacy two-field roster tags before the assertions run. The extraction PR is intended to be a pure move, so this fixture correction is isolated here rather than mixed into the channel-membership ownership diff. ## Non-goals - No production Rust or SQL changes. - No schema, lock, transaction, timeout, retry, API, or client-visible behavior changes. - No change to migration 0032's canonical roster rules. - No store ownership movement; that remains in the child PR. ## Risk Low and test-only. The main risk is accidentally changing the scenario rather than only its representation. The tests retain the same member counts, stale-versus-complete distinction, tenant collision, signer isolation, and lock-freshness assertions. ## Blox verification Author workstation: `buzz-tornquist-issue-2-store-stack` (`2046520`), native PostgreSQL 17.11. - Red before the change on a freshly migrated database: both focused tests failed with migration 0032's `kind 39002 roster contains an invalid p tag` constraint. - `cargo fmt --all --check`: pass - `git diff --check`: pass - `cargo clippy -p buzz-db --all-targets -- -D warnings`: pass - `channel::tests::large_roster_reconciliation_candidates_respect_snapshot_count_and_signer`: pass - `channel::tests::locked_member_snapshot_blocks_post_capture_membership_mutation`: pass - Cumulative exact-tip PostgreSQL matrix: pass ## Superseded pre-comment restack verification PR #6700 merged before publication completed. This layer was restacked onto current main through the exact parent named above; the final cumulative tip is 2ddcc8a29f95c8c8c9cb87bb6cf59335f2190fae. Cumulative author gates passed: formatting and diff checks; buzz-db and buzz-relay all-target clippy with -D warnings; DB lib 111 passed / 200 ignored; ownership 22/22; observability 1/1; the full isolated PostgreSQL domain matrix; and relay lib 910 passed / 49 ignored. - Workstation: `buzz-tornquist-pr-6819-final-review` (`2057618`), fresh shallow checkout - Base: `ffbeaaf00810aa359ab85818ff4820f92263e45f` - Head: `c60e793eadde79d9eab9f48bbb2ede0ad4831f9b` - Findings: none Reviewed the test-only roster-fixture correction. The affected large-roster and owner fixture events now use canonical four-field `p` tags and preserve the intended roster cardinalities. The distinct other-community fixture remains isolated and the production implementation, SQL, spans, and API are untouched. Verification: format and diff checks passed; `buzz-db --all-targets` clippy passed with `-D warnings`; DB lib tests passed (111 passed, 200 PostgreSQL tests ignored); ownership (1/1) and observability (1/1) guards passed; all 18 channel PostgreSQL tests passed on native PostgreSQL 17 with migrations 1-32 successful. Final worktree was detached at the exact head and clean. Complete evidence archive SHA-256: `da8379f4f0ae3989eb3573162f0f19cbde733400000756ab0f63af3322244d4b`. ## Comment-addressed restack Review follow-up on #6777 removed only the low-value replaceable ownership source test. This PR was restacked onto its rewritten parent; its production patch is unchanged. - Exact base: `da018405cc83605362125c2d5e5a3f91492431ac` - Exact head: `21d1b265c133292e6707e766cd4204e6a43f08af` - Final cumulative tip: `6fa2f104d42c6ba85bdf62e7ccb74ceaf4a84f67` - Per-layer patch-ID and tree audits confirm this PR’s production diff is unchanged from its pre-comment head. - Cumulative Blox gate: formatting and diff checks; strict `buzz-db`/`buzz-relay` Clippy; DB lib 111 passed / 200 ignored; ownership 21/21; observability 1/1; every moved PostgreSQL test; relay lib 910 passed / 49 ignored. - Independent re-review at this exact head: no findings; fresh exact-parent/head Blox review passed fmt/diff, strict `buzz-db` Clippy, DB lib 111 passed / 200 ignored, observability, and all 18 channel PostgreSQL tests; relay compilation was not applicable to this test-only layer. Signed-off-by: tornquist --- crates/buzz-db/src/channel.rs | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/crates/buzz-db/src/channel.rs b/crates/buzz-db/src/channel.rs index 98790e3d62..2bb0af44b3 100644 --- a/crates/buzz-db/src/channel.rs +++ b/crates/buzz-db/src/channel.rs @@ -2434,11 +2434,35 @@ mod tests { let stale_tags: Vec = std::iter::once(serde_json::json!(["d", channel.id.to_string()])) - .chain((0..1_000).map(|n| serde_json::json!(["p", format!("{n:064x}")]))) + .chain(std::iter::once(serde_json::json!([ + "p", + hex::encode(&creator), + "", + "owner" + ]))) + .chain( + (1..1_000).map(|n| serde_json::json!(["p", format!("{n:064x}"), "", "member"])), + ) .collect(); let complete_tags: Vec = std::iter::once(serde_json::json!(["d", channel.id.to_string()])) - .chain((0..1_501).map(|n| serde_json::json!(["p", format!("{n:064x}")]))) + .chain(std::iter::once(serde_json::json!([ + "p", + hex::encode(&creator), + "", + "owner" + ]))) + .chain( + (1..=1_500) + .map(|n| serde_json::json!(["p", format!("{n:064x}"), "", "member"])), + ) + .collect(); + let other_complete_tags: Vec = + std::iter::once(serde_json::json!(["d", channel.id.to_string()])) + .chain( + (0..=1_500) + .map(|n| serde_json::json!(["p", format!("{n:064x}"), "", "member"])), + ) .collect(); // Insert canonical-looking history first, then corrupt the newest row @@ -2517,7 +2541,7 @@ mod tests { .bind(other_community_id) .bind(random_pubkey()) .bind(&relay_pubkey) - .bind(serde_json::Value::Array(complete_tags.clone())) + .bind(serde_json::Value::Array(other_complete_tags)) .bind(vec![0u8; 64]) .bind(channel.id) .bind(channel.id.to_string()) @@ -3102,7 +3126,7 @@ mod tests { let event = nostr::EventBuilder::new(nostr::Kind::Custom(39002), "") .tags(vec![ nostr::Tag::parse(["d", &channel.id.to_string()]).expect("d tag"), - nostr::Tag::parse(["p", &hex::encode(&owner)]).expect("p tag"), + nostr::Tag::parse(["p", &hex::encode(&owner), "", "owner"]).expect("p tag"), ]) .sign_with_keys(&relay_keys) .expect("sign roster");