"""Настройки приложения""" import datetime import os from os import environ from pathlib import Path from typing import Literal, cast # Корневая директория проекта ROOT_DIR = Path(__file__).parent.absolute() DEV_SERVER_PID_FILE_NAME = "dev-server.pid" PORT = environ.get("PORT") or 8000 # storages DB_URL = ( environ.get("DATABASE_URL", "").replace("postgres://", "postgresql://") or environ.get("DB_URL", "").replace("postgres://", "postgresql://") or "sqlite:///discoursio.db" ) DATABASE_URL = DB_URL REDIS_URL = environ.get("REDIS_URL") or "redis://127.0.0.1" # debug GLITCHTIP_DSN = environ.get("GLITCHTIP_DSN") # auth ADMIN_SECRET = environ.get("AUTH_SECRET") or "nothing" ADMIN_EMAILS = ( environ.get("ADMIN_EMAILS") or "services@discours.io,guests@discours.io,welcome@discours.io,test_admin@discours.io" ) # own auth ONETIME_TOKEN_LIFE_SPAN = 60 * 15 # 15 минут SESSION_TOKEN_LIFE_SPAN = 60 * 60 * 24 * 30 # 30 дней SESSION_TOKEN_HEADER = "Authorization" JWT_ALGORITHM = "HS256" JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "default_secret_key_change_in_production-ok?") JWT_ISSUER = "discours" JWT_EXPIRATION_DELTA = datetime.timedelta(days=30) # Токен действителен 30 дней # URL фронтенда FRONTEND_URL = os.getenv("FRONTEND_URL", "http://localhost:3000") # Настройки OAuth провайдеров OAUTH_CLIENTS = { "GOOGLE": { "id": os.getenv("GOOGLE_CLIENT_ID", ""), "key": os.getenv("GOOGLE_CLIENT_SECRET", ""), }, "GITHUB": { "id": os.getenv("GITHUB_CLIENT_ID", ""), "key": os.getenv("GITHUB_CLIENT_SECRET", ""), }, "FACEBOOK": { "id": os.getenv("FACEBOOK_APP_ID", ""), "key": os.getenv("FACEBOOK_APP_SECRET", ""), }, "X": { "id": os.getenv("X_CLIENT_ID", ""), "key": os.getenv("X_CLIENT_SECRET", ""), }, "YANDEX": { "id": os.getenv("YANDEX_CLIENT_ID", ""), "key": os.getenv("YANDEX_CLIENT_SECRET", ""), }, "VK": { "id": os.getenv("VK_APP_ID", ""), "key": os.getenv("VK_APP_SECRET", ""), }, "TELEGRAM": { "id": os.getenv("TELEGRAM_CLIENT_ID", ""), "key": os.getenv("TELEGRAM_CLIENT_SECRET", ""), }, } # Настройки JWT JWT_SECRET_KEY = os.getenv("JWT_SECRET_KEY", "your-secret-key") JWT_ACCESS_TOKEN_EXPIRE_MINUTES = 30 JWT_REFRESH_TOKEN_EXPIRE_DAYS = int(environ.get("JWT_REFRESH_TOKEN_EXPIRE_DAYS", "30")) # Настройки для HTTP cookies (используется в auth middleware) SESSION_COOKIE_NAME = "session_token" # 🔒 Автоматически определяем HTTPS на основе окружения SESSION_COOKIE_SECURE = os.getenv("HTTPS_ENABLED", "true").lower() in ["true", "1", "yes"] SESSION_COOKIE_HTTPONLY = True # 🌐 Для cross-origin SSE на поддоменах SESSION_COOKIE_DOMAIN = os.getenv("SESSION_COOKIE_DOMAIN", ".discours.io") # ✅ Работает для всех поддоменов # ✅ Типобезопасная настройка SameSite для cross-origin _samesite_env = os.getenv("SESSION_COOKIE_SAMESITE", "none") SESSION_COOKIE_SAMESITE: Literal["strict", "lax", "none"] = cast( Literal["strict", "lax", "none"], _samesite_env if _samesite_env in ["strict", "lax", "none"] else "none" ) SESSION_COOKIE_MAX_AGE = 30 * 24 * 60 * 60 # 30 дней MAILGUN_API_KEY = os.getenv("MAILGUN_API_KEY", "") MAILGUN_DOMAIN = os.getenv("MAILGUN_DOMAIN", "discours.io") # Search service configuration SEARCH_MAX_BATCH_SIZE = int(os.environ.get("SEARCH_MAX_BATCH_SIZE", "25")) SEARCH_CACHE_ENABLED = bool(os.environ.get("SEARCH_CACHE_ENABLED", "true").lower() in ["true", "1", "yes"]) SEARCH_CACHE_TTL_SECONDS = int(os.environ.get("SEARCH_CACHE_TTL_SECONDS", "300")) SEARCH_PREFETCH_SIZE = int(os.environ.get("SEARCH_PREFETCH_SIZE", "200")) MUVERA_INDEX_NAME = "discours" # 🎯 Search model selection: "biencoder" (default) or "colbert" (better quality) # ColBERT дает +175% recall но медленнее на ~50ms per query SEARCH_MODEL_TYPE = os.environ.get("SEARCH_MODEL_TYPE", "colbert").lower() # "biencoder" | "colbert" # 🚀 FAISS acceleration for large indices (>10K documents) # Двухэтапный поиск: FAISS prefilter → TRUE MaxSim на кандидатах SEARCH_USE_FAISS = os.environ.get("SEARCH_USE_FAISS", "true").lower() in ["true", "1", "yes"] SEARCH_FAISS_CANDIDATES = int(os.environ.get("SEARCH_FAISS_CANDIDATES", "1000")) # Кандидатов для rerank