Fixes issues raised by the whole-branch review before merge:
- Critical: the previous migration hardcoded the live production
functions URL and anon key as the committed default, so every local
`supabase db reset` silently pointed dev/test triggers at the real
project. Adding a new migration instead of editing the already-applied
one (checksum/drift safety), with local dev values as the committed
default; production values are applied out-of-band, never committed.
- Important: verify_jwt=true plus sending the anon key as a bearer
token didn't actually stop anyone, since the anon key is public
(ships in the frontend bundle) — confirmed empirically, a request
with a valid anon key but no shared secret now gets a real 401.
Added a random shared secret known only to the database and the
Edge Functions' secret store.
- Important: notification emails interpolated raw contact fields into
HTML with no escaping. Added escapeHtml() and tests proving injected
markup renders as literal text, not live markup.
- Important: the URL/key/secret functions moved from public to a
private schema with EXECUTE revoked from anon/authenticated, closing
an unintended PostgREST RPC endpoint (verified 404 after the fix).
Also adds a test:functions npm script now that Deno is confirmed
available and the shared email builders' tests pass (12 total incl.
the new escaping cases).
Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH
Wires pg_net-based database triggers on bookings/inquiries to invoke the two
Edge Functions on insert. Two empirically-discovered fixes over the brief's
literal SQL were required to make this work locally:
- ALTER DATABASE ... SET for a custom GUC needs superuser, but the local
migration role (postgres) isn't superuser in this Supabase CLI stack (only
supabase_admin is) - inlined the base URL as a literal constant in each
trigger function instead.
- pg_net's http_post lives in schema `net`, not `extensions.net` - fixed the
function calls accordingly.
Also disabled verify_jwt for both functions in config.toml since they're
invoked by pg_net (no Authorization header), not by end-user clients.
Claude-Session: https://claude.ai/code/session_01NhxA4npAXAxmCDEJt6kxSH