CSRF Protection
State-changing requests (POST/PUT/PATCH/DELETE) are guarded against cross-site request forgery. Attach the csrf middleware (CsrfMiddleware) to a route; it reads the csrf_token field or the X-CSRF-Token header and validates it with Security::csrfValid() — a constant-time hash_equals() check — returning 419 Invalid CSRF token on failure. Tokens are minted with Security::generateCsrfToken() (32 random bytes, session-stored). For a hard stop, Security::verifyCsrfToken() logs the client IP and die()s with 403 instead.