### Task 7: API Discovery **Files:** - Create: `backend/app/routers/discovery_routes.py` - Modify: `backend/app/main.py` (регистрация роутера) **Interfaces:** - Prefix `/api/discovery`, auth `current_login`: - `GET /tasks`, `POST /tasks`, `PATCH /tasks/{id}`, `DELETE /tasks/{id}`, `POST /tasks/{id}/start`, `POST /tasks/{id}/pause` - `POST /tasks/{id}/generate-keywords` — ИИ: промпт по description → JSON `{"keywords": [...]}` (8–16 строк RU+EN); ИИ недоступен/выключен → `{"keywords": [], "error": "..."}`. - `GET /tasks/{id}/candidates?status=` - `POST /candidates/{dialog_id}/join` — ручное вступление (вне квот): `tg.discovery_join` + `add_dialog_monitored` + `mark_joined(auto=False)`; 400 при ошибке. - `POST /candidates/{dialog_id}/reject` — `mark_rejected` (добавляет в чёрный список). Если кандидат уже `joined` — 400. - `GET /blacklist`, `DELETE /blacklist/{dialog_id}` - `GET /tasks/{id}/log` Pydantic-модели: `TaskCreate` (name, description, keywords, minSubscribers, lang, threshold, sampleSize, planJoins, autoJoin), `TaskPatch` (все optional), `GenKeywordsBody` не нужен (id в пути). - [ ] **Step 1: Реализовать роутер** (ValueError → HTTPException 400; KeyError → 404). - [ ] **Step 2: Зарегистрировать в main.py**. - [ ] **Step 3: Проверить API на живом контейнере**: логин, создание задачи plan=1, list, delete; `generate-keywords` вернёт error-ветку без настроенного ИИ (не падает). ---