import os from pathlib import Path BASE_DIR = Path(__file__).resolve().parent def environment_flag(name: str, *, default: bool = False) -> bool: value = os.environ.get(name) if value is None: return default return value.strip().lower() in {"1", "true", "yes", "on"} def environment_list(name: str) -> list[str] | None: values = [value.strip() for value in os.environ.get(name, "").split(",")] filtered = [value for value in values if value] return filtered or None class Config: """Shared settings with secure production-oriented defaults.""" SECRET_KEY = os.environ.get("SECRET_KEY") SQLALCHEMY_DATABASE_URI = os.environ.get( "DATABASE_URL", f"sqlite:///{BASE_DIR / 'instance' / 'steady.db'}", ) SQLALCHEMY_TRACK_MODIFICATIONS = False SESSION_COOKIE_HTTPONLY = True SESSION_COOKIE_SAMESITE = "Lax" SESSION_COOKIE_SECURE = True REMEMBER_COOKIE_HTTPONLY = True REMEMBER_COOKIE_SAMESITE = "Lax" REMEMBER_COOKIE_SECURE = True WTF_CSRF_TIME_LIMIT = 3600 MAX_CONTENT_LENGTH = 2 * 1024 * 1024 TRUSTED_HOSTS = environment_list("TRUSTED_HOSTS") TRUST_PROXY_HEADERS = environment_flag("TRUST_PROXY_HEADERS") ENABLE_HSTS = False FEATURE_ADMIN = environment_flag("FEATURE_ADMIN") FEATURE_API_V1 = False FEATURE_BROWSER_REMINDERS = False class DevelopmentConfig(Config): DEBUG = True SECRET_KEY = os.environ.get("SECRET_KEY", "development-only-change-me") SESSION_COOKIE_SECURE = False REMEMBER_COOKIE_SECURE = False class TestingConfig(Config): TESTING = True SECRET_KEY = "testing-only" SQLALCHEMY_DATABASE_URI = "sqlite:///:memory:" WTF_CSRF_ENABLED = False SESSION_COOKIE_SECURE = False REMEMBER_COOKIE_SECURE = False class ProductionConfig(Config): ENABLE_HSTS = True PREFERRED_URL_SCHEME = "https" CONFIGS = { "development": DevelopmentConfig, "testing": TestingConfig, "production": ProductionConfig, }