Ships the cross-cutting hardening set: - SecurityHeadersMiddleware: per-request nonce-based CSP, HSTS (production only), Referrer-Policy, Permissions-Policy, X-Content-Type-Options, frame-ancestors 'none', form-action 'self'. - AccessLogMiddleware: one http_request INFO event per request (method/path/status/duration_ms/ip/ua). Skips /healthz, redacts /admin/auth/consume/<token> paths, logs 500 + re-raises on downstream exceptions. - Public base.html inline nav-toggle script gets a nonce so it passes strict CSP without relaxing to 'unsafe-inline'. - Dockerfile: non-root app user (uid/gid 10001) + stdlib-only HEALTHCHECK against /healthz. - scripts/backup.sh: sqlite3 .backup + tar data/media with 14-entry retention; host-side cron install documented. - .gitea/workflows/build-image.yml: on push to master / workflow_dispatch, builds and publishes git.sneakygeek.net/ptarrant/chicken_babies_site:latest + sha-<short>, with GIT_COMMIT_SHA threaded as a build-arg so /healthz keeps reporting the right commit in deployed images. - 8 new tests (security headers + access log). Pre-existing dev failures (logo asset rename + RESEND env pollution) remain unchanged; verified not Phase 6 regressions. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
27 lines
996 B
Python
27 lines
996 B
Python
"""Application-level Starlette middlewares.
|
|
|
|
Each middleware is a :class:`starlette.middleware.base.BaseHTTPMiddleware`
|
|
subclass wired up in :mod:`app.main`. They are kept in their own package
|
|
(rather than buried in ``app/main.py``) because Phase 6 introduced two
|
|
cross-cutting middlewares — security headers and access logging — that
|
|
benefit from isolated unit tests and clear homes for future additions
|
|
(rate-limit re-shaping, request-id propagation, etc.).
|
|
|
|
Public surface:
|
|
|
|
- :class:`SecurityHeadersMiddleware` — per-request CSP nonce + strict
|
|
response headers. See :mod:`app.middleware.security_headers`.
|
|
- :class:`AccessLogMiddleware` — structured ``http_request`` log line
|
|
after every response. See :mod:`app.middleware.access_log`.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from app.middleware.access_log import AccessLogMiddleware
|
|
from app.middleware.security_headers import SecurityHeadersMiddleware
|
|
|
|
__all__ = [
|
|
"AccessLogMiddleware",
|
|
"SecurityHeadersMiddleware",
|
|
]
|