> ## Documentation Index
> Fetch the complete documentation index at: https://rapidreview.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Configure auth

> Turn on authentication for a self-hosted brain: the Supabase Auth verifier, project membership, and what each optional key unlocks.

The reference stack ships with `MERV_REQUIRE_AUTH=1`. Authentication reuses a Supabase Auth project (the same one RapidReview uses, or your own); Merv's data never lives there.

## Variables

| Variable               | Required | Unlocks                                                                                                                                                                                                                                                                                    |
| ---------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `SUPABASE_URL`         | yes      | Together with the JWT secret, builds the verifier — without both the brain won't start                                                                                                                                                                                                     |
| `SUPABASE_JWT_SECRET`  | yes      | Local HS256 verification of browser session JWTs (audience `authenticated`); no per-request round-trip                                                                                                                                                                                     |
| `SUPABASE_SERVICE_KEY` | no       | `rr_sk_` API-key lookups and add-member-by-email; without it those features are disabled                                                                                                                                                                                                   |
| `SUPABASE_ANON_KEY`    | no       | Published through `/api/meta` so the hosted UI can sign users in                                                                                                                                                                                                                           |
| `MERV_REQUIRE_AUTH`    | —        | `1` (default in the reference stack). A record-only dev stack that wants no auth sets `0` **and** `MERV_ALLOW_OPEN_CONTROL=1`; the brain then logs its open state on every boot. `MERV_ALLOW_OPEN_CONTROL` accepts only `1/true/yes/on` or `0/false/no/off` — anything else fails the boot |

Keep secrets in managed secret storage; rotate through Supabase and your deployment runbooks.

## What a verified credential can do

One `Authorization: Bearer <credential>` header, three shapes:

| Credential           | Who                                                                                                 | Scope                                                                         |
| -------------------- | --------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| Supabase session JWT | Browser UI users                                                                                    | Their member projects                                                         |
| `rr_sk_` API key     | Headless callers, minted in RapidReview                                                             | Owner-scoped                                                                  |
| `mk_` key            | Minted in Merv (OAuth access tokens are audience-confined `mk_` tokens; static keys for runners/CI) | `project` (one project, gateway-enforced) or `account` (every member project) |

**Project membership** is the authorization layer: `project_members` rows decide what a user sees. Creating a project records the creator as its first member; any member can add or remove members (`POST /api/projects/{id}/members` with `user_id` or, with a user directory configured, `email`). Existing databases must contain one membership row per authorized user/project pair before enabling auth. Email sharing also expects the service-role `lookup_user_for_share` and `user_display_profiles` RPCs in the auth project.

## Interactive clients

Nothing changes on the client side: manifests are URL-only, the client gets a 401 from your brain, discovers OAuth (RFC 9728/8414), registers dynamically, and completes PKCE consent in the browser. Point the MCP `url` at your brain. See [Authentication](/docs/merv/clients/authentication).

## Notes

* Under auth, EventSource can't send the header, so the hosted stream 401s and the UI falls back to ETag polling (\~3 s).
* `/api/admin/*` is an operator surface — keep it network-restricted even with auth on.
* Custom identity providers: pass your own user directory to `create_fastapi_app(user_directory=…)`; it must return the same opaque ids as your verifier. See `merv/docs/AUTH.md`.
