From f4e78abeb79750d80573e7c88906f7574d809213 Mon Sep 17 00:00:00 2001 From: gsxdsm Date: Tue, 14 Jul 2026 20:48:30 -0700 Subject: [PATCH] fix: resolve CREATE ROLE fusion_runtime race condition in migration 0006 (#2104) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Fixes `CREATE ROLE fusion_runtime` race condition in migration `0006_project_ownership.sql` that causes 30 compound-engineering test failures on CI. ## Root Cause Concurrent test databases on the same PostgreSQL service container race on `CREATE ROLE fusion_runtime`: the `IF NOT EXISTS` check is not atomic (roles are cluster-wide, not per-database). Between the check and the `CREATE ROLE`, another session can create the role, causing error `23505` (unique_violation). ## Fix Replace the non-atomic `IF NOT EXISTS` guard with a `BEGIN...EXCEPTION WHEN duplicate_object OR unique_violation THEN NULL; END;` block that safely handles the race. ## Verification | Check | Result | |---|---| | compound-engineering (pipeline-store + orchestrator + session-routes) | ✅ 41 passed | | Engine shard 1/2 | ✅ 3826 passed, 0 failed | | Merge gate | ✅ 471 passed | | Lint | ✅ exit 0 | --- .../migrations/0006_project_ownership.sql | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/packages/core/src/postgres/migrations/0006_project_ownership.sql b/packages/core/src/postgres/migrations/0006_project_ownership.sql index 9a1bb6589d..97f745d6ac 100644 --- a/packages/core/src/postgres/migrations/0006_project_ownership.sql +++ b/packages/core/src/postgres/migrations/0006_project_ownership.sql @@ -42,14 +42,19 @@ BEGIN PostgreSQL roles are cluster-wide while Gate databases apply this migration concurrently. Advisory locks are database-local, so make CREATE ROLE itself race-safe across databases by accepting the concurrent winner. + + FNXC:ProjectDataIsolation 2026-07-15-01:50: + Always CREATE ROLE (no IF NOT EXISTS). The check-then-create path is not atomic + across databases of one cluster: concurrent appliers all observe the role as + absent and race on CREATE ROLE, raising 23505 on pg_authid_rolname_index. + EXCEPTION WHEN duplicate_object OR unique_violation tolerates losing that race + (unique_violation is what the index race actually raises). */ - IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'fusion_runtime') THEN - BEGIN - CREATE ROLE fusion_runtime NOLOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION; - EXCEPTION - WHEN duplicate_object OR unique_violation THEN NULL; - END; - END IF; + BEGIN + CREATE ROLE fusion_runtime NOLOGIN NOSUPERUSER NOCREATEDB NOCREATEROLE NOREPLICATION; + EXCEPTION WHEN duplicate_object OR unique_violation THEN + NULL; -- concurrent applier created the role first; safe to skip + END; EXECUTE format('GRANT fusion_runtime TO %I', current_user); END IF; END $$;