# HAN Chat API backend FastAPI-сервис публичного API, internal Open Lines/settings API, WebSocket realtime, Message Safety orchestration, S3 lifecycle и PostgreSQL workers. ## Запуск Python 3.12+: ```bash python -m venv .venv .venv/Scripts/pip install -e ".[dev]" alembic upgrade head uvicorn app.main:app --host 0.0.0.0 --port 8000 ``` Миграции выполняются отдельным deployment step. Приложение не применяет DDL при старте. Workers запускаются независимо: ```bash han-delivery-worker han-safety-worker han-cleanup-worker han-notification-expire-worker han-notification-draft-cleanup-worker ``` ## Переменные окружения Сервис читает только инфраструктурные параметры и секреты из корневого `backend/.env`. Локальный `.env` не коммитится. Business settings создаются миграцией в `han_app.app_settings`. Обязательны: - `APP_ENV`, `API_PORT`, `LOG_LEVEL`, `DATABASE_URL`; - `REDIS_URL`, `REDIS_REALTIME_URL`; - `KEYCLOAK_PUBLIC_URL`, `KEYCLOAK_INTERNAL_URL`, `KEYCLOAK_REALM`, `KEYCLOAK_AUDIENCE`; - `MESSAGE_SAFETY_URL`, `MESSAGE_SAFETY_SERVICE_TOKEN`, `MESSAGE_SAFETY_POST_TIMEOUT_SEC`, `MESSAGE_SAFETY_TASK_POLL_INTERVAL_SEC`, `MESSAGE_SAFETY_TASK_POLL_MAX_SEC`, `MESSAGE_SAFETY_CIRCUIT_FAILURE_THRESHOLD`, `MESSAGE_SAFETY_CIRCUIT_OPEN_SEC`; - `BITRIX_LOCAL_APP_BASE_URL`, `BITRIX_LOCAL_APP_INTERNAL_TOKEN`, `BITRIX_API_INBOX_TOKEN`, `BITRIX_LOCAL_APP_HTTP_TIMEOUT_SEC`, `BITRIX_LOCAL_APP_CIRCUIT_FAILURE_THRESHOLD`, `BITRIX_LOCAL_APP_CIRCUIT_OPEN_SEC`; - `KEYCLOAK_SETTINGS_BRIDGE_TOKEN`; - `SELECTEL_S3_ENDPOINT_URL`, `SELECTEL_S3_BUCKET_DOCUMENTS`, `SELECTEL_S3_BUCKET_ATTACHMENTS`, `SELECTEL_S3_BUCKET_QUARANTINE`, `SELECTEL_S3_ACCESS_KEY`, `SELECTEL_S3_SECRET_KEY`; - `CURSOR_HMAC_SECRET` — случайный секрет не короче 32 байт; - `NOTIFICATIONS_TOKEN_PRODUCER_TEST` — отдельный bearer token тестового продюсера Notification Center; в БД синхронизируется только SHA-256 hash; - `OTEL_EXPORTER_OTLP_ENDPOINT` — опциональный endpoint collector. Токены генерируются `openssl rand -hex 32`. S3 read-only credentials Message Safety не передаются этому контейнеру. В production подключение PostgreSQL должно использовать TLS, а internal endpoints — быть доступны только из backend-сети. Smoke-сценарий `producer_test`: отправить `POST /internal/notifications/v1/notifications` с `Authorization: Bearer $NOTIFICATIONS_TOKEN_PRODUCER_TEST`, `source=producer_test` и уникальным `external_id`; повтор того же тела вернёт `200`. Затем передать ту же пару `source`/`external_id` в `POST /internal/notifications/v1/notifications/cancel` с `close_reason=cancelled`; повторная отмена также вернёт `200`. ## Проверки ```bash ruff check . ruff format --check . mypy app pytest ``` `/health/live` проверяет процесс. `/health/ready` проверяет критические зависимости и возвращает `503`, если сервис не может безопасно обслуживать protected API.