Mercury/docs/superpowers/specs/2026-08-09-disable-auth-env-var-design.md
Matthew L McPeak 2d95265e7d
Some checks failed
ci / build-ui (pull_request) Successful in 21s
ci / test (pull_request) Failing after 34s
ci / publish (pull_request) Has been skipped
fix: cleanup
2026-08-09 14:34:28 -04:00

52 lines
2.5 KiB
Markdown

# DISABLE_AUTH env var — design
## Purpose
Add a dev-only `DISABLE_AUTH` environment variable that bypasses authentication
and permission checks end-to-end (API + admin UI), so the app can be driven
by tooling (e.g. browser automation) without a login step. Insecure by design;
must default to off and be documented as such.
## Backend
- `Config` (`src/config.rs`) gains `disable_auth: bool`, read from `DISABLE_AUTH`.
Truthy values: `1`, `true` (case-insensitive). Default: `false`.
- `src/auth/middleware.rs` gains `authenticate_or_bypass(state, req)`:
- If `state.config.disable_auth`, return a synthetic super-admin `Claims`
(`sub: "dev-bypass"`, `permissions: u128::MAX.to_string()`, `exp: usize::MAX`)
without inspecting the request at all.
- Otherwise, delegate to the existing `extract_bearer` + `authenticate` flow.
- `require_auth`, `require_super_admin`, `require_admin_query`,
`require_admin_cache`, and `blacklist_layer` switch from
`extract_bearer(...).ok_or(UNAUTHORIZED)?` + `authenticate(...)` to
`authenticate_or_bypass(...)`, so the bypass applies uniformly (including
blacklist `bypass_mask` checks, since the caller mask is `u128::MAX`).
- New route `GET /auth/config` (`src/routes/auth.rs`), unauthenticated,
returns `{"disable_auth": bool}` so the frontend can detect the mode.
## Frontend
- `ui/src/stores/auth.ts`: on first access, fetch `GET /auth/config`. If
`disable_auth` is `true`, set an `authDisabled` ref and short-circuit
`isAuthenticated` / `isSuperAdmin` / `hasPermission` to always report a
fully-privileged, logged-in user — no token needed.
- `ui/src/router/index.ts`: `beforeEach` awaits the auth store's boot check
(memoized, runs once) before evaluating `requiresAuth`, so `/admin/*`
routes never redirect to `/login` while the flag is set.
- No changes to `Login.vue` itself; it simply becomes unreachable in this mode
(redirect away from `/login` when already "authenticated").
## Docs / plumbing
- `.env.example`: add `DISABLE_AUTH=` (commented, default off) with a warning.
- `docker-compose.yml`: add `DISABLE_AUTH: ${DISABLE_AUTH:-false}` under the
`api` service environment.
- `README.md`: add `DISABLE_AUTH` to the Configuration table, marked
dev-only / insecure — do not use in production.
## Out of scope
- No change to `/auth/login` behavior when the flag is off.
- No new permission bits or config for partial bypass (all-or-nothing).
- No changes to how the FE issues investigation (separate task, done live
with agent-browser after this lands).