# MVNexus Security Checklist

## Application

- [ ] `APP_DEBUG=false` in production
- [ ] Unique `APP_KEY` per environment
- [ ] Rate limits enabled (`RATE_LIMIT_*`, `OTP_*` throttles on auth routes)
- [ ] **No API bearer tokens in `localStorage`** — auth uses Sanctum SPA **httpOnly session cookies** + CSRF (`/sanctum/csrf-cookie`)
- [ ] `SANCTUM_STATEFUL_DOMAINS` restricted to production frontend hostnames
- [ ] `CORS_ALLOWED_ORIGINS` lists exact SPA origins (no `*` with credentials)
- [ ] `SESSION_SECURE_COOKIE=true` behind HTTPS
- [ ] `SESSION_HTTP_ONLY=true`, `SESSION_SAME_SITE=lax` or `strict`
- [ ] `SESSION_DOMAIN` set correctly for SPA/API cookie scope (e.g. shared parent domain)

## Passwordless auth (OTP, magic links, invites)

- [ ] `OTP_ALLOWED_EMAIL_DOMAIN` enforced in production
- [ ] OTP/magic-link/invite tokens stored **hashed** only (`login_otps`, `auth_magic_links`, `user_invites`)
- [ ] Short expiry: `OTP_EXPIRES_MINUTES`, `MAGIC_LINK_EXPIRES_MINUTES`, `USER_INVITE_EXPIRES_DAYS`
- [ ] Resend/rate limits configured (`OTP_RESEND_COOLDOWN_SECONDS`, per-email/IP windows)
- [ ] Mailgun credentials in secrets manager, not git (`MAILGUN_SECRET`)
- [ ] Generic success messages on OTP request (no user enumeration)
- [ ] Trusted device window reviewed (`OTP_TRUSTED_DEVICE_DAYS`); users can revoke via `/api/v1/auth/sessions`
- [ ] Do **not** configure Microsoft Entra/OAuth unless implementing SSO — `sso_identities` is unused legacy schema

## API authorization

- [ ] Department isolation middleware on ticket routes
- [ ] Note broadcasts use `ticket.{id}.notes` channel (agents/managers only)
- [ ] Broadcasting auth uses policies (`routes/channels.php`)
- [ ] Settings encrypted values never returned decrypted in public endpoints

## Transport & headers

- [ ] TLS everywhere
- [ ] nginx security headers (see `docker/nginx/default.conf`)
- [ ] CSP: recommend `default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' wss:; img-src 'self' data:; frame-ancestors 'none'`
- [ ] Disable directory listing; block `.env` exposure

## Uploads

- [ ] Validate MIME/size in attachment services (verify limits match nginx `client_max_body_size`)
- [ ] Store uploads outside public web root
- [ ] Scan uploads if policy requires AV scanning

## Secrets

- [ ] No secrets in git (use CI secrets / vault)
- [ ] Rotate `REVERB_APP_SECRET`, DB passwords, `MAILGUN_SECRET` periodically
- [ ] Mask encrypted settings in admin UI (already masked client-side)

## CI/CD

- [ ] Branch protection on `main`
- [ ] Required checks: backend, frontend, docker
- [ ] Dependency update policy (Composer/npm audit)

## Logging

- [ ] No passwords/OTP codes/magic-link tokens in logs
- [ ] `authentication_logs` enabled for auth events
- [ ] Log retention policy defined
