# Supabase Edge Functions: key choice and JWT verification
Edge Functions run on Deno at the edge with two Supabase keys available. Picking the wrong one is the most common agent failure: service role for everything (bypasses RLS, a security hole), or anon key for admin work (mysterious permission errors).
## Checkable procedure
1. For user-scoped work, create the client with the anon (publishable) key and forward the caller's JWT: read the `Authorization` header from the request and set it on the client. RLS then applies as that user. Verify with `auth.getClaims()` before trusting the user id.
2. For admin work (creating users, bypassing RLS for system writes), create a separate client with the service role key from `Deno.env`. Keep the two clients in clearly named variables; never let the service role client touch user input directly.
3. Set `verify_jwt = false` in `config.toml` for functions called by external services (Stripe webhooks, cron triggers, third-party callbacks). Those callers have no Supabase JWT, so verification 401s every request. Keep it on for functions your app calls with a user session.
4. Handle CORS: respond to `OPTIONS` with the CORS headers and include them on every response. Browser calls fail before your code runs if this is missing, and agents misdiagnose it as an auth problem.
5. Secrets go in the function secrets store (`supabase secrets set`), read via `Deno.env`. Never hardcode keys in the function source; deployed function code is visible to project members.
## Quick test
Call the function with a user JWT and confirm RLS-scoped data returns. Call it with no JWT and confirm 401 when verify_jwt is on. Flip verify_jwt off for a webhook function and confirm the external caller gets through.