env | grep -i supabase | sed 's/=.*/=<set>/'; echo "---"; which psql curl jq; psql --version
SUPABASE_DB_PASSWORD=<set> SUPABASE_DB_URL=<set> SUPABASE_URL=<set> SUPABASE_SERVICE_ROLE_KEY=<set> SUPABASE_PROJECT_REF=<set> SUPABASE_ANON_KEY=<set> --- /usr/bin/psql /usr/bin/curl /usr/bin/jq psql (PostgreSQL) 18.4 (Debian 18.4-1.pgdg12+1)
echo $SUPABASE_URL; echo $SUPABASE_PROJECT_REF; echo "DBURL host:"; echo $SUPABASE_DB_URL | sed 's/:[^:@]*@/:***@/'
https://<ref>.supabase.co <ref> DBURL host: postgresql://postgres.<ref>:***@aws-0-us-east-1.pooler.supabase.com:5432/postgres
cd /tmp && psql "$SUPABASE_DB_URL" -c "select version();" -c "\d public.signups" -c "\d public.webhook_receipts" 2>&1 | head -60
version
------------------------------------------------------------------------------
PostgreSQL 17.6 on x86_64-pc-linux-gnu, compiled by gcc (GCC) 15.2.0, 64-bit
(1 row)
Table "public.signups"
Column | Type | Collation | Nullable | Default
------------+--------------------------+-----------+----------+----------------------------------
id | bigint | | not null | generated by default as identity
email | text | | not null |
plan | text | | not null | 'free'::text
created_at | timestamp with time zone | | not null | now()
Indexes:
"signups_pkey" PRIMARY KEY, btree (id)
Table "public.webhook_receipts"
Column | Type | Collation | Nullable | Default
-------------+--------------------------+-----------+----------+----------------------------------
id | bigint | | not null | generated by default as identity
received_at | timestamp with time zone | | not null | now()
payload | jsonb | | not null |
Indexes:
"webhook_receipts_pkey" PRIMARY KEY, btree (id)
curl -s -o /dev/null -w "%{http_code}\n" -X POST "$SUPABASE_URL/functions/v1/hook-recorder" -H "Authorization: Bearer $SUPABASE_ANON_KEY" -H "Content-Type: application/json" -d '{"email":"probe@example.com","plan":"probe"}'200
psql "$SUPABASE_DB_URL" -c "select * from public.webhook_receipts order by id desc limit 5;"
id | received_at | payload
----+-------------------------------+-------------------------------------------------
2 | 2026-07-25 06:41:05.394325+00 | {"plan": "probe", "email": "probe@example.com"}
(1 row)
psql "$SUPABASE_DB_URL" -c "select name, default_version, installed_version from pg_available_extensions where name in ('pg_net','http','pg_cron','supabase_vault','pgsodium') order by name;" -c "select extname, extnamespace::regnamespace from pg_extension order by 1;" name | default_version | installed_version
----------------+-----------------+-------------------
http | 1.6 |
pg_cron | 1.6.4 |
pg_net | 0.20.4 |
pgsodium | 3.1.8 |
supabase_vault | 0.3.1 | 0.3.1
(5 rows)
extname | extnamespace
--------------------+--------------
pg_stat_statements | extensions
pgcrypto | extensions
plpgsql | pg_catalog
supabase_vault | vault
uuid-ossp | extensions
(5 rows)
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -c "create extension if not exists pg_net with schema extensions;" -c "select extname, extversion, extnamespace::regnamespace from pg_extension where extname='pg_net';"
CREATE EXTENSION extname | extversion | extnamespace ---------+------------+-------------- pg_net | 0.20.4 | extensions (1 row)
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 <<'SQL'
select vault.create_secret(current_setting('my.v'), 'hook_recorder_url', 'Webhook receiver endpoint for signups')
from (select 1) s(x), (select set_config('my.v', :'url', false) as v) t;
SQL
ERROR: syntax error at or near ":"
LINE 2: from (select 1) s(x), (select set_config('my.v', :'url', fal...
^
cd /tmp && psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 \
-v url="$SUPABASE_URL/functions/v1/hook-recorder" \
-v key="$SUPABASE_ANON_KEY" <<'SQL'
-- remove any prior versions so this is idempotent
do $$
begin
perform vault.delete_secret(id) from vault.secrets where name in ('hook_recorder_url','hook_recorder_jwt');
exception when undefined_function then
delete from vault.secrets where name in ('hook_recorder_url','hook_recorder_jwt');
end $$;
select vault.create_secret(:'url', 'hook_recorder_url', 'Signups webhook receiver endpoint');
select vault.create_secret(:'key', 'hook_recorder_jwt', 'Project JWT used to authenticate to the receiver');
select name, description from vault.secrets order by name;
SQL
DO
create_secret
--------------------------------------
43af13eb-1078-4f4f-8db7-e5af928e25ef
(1 row)
create_secret
--------------------------------------
29d1726e-dadc-47c5-84b4-1064f5bcedb1
(1 row)
name | description
---------------------+------------------------------------------------------------
hook_recorder_jwt | Project JWT used to authenticate to the receiver
hook_recorder_token | Bearer token (project JWT) for hook-recorder edge function
hook_recorder_url | Signups webhook receiver endpoint
project_url | Base URL of this Supabase project
service_role_key | Service role JWT used for internal webhook calls
signups_webhook_jwt | Project JWT used as Bearer token for signups webhook
signups_webhook_key | Project JWT used to authenticate to hook-recorder
signups_webhook_url | Endpoint for signups INSERT webhook
(8 rows)
psql "$SUPABASE_DB_URL" -c "select tgname, tgenabled, pg_get_triggerdef(oid) from pg_trigger where tgrelid='public.signups'::regclass and not tgisinternal;"
tgname | tgenabled | pg_get_triggerdef --------+-----------+------------------- (0 rows)
psql "$SUPABASE_DB_URL" -c "select n.nspname, p.proname from pg_proc p join pg_namespace n on n.oid=p.pronamespace where p.proname ilike '%signup%' or p.proname ilike '%webhook%' or p.proname ilike '%hook%' order by 1,2;"
nspname | proname ---------+------------------------ private | deliver_signup_webhook (1 row)
psql "$SUPABASE_DB_URL" -c "select pg_get_functiondef(p.oid) from pg_proc p join pg_namespace n on n.oid=p.pronamespace where n.nspname='private' and p.proname='deliver_signup_webhook';"
pg_get_functiondef
-------------------------------------------------------------------------------------------------------------------
CREATE OR REPLACE FUNCTION private.deliver_signup_webhook() +
RETURNS trigger +
LANGUAGE plpgsql +
SECURITY DEFINER +
SET search_path TO '' +
AS $function$ +
DECLARE +
v_url text; +
v_jwt text; +
v_request_id bigint; +
BEGIN +
SELECT decrypted_secret INTO STRICT v_url +
FROM vault.decrypted_secrets +
WHERE name = 'signups_webhook_url' +
ORDER BY created_at DESC LIMIT 1; +
+
SELECT decrypted_secret INTO STRICT v_jwt +
FROM vault.decrypted_secrets +
WHERE name = 'signups_webhook_jwt' +
ORDER BY created_at DESC LIMIT 1; +
+
SELECT net.http_post( +
url := v_url, +
body := jsonb_build_object('id', NEW.id, 'email', NEW.email, 'plan', NEW.plan, 'created_at', NEW.created_at),+
headers := jsonb_build_object('Content-Type', 'application/json', 'Authorization', 'Bearer ' || v_jwt), +
timeout_milliseconds := 5000 +
) INTO v_request_id; +
RETURN NEW; +
END +
$function$ +
(1 row)
cd /tmp && psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 <<'SQL' -- clean slate for previous partial attempts drop trigger if exists signups_webhook_trigger on public.signups; drop function if exists private.deliver_signup_webhook() cascade; create schema if not exists private; revoke all on schema private from anon, authenticated; -- audit log so operators can see every delivery attempt / failure create table if not exists private.signup_webhook_log ( id bigint generated by default as identity primary key, signup_id bigint, email text, plan text, request_id bigint, error text, created_at timestamptz not null default now() ); revoke all on table private.signup_webhook_log from anon, authenticated; SQL echo "=== schema ok ==="
DROP TRIGGER DROP FUNCTION CREATE SCHEMA REVOKE CREATE TABLE REVOKE === schema ok ===
NOTICE: trigger "signups_webhook_trigger" for relation "public.signups" does not exist, skipping NOTICE: schema "private" already exists, skipping
cd /tmp && cat > fn.sql <<'SQL'
create or replace function private.deliver_signup_webhook()
returns trigger
language plpgsql
security definer
set search_path = ''
as $function$
declare
v_url text;
v_jwt text;
v_req bigint;
begin
select decrypted_secret into v_url
from vault.decrypted_secrets
where name = 'hook_recorder_url'
order by created_at desc limit 1;
select decrypted_secret into v_jwt
from vault.decrypted_secrets
where name = 'hook_recorder_jwt'
order by created_at desc limit 1;
if v_url is null or v_jwt is null then
insert into private.signup_webhook_log(signup_id, email, plan, error)
values (new.id, new.email, new.plan, 'missing vault secret hook_recorder_url/hook_recorder_jwt');
return null;
end if;
-- pg_net queues the request and a background worker performs it,
-- so the INSERT is never blocked by receiver latency.
select net.http_post(
url := v_url,
body := jsonb_build_object(
'id', new.id,
'email', new.email,
'plan', new.plan,
'created_at', new.created_at
),
headers := jsonb_build_object(
'Content-Type', 'application/json',
'Authorization', 'Bearer ' || v_jwt
),
timeout_milliseconds := 8000
) into v_req;
insert into private.signup_webhook_log(signup_id, email, plan, request_id)
values (new.id, new.email, new.plan, v_req);
return null;
exception when others then
-- never let webhook trouble roll back a legitimate signup
begin
insert into private.signup_webhook_log(signup_id, email, plan, error)
values (new.id, new.email, new.plan, sqlstate || ': ' || sqlerrm);
exception when others then null;
end;
return null;
end
$function$;
create trigger signups_webhook_trigger
after insert on public.signups
for each row
execute function private.deliver_signup_webhook();
SQL
psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -f fn.sqlCREATE FUNCTION CREATE TRIGGER
psql "$SUPABASE_DB_URL" -c "select tgname, tgenabled, pg_get_triggerdef(oid) from pg_trigger where tgrelid='public.signups'::regclass and not tgisinternal;"
tgname | tgenabled | pg_get_triggerdef -------------------------+-----------+-------------------------------------------------------------------------------------------------------------------------------------- signups_webhook_trigger | O | CREATE TRIGGER signups_webhook_trigger AFTER INSERT ON public.signups FOR EACH ROW EXECUTE FUNCTION private.deliver_signup_webhook() (1 row)
cd /tmp && T="sql-$(date +%s)@example.com" && echo "TEST EMAIL: $T" && psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -c "insert into public.signups(email, plan) values ('$T','pro') returning id, email, plan;" && echo "$T" > /tmp/t1.txt && sleep 6 && psql "$SUPABASE_DB_URL" -c "select * from private.signup_webhook_log order by id desc limit 3;" -c "select id, received_at, payload from public.webhook_receipts where payload->>'email'='$T';"TEST EMAIL: sql-1784961733@example.com
id | email | plan
----+----------------------------+------
1 | sql-1784961733@example.com | pro
(1 row)
INSERT 0 1
id | signup_id | email | plan | request_id | error | created_at
----+-----------+----------------------------+------+------------+-------+------------------------------
1 | 1 | sql-1784961733@example.com | pro | 1 | | 2026-07-25 06:42:14.14244+00
(1 row)
id | received_at | payload
----+-------------------------------+------------------------------------------------------------------------------------------------------------------
3 | 2026-07-25 06:42:14.444054+00 | {"id": 1, "plan": "pro", "email": "sql-1784961733@example.com", "created_at": "2026-07-25T06:42:14.14244+00:00"}
(1 row)
psql "$SUPABASE_DB_URL" -c "select id, status_code, content::text from net._http_response order by id desc limit 3;"
id | status_code | content
----+-------------+-------------
1 | 200 | {"ok":true}
(1 row)
cd /tmp && T="rest-$(date +%s)@example.com" && echo "$T" > /tmp/t2.txt && echo "REST TEST: $T" && curl -s -X POST "$SUPABASE_URL/rest/v1/signups" -H "apikey: $SUPABASE_SERVICE_ROLE_KEY" -H "Authorization: Bearer $SUPABASE_SERVICE_ROLE_KEY" -H "Content-Type: application/json" -H "Prefer: return=representation" -d "{\"email\":\"$T\",\"plan\":\"enterprise\"}"REST TEST: rest-1784961748@example.com
[{"id":2,"email":"rest-1784961748@example.com","plan":"enterprise","created_at":"2026-07-25T06:42:28.716476+00:00"}]sleep 6; T2=$(cat /tmp/t2.txt); psql "$SUPABASE_DB_URL" -c "select id, received_at, payload from public.webhook_receipts where payload->>'email'='$T2';" -c "select r.id, r.status_code, r.content::text from net._http_response r order by r.id desc limit 3;"
id | received_at | payload
----+-------------------------------+---------------------------------------------------------------------------------------------------------------------------
4 | 2026-07-25 06:42:28.871846+00 | {"id": 2, "plan": "enterprise", "email": "rest-1784961748@example.com", "created_at": "2026-07-25T06:42:28.716476+00:00"}
(1 row)
id | status_code | content
----+-------------+-------------
2 | 200 | {"ok":true}
1 | 200 | {"ok":true}
(2 rows)
cd /tmp && S=$(date +%s) && psql "$SUPABASE_DB_URL" -v ON_ERROR_STOP=1 -c "insert into public.signups(email,plan) values ('bulkA-$S@example.com','free'),('bulkB-$S@example.com','pro'),('bulkC-$S@example.com','team');" && echo "$S" > /tmp/s.txt && sleep 7 && psql "$SUPABASE_DB_URL" -c "select payload->>'email' email, payload->>'plan' plan from public.webhook_receipts where payload->>'email' like 'bulk%$S@example.com' order by 1;"INSERT 0 3
email | plan
------------------------------+------
bulkA-1784961765@example.com | free
bulkB-1784961765@example.com | pro
bulkC-1784961765@example.com | team
(3 rows)
14 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