Files
han-app/VM1_app/codebase/backend/api-backend/README.md
T

102 lines
5.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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_CA_FILE`, `MESSAGE_SAFETY_API_PREFIX=/internal/safety/v2`,
`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`. `MESSAGE_SAFETY_SERVICE_TOKEN`
сохраняется как caller secret API backend; S3 credentials сервису Safety не
передаются. В production подключение PostgreSQL должно использовать TLS. Target
задаётся через `MESSAGE_SAFETY_URL=https://<private-vm2-name>:8443`
(`processing.internal` — только пример), API prefix `/internal/safety/v2`;
certificate проверяется по CA из
`MESSAGE_SAFETY_CA_HOST_PATH`, plaintext HTTP запрещён.
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` проверяет критические
зависимости read API. Remote Message Safety не выключает чтение/общую readiness:
send endpoint отдельно проверяет требуемую capability и fail-closed возвращает
`503`, если ВМ2 недоступна.
## Публичная конфигурация мобильных обновлений
`GET /api/v1/public/app-config` возвращает строгий объект `mobile_update` с
политиками `google_play`, `rustore` и `app_store`. Для включённого магазина
обязательны `latest_build`, `minimum_build`, `latest_version` и HTTPS `store_url`;
`minimum_build` не может превышать `latest_build`. Для отключённого магазина
эти поля возвращаются как `null`. Опциональное `release_notes` также возвращается
как `null`, если в settings задана пустая строка. Канонический URL RuStore:
`https://www.rustore.ru/catalog/app/ru.han.chat`.
Ответ содержит `ETag`, поддерживает `If-None-Match` с ответом `304` и в
production-like конфигурации кэшируется клиентом и nginx 60 секунд. Изменения
политики применяются через штатный идемпотентный `seed-settings`; некорректные
пороги, типы и URL блокируют загрузку settings.