ddf7788d77
Aggiunge POST /api/vision/execute: route l'immagine al worker di visione, mappa le uscite del grafo sulle quote e le salva con save_measurement - stesso verdetto, stesso gate del fuori tolleranza di ogni altra misura. Nuova tabella vision_results (una riga per acquisizione, non per quota) e input_method 'camera' su measurements. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014BBnuACZSCJqXrMYC3LUMU
77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
"""TieMeasureFlow Server Configuration."""
|
|
from pathlib import Path
|
|
from pydantic_settings import BaseSettings
|
|
|
|
|
|
class Settings(BaseSettings):
|
|
"""Application settings loaded from environment variables."""
|
|
|
|
# Database
|
|
db_host: str = "localhost"
|
|
db_port: int = 3306
|
|
db_name: str = "tiemeasureflow"
|
|
db_user: str = "tmflow"
|
|
db_password: str = "change_me_in_production"
|
|
|
|
# Server
|
|
server_host: str = "0.0.0.0"
|
|
server_port: int = 8000
|
|
server_secret_key: str = "change-this-to-a-random-secret-key"
|
|
server_cors_origins: str = "http://localhost:5000"
|
|
|
|
# File Storage
|
|
upload_dir: str = "uploads"
|
|
max_upload_size_mb: int = 50
|
|
|
|
# Rate Limiting (requests per minute, per real client IP)
|
|
rate_limit_login: int = 5
|
|
rate_limit_general: int = 300
|
|
|
|
# SSL (Production)
|
|
ssl_certfile: str | None = None
|
|
ssl_keyfile: str | None = None
|
|
|
|
# Setup page (empty = disabled)
|
|
setup_password: str | None = None
|
|
|
|
# AI / OpenRouter (for technical sheet parsing)
|
|
openrouter_api_key: str | None = None
|
|
openrouter_model: str = "anthropic/claude-sonnet-4"
|
|
|
|
# Vision worker (internal network only, reachable as `vision` in Compose)
|
|
vision_worker_url: str = "http://vision:8100"
|
|
|
|
@property
|
|
def database_url(self) -> str:
|
|
"""Async MySQL connection string."""
|
|
return (
|
|
f"mysql+asyncmy://{self.db_user}:{self.db_password}"
|
|
f"@{self.db_host}:{self.db_port}/{self.db_name}"
|
|
)
|
|
|
|
@property
|
|
def cors_origins(self) -> list[str]:
|
|
"""Parse CORS origins from comma-separated string."""
|
|
return [origin.strip() for origin in self.server_cors_origins.split(",")]
|
|
|
|
@property
|
|
def upload_path(self) -> Path:
|
|
"""Absolute path to upload directory.
|
|
|
|
After the V2.0.0 restructure, uploads live at the project root
|
|
(mounted as a Docker volume), not inside the backend tree.
|
|
"""
|
|
# Path(__file__) = src/backend/config.py → parents[2] = project root
|
|
return Path(__file__).resolve().parents[2] / self.upload_dir
|
|
|
|
# Always resolve .env against the project root regardless of cwd
|
|
# (pydantic-settings would otherwise treat the path as cwd-relative).
|
|
model_config = {
|
|
"env_file": str(Path(__file__).resolve().parents[2] / ".env"),
|
|
"env_file_encoding": "utf-8",
|
|
"extra": "ignore",
|
|
}
|
|
|
|
|
|
settings = Settings()
|