Skip to content

Commit 8972dc5

Browse files
committed
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.
1 parent 8180a42 commit 8972dc5

1 file changed

Lines changed: 15 additions & 2 deletions

File tree

scripts/supabase-target/index.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,20 @@ async function validateRoleMemberships(client: PgClient): Promise<string[]> {
200200
where member.rolname = any($1::text[]) or granted.rolname = any($1::text[])`,
201201
[[...RUNTIME_DATABASE_ROLES]],
202202
);
203-
return result.rows.map(
203+
// Supabase's supautils grants every role that `postgres` creates back to
204+
// `postgres` (grantor supabase_admin) so the platform admin can manage it.
205+
// That membership is platform-managed and appears on every project the
206+
// moment the runtime roles are created; only memberships beyond it are
207+
// divergences.
208+
const runtimeRoles: readonly string[] = RUNTIME_DATABASE_ROLES;
209+
const rows = result.rows.filter(
210+
(row) =>
211+
!(
212+
stringField(row, "member_role") === "postgres" &&
213+
runtimeRoles.includes(stringField(row, "granted_role") ?? "")
214+
),
215+
);
216+
return rows.map(
204217
(row) =>
205218
`Runtime role membership ${stringField(row, "granted_role")} -> ${stringField(row, "member_role")} must be revoked.`,
206219
);
@@ -391,7 +404,7 @@ async function validateDataApiDefaultAcl(client: PgClient): Promise<string[]> {
391404

392405
function runtimeAclQuery(): string {
393406
return `select grantee.rolname as role_name, 'table' as object_kind,
394-
relation.relname as object_name,
407+
relation.relname::text as object_name,
395408
(entry).privilege_type as privilege, (entry).is_grantable
396409
from pg_class relation
397410
join pg_namespace namespace on namespace.oid = relation.relnamespace

0 commit comments

Comments
 (0)