# ============================================================ # «Контракт-чек» — production config (see docs/ARCHITECTURE.md §11) # Copy to `.env` and fill in. All config is 12-factor (env-driven). # ============================================================ # --- Runtime --- ENV=dev # dev | staging | prod LOG_LEVEL=INFO LOG_FORMAT=json # json (prod/staging) | console (dev) APP_VERSION=0.1.0 # added to every log line; set at build/deploy time # --- Postgres (async) --- DATABASE_URL=postgresql+asyncpg://contract_check:contract_check@postgres:5432/contract_check # --- Redis (rate-limit / sessions, future; NOT the job queue) --- REDIS_URL=redis://redis:6379/0 # --- RabbitMQ (job queue pipeline) --- RABBITMQ_URL=amqp://contract_check:contract_check@rabbitmq:5672// MQ_PREFETCH_EXTRACT=1 # CPU-bound extraction; tune to CPU count MQ_PREFETCH_ANALYZE=3 # mirrors Ollama Pro concurrency MQ_PREFETCH_NOTIFY=5 # notification worker (I/O bound) MQ_MAX_ATTEMPTS=5 # before a message lands on the DLQ MQ_RETRY_BASE_MS=2000 # exponential backoff base (2s, 4s, 8s, ...) # --- MinIO (object storage) --- S3_ENDPOINT_URL=http://minio:9000 S3_ACCESS_KEY=contract_check S3_SECRET_KEY=contract_check S3_BUCKET=contract-check-docs S3_REGION=us-east-1 S3_SERVER_SIDE_ENCRYPTION=false # true in prod DOC_RETENTION_DAYS=7 # MinIO ILM expiry for raw docs (152-ФЗ lever) TEXT_RETENTION_DAYS=30 # expiry for extracted .txt blobs # --- Billing --- REFUND_POLICY=all # all | infra_only (see docs/ARCHITECTURE.md §8) PLANS_ENABLED=false # subscription quota logic (0011); false = credits-only legacy YOOKASSA_ENABLED=false # payments master switch; false → checkout/refund return 503 YOOKASSA_SHOP_ID= # from ЮKassa merchant profile YOOKASSA_SECRET_KEY= # live/test secret key from ЮKassa YOOKASSA_RETURN_BASE_URL= # e.g. https://contract-check.example.com/pay/{invoice_id} PRICE_PER_DOC_KOPECKS=19900 # pay-per-doc price (199 ₽) BILLING_RETURN_JWT_SECRET= # HS256 for /pay/{id} tokens; empty → falls back to JWT_SECRET BILLING_RETURN_TOKEN_TTL_MINUTES=15 REFUND_WINDOW_DAYS=14 # full-refund window (D10) REFUND_FULL_USAGE_THRESHOLD=0.20 # ≤20% consumed + within window ⇒ full refund # --- Observability (leave empty to disable) --- SENTRY_DSN= OTEL_EXPORTER_OTLP_ENDPOINT= # e.g. http://otel-collector:4317 OTEL_SERVICE_NAME=contract-check # --- LLM provider (abstract port; first realization = Ollama Cloud) --- # For Ollama Cloud use https://ollama.com (not api.ollama.com). Models must be # available on the chosen host — cloud models differ from local Ollama models. LLM_PROVIDER=ollama_cloud OLLAMA_HOST=https://ollama.com OLLAMA_API_KEY=replace-me OLLAMA_MODEL=qwen2.5:14b OLLAMA_FALLBACK_MODEL=qwen2.5:7b OLLAMA_TEMPERATURE=0.2 OLLAMA_NUM_PREDICT=3072 OLLAMA_TIMEOUT=120 OLLAMA_MAX_CONCURRENCY=3 # --- YandexGPT (alternative provider) --- # Set LLM_PROVIDER=yandex_gpt to use. Get API key & folder ID from Yandex Cloud. YANDEXGPT_API_KEY=replace-me YANDEXGPT_FOLDER_ID=replace-me YANDEXGPT_MODEL=yandexgpt-lite # yandexgpt / yandexgpt-lite / yandexgpt-preview etc. YANDEXGPT_FALLBACK_MODEL= # empty disables fallback YANDEXGPT_BASE_URL=https://llm.api.cloud.yandex.net YANDEXGPT_COMPLETION_PATH=/foundationModels/v1/completion YANDEXGPT_TEMPERATURE=0.2 YANDEXGPT_MAX_TOKENS=3072 YANDEXGPT_TIMEOUT=120 YANDEXGPT_MAX_CONCURRENCY=3 CHUNK_SIZE_CHARS=10000 # --- API (FastAPI) --- API_HOST=0.0.0.0 API_PORT=8000 API_METRICS_PORT=9100 B2B_DEFAULT_RATE_LIMIT_RPS=3 # per API key; mirrors Ollama Pro concurrency CORS_ORIGINS= # comma-separated, future web SPA # --- Auth (JWT + Telegram identity verification) --- # Telegram bot token is also used by the API to verify Login Widget / Mini App signatures. TELEGRAM_BOT_TOKEN= JWT_SECRET= # HS256 secret for signing user JWTs; generate with `openssl rand -hex 32` JWT_ALGORITHM=HS256 JWT_ACCESS_TTL_MINUTES=1440 # 24 hours default JWT_REFRESH_TTL_DAYS=30 # refresh-token lifetime for webUI auth # --- WebUI auth (email + password) --- WEB_AUTH_ENABLED=true # toggle /api/v1/auth/{register,login,...} routes WEB_ADMIN_ENABLED=true # toggle the /admin management UI (users role = 'admin') ADMIN_REQUIRED_ROLE=admin # users.role value required to enter /admin ADMIN_DEFAULT_EMAIL=admin@contract-check.local # Default admin password. Set once on first deploy; the user is auto-created with role=admin. # Leave empty to disable default admin creation (create admins manually via DB or register). ADMIN_DEFAULT_PASSWORD=changeme-strong-password PASSWORD_RESET_TTL_MINUTES=60 PASSWORD_MIN_LENGTH=8 WEB_APP_BASE_URL=http://localhost:5173 # SPA base — used to build reset + magic links # --- Passkeys (WebAuthn) --- PASSKEY_ENABLED=true # toggle /api/v1/auth/passkeys/* routes PASSKEY_RP_ID=localhost # effective domain of the webUI (must match the browser URL host) PASSKEY_RP_NAME=Контракт-чек # shown in the browser passkey prompt PASSKEY_RP_ORIGINS=http://localhost:5173 # comma-separated allowed WebAuthn origins PASSKEY_CHALLENGE_TTL_SECONDS=120 # ceremony challenge validity (single-use, Redis) # --- Magic-link auth (passwordless email login) --- MAGIC_LINK_ENABLED=true # toggle /api/v1/auth/magic-link/* routes MAGIC_LINK_TTL_MINUTES=15 # one-time link validity window # --- Prescreen stage (hybrid heuristic + optional LLM fallback) --- PRESCREEN_ENABLED=true PRESCREEN_AUTO_APPROVE=false PRESCREEN_CONFIDENCE_THRESHOLD=0.75 PRESCREEN_HIGH_VALUE_THRESHOLD=100000 PRESCREEN_LLM_FALLBACK_ENABLED=false # kill-switch; set true after burn-in PRESCREEN_LLM_FALLBACK_THRESHOLD=0.75 # <= confidence threshold PRESCREEN_LLM_MAX_CHARS=20000 # cost-control cap for fallback PRESCREEN_KEEP_REGEX=false # temporary rollback to regex-v1 # --- SMTP (notification transport; empty host → dev logger) --- SMTP_HOST= SMTP_PORT=587 SMTP_USERNAME= SMTP_PASSWORD= SMTP_FROM=no-reply@contract-check.local SMTP_USE_TLS=true # --- Edge proxy (Nginx + certbot) --- NGINX_SERVER_NAME=contract-check.example.com # --- Telegram bot (adapter, HTTP-only to api) --- BOT_TOKEN= # same value as TELEGRAM_BOT_TOKEN (kept for the bot image) BOT_SERVICE_TOKEN= # bearer looked up against service_tokens.name="bot-prod" API_URL=http://api:8000 # base URL of the api service (container DNS in compose)