Can Agents Run It? · evidence — Issue 1: Supabase

claude-opus-5 · d2_webhooks · rep 3

pass
model
claude-opus-5
task
d2_webhooks
rep
3
day
2
steps
20
tokens
81,384
est. cost
$0.977
agent time
122s
wave
s4b
started
2026-07-25T06:40:38Z

The task as the agent received it

You have operator access to a hosted Supabase project. Credentials are in environment variables: SUPABASE_URL, SUPABASE_PROJECT_REF, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY, SUPABASE_DB_URL, SUPABASE_DB_PASSWORD. Every INSERT into the existing table public.signups must deliver an HTTP webhook: a POST request with a JSON body containing at least the new row's email and plan values, sent to the receiver endpoint {SUPABASE_URL}/functions/v1/hook-recorder (an edge function that is already deployed on this project; SUPABASE_URL is in your environment). The receiver requires a valid project JWT in the Authorization header and records every payload it accepts. Implement the delivery from the database itself, so it fires for ANY insert into signups no matter which client performs it — no external workers, no cron, no client-side code. Delivery may be asynchronous (a few seconds is fine). Prove it end-to-end with a test insert before finishing: the receiver stores accepted payloads in public.webhook_receipts.

What it ran — 20 commands

#1exit 0
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)
#2exit 0
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
#3exit 0
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)

#4exit 0
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
#5exit 0
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)

#6exit 0
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)

#7exit 0
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)

#8exit 3
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...
                                                         ^
#9exit 0
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)

#10exit 0
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)

#11exit 0
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)

#12exit 0
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)

#13exit 0
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
#14exit 0
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.sql
CREATE FUNCTION
CREATE TRIGGER
#15exit 0
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)

#16exit 0
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)

#17exit 0
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)

#18exit 0
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"}]
#19exit 0
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)

#20exit 0
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)

What it said at the end

Both client paths work. Let me verify a few important edge cases: multi-row inserts, and that a receiver failure can't break the insert.

14 earlier narration turn(s) are in the raw transcript.

How it was graded

A shell script executed against the live project and asserted on the state the agent left behind. No model judged another model.

exit 0 OK

Check it yourself

Raw transcript · Task definition and verifier · Every attempt