---
title: "Supabase 30. októbra: zmena grantov a čo prestane fungovať"
description: "Supabase 30. októbra 2026 prestane na existujúcich projektoch sprístupňovať nové tabuľky v public API. Čo sa pokazí, čo funguje a 4 kontroly, overené lokálne."
url: "https://madsalt.tech/sk/blog/supabase-october-30-grant-change/"
author: "Denys Zaichenko"
language: "sk"
published: 2026-10-26
---

# Supabase 30. októbra: zmena grantov a čo prestane fungovať

TL;DR

Supabase 30. októbra 2026 prestane na každom existujúcom projekte dávať novým tabuľkám v `public` automatické granty pre `anon`, `authenticated` a `service_role`. Tabuľky, ktoré už máte, fungujú ďalej. Každá tabuľka vytvorená po tomto dátume odpovie `supabase-js` aj vášmu secret key chybou `42501 permission denied`, kým jej migrácia nedá grant. Prepnutie som reprodukoval lokálne: nové tabuľky, nové views aj staré tabuľky, ktoré migrácia zmaže a vytvorí znova, zlyhajú; existujúce tabuľky, RPC funkcie a inserty do `serial` fungujú ďalej. Skontrolujte to dvomi SQL dotazmi a jedným grepom nižšie a opravte grantom, RLS a politikou v tej istej migrácii, nikdy nie cez `grant all on all tables`.

Prevádzkujem bezplatný [bezpečnostný checker pre Supabase](https://madsalt.tech/sk/tools/supabase-security-check/), ktorý číta granty na každej sprístupnenej tabuľke, a chcel som presne vidieť, čo táto zmena robí, skôr než na ňu ľudia narazia. Postavil som lokálny stack Supabase, dal mu staré defaulty, prepnutie som aplikoval tak, ako ho opisuje Supabase, a poslal som požiadavku na každý druh objektu, ktorý ma napadol. Tento článok je to, čo prišlo späť, a ako skontrolovať vlastný projekt pred 30.

## Čo sa mení 30. októbra 2026?

Doteraz dostala každá tabuľka vytvorená v schéme `public` cez default privileges Postgresu `select`, `insert`, `update` a `delete` pre `anon`, `authenticated` a `service_role`. Preto bola nová tabuľka dostupná z prehliadača hneď, ako vznikla, chránená RLS alebo nie. [Oznámenie o breaking change](https://supabase.com/changelog/45329-breaking-change-tables-not-exposed-to-data-and-graphql-api-automatically) od Supabase tieto defaulty odoberá v troch krokoch:

| Dátum            | Čo sa stane                                                                          |
| ---------------- | ------------------------------------------------------------------------------------ |
| 28. apríla 2026  | Nové projekty môžu pri vytvorení vypnúť "Automatically expose new tables"            |
| 30. mája 2026    | Nové správanie sa stane predvoleným pre nové projekty, nasadzuje sa niekoľko týždňov |
| 30. októbra 2026 | Nové správanie sa uplatní na všetky existujúce projekty                              |

Na vašom projekte je prepnutie dvojica príkazov, tých istých, ktoré Supabase uvádza pre skoršie prijatie:

```sql
alter default privileges for role postgres in schema public
  revoke select, insert, update, delete on tables from anon, authenticated, service_role;

alter default privileges for role postgres in schema public
  revoke usage, select on sequences from anon, authenticated, service_role;
```

Default privileges platia len pre objekty vytvorené neskôr. Existujúce granty sa nedotknú, preto vaše súčasné tabuľky fungujú ďalej. Čo sa podľa oznámenia nemení: iné schémy (`auth`, `storage`, `realtime`, vaše vlastné), aplikácie komunikujúce s Postgresom priamym pripojením (psql, ORM, server s connection stringom) a samotné RLS. Zmena sa týka Data API: REST, GraphQL a každej klientskej knižnice nad nimi.

## Čo sa pokazí a čo funguje ďalej?

Moje prostredie: Supabase CLI 2.109.1, Postgres 17.6, PostgREST 14.14, 26. októbra 2026. V `config.toml` som nastavil `auto_expose_new_tables = true`, aby som dostal staré defaulty, vytvoril jednu tabuľku s dvoma riadkami, zapnutým RLS a čítacou politikou a potom spustil dva príkazy vyššie. Potom som vytvoril nové objekty a každý som zavolal lokálnym verejným (`anon`) kľúčom a secret (`service_role`) kľúčom, po jednej požiadavke.

![Čo prestane odpovedať po prepnutí 30. októbra. Lokálny Supabase, objekty vytvorené po revoke z changelogu, verejný kľúč, ak nie je uvedené inak. Nová tabuľka s RLS a politikou: create table → politika, bez grantu → 42501, HTTP 401; Tá istá tabuľka so secret key: create table → politika, bez grantu → 42501, HTTP 403; Nový view nad tabuľkou, ktorá ešte funguje: create view → 42501, HTTP 401, bez hintu; Stará tabuľka zmazaná a znova vytvorená migráciou: drop + create table → granty preč → 42501, HTTP 401.](https://madsalt.tech/charts/sk/supabase-october-30-grant-change.svg)

*Moja reprodukcia na lokálnom stacku Supabase (CLI 2.109.1, Postgres 17.6, PostgREST 14.14), 26. októbra 2026.*

![Čo funguje ďalej po prepnutí 30. októbra. Ten istý lokálny stack, ten istý revoke, verejný kľúč. Tabuľka vytvorená pred prepnutím: existujúca tabuľka → granty ostali → 2 riadky, HTTP 200; Nová funkcia volaná cez RPC: create function → execute cez PUBLIC → HTTP 200; Nová serial tabuľka, grant len na select a insert: id serial → sequence má UPDATE → insert, HTTP 201.](https://madsalt.tech/charts/sk/supabase-october-30-grant-change-works.svg)

*Moja reprodukcia na lokálnom stacku Supabase (CLI 2.109.1, Postgres 17.6, PostgREST 14.14), 26. októbra 2026.*

| Objekt, vytvorený po prepnutí, ak nie je uvedené inak                | Kľúč    | Výsledok                                                           |
| -------------------------------------------------------------------- | ------- | ------------------------------------------------------------------ |
| Tabuľka vytvorená pred prepnutím                                     | verejný | HTTP 200, 2 riadky                                                 |
| Nová tabuľka s RLS a politikou `to anon, authenticated`              | verejný | HTTP 401, 42501, hint `GRANT SELECT ON public.new_orders TO anon;` |
| Tá istá nová tabuľka                                                 | secret  | HTTP 403, 42501, hint `… TO service_role;`                         |
| Nový view (`security_invoker`) nad starou tabuľkou                   | verejný | HTTP 401, 42501, `permission denied for view`, hint `null`         |
| Kópia vytvorená cez `create table … (like old_orders including all)` | verejný | HTTP 401, 42501                                                    |
| Stará tabuľka po `drop table` a opätovnom `create table`             | verejný | HTTP 401, 42501                                                    |
| Nová funkcia `public.ping()` cez `/rest/v1/rpc`                      | verejný | HTTP 200                                                           |
| Nová tabuľka s `id serial`, pre `anon` len `select, insert`          | verejný | insert HTTP 201                                                    |

V tejto tabuľke je päť vecí, ktoré stojí za to vedieť pred prepnutím.

**"Existujúce tabuľky si udržia granty" platí, len kým tabuľka existuje.** Migrácia, ktorá tabuľku zmaže a vytvorí znova, kópia cez `create table … (like …)` alebo obnova z dumpu vytvoria novú tabuľku a nová tabuľka nedostane nič. Politika sa vrátila s mojím `create policy`, granty nie. Čokoľvek vo vašom pipeline, čo tabuľky prestavuje namiesto úpravy, zlyhá pri prvom behu po prepnutí.

**Zlyhá aj secret key.** `service_role` obchádza RLS, ale grant stále potrebuje. Takže Edge Function, cron úloha alebo webhook handler, ktorý zapisuje do novej tabuľky, zlyhá s 403, nielen prehliadač. Hint uvádza `service_role`, podľa čoho to rozoznáte.

**Views nedajú hint.** Pri tabuľkách PostgREST vráti presný `GRANT`, ktorý potrebujete. Pri mojom novom view bol hint `null` a správa znela `permission denied for view v_old_orders`. AI nástroj, ktorý opravuje 42501 podľa hintu, tu nemá čo skopírovať; grant je `grant select on public.v_old_orders to authenticated;` a view si má ponechať `security_invoker = true`, aby sa RLS tabuľky ďalej uplatňovalo.

**Funkcie nie sú súčasťou tejto zmeny.** Dva príkazy sa týkajú tabuliek a sekvencií. Moja nová funkcia ostala volateľná pre `anon`, `authenticated` aj `service_role`, lebo Postgres dáva `execute` na každú novú funkciu role `PUBLIC` a revoke na úrovni schémy ho nedokáže odobrať, ako vysvetľuje [príručka Supabase o zabezpečení API](https://supabase.com/docs/guides/api/securing-your-api). RPC volania fungujú aj po 30. októbri; zároveň to znamená, že nová funkcia `security definer` je volateľná vaším verejným kľúčom hneď, ako vznikne.

**Inserty do `serial` fungovali aj bez grantu na sekvenciu.** Veľa rád hovorí, že `serial` id po prepnutí potrebuje `grant usage on sequence … to authenticated`. V mojom behu insert prešiel bez neho: revoke odoberá `usage` a `select` na nových sekvenciách, ale `update` ostáva a `update` na `nextval` stačí. Ak odoberiete všetky default privileges na sekvenciách, ako robí úplný revoke v príručke o zabezpečení API, grant na `usage` potrebujete. Identity stĺpec (`generated by default as identity`) nepotrebuje nič v oboch prípadoch.

Ešte jedna vec, ktorú revoke necháva: nová tabuľka stále prišla s `TRUNCATE`, `REFERENCES` a `TRIGGER` pre všetky tri roly a na Postgrese 17 defaulty obsahujú aj `MAINTAIN`. Na `TRUNCATE` sa nevzťahuje žiadna politika RLS. Písal som o tom v [poznámke o 42501](https://madsalt.tech/sk/notes/supabase-42501-permission-denied/).

## Kde na to narazíte pred 30. októbrom

Prepnutie na vašom hostovanom projekte je 30., ale tri miesta sa už správajú ako po ňom.

**`supabase db reset` na aktuálnom CLI.** CLI v2.102.0 pridalo do `config.toml` kľúč `[api] auto_expose_new_tables`. Na 2.109.1 s vynechaným kľúčom mal môj čerstvý stack už nové defaulty: tabuľky dostali len `MAINTAIN`, `REFERENCES`, `TRIGGER` a `TRUNCATE`, sekvencie len `UPDATE`. Nastavenie na `true` vráti staré granty a vypíše `api.auto_expose_new_tables is deprecated and will be removed on 2026-10-30`. Ak vám teda lokálne tabuľky po resete stále fungujú, skontrolujte najprv tento kľúč. Je to aj najlacnejšie miesto na test: odstráňte ho, urobte reset, spustite aplikáciu.

**Preview branche a projekty vytvorené od 30. mája.** Prehrávajú vaše migrácie na nových defaultoch. Každá tabuľka, ktorej migrácia nemá `grant`, je tam už nedostupná. V [diskusii na GitHube](https://github.com/orgs/supabase/discussions/45329) ľudia s jedným projektom na zákazníka hlásia presne toto: bežiace projekty sú v poriadku, každé nové nasadenie z rovnakých migrácií je rozbité.

**Baseline migrácia, ktorá vráti starý default.** Komentujúci v tej istej diskusii upozorňuje, že prvá migrácia vytvorená cez `supabase db pull` môže obsahovať `alter default privileges … grant all on tables to anon, authenticated, service_role`. Spustil som ten príkaz po prepnutí: ďalšia tabuľka, ktorú som vytvoril, bola znova dostupná, HTTP 200. Lokálne to problém skryje. Na hostovanom projekte potichu zruší zmenu a každá budúca tabuľka je znova otvorená verejnému kľúču, s RLS či bez. Prehľadajte svoje migrácie na `alter default privileges` a prečítajte si každý nález.

## Ako skontrolovať projekt pred 30. októbrom

Štyri kontroly, od najrýchlejšej po najdôkladnejšiu. Prvé dve bežia v SQL Editore hostovaného projektu.

### 1. Prepol sa už váš projekt?

Toto je dotaz z príručky Supabase o zabezpečení API. Vypíše, čo dostanú nové objekty vytvorené používateľom `postgres` v `public`:

```sql
select
  case d.defaclobjtype
    when 'r' then 'tables'
    when 'S' then 'sequences'
    when 'f' then 'functions'
  end as object_type,
  a.grantee::regrole as role,
  string_agg(a.privilege_type, ', ' order by a.privilege_type) as privileges
from pg_default_acl d
cross join lateral aclexplode(d.defaclacl) a
where d.defaclrole = 'postgres'::regrole
  and d.defaclnamespace = 'public'::regnamespace
  and a.grantee in ('anon'::regrole, 'authenticated'::regrole, 'service_role'::regrole)
group by 1, 2
order by 1, 2;
```

Ak riadky `tables` obsahujú `SELECT, INSERT, UPDATE, DELETE`, projekt je ešte na starom defaulte a prepne sa 30. Ak ukazujú len `MAINTAIN, REFERENCES, TRIGGER, TRUNCATE` (alebo žiadne riadky), nové tabuľky sú už zatvorené. Vidíte to aj v Dashboarde v nastaveniach Data API, "Automatically expose new tables".

### 2. Ktoré tabuľky majú politiku, ale nemajú grant?

Politika pre rolu, ktorá nemá grant na daný príkaz, sa nikdy nespustí: požiadavka zlyhá pred RLS. Tento dotaz vypíše také dvojice. V mojom laboratóriu našiel novú tabuľku a znova vytvorenú starú a nič iné:

```sql
select p.schemaname || '.' || p.tablename as "table", r.role, p.cmd
from pg_policies p
cross join lateral unnest(case when 'public' = any(p.roles) then array['anon', 'authenticated']::name[] else p.roles end) as r(role)
join pg_class c on c.relname = p.tablename
join pg_namespace n on n.oid = c.relnamespace and n.nspname = p.schemaname
where p.schemaname = 'public'
  and r.role in ('anon', 'authenticated')
  and not has_table_privilege(r.role::text, c.oid,
        case p.cmd when 'ALL' then 'SELECT' else p.cmd end)
order by 1, 2, 3;
```

Spúšťajte ho po každej migrácii, v CI proti čerstvému `db reset` alebo na stagingu. Na zdravom projekte nevráti nič; po 30. je každý riadok tabuľkou, ktorú vaša aplikácia nedosiahne. Kontroluje granty na úrovni tabuľky, takže tabuľka otvorená len grantmi na stĺpce (`grant select (id, name) on …`) sa tu objaví, aj keď sú tie stĺpce čitateľné.

### 3. Ktoré migrácie vytvárajú tabuľku bez grantu?

Databáza ukazuje len tabuľky, ktoré existujú. Migrácia, ktorú ste ešte neaplikovali, je vidieť len vo vašom repozitári. Tento hrubý grep vypíše každé `create table` v `supabase/migrations` bez `grant … on` pre rovnaké meno:

```bash
for t in $(grep -hioE 'create table( if not exists)? +[a-z0-9_."]+' supabase/migrations/*.sql | awk '{print $NF}' | sort -u); do
  grep -qiF "on $t " supabase/migrations/*.sql || grep -qiF "on table $t " supabase/migrations/*.sql || echo "no grant: $t"
done
```

Je to porovnávanie textu, nie parsovanie SQL: grant, ktorý uvádza viac tabuliek v jednom príkaze, alebo tabuľka pomenovaná raz bez schémy a inde so schémou, dá falošný nález. Prečítajte si každý riadok, ktorý vypíše. Tabuľky, ku ktorým pristupuje len serverový kód priamym pripojením, grant vôbec nepotrebujú.

### 4. Prehrajte všetko na nových defaultoch

Odstráňte `auto_expose_new_tables` z `config.toml`, spustite `supabase db reset` a proti tomu spustite aplikáciu alebo jej testy. To je váš projekt po 30., plus čerstvá kópia každej tabuľky, čo je ťažší prípad. Supabase vypisuje dotknuté tabuľky aj v Security Advisor a v Table Editore označuje sprístupnenie cez Data API.

## Ako to opraviť bez otvorenia každej tabuľky

Grant, RLS a politiky napíšte do migrácie, ktorá tabuľku vytvára, a každej role dajte len to, čo aplikácia používa:

```sql
create table public.invoices (
  id bigint generated by default as identity primary key,
  user_id uuid not null default auth.uid(),
  total numeric not null
);

revoke all on table public.invoices from anon, authenticated, service_role;
grant select, insert on table public.invoices to authenticated;
grant select, insert, update, delete on table public.invoices to service_role;

alter table public.invoices enable row level security;

create policy "Owners read their invoices"
on public.invoices for select
to authenticated
using ((select auth.uid()) = user_id);

create policy "Owners add their invoices"
on public.invoices for insert
to authenticated
with check ((select auth.uid()) = user_id);
```

Tento blok som spustil na tom istom lokálnom stacku: prihlásený testovací používateľ vložil riadok a prečítal ho späť (HTTP 201, potom 200), verejný kľúč bez session dostal 42501 a kontrola 2 vyššie tabuľku už nevypísala. Úvodné `revoke all` odstráni `TRUNCATE`, `TRIGGER` a `REFERENCES`, ktoré prichádzajú s novou tabuľkou, a na projekte, ktorý sa ešte neprepol, dáva rovnaký výsledok. Roli `anon` dávajte grant len na dáta určené pre neprihlásených návštevníkov a `service_role` len ak serverový kód používa na tejto tabuľke secret key. Ako do seba zapadajú granty a politiky v celej aplikácii, je v mojom [bezpečnostnom checkliste pre aplikácie z Lovable](https://madsalt.tech/sk/blog/lovable-app-security-checklist/).

Čo nerobiť, keď príde prvé 42501:

- **Nespúšťajte `grant all on all tables in schema public to anon, authenticated`.** Vráti starý default naraz na všetky tabuľky, aj na tie, kde sa RLS nikdy nezapol, a tie potom prečíta každý, kto má váš verejný kľúč. [Poznámka o 42501](https://madsalt.tech/sk/notes/supabase-42501-permission-denied/) ukazuje, prečo je grant prvý zámok a RLS druhý.
- **Nepridávajte späť `alter default privileges … grant`.** Je to rollback celej zmeny.
- **Nevypínajte RLS kvôli "testovaniu" a nedávajte secret key do frontendu.** Secret key obchádza RLS pre každého, kto otvorí váš bundle; rozdiel medzi kľúčmi je v [anon key vs service role key](https://madsalt.tech/sk/blog/supabase-anon-key-vs-service-role-key/).

Ak vaše migrácie píše AI nástroj, pridajte do jeho pokynov jeden riadok: "every new table in public gets explicit grants per role, enable row level security and policies in the same migration; never grant on all tables in schema public". Hint v chybe ho naučí grant, nikdy nie RLS, ktoré k nemu patrí.

## Otázky, ktoré ľudia kladú

**Prestanú mi 30. októbra fungovať existujúce tabuľky?** Nie. Default privileges platia pre objekty vytvorené neskôr a v mojom behu stará tabuľka po prepnutí odpovedala HTTP 200. Výnimkou je tabuľka, ktorú vaše migrácie zmažú a vytvoria znova.

**Musím niečo robiť, ak tabuľky nikdy nevytváram?** 30. nie. Skontrolujte to, až keď nejakú pridáte vy, kolega alebo AI nástroj, a skontrolujte každý pipeline, ktorý vytvára projekty alebo branche z vašich migrácií.

**Týka sa to Edge Functions?** Áno, ak používajú `supabase-js` so secret key na novej tabuľke: `service_role` tiež potrebuje grant. Funkcie, ktoré sa pripájajú k Postgresu priamo, to neovplyvní.

**Týka sa to RPC funkcií, Storage alebo Auth?** V tejto zmene nie. Nové funkcie ostávajú volateľné cez `PUBLIC` a `storage` a `auth` nie sú schéma `public`.

**Môžem prepnúť skôr?** Áno. Dva príkazy na začiatku sú prepnutie; spustite ich najprv na stagingu, potom na produkcii. Existujúce tabuľky si granty ponechajú, takže bežiaca aplikácia nič nezbadá a ďalšia nová tabuľka vám hneď povie, či sú vaše migrácie pripravené.

## Ako to vidí checker

Checker sa pripája len na čítanie a číta granty na každej tabuľke vo vašich sprístupnených schémach: do ktorých tabuliek môže verejný kľúč zapisovať bez politiky, ktoré tabuľky majú vypnuté RLS a ktoré default privileges ešte dávajú každej novej tabuľke `TRUNCATE`, `REFERENCES` alebo `TRIGGER`. Vypíše aj každú politiku, ktorej rola nemá grant na daný príkaz, teda tabuľky, ktoré nájde kontrola 2, okrem tých s vypnutým RLS alebo so stĺpcovými grantmi. Nevidí súbory migrácií, ktoré ste ešte neaplikovali, takže kontrola 3 vyššie ostáva na vás. Ak si nie ste istí práve RLS, [ako testovať Supabase RLS](https://madsalt.tech/sk/blog/how-to-test-supabase-rls/) vás ňou prevedie a [poznámka o sprístupnených schémach](https://madsalt.tech/sk/notes/supabase-exposed-schemas/) pokrýva schémy iné než `public`, ktoré táto zmena nechá na pokoji.
