env | grep -i 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>
which psql curl jq python3 2>&1
/usr/bin/psql /usr/bin/curl /usr/bin/jq /usr/bin/python3
cd /tmp && psql "$SUPABASE_DB_URL" -c "select version();" 2>&1 | head -5
version ------------------------------------------------------------------------------ PostgreSQL 17.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 15.2.0, 64-bit (1 row)
echo "$SUPABASE_URL"; echo "ref=$SUPABASE_PROJECT_REF"
https://<ref>.supabase.co ref=<ref>
psql "$SUPABASE_DB_URL" -c "\d public.orgs" -c "\d public.org_members" -c "\d public.tickets" 2>&1
Table "public.orgs"
Column | Type | Collation | Nullable | Default
--------+------+-----------+----------+-------------------
id | uuid | | not null | gen_random_uuid()
name | text | | not null |
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
Table "public.org_members"
Column | Type | Collation | Nullable | Default
---------+------+-----------+----------+---------
org_id | uuid | | not null |
user_id | uuid | | not null |
role | text | | not null |
Indexes:
"org_members_pkey" PRIMARY KEY, btree (org_id, user_id)
Check constraints:
"org_members_role_check" CHECK (role = ANY (ARRAY['admin'::text, 'member'::text]))
Foreign-key constraints:
"org_members_org_id_fkey" FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE CASCADE
"org_members_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth.users(id) ON DELETE CASCADE
Table "public.tickets"
Column | Type | Collation | Nullable | Default
--------+--------+-----------+----------+----------------------------------
id | bigint | | not null | generated by default as identity
org_id | uuid | | not null |
title | text | | not null |
status | text | | not null | 'open'::text
Indexes:
"tickets_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
"tickets_org_id_fkey" FOREIGN KEY (org_id) REFERENCES orgs(id) ON DELETE CASCADE
psql "$SUPABASE_DB_URL" -c "select relname, relrowsecurity, relforcerowsecurity from pg_class where relnamespace='public'::regnamespace and relkind='r';" -c "select schemaname,tablename,policyname,permissive,roles,cmd,qual,with_check from pg_policies where schemaname='public';" 2>&1
relname | relrowsecurity | relforcerowsecurity -------------+----------------+--------------------- org_members | f | f orgs | f | f tickets | f | f (3 rows) schemaname | tablename | policyname | permissive | roles | cmd | qual | with_check ------------+-----------+------------+------------+-------+-----+------+------------ (0 rows)
psql "$SUPABASE_DB_URL" -c "select o.id,o.name,(select count(*) from tickets t where t.org_id=o.id) tickets from orgs o order by name;" -c "select om.org_id, o.name, u.email, om.role from org_members om join orgs o on o.id=om.org_id join auth.users u on u.id=om.user_id order by o.name, u.email;" 2>&1
id | name | tickets
--------------------------------------+--------+---------
3db5bdf0-e44c-41db-aa7e-98d3319d2656 | Acme | 3
cf0677c8-a880-4ef6-8dd0-a49be09bb513 | Globex | 2
(2 rows)
org_id | name | email | role
--------------------------------------+--------+-----------------------+--------
3db5bdf0-e44c-41db-aa7e-98d3319d2656 | Acme | uma-admin@cari.dev | admin
3db5bdf0-e44c-41db-aa7e-98d3319d2656 | Acme | vic-member@cari.dev | member
cf0677c8-a880-4ef6-8dd0-a49be09bb513 | Globex | wen-outsider@cari.dev | member
(3 rows)
psql "$SUPABASE_DB_URL" -c "select table_name, grantee, string_agg(privilege_type,',' order by privilege_type) from information_schema.role_table_grants where table_schema='public' and grantee in ('anon','authenticated','service_role') group by 1,2 order by 1,2;" 2>&1table_name | grantee | string_agg -------------+---------------+--------------------------------------------------------- org_members | anon | DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE org_members | authenticated | DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE org_members | service_role | DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE orgs | anon | DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE orgs | authenticated | DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE orgs | service_role | DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE tickets | anon | DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE tickets | authenticated | DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE tickets | service_role | DELETE,INSERT,REFERENCES,SELECT,TRIGGER,TRUNCATE,UPDATE (9 rows)
cd /tmp && echo "--- anon tickets ---"; curl -s "$SUPABASE_URL/rest/v1/tickets?select=*" -H "apikey: $SUPABASE_ANON_KEY" | jq -c .; echo "--- anon org_members ---"; curl -s "$SUPABASE_URL/rest/v1/org_members?select=*" -H "apikey: $SUPABASE_ANON_KEY" | jq -c .
--- anon tickets ---
[{"id":1,"org_id":"3db5bdf0-e44c-41db-aa7e-98d3319d2656","title":"Fix login","status":"open"},{"id":2,"org_id":"3db5bdf0-e44c-41db-aa7e-98d3319d2656","title":"Update billing","status":"open"},{"id":3,"org_id":"3db5bdf0-e44c-41db-aa7e-98d3319d2656","title":"Rotate keys","status":"open"},{"id":4,"org_id":"cf0677c8-a880-4ef6-8dd0-a49be09bb513","title":"Migrate DNS","status":"open"},{"id":5,"org_id":"cf0677c8-a880-4ef6-8dd0-a49be09bb513","title":"Renew cert","status":"open"}]
--- anon org_members ---
[{"org_id":"3db5bdf0-e44c-41db-aa7e-98d3319d2656","user_id":"ca5b2325-03e4-4e22-a797-75e7f85b8abe","role":"admin"},{"org_id":"3db5bdf0-e44c-41db-aa7e-98d3319d2656","user_id":"61935ae8-09e6-405b-9e8a-8fc2a5b5c54a","role":"member"},{"org_id":"cf0677c8-a880-4ef6-8dd0-a49be09bb513","user_id":"3e899d11-4ea5-4d53-b15c-7bc37d0dfad1","role":"member"}]
cat > /tmp/rls.sql <<'SQL'
begin;
-- Helper functions: SECURITY DEFINER so they bypass RLS on org_members and
-- avoid infinite policy recursion when used inside org_members policies.
create or replace function public.is_org_member(p_org_id uuid)
returns boolean
language sql
stable
security definer
set search_path = public, pg_temp
as $$
select exists (
select 1 from public.org_members m
where m.org_id = p_org_id
and m.user_id = (select auth.uid())
);
$$;
create or replace function public.is_org_admin(p_org_id uuid)
returns boolean
language sql
stable
security definer
set search_path = public, pg_temp
as $$
select exists (
select 1 from public.org_members m
where m.org_id = p_org_id
and m.user_id = (select auth.uid())
and m.role = 'admin'
);
$$;
revoke all on function public.is_org_member(uuid) from public, anon;
revoke all on function public.is_org_admin(uuid) from public, anon;
grant execute on function public.is_org_member(uuid) to authenticated;
grant execute on function public.is_org_admin(uuid) to authenticated;
-- Remove overly broad write grants from anon (RLS also blocks, defence in depth)
revoke insert, update, delete, truncate, references, trigger on public.tickets from anon;
revoke insert, update, delete, truncate, references, trigger on public.org_members from anon;
revoke insert, update, delete, truncate, references, trigger on public.orgs from anon;
revoke truncate, references, trigger on public.tickets, public.org_members, public.orgs from authenticated;
-- org_members / orgs are read-only for end users; membership changes go through
-- service_role (which bypasses RLS) rather than the public REST API.
revoke insert, update, delete on public.org_members from authenticated;
revoke insert, update, delete on public.orgs from authenticated;
-- Enable RLS
alter table public.tickets enable row level security;
alter table public.org_members enable row level security;
alter table public.orgs enable row level security;
drop policy if exists tickets_select_members on public.tickets;
drop policy if exists tickets_insert_admins on public.tickets;
drop policy if exists tickets_update_admins on public.tickets;
drop policy if exists tickets_delete_admins on public.tickets;
drop policy if exists org_members_select_same_org on public.org_members;
drop policy if exists orgs_select_members on public.orgs;
-- TICKETS: read for any member of the org; write only for admins of the org.
create policy tickets_select_members on public.tickets
for select to authenticated
using (public.is_org_member(org_id));
create policy tickets_insert_admins on public.tickets
for insert to authenticated
with check (public.is_org_admin(org_id));
-- both USING and WITH CHECK so a row cannot be moved into another org
create policy tickets_update_admins on public.tickets
for update to authenticated
using (public.is_org_admin(org_id))
with check (public.is_org_admin(org_id));
create policy tickets_delete_admins on public.tickets
for delete to authenticated
using (public.is_org_admin(org_id));
-- ORG_MEMBERS: rows visible only to members of that same org.
create policy org_members_select_same_org on public.org_members
for select to authenticated
using (public.is_org_member(org_id));
-- ORGS: stays readable, but only to orgs the user belongs to.
create policy orgs_select_members on public.orgs
for select to authenticated
using (public.is_org_member(id));
commit;
SQL
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -f /tmp/rls.sql 2>&1BEGIN CREATE FUNCTION CREATE FUNCTION REVOKE REVOKE GRANT GRANT REVOKE REVOKE REVOKE REVOKE REVOKE REVOKE ALTER TABLE ALTER TABLE ALTER TABLE psql:/tmp/rls.sql:54: NOTICE: policy "tickets_select_members" for relation "public.tickets" does not exist, skipping DROP POLICY psql:/tmp/rls.sql:55: NOTICE: policy "tickets_insert_admins" for relation "public.tickets" does not exist, skipping DROP POLICY psql:/tmp/rls.sql:56: NOTICE: policy "tickets_update_admins" for relation "public.tickets" does not exist, skipping DROP POLICY psql:/tmp/rls.sql:57: NOTICE: policy "tickets_delete_admins" for relation "public.tickets" does not exist, skipping DROP POLICY psql:/tmp/rls.sql:58: NOTICE: policy "org_members_select_same_org" for relation "public.org_members" does not exist, skipping DROP POLICY psql:/tmp/rls.sql:59: NOTICE: policy "orgs_select_members" for relation "public.orgs" does not exist, skipping DROP POLICY CREATE POLICY CREATE POLICY CREATE POLICY CREATE POLICY CREATE POLICY CREATE POLICY COMMIT
cd /tmp && login(){ curl -s "$SUPABASE_URL/auth/v1/token?grant_type=password" -H "apikey: $SUPABASE_ANON_KEY" -H "Content-Type: application/json" -d "{\"email\":\"$1\",\"password\":\"$2\"}"; }
login uma-admin@cari.dev Passw0rd-uma-11 | jq -r '.access_token // .' > uma.jwt
login vic-member@cari.dev Passw0rd-vic-22 | jq -r '.access_token // .' > vic.jwt
login wen-outsider@cari.dev Passw0rd-wen-33 | jq -r '.access_token // .' > wen.jwt
for f in uma vic wen; do printf "%s: " $f; head -c 20 $f.jwt; echo "... len=$(wc -c < $f.jwt)"; doneuma: eyJhbGciOiJFUzI1NiIs... len=797 vic: eyJhbGciOiJFUzI1NiIs... len=799 wen: eyJhbGciOiJFUzI1NiIs... len=801
cd /tmp && cat > test.sh <<'EOS'
#!/bin/bash
ACME=3db5bdf0-e44c-41db-aa7e-98d3319d2656
GLOBEX=cf0677c8-a880-4ef6-8dd0-a49be09bb513
UMA=$(cat uma.jwt); VIC=$(cat vic.jwt); WEN=$(cat wen.jwt)
pass=0; fail=0
# req METHOD PATH TOKEN [body]
req(){ local m=$1 p=$2 tok=$3 body=$4
if [ "$tok" = "anon" ]; then AUTH=(-H "apikey: $SUPABASE_ANON_KEY"); else AUTH=(-H "apikey: $SUPABASE_ANON_KEY" -H "Authorization: Bearer $tok"); fi
if [ -n "$body" ]; then curl -s -o /tmp/body.txt -w '%{http_code}' -X $m "$SUPABASE_URL/rest/v1/$p" "${AUTH[@]}" -H "Content-Type: application/json" -H "Prefer: return=representation" -d "$body"
else curl -s -o /tmp/body.txt -w '%{http_code}' -X $m "$SUPABASE_URL/rest/v1/$p" "${AUTH[@]}"; fi; }
# check NAME EXPECTED_COUNT_OR_CODE ...
chk(){ local name="$1" cond="$2" got="$3"
if [ "$cond" = "$got" ]; then echo " PASS | $name (got: $got)"; pass=$((pass+1));
else echo " FAIL | $name (expected: $cond, got: $got) body=$(head -c 200 /tmp/body.txt)"; fail=$((fail+1)); fi; }
cnt(){ jq 'if type=="array" then length else -1 end' /tmp/body.txt; }
echo "=== 1. ANONYMOUS sees nothing ==="
req GET "tickets?select=*" anon >/dev/null; chk "anon reads 0 tickets" 0 "$(cnt)"
req GET "org_members?select=*" anon >/dev/null; chk "anon reads 0 org_members" 0 "$(cnt)"
c=$(req POST "tickets" anon '{"org_id":"'$ACME'","title":"anon-hack"}'); chk "anon INSERT ticket blocked" "yes" "$([ "$c" -ge 400 ] && echo yes || echo "no($c)")"
c=$(req DELETE "tickets?id=eq.1" anon); chk "anon DELETE ticket blocked" "yes" "$([ "$c" -ge 400 ] && echo yes || echo "no($c)")"
echo "=== 2. READ: members of an org read that org's tickets ==="
req GET "tickets?select=*" "$UMA" >/dev/null; chk "uma(Acme admin) sees 3 tickets" 3 "$(cnt)"
req GET "tickets?select=*" "$VIC" >/dev/null; chk "vic(Acme member) sees 3 tickets" 3 "$(cnt)"
req GET "tickets?select=*" "$WEN" >/dev/null; chk "wen(Globex member) sees 2 tickets" 2 "$(cnt)"
req GET "tickets?select=org_id" "$UMA" >/dev/null; chk "uma sees ONLY Acme org_ids" "$ACME" "$(jq -r '[.[].org_id]|unique|join(",")' /tmp/body.txt)"
req GET "tickets?select=org_id" "$WEN" >/dev/null; chk "wen sees ONLY Globex org_ids" "$GLOBEX" "$(jq -r '[.[].org_id]|unique|join(",")' /tmp/body.txt)"
echo "=== 3. Cross-tenant reads leak nothing ==="
req GET "tickets?select=*&org_id=eq.$GLOBEX" "$UMA" >/dev/null; chk "uma filtering Globex gets 0" 0 "$(cnt)"
req GET "tickets?select=*&org_id=eq.$ACME" "$WEN" >/dev/null; chk "wen filtering Acme gets 0" 0 "$(cnt)"
req GET "tickets?select=*&id=eq.4" "$UMA" >/dev/null; chk "uma direct-id Globex ticket gets 0" 0 "$(cnt)"
echo "=== 4. WRITE: only admins write their org's tickets ==="
c=$(req POST "tickets" "$VIC" '{"org_id":"'$ACME'","title":"vic-should-fail"}'); chk "vic(member) INSERT denied" "yes" "$([ "$c" -ge 400 ] && echo yes || echo "no($c)")"
c=$(req PATCH "tickets?id=eq.1" "$VIC" '{"status":"closed"}'); n=$(cnt); chk "vic(member) UPDATE affects 0 rows" "yes" "$([ "$c" -ge 400 ] || [ "$n" = "0" ] && echo yes || echo "no(code=$c rows=$n)")"
c=$(req DELETE "tickets?id=eq.1" "$VIC"); n=$(cnt); chk "vic(member) DELETE affects 0 rows" "yes" "$([ "$c" -ge 400 ] || [ "$n" = "0" ] && echo yes || echo "no(code=$c rows=$n)")"
c=$(req POST "tickets" "$WEN" '{"org_id":"'$ACME'","title":"wen-cross-tenant"}'); chk "wen INSERT into Acme denied" "yes" "$([ "$c" -ge 400 ] && echo yes || echo "no($c)")"
c=$(req PATCH "tickets?id=eq.1" "$UMA" '{"org_id":"'$GLOBEX'"}'); n=$(cnt); chk "uma cannot move ticket to Globex" "yes" "$([ "$c" -ge 400 ] || [ "$n" = "0" ] && echo yes || echo "no(code=$c rows=$n)")"
echo "=== 5. ORG_MEMBERS visibility ==="
req GET "org_members?select=*" "$UMA" >/dev/null; chk "uma sees 2 Acme members only" 2 "$(cnt)"
req GET "org_members?select=*" "$VIC" >/dev/null; chk "vic sees 2 Acme members only" 2 "$(cnt)"
req GET "org_members?select=*" "$WEN" >/dev/null; chk "wen sees 1 Globex member only" 1 "$(cnt)"
req GET "org_members?select=org_id" "$UMA" >/dev/=== 1. ANONYMOUS sees nothing === PASS | anon reads 0 tickets (got: 0) PASS | anon reads 0 org_members (got: 0) PASS | anon INSERT ticket blocked (got: yes) PASS | anon DELETE ticket blocked (got: yes) === 2. READ: members of an org read that org's tickets === PASS | uma(Acme admin) sees 3 tickets (got: 3) PASS | vic(Acme member) sees 3 tickets (got: 3) PASS | wen(Globex member) sees 2 tickets (got: 2) PASS | uma sees ONLY Acme org_ids (got: 3db5bdf0-e44c-41db-aa7e-98d3319d2656) PASS | wen sees ONLY Globex org_ids (got: cf0677c8-a880-4ef6-8dd0-a49be09bb513) === 3. Cross-tenant reads leak nothing === PASS | uma filtering Globex gets 0 (got: 0) PASS | wen filtering Acme gets 0 (got: 0) PASS | uma direct-id Globex ticket gets 0 (got: 0) === 4. WRITE: only admins write their org's tickets === PASS | vic(member) INSERT denied (got: yes) PASS | vic(member) UPDATE affects 0 rows (got: yes) FAIL | vic(member) DELETE affects 0 rows (expected: yes, got: no(code=204 rows=)) body= PASS | wen INSERT into Acme denied (got: yes) PASS | uma cannot move ticket to Globex (got: yes) === 5. ORG_MEMBERS visibility === PASS | uma sees 2 Acme members only (got: 2) PASS | vic sees 2 Acme members only (got: 2) PASS | wen sees 1 Globex member only (got: 1) PASS | uma org_members scoped to Acme (got: 3db5bdf0-e44c-41db-aa7e-98d3319d2656) PASS | wen org_members scoped to Globex (got: cf0677c8-a880-4ef6-8dd0-a49be09bb513) PASS | wen probing Acme members gets 0 (got: 0) === 6. Legitimate access preserved (orgs + embeds) === PASS | uma reads own org (got: 1) PASS | wen reads own org (got: 1) PASS | uma embed tickets->orgs works (got: Acme) RESULT: 25 passed, 1 failed
psql "$SUPABASE_DB_URL" -c "select id,org_id,title,status from tickets order by id;" -c "select count(*) as total_tickets from tickets;" 2>&1
id | org_id | title | status
----+--------------------------------------+----------------+--------
1 | 3db5bdf0-e44c-41db-aa7e-98d3319d2656 | Fix login | open
2 | 3db5bdf0-e44c-41db-aa7e-98d3319d2656 | Update billing | open
3 | 3db5bdf0-e44c-41db-aa7e-98d3319d2656 | Rotate keys | open
4 | cf0677c8-a880-4ef6-8dd0-a49be09bb513 | Migrate DNS | open
5 | cf0677c8-a880-4ef6-8dd0-a49be09bb513 | Renew cert | open
(5 rows)
total_tickets
---------------
5
(1 row)
cd /tmp && sed -i 's|c=$(req DELETE "tickets?id=eq.1" "$VIC"); n=$(cnt); chk "vic(member) DELETE affects 0 rows" "yes" "$(\[ "$c" -ge 400 \] \|\| \[ "$n" = "0" \] && echo yes \|\| echo "no(code=$c rows=$n)")"|before=$(psql "$SUPABASE_DB_URL" -tAc "select count(*) from tickets"); c=$(req DELETE "tickets?id=eq.1\&select=*" "$VIC"); after=$(psql "$SUPABASE_DB_URL" -tAc "select count(*) from tickets"); chk "vic(member) DELETE removes 0 rows" "yes" "$([ "$before" = "$after" ] \&\& echo yes || echo "no(before=$before after=$after code=$c)")"|' test.sh grep -n "vic(member) DELETE" test.sh
38:c=$(req DELETE "tickets?id=eq.1" "$VIC"); n=$(cnt); chk "vic(member) DELETE affects 0 rows" "yes" "$([ "$c" -ge 400 ] || [ "$n" = "0" ] && echo yes || echo "no(code=$c rows=$n)")"
sed: -e expression #1, char 473: unknown option to `s'
cd /tmp && python3 - <<'PY'
lines = open('test.sh').read().split('\n')
new = '''before=$(psql "$SUPABASE_DB_URL" -tAc "select count(*) from tickets")
c=$(req DELETE "tickets?id=eq.1" "$VIC")
after=$(psql "$SUPABASE_DB_URL" -tAc "select count(*) from tickets")
if [ "$before" = "$after" ]; then r=yes; else r="no(before=$before after=$after code=$c)"; fi
chk "vic(member) DELETE removes 0 rows" "yes" "$r"'''
for i,l in enumerate(lines):
if 'vic(member) DELETE' in l:
lines[i] = new
open('test.sh','w').write('\n'.join(lines))
PY
grep -n "DELETE removes" test.sh42:chk "vic(member) DELETE removes 0 rows" "yes" "$r"
cd /tmp && ./test.sh
=== 1. ANONYMOUS sees nothing === PASS | anon reads 0 tickets (got: 0) PASS | anon reads 0 org_members (got: 0) PASS | anon INSERT ticket blocked (got: yes) PASS | anon DELETE ticket blocked (got: yes) === 2. READ: members of an org read that org's tickets === PASS | uma(Acme admin) sees 3 tickets (got: 3) PASS | vic(Acme member) sees 3 tickets (got: 3) PASS | wen(Globex member) sees 2 tickets (got: 2) PASS | uma sees ONLY Acme org_ids (got: 3db5bdf0-e44c-41db-aa7e-98d3319d2656) PASS | wen sees ONLY Globex org_ids (got: cf0677c8-a880-4ef6-8dd0-a49be09bb513) === 3. Cross-tenant reads leak nothing === PASS | uma filtering Globex gets 0 (got: 0) PASS | wen filtering Acme gets 0 (got: 0) PASS | uma direct-id Globex ticket gets 0 (got: 0) === 4. WRITE: only admins write their org's tickets === PASS | vic(member) INSERT denied (got: yes) PASS | vic(member) UPDATE affects 0 rows (got: yes) PASS | vic(member) DELETE removes 0 rows (got: yes) PASS | wen INSERT into Acme denied (got: yes) PASS | uma cannot move ticket to Globex (got: yes) === 5. ORG_MEMBERS visibility === PASS | uma sees 2 Acme members only (got: 2) PASS | vic sees 2 Acme members only (got: 2) PASS | wen sees 1 Globex member only (got: 1) PASS | uma org_members scoped to Acme (got: 3db5bdf0-e44c-41db-aa7e-98d3319d2656) PASS | wen org_members scoped to Globex (got: cf0677c8-a880-4ef6-8dd0-a49be09bb513) PASS | wen probing Acme members gets 0 (got: 0) === 6. Legitimate access preserved (orgs + embeds) === PASS | uma reads own org (got: 1) PASS | wen reads own org (got: 1) PASS | uma embed tickets->orgs works (got: Acme) RESULT: 26 passed, 0 failed
11 earlier narration turn(s) are in the raw transcript.
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