From 8972dc54031707864f86ae0b6f63b086dcc46cdb Mon Sep 17 00:00:00 2001 From: iamjr15 Date: Fri, 31 Jul 2026 23:58:32 +0530 Subject: [PATCH] fix(db): align supabase-target checks with platform-managed state Two checker corrections surfaced by the first post-contract apply against production, both verified with live probes on production and on a fresh project: - the runtime ACL union resolved object_name to type name (63-byte limit) because the first branch selected relname bare, silently truncating any function signature longer than 63 characters so it could never match the expected set; the six long-signature webhooks functions were falsely flagged. Casting the first branch to text fixes resolution for the whole union. - supautils grants every role that postgres creates back to postgres (grantor supabase_admin) on every Supabase project, including fresh ones (probe-verified). The zero-membership check now exempts exactly that platform-managed membership and still flags everything else. --- scripts/supabase-target/index.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/scripts/supabase-target/index.ts b/scripts/supabase-target/index.ts index 6173247d..3f30d289 100644 --- a/scripts/supabase-target/index.ts +++ b/scripts/supabase-target/index.ts @@ -200,7 +200,20 @@ async function validateRoleMemberships(client: PgClient): Promise { where member.rolname = any($1::text[]) or granted.rolname = any($1::text[])`, [[...RUNTIME_DATABASE_ROLES]], ); - return result.rows.map( + // Supabase's supautils grants every role that `postgres` creates back to + // `postgres` (grantor supabase_admin) so the platform admin can manage it. + // That membership is platform-managed and appears on every project the + // moment the runtime roles are created; only memberships beyond it are + // divergences. + const runtimeRoles: readonly string[] = RUNTIME_DATABASE_ROLES; + const rows = result.rows.filter( + (row) => + !( + stringField(row, "member_role") === "postgres" && + runtimeRoles.includes(stringField(row, "granted_role") ?? "") + ), + ); + return rows.map( (row) => `Runtime role membership ${stringField(row, "granted_role")} -> ${stringField(row, "member_role")} must be revoked.`, ); @@ -391,7 +404,7 @@ async function validateDataApiDefaultAcl(client: PgClient): Promise { function runtimeAclQuery(): string { return `select grantee.rolname as role_name, 'table' as object_kind, - relation.relname as object_name, + relation.relname::text as object_name, (entry).privilege_type as privilege, (entry).is_grantable from pg_class relation join pg_namespace namespace on namespace.oid = relation.relnamespace