# План интеграции AstraDeploy и бота (FSM + callback API) ## Цели Сделать наблюдаемую, устойчивую и воспроизводимую установку через бота с поэтапными статусами. Скрипт уже умеет отдавать: - `started` - `step` - `success` - `failed` Нужно оборачивать это в `FSM`-движок на бэкенде бота. ## 1. Точка входа callback ### Endpoint - `POST /astra-deploy/report` - Заголовок: `Authorization: Bearer ` - Content-Type: `application/json` ### Тело (из скрипта) ```json { "status": "step", "core": "paper", "dir": "/opt/minecraft/paper", "port": 25565, "protocol": "tcp", "service": "tmux-systemd", "message": "Installing base packages", "step": "preflight_packages", "step_index": 14, "step_total": 80, "step_percent": 17 } ``` ### Рекомендуемый расширенный payload (бот-раннер может добавить) ```json { "request_id": "uuid", "job_id": "job_123", "user_id": "123", "locale": "ru" } ``` ### Ответ - `200/204` с `{ "ok": true }` или пустым телом. - Идемпотентность по `(request_id, status, step, step_index, step_total, ts_sec)` или аналогичной паре. ## 2. Запуск задачи из бота Ключевые параметры запускаемого процесса: - `--core ...` - `--dir ...` - `--port ...` - `--service systemd|tmux-systemd|screen|none` - `--user ...` - `--firewall yes|no` - `--yes` - `--accept-license yes` (обязательно в автоматическом) - `--accept-eula yes` для Java-ядер - `--report-url ...` - `--report-token ...` - `--locale ru|en` (или `LANGUAGE`/`LANG`) - `--dry-run`, `--update`, `--force-clean`, `--backup-existing`, `--allow-existing` - `--build`, `--mc-version` для `nethergamesmc` ## 3. FSM состояния ### Состояния - `QUEUED` - `RUNNING` - `VALIDATION` - `PREPARE_ENV` - `CORE_INSTALL` - `POST_INSTALL` - `WAITING_INPUT` - `ROLLBACK` - `DONE` - `FAILED` - `DRY_RUN` - `STALLED` (таймаут между шагами) ### Переходы - `started` -> `RUNNING` - `step(parse_complete|prepare_defaults|preflight_*)` -> `VALIDATION` - `step(preflight_packages|preflight_java|preflight_user|preflight_directory)` -> `PREPARE_ENV` - `step(install_core|deploy_core|update_core|core_*)` -> `CORE_INSTALL` - `step(core_post|core_service|service_*|finalize)` -> `POST_INSTALL` - `status=success` -> `DONE` - `status=failed` -> `FAILED` - `--dry-run` (локально определено) -> `DRY_RUN` - долгий таймаут без новых step -> `STALLED` - interactive без автоматических флагов и требующие ответа -> `WAITING_INPUT` ### Идёмпотентная обработка - Игнорировать дубликаты последнего шага в том же `request_id`. - Обновлять состояние только если новый `step_index` выше предыдущего или статус изменился на более поздний. ## 4. Полная карта `step` ### Общая фаза и предзапуск - `parse_complete` - `prepare_defaults` - `preflight_start` - `install_start` - `finalize` - `core_runtime` - `core_install` - `core_update` ### Предпроверки - `preflight_begin` - `preflight_validate_root` - `preflight_detect` - `preflight_detect_os` - `preflight_validate_support` - `preflight_update_mode_check` - `preflight_validate_plan` - `preflight_validate_licenses` - `preflight_validate_port` - `preflight_directory` - `preflight_packages` - `preflight_java` - `preflight_user` ### Установка/обновление ядер - `core_resolve_channel` - `core_resolve_download` - `core_fetch` - `core_render` - `core_configure` - `core_post` - `core_service` - `core_chown` - `core_backup` - `core_update_done` - `core_phpbuild_resolve` - `core_phpbuild_fetch` - `core_composer` - `core_repo_clone` - `core_install` - `install_core` - `deploy_core` - `update_core` ### Системные шаги - `packages_start` - `packages_dry_run` - `packages_index` - `download_start` - `download_completed` - `download_swap` - `firewall_start` - `firewall_done` - `firewall_manual` - `java_install` - `render_start_script` - `chmod_start_script` - `service_stop` - `service_create` - `service_reload_enable` - `service_start` - `user_create` - `user_exists` - `prepare_dir` - `permission_fix` ## 5. Маппинг на UX-сообщения (ru/en) ### RU - `preflight_*` → «Подготовка окружения и проверок» - `preflight_packages` / `packages_*` → «Установка базовых пакетов» - `core_*` → «Установка и настройка ядра» - `service_*`, `core_service` → «Настройка автозапуска» - `core_chown` / `prepare_dir` / `permission_fix` → «Настройка доступа» - `success` → «Установка завершена» - `failed` → «Ошибка установки» ### EN - `preflight_*` → `Environment preflight` - `core_*` → `Core installation` - `service_*` → `Service setup` - `failed` → `Deployment failed` ## 6. Edge-cases по сценариям запуска - **Interactive (без `--yes`)** - может остановиться на подтверждении лицензии/ЕULA/директории - статус `WAITING_INPUT` - **`--easy`** - обычный процесс, добавляется план-сводка до preflight - **`--update`** - `step_total` уменьшается на 6, проверяется существующая непустая директория - **`--dry-run`** - физически без изменений, callback может отсутствовать (как реализовано сейчас) - **`--force-clean`** - удаление содержимого директории перед установкой - **`--backup-existing`** - резервная копия `*.backup-` - **`--allow-existing`** - пропуск проверки непустой директории - **Неправильный `core` / OS** - жёсткий fail с объяснением - **Порт занят** - fail с деталями `tcp/udp` и предложением сменить порт - **Сбой callback API** - для скрипта не фатальный; бот не должен переводить задачу в `FAILED` из-за 5xx webhook-а ## 7. Rollback и пост-факту На фатальной ошибке скрипт делает: - лог ошибки - попытку удаления созданного сервиса (если был создан) - сообщение с путём лога (`/var/log/astra-deploy/...`) - завершение с кодом ошибки Для бота: - статусы -> `ROLLBACK` (внутренний подстейт) - показать пользователю: - возможная причина - путь лога - безопасный список ручных действий ## 8. Минимальная модель хранения ### `jobs` - `id` - `user_id` - `core`, `dir`, `port`, `service`, `locale` - `fsm_state` - `status` - `percent` - `step`, `step_index`, `step_total`, `message` - `request_id`, `report_token_id`, `process_pid` - `created_at`, `updated_at` ### `job_events` - `job_id` - `status`, `step`, `step_index`, `step_total`, `step_percent` - `message` - `raw_payload` (json) - `created_at` ## 9. Шаблоны уведомлений ### Telegram (RU) 1) Запуск: `🚀 Установка AstraDeploy запущена` 2) Шаг: `⚙️ {percent}% | {state} | {step}` 3) Успех: `✅ Установка завершена` 4) Ошибка: `❌ Установка завершена с ошибкой` ### Telegram (EN) 1) `🚀 AstraDeploy started` 2) `⚙️ {percent}% | {state} | {step}` 3) `✅ Installation completed` 4) `❌ Installation failed` Кнопки: - `Получить статус` - `Логи` - `Запустить проверку` - `Повторить (dry-run)` ## 10. Безопасность - Токены webhook не логировать. - Проверять `Authorization` строго. - Проверка whitelist по разрешённым `step`. - Rate limit на report endpoint. - Защищённое хранение токенов (vault/secret/env). ## 11. Проверочный набор для интеграции - `paper` non-interactive, валидные флаги - `paper` без `--accept-eula` и с `--yes` -> `failed` - `nethergamesmc --dry-run` -> без изменений, шаги в локальном логе - занятый порт -> `failed` - `--update` на пустой директории -> `failed` - `--force-clean` на непустой директории -> success после очистки - callback 5xx -> установка продолжается, без ложного FAILED в UI ## 12. Что отдаёт разработчику бота на старте - список поддерживаемых `core`: `pmmp,paper,purpur,velocity,powernukkitx,nethergamesmc` - поддерживаемые режимы сервиса: `systemd`, `tmux-systemd`, `screen`, `none` - список ключевых шагов из этого плана выше - статусные правила и fallback-поведение для отсутствующего callback