""" app/config.py ───────────── Central settings object built from environment variables via pydantic-settings. All sensitive values must be supplied via the .env file or container env vars — never hard-coded here. """ from __future__ import annotations from typing import Optional from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", extra="allow", # allow arbitrary env vars (forwarded to /api/config) case_sensitive=True, ) # ── Database ────────────────────────────────────────────────────────────── DATABASE_URL: str # ── JWT / Authentication ────────────────────────────────────────────────── SECRET_KEY: str ALGORITHM: str = "HS256" ACCESS_TOKEN_EXPIRE_MINUTES: int = 120 # ── CORS ────────────────────────────────────────────────────────────────── # Comma-separated list of allowed origins, e.g. "http://localhost:3000,https://pmdi.example.com" ALLOWED_ORIGINS: str = "http://localhost:3000" # ── Cron endpoint guard ─────────────────────────────────────────────────── CRON_SECRET_TOKEN: str # ── Seed admin (first-boot only) ────────────────────────────────────────── ADMIN_USERNAME: str = "admin" ADMIN_PASSWORD: str = "changeme" # ── Mail sender identity ────────────────────────────────────────────────── MAIL_FROM: str = "noreply@example.com" MAIL_FROM_NAME: str = "PMDI Invoice System" # ── Mail Mode A – Authenticated TLS relay ───────────────────────────────── # All three must be set to activate Mode A. MAIL_RELAYHOST: Optional[str] = None # "smtp.example.com:587" MAIL_RELAYHOST_USERNAME: Optional[str] = None MAIL_RELAYHOST_PASSWORD: Optional[str] = None # ── Mail Mode B – Simple container/host proxy relay ─────────────────────── # Set to the hostname of the relay container (e.g. "postfix"). MAIL_RELAY_HOST: Optional[str] = None # Module-level singleton — import this everywhere instead of re-instantiating. settings = Settings()