Phase 9: production hardening
Config via env, abuse/resource limits, and production serving so the app is safe to expose publicly: - Fail-fast on missing SECRET_KEY when MULTI_USER=true - quickjs per-execution time/memory limits (while(true) can't hang server) - Per-user/per-IP rate limiting on turn/script/auth endpoints - Request body size limit + per-user row caps - Security headers (CSP, X-Frame-Options, nosniff, referrer-policy) incl. SSE - Debug router 403 and /docs disabled in multi-user mode - DATABASE_URL support (defaults to Neon Postgres) alongside SQLite - Documented all env vars in backend/.env.example Verified locally via uvicorn (MULTI_USER=1, SQLite); see plan/09-phase-hardening.md. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017e6tQuojBLYPetUfmhit4X
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
de4db373f2
commit
4772171b6c
+29
-5
@@ -9,6 +9,22 @@
|
||||
# Docker compose sets this to /data/data.db (a named volume).
|
||||
AIDND_DB_PATH=
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 9 — production hardening
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# Switch from SQLite to a server database (hosted deploys use Neon Postgres).
|
||||
# Any SQLAlchemy URL; postgres:// and postgresql:// schemes are rewritten to
|
||||
# the psycopg3 driver automatically. The platform-conventional DATABASE_URL
|
||||
# is honored too (AIDND_DATABASE_URL wins if both are set). Unset = SQLite.
|
||||
AIDND_DATABASE_URL=
|
||||
|
||||
# Comma-separated list of allowed CORS origins. Only needed when the frontend
|
||||
# is served from a different origin than the API; the production build is
|
||||
# served same-origin by FastAPI, so hosted deploys can leave this unset.
|
||||
# Default: http://localhost:5173,http://127.0.0.1:5173 (the Vite dev server).
|
||||
AIDND_CORS_ORIGINS=
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# Phase 8 — optional accounts & multi-user (all optional; defaults keep the
|
||||
# app in frictionless single-user "local mode")
|
||||
@@ -19,12 +35,17 @@ AIDND_DB_PATH=
|
||||
AIDND_MULTI_USER=
|
||||
|
||||
# Secret for signing session cookies and encrypting stored API keys at rest.
|
||||
# If unset, one is auto-generated into `secret.key` next to the database
|
||||
# (fine for local/docker-volume runs). Set it explicitly on hosted deploys so
|
||||
# sessions survive redeploys when the disk is ephemeral or replaced.
|
||||
# If unset in local mode, one is auto-generated into `secret.key` next to the
|
||||
# database (fine for local/docker-volume runs). REQUIRED when
|
||||
# AIDND_MULTI_USER is on — the app refuses to start without it, because a
|
||||
# regenerated secret on an ephemeral hosted filesystem would log out every
|
||||
# user on each deploy. Generate one:
|
||||
# python -c "import secrets; print(secrets.token_urlsafe(48))"
|
||||
AIDND_SECRET_KEY=
|
||||
|
||||
# "1" marks session cookies Secure (HTTPS-only). Turn on in production.
|
||||
# Session cookie Secure flag (HTTPS-only). Defaults to on when
|
||||
# AIDND_MULTI_USER is on, off otherwise — set 0/1 only to override (e.g. 0
|
||||
# when testing multi-user mode over plain http on a LAN address).
|
||||
AIDND_COOKIE_SECURE=
|
||||
|
||||
# --- Shared demo key (BYOK fallback; only active when AIDND_MULTI_USER=1) ---
|
||||
@@ -41,4 +62,7 @@ AIDND_DEMO_TURNS_PER_DAY=
|
||||
|
||||
# The AI endpoint/API key/model are NOT env vars — they are configured at
|
||||
# runtime in the app's Settings page and stored (encrypted) in the database.
|
||||
# Phase 9 will add: rate limiting and CORS_ORIGINS.
|
||||
#
|
||||
# Rate limits, request size limits, and per-user row caps are hardcoded with
|
||||
# generous values (see backend/app/limits.py) and active only in multi-user
|
||||
# mode — local installs are never throttled.
|
||||
|
||||
Reference in New Issue
Block a user