create extension if not exists pg_net with schema extensions; -- The Edge Functions base URL is environment-specific: for local development -- it points at the local functions runtime; Task 9 updates it to the real -- deployed URL in production. -- -- NOTE ON IMPLEMENTATION: the brief originally called for storing this as a -- database-level GUC via `alter database postgres set -- app.settings.edge_function_base_url = '...'`, read back in each trigger -- function via current_setting(). That statement fails locally with -- `permission denied to set parameter "app.settings.edge_function_base_url"` -- (SQLSTATE 42501): in this Supabase CLI version's local Postgres stack, the -- `postgres` role that runs migrations is deliberately NOT a superuser -- (Create role/Create DB/Replication/Bypass RLS only) — only `supabase_admin` -- is superuser, mirroring the hosted permission model. Setting an arbitrary -- custom GUC at the database level requires either superuser or a `GRANT SET -- ON PARAMETER` from a superuser, and the migration has no way to grant -- itself that privilege. Empirically verified via `docker exec -- supabase_db_ psql -U postgres -d postgres -c "alter database -- postgres set app.settings.edge_function_base_url = '...'"` (denied) vs the -- same command as `-U supabase_admin` (succeeds). -- -- Rather than depend on a migration-time GRANT (fragile, and would still -- need to run as supabase_admin some other way), the base URL is inlined as -- a literal constant in each trigger function below. Task 9 (or any future -- environment change) updates it by editing the constant here and -- re-migrating — the same operational shape the GUC approach would have had. -- -- Default here is the local Supabase CLI functions gateway address, -- confirmed to resolve from inside the Postgres container in Step 5 below -- (curl from supabase_db_ to http://host.docker.internal:54321 -- reached the edge runtime and got a real HTTP response, not a connection -- failure). -- -- SECOND CORRECTION: the brief's SQL called `extensions.net.http_post(...)` -- (treating `net` as a schema nested under `extensions`). Empirically, even -- though `pg_extension.extnamespace` for pg_net reports `extensions` (from -- `with schema extensions` above), pg_net's install script hardcodes its own -- `net` schema for the actual functions (confirmed via `select n.nspname, -- p.proname from pg_proc p join pg_namespace n on p.pronamespace = n.oid -- where p.proname = 'http_post'` -> `net.http_post`). Calling -- `extensions.net.http_post` therefore fails with "cross-database -- references are not implemented: extensions.net.http_post" (Postgres reads -- `extensions.net` as database.schema). Fixed to call `net.http_post` -- directly below. create or replace function public.notify_booking_created() returns trigger language plpgsql security definer set search_path = '' as $$ declare base_url text := 'http://host.docker.internal:54321/functions/v1'; begin perform net.http_post( url := base_url || '/on-booking-created', headers := jsonb_build_object('Content-Type', 'application/json'), body := jsonb_build_object('record', to_jsonb(new)) ); return new; end; $$; create trigger booking_created_notify after insert on public.bookings for each row execute function public.notify_booking_created(); create or replace function public.notify_inquiry_created() returns trigger language plpgsql security definer set search_path = '' as $$ declare base_url text := 'http://host.docker.internal:54321/functions/v1'; begin perform net.http_post( url := base_url || '/on-inquiry-created', headers := jsonb_build_object('Content-Type', 'application/json'), body := jsonb_build_object('record', to_jsonb(new)) ); return new; end; $$; create trigger inquiry_created_notify after insert on public.inquiries for each row execute function public.notify_inquiry_created();