feat: add bds core, locale updates and safety fixes

This commit is contained in:
2026-05-31 14:01:34 +03:00
parent d1686355e8
commit c769140913
34 changed files with 1535 additions and 12 deletions

291
bot-integration-fsm-plan.md Normal file
View 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