e5514fe3bf
- App factory pattern (FUND-8): create_app() produces fresh app per test
- Logging config (structured, no secrets)
- Config validation: SLAB_AES_KEY required, WOO_BASE_URL HTTPS-only
- GET /api/health returns 200 {status: ok, version, woo_reachable: false}
- SQLite + alembic skeleton: full DATA-MODEL schema, initial migration
- API contract tests via httpx TestClient: 5 cases all green
- test_returns_200, test_returns_ok_status, test_woo_reachable_false
- test_response_shape, test_with_test_client_lifespan (FUND-9/10)
47 lines
1.7 KiB
Python
47 lines
1.7 KiB
Python
"""Application settings loaded from environment."""
|
|
|
|
from pydantic_settings import BaseSettings, SettingsConfigDict
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""FastAPI application settings.
|
|
|
|
WOO_BASE_URL is the deploy-time SoT for the WooCommerce store.
|
|
It must be HTTPS. FastAPI refuses startup when missing or HTTP.
|
|
|
|
SLAB_AES_KEY is the AES-GCM master key (32-byte base64). Required.
|
|
Missing key refuses startup.
|
|
|
|
All Woo credentials and inference secrets are stored AES-GCM encrypted
|
|
in the settings table at runtime, not passed as env vars.
|
|
"""
|
|
|
|
model_config = SettingsConfigDict(env_prefix="SLAB_", env_file=".env", env_file_encoding="utf-8")
|
|
|
|
aes_key: str | None = None
|
|
woo_base_url: str | None = None
|
|
app_hostname: str | None = None
|
|
|
|
# Image output constants (from TECH-SPEC)
|
|
aspect_ratio: str = "3:4"
|
|
output_px: int = 1600
|
|
output_px_min: int = 1600
|
|
fill_target: float = 0.80
|
|
|
|
def validate(self) -> None:
|
|
"""Refuse startup on invalid config."""
|
|
if self.aes_key is None:
|
|
raise ValueError("SLAB_AES_KEY environment variable is required")
|
|
if len(self.aes_key) < 32:
|
|
raise ValueError("SLAB_AES_KEY must be at least 32 bytes base64")
|
|
|
|
if self.woo_base_url is None:
|
|
raise ValueError("WOO_BASE_URL environment variable is required")
|
|
if not self.woo_base_url.startswith("https://"):
|
|
raise ValueError("WOO_BASE_URL must be HTTPS")
|
|
|
|
@property
|
|
def woo_credentials_configured(self) -> bool:
|
|
"""Whether Woo application password has been stored (checked via DB at runtime)."""
|
|
return False # Always false from config alone; checked via settings table at runtime
|