## Why
Сейчас публикатор встроен в веб-приложение (web/app.py импортирует publisher.bot напрямую
и вызывает publish_multi). Это нарушает изоляцию элементов системы и мешает масштабированию:
- публикация привязана к процессу веба (ошибка Bot API роняет весь approve);
- нет отдельного жизненного цикла (нельзя перезапустить/обновить публикатор отдельно);
- каналы захардкожены шаблоном @dedinit_vesti_
__bot, а реальная схема —
«один бот-контроллер, несколько каналов» (на старте один @dedinit_vesti, потом больше);
- нет единой точки входа для публикации из любых компонентов (веб, cron, будущие боты VK/fediverse).
Цель — вынести публикацию в **изолированный микросервис** (отдельный FastAPI-сервис в
контейнере), который вызывается HTTP-запросом при необходимости. Это соответствует
архитектурному решению «сегментировать элементы системы на микросервисы в отдельных
контейнерах» (PRD, раздел 5).
## What Changes
- Новый сервис `publisher/` (или `services/publisher/`): FastAPI-приложение с эндпоинтом
`POST /api/v1/publish` (публикация карточки в один или несколько каналов) и
`GET /healthz` (healthcheck).
- Конфигурация сервиса: `VESTI_BOT_TOKEN` (токен бота-контроллера @dedinit_controller_bot),
`TG_PROXY=socks5://127.0.0.1:1080` (Telegram из РФ доступен только через SOCKS5),
список каналов (сейчас `@dedinit_vesti`, потом несколько) — из .env или отдельного YAML.
- Бот-контроллер: один (id 7765665742, @dedinit_controller_bot), публикует во все каналы,
в которые добавлен администратором.
- `publisher/bot.py` переносится в сервис (логика publish_card/publish_multi/get_views),
но с конфигом каналов вместо шаблона @dedinit_vesti___bot.
- `web/app.py` больше НЕ импортирует publisher напрямую: вместо publish_multi — HTTP POST
на publisher-service `/api/v1/publish`.
- Dockerfile + docker-compose для сервиса; healthcheck; логирование.
### Не меняется
- Карточка (publisher/card.py) остаётся (формат ≤4096, атрибуция «Дед в АйТи», ссылка на оригинал).
- Режим публикации «черновик на подтверждение» (веб подтверждает → публикация). Без автопостинга.
## Capabilities
### New Capabilities
- `tg-publisher-service`: Изолированный FastAPI-сервис публикации в Telegram:
единая точка `POST /api/v1/publish`, конфиг каналов, прокси SOCKS5 для Bot API,
сбор views, healthcheck.
### Modified Capabilities
- `tg-publisher`: логика публикации переезжает в сервис; вызывающий код (веб) использует HTTP.
- `vesti-web`: approve вызывает publisher-service по HTTP вместо прямого импорта.
- `news-store`: без изменений (бандлы создаёт веб, как раньше).
## Impact
- Затронутые сервисы/порты: publisher-service — новый порт (напр. 8410, локально);
vesti-web :8400 — меняет способ вызова публикатора (HTTP вместо импорта).
- Файлы:
- новый: services/publisher/ (app/, Dockerfile, docker-compose.yml, requirements.py, README.md)
- изменён: web/app.py (HTTP-вызов), .env.example (VESTI_BOT_CHANNELS, TG_PROXY)
- перенос: publisher/bot.py → services/publisher/ (логика сохраняется)
- Данные: без миграций БД (published.tg_message_id/distributed_dirs остаются).
- Секреты: тот же VESTI_BOT_TOKEN (бот-контроллер); TG_PROXY переиспользуется.
- Прокси: Bot API ТОЛЬКО через SOCKS5 127.0.0.1:1080 (api.telegram.org из РФ недоступен).
- Rollback: вернуть в web/app.py импорт publisher.bot (старый путь); сервис можно не запускать.
## Risks
- SOCKS5-прокси недоступен → сервис не может опубликовать: healthcheck должен это показывать.
- Бот не админ канала → sendMessage 403: сервис возвращает понятную ошибку, веб показывает ее.
- Несколько каналов в будущем: конфиг списком (VESTI_BOT_CHANNELS=@a,@b), fan-out по каналам.
- Рестарт сервисов — только извне (SSH sudo systemctl restart) — правило окружения.