--- paths: - "src/app/api/**" - "src/lib/auth*" - "src/server/**" - ".env*" - "next.config.*" - "Dockerfile" - "compose.yaml" --- # Security Rules ## Authentication: Better Auth with passkeys (mandatory) Whenever a project needs authentication, it uses **Better Auth** with the **passkey plugin**. Do not substitute another auth library, and do not build a custom session/credential layer. ```bash npm install better-auth # passkey support ships as a Better Auth plugin — enable it in the auth config ``` **Passkeys are the primary method.** The sign-in screen offers passkey first and presents it as the default path. A password flow is permitted only as a fallback for users whose device cannot do WebAuthn. Requirements whenever auth is present: - Passkey registration is offered during sign-up, not hidden in settings - Existing password users are prompted to add a passkey after signing in - The WebAuthn relying-party ID must match the deployment hostname. It is derived from `NEXT_PUBLIC_APP_URL` / `BETTER_AUTH_URL` — a mismatch makes every passkey fail verification, and it fails silently. - Passkeys require HTTPS in production (localhost is exempt). The reverse proxy terminates TLS — see `docs/DEPLOYMENT.md`. - If the password fallback exists: rate-limit it, never reveal whether an account exists, and store hashes only through Better Auth's own primitives ## Authorization - Verify the session in every route handler before any work - Authorization is per resource, not per route: having a session does not mean owning the record. Scope the query by the session user. - Never trust an ID coming from the client as proof of ownership ## Secrets - Never commit secrets. `.env` is gitignored; only `.env.example` is committed. - Every new variable is documented in `.env.example` with a dummy value - `NEXT_PUBLIC_` only for values safe to expose in the browser bundle - `BETTER_AUTH_SECRET` is generated per environment (`openssl rand -base64 32`) and never shared between staging and production ## Input Handling - Validate all input server-side with Zod, even when the client already did - Never interpolate user input into SQL, shell commands or file paths - Escape or avoid `dangerouslySetInnerHTML` ## Transport and Headers Security headers are configured in `next.config.ts`: `X-Frame-Options: DENY`, `X-Content-Type-Options: nosniff`, `Referrer-Policy: origin-when-cross-origin`, `Strict-Transport-Security`. Verify they survive the reverse proxy after deploying. ## Changes That Need Explicit User Approval - Any change to the authentication flow - Weakening or removing the passkey requirement - Any change to authorization or ownership checks - New environment variables (must land in `.env.example` in the same commit)