Skip to content

Missing grants in generated migration generated with version 2.33.0 and above (db pull --linked) #4068

@ex0ns

Description

@ex0ns

Describe the bug

When generating database migrations, Supabase CLI 2.33.0 output's is very different from previous version:

  • does not include GRANT on the newly created table
  • revoke existing privilege (this is probably wrong and dangerous !)
  • re-create all functions in our database

To Reproduce

supabase db pull  -s public,private --linked

Expected behavior
As of 2.32.0, the generated migration was:

create table "public"."sample_table" (
    "id" bigint generated by default as identity not null,
    "company_id" bigint not null,
    "name" text not null,
    "created_at" timestamp with time zone not null default now()
);

alter table "public"."sample_table" enable row level security;

-- INDEX CREATION
CREATE UNIQUE INDEX sample_table_pkey ON public.sample_table USING btree (id);

-- CONSTRAINTS
alter table "public"."sample_table" add constraint "sample_table_pkey" PRIMARY KEY using index "sample_table_pkey";
alter table "public"."sample_table" add constraint "sample_table_company_id_fkey" FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE not valid;
alter table "public"."sample_table" validate constraint "sample_table_company_id_fkey";

-- PERMISSION GRANTS (✅ Present in 2.32.0)
grant delete on table "public"."sample_table" to "anon";
grant insert on table "public"."sample_table" to "anon";
grant references on table "public"."sample_table" to "anon";
grant select on table "public"."sample_table" to "anon";
grant trigger on table "public"."sample_table" to "anon";
grant truncate on table "public"."sample_table" to "anon";
grant update on table "public"."sample_table" to "anon";

grant delete on table "public"."sample_table" to "authenticated";
grant insert on table "public"."sample_table" to "authenticated";
grant references on table "public"."sample_table" to "authenticated";
grant select on table "public"."sample_table" to "authenticated";
grant trigger on table "public"."sample_table" to "authenticated";
grant truncate on table "public"."sample_table" to "authenticated";
grant update on table "public"."sample_table" to "authenticated";

grant delete on table "public"."sample_table" to "service_role";
grant insert on table "public"."sample_table" to "service_role";
grant references on table "public"."sample_table" to "service_role";
grant select on table "public"."sample_table" to "service_role";
grant trigger on table "public"."sample_table" to "service_role";
grant truncate on table "public"."sample_table" to "service_role";
grant update on table "public"."sample_table" to "service_role";

-- RLS POLICIES
create policy "Users can access sample table"
on "public"."sample_table"
as permissive
for all
to authenticated
using ((( SELECT (((auth.jwt() -> 'app_metadata'::text) ->> 'user_role'::text) = 'admin'::text)) AND (( SELECT private.get_company_for_user() AS get_company_for_user) = company_id)))
with check ((( SELECT (((auth.jwt() -> 'app_metadata'::text) ->> 'user_role'::text) = 'admin'::text)) AND (( SELECT private.get_company_for_user() AS get_company_for_user) = company_id)));

-- TRIGGERS
CREATE TRIGGER handle_updated_at BEFORE UPDATE ON public.sample_table FOR EACH ROW EXECUTE FUNCTION moddatetime('updated_at');

Current results

-- ❌ REVOKES existing permissions (this part is unexpected)
revoke delete on table "public"."existing_table_1" from "anon";
revoke insert on table "public"."existing_table_1" from "anon";
-- ... (many more revoke statements for existing tables)

revoke delete on table "public"."existing_table_2" from "authenticated";
revoke insert on table "public"."existing_table_2" from "authenticated";
-- ... (many more revoke statements for existing tables)

-- NEW TABLE CREATION (same as 2.32.0)
create table "public"."sample_table" (
    "id" bigint generated by default as identity not null,
    "company_id" bigint not null,
    "name" text not null,
    "created_at" timestamp with time zone not null default now()
);

alter table "public"."sample_table" enable row level security;

CREATE UNIQUE INDEX sample_table_pkey ON public.sample_table USING btree (id);
alter table "public"."sample_table" add constraint "sample_table_pkey" PRIMARY KEY using index "sample_table_pkey";
alter table "public"."sample_table" add constraint "sample_table_company_id_fkey" FOREIGN KEY (company_id) REFERENCES companies(id) ON DELETE CASCADE not valid;
alter table "public"."sample_table" validate constraint "sample_table_company_id_fkey";

-- ❌ MISSING: No GRANT statements for the new table

-- RLS POLICIES (present)
create policy "Users can access sample table"
on "public"."sample_table"
as permissive
for all
to authenticated
using ((( SELECT (((auth.jwt() -> 'app_metadata'::text) ->> 'user_role'::text) = 'admin'::text)) AND (( SELECT private.get_company_for_user() AS get_company_for_user) = company_id)))
with check ((( SELECT (((auth.jwt() -> 'app_metadata'::text) ->> 'user_role'::text) = 'admin'::text)) AND (( SELECT private.get_company_for_user() AS get_company_for_user) = company_id)));

-- TRIGGERS (present)
CREATE TRIGGER handle_updated_at BEFORE UPDATE ON public.sample_table FOR EACH ROW EXECUTE FUNCTION moddatetime('updated_at');

-- ALL FUNCTIONS RECREATED
-- Note: 2.33.0 recreates all existing functions, which seems unnecessary
-- CREATE OR REPLACE FUNCTION ... (many functions recreated)

System information

  • Version of OS: OSX 15.6
  • Version of CLI: 2.33.0
  • Versions of services:
   SERVICE IMAGE          | LOCAL                  | LINKED    
  ------------------------|------------------------|-----------
   supabase/postgres      | 15.1.1.25              | 15.1.1.25 
   supabase/gotrue        | v2.178.0               | v2.178.0  
   postgrest/postgrest    | v12.0.2                | v12.0.2   
   supabase/realtime      | v2.41.3                | -         
   supabase/storage-api   | v1.25.9                | -         
   supabase/edge-runtime  | v1.68.0                | -         
   supabase/studio        | 2025.07.21-sha-88dca02 | -         
   supabase/postgres-meta | v0.91.1                | -         
   supabase/logflare      | 1.14.2                 | -         
   supabase/supavisor     | 2.5.7                  | -         

Additional context
I also tried with the latest version of the CLI and it's the same as with 2.33.0. I used this version to narrow down the problem but I can't find anything in v2.32.0...v2.33.0 that could explain that difference.

I also tested on 2.38.2 and it's the same

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions