Skip to content

Backend / Edge Functions

The backend is Supabase: PostgreSQL + RLS, Postgres RPCs (reads), and Deno/TypeScript Edge Functions (writes, secrets, external HTTP, multi-step). This page covers the EF model; see the Edge Function Index for the live list and Shared Kit for the utilities.

Function types

TypeAuthJWT verifyNamingExample
Type ArequireAuth / requireAdmin / optionalAuthtruedomain-actionmanage-profile, get-public-menu
Type Bservice-role, cron/internalfalse (--no-verify-jwt)domain-noun-verbpublic_page_ops_cache_refresh
WebhookHMAC signaturefalse(none yet)

verify_jwt per function is configured in supabase/config.toml — Type A user-facing + public-capable EFs true; Type B cron/internal public_page_ops_* false.

The shared entrypoint pattern [ENFORCED]

Every function follows this exact skeleton (helpers in helpers.ts for complex logic):

ts
const preflight = handleCors(req); if (preflight) return preflight;
try {
  const { user, serviceClient } = await requireAuth(req);   // requireAdmin | optionalAuth
  const body = await req.json();
  if (!body.required) throw new ValidationError('required is required.');
  // business logic — complex parts in helpers.ts
  return ok({ result });
} catch (e) { return err('<name>', e); }

Rules [ENFORCED]

  • Pin @supabase/supabase-js to one exact version (currently 2.30.0).
  • Every EF ships co-located Deno tests/ — success, validation, auth/authz, safe 500s, edge cases — green before deploy.
  • Register the name in the feature EDGE_FN map; never inline EF-name strings.
  • Re-run docs:gen to update the EF index after adding/removing a function.
  • Safe errors only — no secret/table/stack leakage to the client; details go to structured logs.

Deploy

bash
npm run functions:deploy -- --project-ref <ref> [--only fn-a,fn-b] [--dry-run]

tools/deploy-functions.js always requires an explicit --project-ref (never relies on supabase link state) and skips _shared/utils (no index.ts). Promote to both Supabase projects deliberately — see Deployment & Promotion.

[TRANSITIONAL] notes

  • Existing functions were historically in two un-unified "camps"; the program is unifying them onto the _shared kit (recent commits: the Type A and Type B/public refactors).
  • Some functions violated the version pin — unify onto the single pinned version.
  • Standards doc: EDGE_FUNCTION_GUIDELINES.md (kept in sync with this portal).