env | grep '^SUPABASE_' | sed 's/=.*/=<set>/'
SUPABASE_DB_PASSWORD=<set> SUPABASE_DB_URL=<set> SUPABASE_URL=<set> SUPABASE_SERVICE_ROLE_KEY=<set> SUPABASE_PROJECT_REF=<set> SUPABASE_ANON_KEY=<set>
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -Atc "select schemaname, tablename, rowsecurity from pg_tables where schemaname='public' and tablename in ('orgs','org_members','tickets'); select policyname, tablename, cmd, roles, qual, with_check from pg_policies where schemaname='public' and tablename in ('orgs','org_members','tickets') order by tablename,policyname;"public|org_members|f public|orgs|f public|tickets|f
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -P pager=off -c "\d+ public.orgs \d+ public.org_members \d+ public.tickets; select grantee,table_name,privilege_type from information_schema.role_table_grants where table_schema='public' and table_name in ('orgs','org_members','tickets') and grantee in ('anon','authenticated') order by table_name,grantee,privilege_type;" Table "public.orgs"
Column | Type | Collation | Nullable | Default | Storage | Compression | Stats target | Description
--------+------+-----------+----------+-------------------+----------+-------------+--------------+-------------
id | uuid | | not null | gen_random_uuid() | plain | | |
name | text | | not null | | extended | | |
Indexes:
"orgs_pkey" PRIMARY KEY, btree (id)
"orgs_name_key" UNIQUE CONSTRAINT, btree (name)
Referenced by:
TABLE "org_members" CONSTRAINT "org_members_org_id_fkey" FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE CASCADE
TABLE "tickets" CONSTRAINT "tickets_org_id_fkey" FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE CASCADE
Access method: heap
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -P pager=off -c "select policyname, tablename, cmd, roles, qual, with_check from pg_policies where schemaname='public' and tablename in ('orgs','org_members','tickets') order by tablename,policyname;" -c "select grantee,table_name,privilege_type from information_schema.role_table_grants where table_schema='public' and table_name in ('orgs','org_members','tickets') and grantee in ('anon','authenticated') order by table_name,grantee,privilege_type;" -c "select id,name from public.orgs; select org_id, user_id, role from public.org_members;" policyname | tablename | cmd | roles | qual | with_check
------------+-----------+-----+-------+------+------------
(0 rows)
grantee | table_name | privilege_type
---------------+-------------+----------------
anon | org_members | DELETE
anon | org_members | INSERT
anon | org_members | REFERENCES
anon | org_members | SELECT
anon | org_members | TRIGGER
anon | org_members | TRUNCATE
anon | org_members | UPDATE
authenticated | org_members | DELETE
authenticated | org_members | INSERT
authenticated | org_members | REFERENCES
authenticated | org_members | SELECT
authenticated | org_members | TRIGGER
authenticated | org_members | TRUNCATE
authenticated | org_members | UPDATE
anon | orgs | DELETE
anon | orgs | INSERT
anon | orgs | REFERENCES
anon | orgs | SELECT
anon | orgs | TRIGGER
anon | orgs | TRUNCATE
anon | orgs | UPDATE
authenticated | orgs | DELETE
authenticated | orgs | INSERT
authenticated | orgs | REFERENCES
authenticated | orgs | SELECT
authenticated | orgs | TRIGGER
authenticated | orgs | TRUNCATE
authenticated | orgs | UPDATE
anon | tickets | DELETE
anon | tickets | INSERT
anon | tickets | REFERENCES
anon | tickets | SELECT
anon | tickets | TRIGGER
anon | tickets | TRUNCATE
anon | tickets | UPDATE
authenticated | tickets | DELETE
authenticated | tickets | INSERT
authenticated | tickets | REFERENCES
authenticated | tickets | SELECT
authenticated | tickets | TRIGGER
authenticated | tickets | TRUNCATE
authenticated | tickets | UPDATE
(42 rows)
id | name
--------------------------------------+--------
7e70907e-dba8-4240-85c5-14945610a402 | Acme
967dd29a-a3bf-4d44-b61c-b486ac061bef | Globex
(2 rows)
org_id | user_id | role
--------------------------------------+--------------------------------------+--------
7e70907e-dba8-4240-85c5-14945610a402 | beaa0136-9c39-45ea-9642-427e710df06a | admin
7e70907e-dba8-4240-85c5-14945610a402 | 8c50526c-296c-455b-a2d2-023da32f4874 | member
967dd29a-a3bf-4d44-b61c-b486ac061bef | ff928665-16df-40d9-bd9f-b46e20ad7a2e | member
(3 rows)
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 <<'SQL'
create schema if not exists private;
create or replace function private.is_org_member(p_org_id uuid)
returns boolean
language sql
stable
security definer
set search_path = pg_catalog, public
as $$
select exists (
select 1 from public.org_members om
where om.org_id = p_org_id and om.user_id = (select auth.uid())
);
$$;
create or replace function private.is_org_admin(p_org_id uuid)
returns boolean
language sql
stable
security definer
set search_path = pg_catalog, public
as $$
select exists (
select 1 from public.org_members om
where om.org_id = p_org_id and om.user_id = (select auth.uid()) and om.role = 'admin'
);
$$;
revoke all on function private.is_org_member(uuid) from public;
revoke all on function private.is_org_admin(uuid) from public;
grant execute on function private.is_org_member(uuid), private.is_org_admin(uuid) to authenticated;
alter table public.tickets enable row level security;
alter table public.org_members enable row level security;
drop policy if exists tickets_read_member on public.tickets;
drop policy if exists tickets_insert_admin on public.tickets;
drop policy if exists tickets_update_admin on public.tickets;
drop policy if exists tickets_delete_admin on public.tickets;
drop policy if exists org_members_read_member on public.org_members;
create policy tickets_read_member on public.tickets
for select to authenticated
using (private.is_org_member(org_id));
create policy tickets_insert_admin on public.tickets
for insert to authenticated
with check (private.is_org_admin(org_id));
create policy tickets_update_admin on public.tickets
for update to authenticated
using (private.is_org_admin(org_id))
with check (private.is_org_admin(org_id));
create policy tickets_delete_admin on public.tickets
for delete to authenticated
using (private.is_org_admin(org_id));
create policy org_members_read_member on public.org_members
for select to authenticated
using (private.is_org_member(org_id));
SQLCREATE SCHEMA CREATE FUNCTION CREATE FUNCTION REVOKE REVOKE GRANT ALTER TABLE ALTER TABLE DROP POLICY DROP POLICY DROP POLICY DROP POLICY DROP POLICY CREATE POLICY CREATE POLICY CREATE POLICY CREATE POLICY CREATE POLICY
NOTICE: schema "private" already exists, skipping NOTICE: policy "tickets_read_member" for relation "public.tickets" does not exist, skipping NOTICE: policy "tickets_insert_admin" for relation "public.tickets" does not exist, skipping NOTICE: policy "tickets_update_admin" for relation "public.tickets" does not exist, skipping NOTICE: policy "tickets_delete_admin" for relation "public.tickets" does not exist, skipping NOTICE: policy "org_members_read_member" for relation "public.org_members" does not exist, skipping
set -e
base="$SUPABASE_URL"; key="$SUPABASE_ANON_KEY"
login(){ curl -sS "$base/auth/v1/token?grant_type=password" -H "apikey: $key" -H 'Content-Type: application/json' --data "{\"email\":\"$1\",\"password\":\"$2\"}"; }
for spec in 'uma-admin@cari.dev|Passw0rd-uma-11' 'vic-member@cari.dev|Passw0rd-vic-22' 'wen-outsider@cari.dev|Passw0rd-wen-33'; do IFS='|' read e p <<EOF
$spec
EOF
t=$(login "$e" "$p"); echo "$e $(echo "$t" | jq -r '.access_token' | cut -c1-12)"; echo "$t" > "/tmp/${e%%@*}.json"; done
for who in anon uma-admin vic-member wen-outsider; do
if [ "$who" = anon ]; then h="apikey: $key"; else h="apikey: $key"; auth="Authorization: Bearer $(jq -r .access_token /tmp/$who.json)"; fi
echo "== $who tickets"; curl -sS "$base/rest/v1/tickets?select=id,org_id,title" -H "$h" ${auth:+-H "$auth"}; echo
echo "== $who members"; curl -sS "$base/rest/v1/org_members?select=org_id,user_id,role" -H "$h" ${auth:+-H "$auth"}; echo
doneuma-admin@cari.dev eyJhbGciOiJF
vic-member@cari.dev eyJhbGciOiJF
wen-outsider@cari.dev eyJhbGciOiJF
== anon tickets
[]
== anon members
[]
== uma-admin tickets
[{"id":1,"org_id":"7e70907e-dba8-4240-85c5-14945610a402","title":"Fix login"},
{"id":2,"org_id":"7e70907e-dba8-4240-85c5-14945610a402","title":"Update billing"},
{"id":3,"org_id":"7e70907e-dba8-4240-85c5-14945610a402","title":"Rotate keys"}]
== uma-admin members
[{"org_id":"7e70907e-dba8-4240-85c5-14945610a402","user_id":"beaa0136-9c39-45ea-9642-427e710df06a","role":"admin"},
{"org_id":"7e70907e-dba8-4240-85c5-14945610a402","user_id":"8c50526c-296c-455b-a2d2-023da32f4874","role":"member"}]
== vic-member tickets
[{"id":1,"org_id":"7e70907e-dba8-4240-85c5-14945610a402","title":"Fix login"},
{"id":2,"org_id":"7e70907e-dba8-4240-85c5-14945610a402","title":"Update billing"},
{"id":3,"org_id":"7e70907e-dba8-4240-85c5-14945610a402","title":"Rotate keys"}]
== vic-member members
[{"org_id":"7e70907e-dba8-4240-85c5-14945610a402","user_id":"beaa0136-9c39-45ea-9642-427e710df06a","role":"admin"},
{"org_id":"7e70907e-dba8-4240-85c5-14945610a402","user_id":"8c50526c-296c-455b-a2d2-023da32f4874","role":"member"}]
== wen-outsider tickets
[{"id":4,"org_id":"967dd29a-a3bf-4d44-b61c-b486ac061bef","title":"Migrate DNS"},
{"id":5,"org_id":"967dd29a-a3bf-4d44-b61c-b486ac061bef","title":"Renew cert"}]
== wen-outsider members
[{"org_id":"967dd29a-a3bf-4d44-b61c-b486ac061bef","user_id":"ff928665-16df-40d9-bd9f-b46e20ad7a2e","role":"member"}]
set -u
base="$SUPABASE_URL/rest/v1/tickets"; key="$SUPABASE_ANON_KEY"
req(){ who=$1; method=$2; url=$3; data=${4-}; auth=""; [ "$who" != anon ] && auth="-H 'Authorization: Bearer $(jq -r .access_token /tmp/$who.json)'"; eval "curl -sS -o /tmp/out -w '%{http_code}' -X $method '$url' -H 'apikey: $key' $auth -H 'Content-Type: application/json' -H 'Prefer: return=representation,tx=rollback' ${data:+--data '$data'}"; echo " $(cat /tmp/out)"; }
acme=7e70907e-dba8-4240-85c5-14945610a402; globex=967dd29a-a3bf-4d44-b61c-b486ac061bef
printf 'member insert (expect 403): '; req vic-member POST "$base" "{\"org_id\":\"$acme\",\"title\":\"probe\",\"status\":\"open\"}"
printf 'admin insert rollback (expect 201): '; req uma-admin POST "$base" "{\"org_id\":\"$acme\",\"title\":\"probe\",\"status\":\"open\"}"
printf 'member update (expect 403/empty): '; req vic-member PATCH "$base?id=eq.1" '{"title":"probe"}'
printf 'admin update rollback (expect 200): '; req uma-admin PATCH "$base?id=eq.1" '{"title":"probe"}'
printf 'member delete (expect 403/empty): '; req vic-member DELETE "$base?id=eq.1"
# Verify unchanged
curl -sS "$base?id=eq.1&select=title" -H "apikey: $key" -H "Authorization: Bearer $(jq -r .access_token /tmp/uma-admin.json)"member insert (expect 403): 403 {"code":"42501","details":null,"hint":null,"message":"new row violates row-level security policy for table \"tickets\""}
admin insert rollback (expect 201): 201 [{"id":7,"org_id":"7e70907e-dba8-4240-85c5-14945610a402","title":"probe","status":"open"}]
member update (expect 403/empty): 200 []
admin update rollback (expect 200): 200 [{"id":1,"org_id":"7e70907e-dba8-4240-85c5-14945610a402","title":"probe","status":"open"}]
member delete (expect 403/empty): 200 []
[{"title":"probe"}]psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -c "update public.tickets set title='Fix login' where id=1; delete from public.tickets where id=7;" && psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -P pager=off -c "select tablename, rowsecurity from pg_tables where schemaname='public' and tablename in ('org_members','tickets'); select policyname,tablename,cmd,roles,qual,with_check from pg_policies where schemaname='public' and tablename in ('org_members','tickets') order by tablename,policyname;" && curl -sS "$SUPABASE_URL/rest/v1/tickets?select=id,title&order=id" -H "apikey: $SUPABASE_ANON_KEY" -H "Authorization: Bearer $(jq -r .access_token /tmp/uma-admin.json)"UPDATE 1
DELETE 1
tablename | rowsecurity
-------------+-------------
org_members | t
tickets | t
(2 rows)
policyname | tablename | cmd | roles | qual | with_check
-------------------------+-------------+--------+-----------------+-------------------------------+------------------------------
org_members_read_member | org_members | SELECT | {authenticated} | private.is_org_member(org_id) |
tickets_delete_admin | tickets | DELETE | {authenticated} | private.is_org_admin(org_id) |
tickets_insert_admin | tickets | INSERT | {authenticated} | | private.is_org_admin(org_id)
tickets_read_member | tickets | SELECT | {authenticated} | private.is_org_member(org_id) |
tickets_update_admin | tickets | UPDATE | {authenticated} | private.is_org_admin(org_id) | private.is_org_admin(org_id)
(5 rows)
[{"id":1,"title":"Fix login"},
{"id":2,"title":"Update billing"},
{"id":3,"title":"Rotate keys"}]A shell script executed against the live project and asserted on the state the agent left behind. No model judged another model.
Raw transcript · Task definition and verifier · Every attempt