feat: add bds core, locale updates and safety fixes
This commit is contained in:
291
bot-integration-fsm-plan.md
Normal file
291
bot-integration-fsm-plan.md
Normal file
@@ -0,0 +1,291 @@
|
||||
# План интеграции AstraDeploy и бота (FSM + callback API)
|
||||
|
||||
## Цели
|
||||
|
||||
Сделать наблюдаемую, устойчивую и воспроизводимую установку через бота с поэтапными статусами.
|
||||
|
||||
Скрипт уже умеет отдавать:
|
||||
- `started`
|
||||
- `step`
|
||||
- `success`
|
||||
- `failed`
|
||||
|
||||
Нужно оборачивать это в `FSM`-движок на бэкенде бота.
|
||||
|
||||
## 1. Точка входа callback
|
||||
|
||||
### Endpoint
|
||||
- `POST /astra-deploy/report`
|
||||
- Заголовок: `Authorization: Bearer <report-token>`
|
||||
- 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-<timestamp>`
|
||||
- **`--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
|
||||
Reference in New Issue
Block a user