"""Application configuration (pydantic-settings). `Settings` loads from environment variables (prefix ``APP_``) and an optional ``.env`` file, falling back to the defaults below for local dev. Keep secrets (JWT_SECRET, HMAC_PEPPER, scraper credentials, ...) in the environment / a secret store, never in source. The Swedish parental-leave rule values live in the nested, frozen ``LeaveRules`` model. They are domain defaults rather than routine deployment config, but are modelled as settings so they're typed, validated, and overridable should a rule year change (e.g. ``APP_RULES__MAX_SAVABLE_DAYS_AT_AGE_4=96``). NOTE: these are the common-case figures — children born before 2014, multiples, and single custody differ and should become explicit config when tackled. """ from pydantic import BaseModel, ConfigDict from pydantic_settings import BaseSettings, SettingsConfigDict class LeaveRules(BaseModel): """Frozen Swedish föräldrapenning rule defaults (single source of truth).""" model_config = ConfigDict(frozen=True) total_days_per_child: int = 480 sjukpenning_days: int = 390 # income-based tier lagsta_niva_days: int = 90 # flat low-rate tier days_per_parent: int = 240 # default joint-custody split reserved_days_per_parent: int = 90 # non-transferable ("reserverade dagar") max_dubbeldagar: int = 60 # both parents, same child-day dubbeldagar_months_limit: int = 15 # only within the child's first 15 months max_savable_days_at_age_4: int = 96 # age-4 ceiling hard_expiry_age_years: int = 12 sgi_protected_first_months: int = 12 sgi_min_days_per_week_after_age_1: int = 5 # Default reserve for preschool planning-day ("studiedagar") closures — the # per-child value is user-editable; this is just the seeded default. preschool_planning_days_per_year: int = 6 @property def transferable_days_per_parent(self) -> int: return self.days_per_parent - self.reserved_days_per_parent class Settings(BaseSettings): model_config = SettingsConfigDict( env_prefix="APP_", env_nested_delimiter="__", env_file=".env", extra="ignore", ) # 'sqlite' for local dev, 'postgres' for production (swap repository impls). database_type: str = "sqlite" sqlite_path: str = "./foraldraledig.db" # Lock CORS down to the frontend origin(s). cors_origins: list[str] = ["http://localhost:5173"] # Auth — change jwt_secret in production (min 32 chars). jwt_secret: str = "dev-secret-change-in-production-min-32-chars" jwt_algorithm: str = "HS256" jwt_access_token_expire_minutes: int = 15 jwt_refresh_token_expire_days: int = 7 # FK scraper — disabled until legal/ToS + BankID review (§2.3). scraper_enabled: bool = False rules: LeaveRules = LeaveRules() settings = Settings()