/** * Dev-auth bypass middleware (Pitfall 7 — T-02-01). * * Active ONLY when DEV_AUTH_BYPASS=true AND NODE_ENV !== 'production'. * Injects a fixed dev user into the Hono context so the OIDC auth guard is effectively * bypassed for local development WITHOUT live Authelia (D-14). * * Mount BEFORE oidcAuthMiddleware on /api/* in index.ts. * When the bypass is inactive (wrong env, or NODE_ENV=production) the middleware is a * pure no-op passthrough — production behaviour is unchanged. * * Context key: 'user' — matches the key read by downstream consumers. * In dev bypass mode, c.get('user') returns DEV_USER. index.ts does NOT mount * oidcAuthMiddleware when devBypassActive is true, so getAuth(c) is never called. * routes/me.ts reads c.get('user') first and returns the dev identity directly, * skipping the DB upsert and getAuth path entirely. Other routes (e.g. events) * also read c.get('user') directly — same pattern, no change needed there. * * Security: * - The FIRST conditional is always `NODE_ENV === 'production'` — checked before reading * any other env var. This is the hard guard (T-02-01). Even if DEV_AUTH_BYPASS is * accidentally set in production config, the guard fires and returns a no-op. * - The production Docker Compose MUST NOT set DEV_AUTH_BYPASS. See docs/deployment.md. * - This file must never be removed — the pattern is referenced by Plan 02 routes. */ import type { MiddlewareHandler } from 'hono' import { COLOR_PALETTE } from './user.js' export const DEV_USER = { id: 1, oidcIss: 'dev', oidcSub: 'dev-user', displayName: 'Dev User', color: COLOR_PALETTE[0], // '#4A90D9' — first palette slot } as const /** * Extend Hono's ContextVariableMap so that c.get('user') / c.set('user', ...) * are statically typed throughout the app. The value type is the DEV_USER shape, * which is compatible with both the bypass path and any future app-level user object * stored on context (they share the same id/displayName/color subset). */ declare module 'hono' { interface ContextVariableMap { user: typeof DEV_USER } } /** * Returns a Hono MiddlewareHandler that injects DEV_USER into the request context * when the dev-auth bypass is active, or a pure passthrough when inactive. * * The function evaluates env vars at call time (when the app starts), not at request time. * This means the middleware choice is fixed for the lifetime of the process — intentional, * since changing auth mode requires a restart. */ export function devAuthBypass(): MiddlewareHandler { // Hard production guard — FIRST check, before reading any other env var. // Ensures this middleware can never grant access in production regardless of config. if (process.env.NODE_ENV === 'production') { return async (_c, next) => next() } // Bypass flag not set — passthrough; OIDC auth proceeds normally. if (process.env.DEV_AUTH_BYPASS !== 'true') { return async (_c, next) => next() } // Bypass active: inject fixed dev user into Hono context. // Routes that read c.get('user') will receive DEV_USER. return async (c, next) => { c.set('user', DEV_USER) await next() } }