# Backend — FastAPI приложение

HTTP API сервер для VidConf: аутентификация (JWT), динамические конференции
(создание, календарь, вход по ссылке/номеру, гостевой доступ), чат в
реальном времени, администрирование (конференции/пользователи/команды/
настройки инстанса), контракты плагинов (Transcriber/Summarizer) и интеграция
с LiveKit (токены, webhook-приёмник).

## Структура

```
backend/
├── api/                    HTTP endpoint'ы
│   ├── __init__.py
│   ├── deps.py            JWT-зависимости для аутентификации
│   ├── auth.py            Регистрация, подтверждение email, вход, refresh, выход
│   ├── users.py           Профиль, аватары, поиск пользователей (GET/PATCH /users/me,
│   │                      POST/DELETE /users/me/avatar, POST /users/me/password, GET /users?q=)
│   ├── teams.py           Справочник команд (GET /teams)
│   ├── admin.py           Администрирование конференций, пользователей, команд, настроек инстанса
│   ├── health.py          GET /api/health
│   ├── metrics.py         GET /metrics (Prometheus)
│   ├── conferences.py     Динамические конференции (create, my, calendar, resolve,
│   │                      join, guest-join, GET/PATCH/DELETE /{id})
│   ├── chat.py            WS-эндпоинт чата (auth по LiveKit-токену, история, broadcast через Redis pub/sub)
│   └── livekit_webhook.py Webhook-приёмник событий LiveKit
├── core/                   Основные модули
│   ├── config.py          Конфиг из .env (Settings)
│   ├── security.py        Hash/verify пароля (argon2), JWT токены
│   ├── db.py              Управление сеансами БД (async)
│   ├── redis.py           Redis клиент
│   ├── rate_limit.py      Rate limiting для публичных endpoint'ов
│   ├── summarization/     Чанкинг транскрипта, LLM-клиент, подсчёт токенов
│   └── plugins/           Контракты Transcriber/Summarizer, factory, реализации
│       ├── transcriber.py     Контракт Transcriber
│       ├── summarizer.py      Контракт Summarizer
│       ├── config.py          Pydantic-конфиг плагинов
│       ├── factory.py         Регистрация и создание провайдеров
│       ├── null.py            NullTranscriber, NullSummarizer (no-op)
│       ├── faster_whisper.py  FasterWhisperCPU, FasterWhisperGPU
│       └── qwen_local.py      QwenLocal (map-reduce суммаризация через llama.cpp)
├── models/                SQLAlchemy ORM (14 таблиц, см. docs/db/schema.md)
│   ├── base.py            Base class
│   ├── user.py            User
│   ├── team.py             Team (справочник команд)
│   ├── email_verification.py  EmailVerificationToken
│   ├── conference.py      Conference (номер, slug, владелец, recurrence)
│   ├── invitee.py         ConferenceInvitee (приглашённые: user_id ИЛИ email)
│   ├── guest.py           GuestAccess (display_name, email)
│   ├── session.py         ConferenceSession (один запуск конференции, pipeline_status)
│   ├── participant.py     ConferenceParticipant (user_id ИЛИ guest_id, session_id)
│   ├── audio_track.py     SessionAudioTrack (аудиодорожка участника)
│   ├── phrase.py          Phrase (текстовые сегменты транскрибации, participant_id, session_id)
│   ├── chat.py            ChatMessage (автор: пользователь ИЛИ гость, author_name, session_id)
│   ├── email_delivery.py  EmailDelivery (журнал отправленных писем)
│   ├── instance_setting.py InstanceSetting (key-value настройки инстанса, JSONB)
│   └── webhook_event.py   LivekitWebhookEvent
├── repositories/          Async слой доступа к данным
│   ├── users.py
│   ├── conferences.py
│   ├── chat.py            ChatMessageRepository (последние N сообщений, добавление)
│   └── admin.py
├── services/              Бизнес-логика
│   ├── auth.py                Аутентификация (регистрация, вход)
│   ├── conferences.py         CRUD и валидация конференций, жизненный цикл, участники, .ics-приглашения
│   ├── conference_access.py   Проверка доступа (пароль, статус ended)
│   ├── conference_ids.py      Генерация номера (9 цифр) и slug (base64url)
│   ├── recurrence.py          RecurrenceRule, развёртка occurrences
│   ├── avatars.py             Загрузка, валидация (magic bytes), удаление аватаров
│   ├── profile.py             Обновление профиля (ФИО, команда)
│   ├── invitations_producer.py  Постановка .ics-приглашений в очередь Celery
│   ├── chat.py                 ChatService (auth по LiveKit-токену, history, persist+publish)
│   ├── livekit_tokens.py       Генерация LiveKit JWT-токенов
│   ├── webhook_handlers.py     Обработчики webhook-событий от LiveKit
│   ├── egress.py                Запуск/остановка записи аудио через LiveKit Egress
│   ├── email.py / email_templates.py  Отправка писем (саммари, приглашения)
│   ├── ics.py                  Генерация .ics-приглашений
│   ├── instance_settings.py    Эффективная конфигурация инстанса (уровень AI, чат и т.д.)
│   ├── ai_levels.py / ai_tiers.py  Матрица уровней AI (min/medium/max), детект доступности
│   └── pipeline_producer.py    Постановка задач пайплайна пост-обработки в Celery
├── schemas/               Pydantic-схемы для запросов/ответов
│   ├── auth.py            Auth, профиль пользователя
│   ├── admin.py           Админка (конференции, пользователи, команды, настройки)
│   ├── conferences.py     ConferenceCreateIn/UpdateIn, ConferenceOut, JoinOut, ResolveOut, OccurrenceOut, InviteeIn/Out
│   └── chat.py            ChatAuthIn, ChatMessageIn/Out, ChatHistoryOut, ChatErrorOut
├── alembic/               Миграции БД
│   ├── versions/          9 миграций от initial schema до teams/avatars/settings
│   └── env.py
├── scripts/               Утилиты
│   ├── __init__.py
│   ├── seed.py                    Идемпотентный сид: единственный админ-пользователь
│   └── apply_preset_settings.py   Применить настройки инстанса под пресет install.sh
├── tests/                 Тесты (pytest, см. полный список файлов в каталоге)
│   ├── conftest.py
│   ├── test_health.py
│   ├── test_auth.py / test_rbac.py / test_tokens.py
│   ├── test_conferences_api.py / test_conference_service.py / test_recurrence.py
│   ├── test_chat_ws.py
│   ├── test_admin_api.py / test_admin_teams.py / test_teams_api.py / test_users_api.py
│   ├── test_plugins_factory.py / test_qwen_local.py / test_llm_client.py
│   ├── test_pipeline.py / test_build_phrases.py / test_summarize_task.py / test_notify_task.py
│   └── ...
├── main.py                Точка входа FastAPI приложения
└── README.md               Этот файл
```

## Быстрый старт

### Требования

- Python 3.12+
- `uv`: `brew install uv`
- PostgreSQL 16 + Redis (через docker-compose или локально)

### 1. Установка зависимостей

```bash
cd backend
uv sync
```

### 2. Запуск миграций

```bash
uv run alembic upgrade head
```

Создаёт 14 таблиц и включает расширение PostgreSQL `btree_gist` (установлено, но
на текущей схеме не используется ни одним constraint'ом).

### 3. Загрузка тестовых данных (опционально)

```bash
uv run python -m scripts.seed
```

Идемпотентный сид: создаёт единственного администратора (`SEED_ADMIN_EMAIL` /
`SEED_ADMIN_PASSWORD`), если его ещё нет. Конференции создаются пользователями
динамически, предустановленных данных не требуется.

### 4. Запуск сервера

```bash
uv run uvicorn main:app --reload --host 0.0.0.0 --port 8000
```

API доступен по адресу `http://localhost:8000`.

Документация:
- Swagger: `http://localhost:8000/docs`
- ReDoc: `http://localhost:8000/redoc`

## Тестирование

```bash
# Запуск всех тестов
uv run pytest -q

# Запуск с покрытием
uv run pytest --cov=. --cov-report=html

# Запуск конкретного теста
uv run pytest tests/test_health.py -v
```

## Качество кода

```bash
# Linting
uv run ruff check .

# Проверка форматирования
uv run ruff format --check .

# Автоматическое форматирование
uv run ruff format .

# Проверка типов
uv run mypy .
```

Все проверки должны пройти перед мёржем.

## Конфигурация

### Переменные окружения (`.env`)

Полный список переменных (БД, Redis, JWT, LiveKit, Coturn, email/SMTP, уровни
AI, обнаруженное железо для install.sh и т.д.) и их назначение — см.
[docs/deploy/env.md](../docs/deploy/env.md). Модель `Settings` в
`core/config.py` — единственный источник дефолтов.

### Конфигурация плагинов (`config/plugins.yaml`)

```yaml
transcriber:
  enabled: true
  provider: "null"
  model: null
  language: ru

summarizer:
  enabled: true
  provider: "null"
  model: null
  chunk_minutes: 20

chat:
  enabled: true
```

Подробнее о плагинах см. [docs/plugins/contracts.md](../docs/plugins/contracts.md).

## База данных

### Схема

**14 ORM моделей:**
- `users` — зарегистрированные пользователи
- `teams` — справочник команд
- `email_verification_tokens` — одноразовые токены верификации email
- `conferences` — постоянные сущности конференций (номер, slug, владелец, recurrence)
- `conference_invitees` — приглашённые на конференцию (пользователь или внешний email)
- `guest_access` — гости, представившиеся при входе (display_name, email)
- `conference_sessions` — один запуск конференции (pipeline_status, summary_data)
- `conference_participants` — отслеживание присутствия в сеансе (user_id ИЛИ guest_id, session_id)
- `session_audio_tracks` — аудиодорожки участников сеанса
- `phrases` — текстовые сегменты транскрибации (participant_id, session_id)
- `chat_messages` — сообщения в сеансе (session_id, автор — пользователь или гость)
- `email_deliveries` — журнал отправленных писем
- `instance_settings` — key-value настройки инстанса (JSONB)
- `livekit_webhook_events` — журнал webhook-событий для идемпотентности

Полную ER-диаграмму и обоснования дизайна см. [docs/db/schema.md](../docs/db/schema.md).

### Миграции

Alembic управляет схемой:

```bash
# Проверить текущую версию
uv run alembic current

# Обновить до последней версии
uv run alembic upgrade head

# Создать миграцию после изменений модели
uv run alembic revision --autogenerate -m "description"
```

**Правило:** Модель + миграция коммитятся вместе; никогда только модель.

### Временные метки

Все `DateTime(timezone=True)` сохраняются как UTC в PostgreSQL. Клиент преобразует в локальный часовой пояс.

## API

Полная спецификация: [docs/api/README.md](../docs/api/README.md).

- `GET /api/health` — проверка здоровья (БД, Redis)
- `GET /metrics` — метрики Prometheus
- `/api/v1/auth/*` — регистрация, подтверждение email, вход, refresh, выход
- `/api/v1/users/*` — профиль, аватар, смена пароля, поиск пользователей
- `/api/v1/teams` — справочник команд
- `/api/v1/conferences/*` — создание, календарь, вход по ссылке/номеру, гостевой вход, изменение/удаление
- `WS /api/v1/conferences/{id}/chat` — текстовый чат в реальном времени
- `/api/v1/admin/*` — администрирование конференций, пользователей, команд, настроек
- `/api/v1/livekit/webhook` — приёмник webhook-событий LiveKit

## Плагины

Контракты плагинов в `backend/core/plugins/`:

**Transcriber:**
```python
class Transcriber(ABC):
    provider: ClassVar[str]
    def transcribe(self, audio_path: str, language: str = "ru") -> list[Segment]: ...
```

**Summarizer:**
```python
class Summarizer(ABC):
    provider: ClassVar[str]
    def summarize(self, transcript: str) -> str: ...
```

**Реализации:**
- `NullTranscriber`, `NullSummarizer` — no-op (`provider: "null"`, дефолт)
- `FasterWhisperCPU`, `FasterWhisperGPU` — [docs/plugins/transcriber.md](../docs/plugins/transcriber.md)
- `QwenLocal` — map-reduce суммаризация через llama.cpp — [docs/plugins/summarizer.md](../docs/plugins/summarizer.md)

**Как добавить новый плагин:**
1. Создайте класс, наследующий Transcriber/Summarizer
2. Декоратор: `@register_transcriber` или `@register_summarizer`
3. Укажите провайдера в `config/plugins.yaml`

Все контракты и фабрика: [docs/plugins/contracts.md](../docs/plugins/contracts.md).

## Celery воркеры

Пост-обработка (транскрибирование, суммаризация, email-уведомления и
приглашения) выполняется в Celery-воркерах. См. [workers/README.md](../workers/README.md).

## Решение проблем

**ImportError:**
```bash
uv sync --all-extras
```

**Ошибка подключения к БД:**
```bash
docker compose -f ../deploy/docker-compose.yml ps
echo $DATABASE_URL
```

**Миграции не выполняются:**
```bash
uv run alembic current
uv run alembic downgrade base
uv run alembic upgrade head
```

**Ошибки типов:**
- Python 3.12+: `python --version`
- Пересборка: `uv sync --refresh`

## Процесс разработки

1. **Ветка:** `git checkout -b feature/my-feature`
2. **Напишите тесты:** `tests/test_*.py`
3. **Реализуйте** в соответствующем модуле
4. **Качество:** `pytest -q && ruff check . && mypy .`
5. **Коммит:** включите резюме тестов

Пример:
```
feat: добавить реестр Transcriber плагинов

- Реализовать декоратор @register_transcriber
- Добавить NullTranscriber no-op реализацию
- Добавить test_plugins_factory.py

Тесты: пройдены
```

## Ссылки

- [Корневой README](../README.md) — обзор проекта
- [Схема БД](../docs/db/schema.md) — ER диаграмма & дизайн
- [Контракты плагинов](../docs/plugins/contracts.md) — гайд расширений плагинов
- [API справка](../docs/api/README.md) — endpoint'ы
- [Архитектура](../docs/architecture/README.md) — дизайн системы
- [Dev Setup](../docs/deploy/dev-setup.md) — локальное окружение
