Documentation menu

Providers

Supabase

Uses the Ahena CLI (beta). Install it with npm install -g @ahena/cli, or prefix commands with npx @ahena/cli. See Installation. The dashboard covers projects, connections, Doctor, the Stack Graph, plans and approvals without it.

Overview

Ahena connects to a Supabase project you own, checks it, and configures auth URLs. Your app talks to Supabase directly through the generated src/ahena/ code. Ahena is never in the request path.

Package: @ahena/provider-supabase · Category: database Capabilities: postgres, auth, auth-redirects, rls-inspection, migration-inspection, project-health

Connection

Method: API credential (OAuth will be added once Ahena is registered as a Supabase OAuth app).

Field Secret Where it's stored
SUPABASE_ACCESS_TOKEN, a personal access token (sbp_…) yes encrypted_credentials, envelope-encrypted, bound to the environment
SUPABASE_PROJECT_REF, the 20-letter project id no provider_connections.settings
SUPABASE_ACCESS_TOKEN=sbp_… ahena connect supabase -e production
# or pipe it, or let Ahena prompt (hidden). Never pass it as an argument.

If you don't pass --set SUPABASE_PROJECT_REF=…, Ahena lists your projects and you pick one. That listing uses the token without storing it.

Permissions

A Supabase personal access token can manage every project in the account. Ahena reports this as personal-access-token:full-account and shows a warning when you connect. Ahena only calls these endpoints (OAuth scope in brackets):

Endpoint Used for Scope
GET /v1/projects, GET /v1/projects/{ref} discovery, validation, status projects:read
GET /v1/projects/{ref}/health service health projects:read
GET /v1/projects/{ref}/config/auth site URL, redirects, sign-in methods auth:read
PATCH /v1/projects/{ref}/config/auth site_url and uri_allow_list only, after approval auth:write
GET /v1/projects/{ref}/database/migrations migration status database:read
POST /v1/projects/{ref}/database/query/read-only RLS inspection (pg_class/pg_policy only) database:read

A future OAuth connection needs only those four scopes. The auth-config response also contains OAuth client secrets, SMTP passwords and SMS tokens. Ahena parses it through an allowlist (AUTH_FIELDS) and drops everything else at the boundary.

Use a dedicated Supabase account or organization for production if you want to limit what the token can reach.

Capabilities

  • Validate: token works, project exists and is active.
  • Inspect (ahena inspect supabase): project, region, Postgres version, site URL, redirect URLs, enabled sign-in methods, migration count.
  • Doctor (ahena doctor): see below.
  • Configure (ahena configure supabase): site URL and redirect allow list. Setting a missing site URL and adding redirect URLs are CONFIRMATION_REQUIRED; replacing the site URL and removing a redirect URL are DESTRUCTIVE (sign-in links that use the old value stop working). Every change is shown as a diff first. Ahena refuses localhost, plain-HTTP and wildcard-domain URLs in production.
  • Generate (ahena generate supabase --framework nextjs|node): src/ahena/providers/supabase.ts, src/ahena/database, src/ahena/auth (each with a raw escape hatch) and an .env.example.supabase. The generated code reads keys from environment variables. Sessions never leak between server requests: the browser gets one shared client that keeps the user's session, but on the server supabase() returns a new client on every call with persistSession, autoRefreshToken and detectSessionInUrl off. supabase-js keeps a signed-in session inside the client instance, so a shared server client would let one user's sign-in apply to other users' requests, and row level security would evaluate as the wrong person. Server code that should act as a user calls supabaseForRequest(accessToken). auth.getUser(accessToken) and auth.signOut(accessToken) take the token explicitly, and auth.signInWithPassword returns the session for you to store. For Next.js cookie-based sessions, use @supabase/ssr. It isn't installed or generated for you.

Declare expectations in ahena.config.ts so Doctor and configure know what's intended:

export default {
  organization: "acme",
  project: "leo",
  auth: {
    provider: "supabase",
    siteUrl: { production: "https://example.com" },
    redirectUrls: { production: ["https://example.com/auth/callback"] },
  },
};

Doctor also compares supabase/migrations/*.sql in your repository with what's applied.

Limitations

  • No OAuth connection yet (personal access token only).
  • Ahena doesn't apply migrations or change RLS. It tells you exactly what to run.
  • Ahena doesn't fetch the anon or service-role keys. Copy the anon key into your env yourself.
  • Ahena never creates or deletes Supabase projects (that would be billable or destructive).

Manual steps

Situation What to do
Project paused Restore it in the Supabase dashboard, then ahena doctor.
Tables without RLS Add alter table … enable row level security; plus policies in a migration (Doctor prints the statements).
Pending migrations supabase link --project-ref <ref> then supabase db push.
Rotating the token Create a new token, ahena disconnect supabase, ahena connect supabase, then delete the old token.

Doctor checks

Id Severity Meaning
supabase.project.status PASS / WARNING / FAIL Project active, transitioning, or paused/failed.
supabase.health.{db,auth,rest,storage} PASS / WARNING / FAIL Service health from Supabase.
supabase.db.rls PASS / FAIL Public tables without row level security (readable with the anon key).
supabase.db.rls_policies INFO RLS enabled but no policies (denies all API access).
supabase.db.migrations INFO / PASS / WARNING / FAIL Applied vs. repository migrations. Pending is FAIL in production.
supabase.db.migrations_unknown WARNING Applied migrations missing from the repository.
supabase.auth.site_url PASS / WARNING / FAIL Missing, development URL in production, or differs from config.
supabase.auth.redirects_missing PASS / FAIL Redirects declared in ahena.config.ts that Supabase doesn't allow.
supabase.auth.redirects_local WARNING localhost/private addresses allowed in production.
supabase.auth.redirects_broad FAIL Wildcards like https://*.com/** that match domains you don't control.
supabase.auth.autoconfirm WARNING Production sign-ups skip email confirmation.
supabase.auth.password_length WARNING Minimum password length below 8.
supabase.auth.providers PASS / WARNING Enabled sign-in methods, or none.

Disconnect behavior

ahena disconnect supabase removes the connection and deletes the token Ahena stored. Supabase has no API for revoking a personal access token, so Ahena says so and links to https://supabase.com/dashboard/account/tokens for you to delete it. Ahena never deletes projects, data, users or settings in Supabase.