"""Bridge response security headers — P8 CP-C. Pure starlette middleware. Adds the minimal browser-side protections expected of an API origin. The Next.js web frontend has its own (stricter) CSP for HTML responses; this module covers the bridge. """ from __future__ import annotations from starlette.middleware.base import BaseHTTPMiddleware _HEADERS: dict[str, str] = { "Content-Security-Policy": "default-src 'none'; frame-ancestors 'none'", "Strict-Transport-Security": "max-age=63072000; includeSubDomains", "X-Frame-Options": "DENY", "X-Content-Type-Options": "nosniff", "Referrer-Policy": "strict-origin-when-cross-origin", "Permissions-Policy": "camera=(), microphone=(), geolocation=(), interest-cohort=()", } class SecurityHeadersMiddleware(BaseHTTPMiddleware): """Adds security headers to every response. Uses `setdefault` semantics so route handlers can opt-out per header (e.g. Cache-Control). HSTS on HTTP responses is harmless — browsers ignore it outside HTTPS. """ async def dispatch(self, request, call_next): response = await call_next(request) for k, v in _HEADERS.items(): if k not in response.headers: response.headers[k] = v return response