From edb8238f3e0886724611ef8bab8b71cd0c302ff2 Mon Sep 17 00:00:00 2001 From: John Tennant Date: Wed, 2 Sep 2026 16:10:43 -0400 Subject: [PATCH] fix(db): fence Project relation overrides Signed-off-by: John Tennant --- crates/buzz-db/src/runtime/migration.rs | 11 +++++++++ crates/buzz-db/src/runtime/tests.rs | 24 +++++++++++++++++++ ...0045_project_related_channel_overrides.sql | 2 ++ schema/schema.sql | 2 +- 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/crates/buzz-db/src/runtime/migration.rs b/crates/buzz-db/src/runtime/migration.rs index 2d3bdf8d13..3fed18db15 100644 --- a/crates/buzz-db/src/runtime/migration.rs +++ b/crates/buzz-db/src/runtime/migration.rs @@ -706,6 +706,10 @@ mod postgres_tests { .sql .as_str() .contains("CREATE TABLE project_related_channel_overrides")); + assert!(migrations[44] + .sql + .as_str() + .contains("attach_community_write_fence('project_related_channel_overrides')")); assert_eq!(&*migrations[0].description, "initial schema"); assert!(migrations[0] .sql @@ -1822,6 +1826,13 @@ mod postgres_tests { ); } let mut expected_fences = migration.fence_attachments.clone(); + let migration_0045: &str = MIGRATOR + .iter() + .find(|migration| migration.version == 45) + .expect("embedded migration 0045") + .sql + .as_ref(); + expected_fences.extend(surface(migration_0045).fence_attachments); expected_fences.remove("product_feedback"); expected_fences.remove("rate_limit_violations"); assert_eq!( diff --git a/crates/buzz-db/src/runtime/tests.rs b/crates/buzz-db/src/runtime/tests.rs index 3022a15e96..bb83bddd29 100644 --- a/crates/buzz-db/src/runtime/tests.rs +++ b/crates/buzz-db/src/runtime/tests.rs @@ -178,6 +178,30 @@ async fn make_community(pool: &PgPool) -> Uuid { id } +#[tokio::test] +#[ignore = "requires Postgres"] +async fn migration_schema_catalog_includes_project_related_channel_write_fence() { + let db = setup_db().await; + db.validate_deletion_serving_catalog() + .await + .expect("migration schema must fence every scoped serving table"); + + let attached: bool = sqlx::query_scalar( + "SELECT EXISTS ( \ + SELECT 1 FROM pg_trigger trigger \ + JOIN pg_class relation ON relation.oid = trigger.tgrelid \ + JOIN pg_proc procedure ON procedure.oid = trigger.tgfoid \ + WHERE relation.relname = 'project_related_channel_overrides' \ + AND procedure.proname = 'enforce_community_write_fence' \ + AND NOT trigger.tgisinternal \ + )", + ) + .fetch_one(&db.pool) + .await + .expect("inspect Project override write fence"); + assert!(attached); +} + #[tokio::test] #[ignore = "requires Postgres"] async fn migration_schema_database_guard_covers_legacy_writer_and_nip09_deletion() { diff --git a/migrations/0045_project_related_channel_overrides.sql b/migrations/0045_project_related_channel_overrides.sql index 21776648c5..d337d33983 100644 --- a/migrations/0045_project_related_channel_overrides.sql +++ b/migrations/0045_project_related_channel_overrides.sql @@ -11,3 +11,5 @@ CREATE TABLE project_related_channel_overrides ( CONSTRAINT chk_project_related_channel_owner_len CHECK (LENGTH(project_owner) = 32), CONSTRAINT chk_project_related_channel_d_len CHECK (LENGTH(project_d) BETWEEN 1 AND 1024) ); + +SELECT attach_community_write_fence('project_related_channel_overrides'); diff --git a/schema/schema.sql b/schema/schema.sql index e649d5c1ee..7daabfcb08 100644 --- a/schema/schema.sql +++ b/schema/schema.sql @@ -1754,6 +1754,7 @@ SELECT attach_community_write_fence('join_policy_acceptances'); SELECT attach_community_write_fence('moderation_actions'); SELECT attach_community_write_fence('moderation_reports'); SELECT attach_community_write_fence('parameterized_event_watermarks'); +SELECT attach_community_write_fence('project_related_channel_overrides'); SELECT attach_community_write_fence('pubkey_allowlist'); SELECT attach_community_write_fence('push_leases'); SELECT attach_community_write_fence('push_match_queue'); @@ -1907,4 +1908,3 @@ CREATE INDEX idx_relay_operator_audit_target INSERT INTO _operator_global_tables (table_name, reason) VALUES ('relay_operator_audit', 'deployment-global append-only roster mutation audit trail; no community_id intentionally'); -