# 📑 PRODUCT REQUIREMENTS DOCUMENT (PRD)## 1. Цели проекта - Основная цель: Создать легковесную CLI-утилиту на Rust для централизованного деплоя хобби-проектов (Node.js, Rust) с локального ПК на слабую VPS по SSH. - Зачем это нужно: Избежать дублирования скриптов деплоя в репозиториях, полностью разгрузить CPU слабой VPS (сборка только на ПК) и получить удовольствие от разработки пет-проекта. ## 2. Ключевые функции (Scope) - Центральный конфиг: Все настройки всех проектов хранятся в одном локальном файле (deploy.toml). - Локальное выполнение: Запуск команд сборки, тестов или линтеров на машине разработчика. - Синхронизация файлов: Передача скомпилированных артефактов (папок dist, бинарников) на VPS. - Удаленное выполнение: Запуск команд управления сервисами (pm2 restart, systemctl restart) на VPS через SSH. - Безопасность: Использование существующего SSH-агента или приватного ключа (~/.ssh/id_rsa), никаких паролей в конфигах. - Аварийная остановка (Fail-Fast): Если любой шаг (локальный или удаленный) падает с ошибкой, деплой немедленно прекращается. ## 3. Пользовательский сценарий (UX) 1. Разработчик находится в любой папке терминала. 2. Вводит команду: xboctploy my-node-app. 3. Утилита красиво (с логами и цветом) показывает прогресс: - 🟢 [Local] running: npm run build... Success! - 🔵 [SFTP] transferring dist/ to /var/www/node-app... Done! - 🟡 [Remote] running: pm2 restart node-app... Success! - 🎉 Deploy successful! ### Разрешение конфигурации Утилита ищет deploy.toml по цепочке: сначала `./deploy.toml` в текущей папке, если не найден — глобальный `~/.config/xboctploy/deploy.toml`. Локальный файл приоритетен для простоты тестирования на конкретном проекте. --- ## 🏗️ ARCHITECTURE DECISION RECORD (ADR)## ADR-001: Выбор языка и формата конфигурации - Решение: Разработка на Rust, формат конфигурации — TOML. - Обоснование: Rust обеспечивает максимальную скорость запуска CLI и безопасность работы с памятью. TOML выбран как «родной» для экосистемы Rust формат (аналогично Cargo.toml), который проще читать и писать вручную, чем YAML, и он строго типизирован в отличие от JSON. ## ADR-002: Управление зависимостями (Крейты) Для минимизации кодовой базы и сохранения легковесности утверждается следующий стек библиотек: - clap (с feature-флагом derive) — для парсинга аргументов командной строки. - serde + toml — для парсинга файла конфигурации в структуры Rust. - ssh2-config + ssh2 (или async-ssh2-lite, если потребуется асинхронность) — для чтения системных настроек SSH (~/.ssh/config) и создания SSH/SFTP сессий. - anyhow — для простой и понятной обработки ошибок без написания кастомных перечислений (enums). ## ADR-003: Модель выполнения (Синхронная vs Асинхронная) - Решение: Использовать синхронную (блокирующую) модель выполнения. - Обоснование: Деплой одного проекта происходит строго последовательно (Шаг 1 -> Шаг 2 -> Шаг 3). Асинхронность (tokio) усложнит код, увеличит размер бинарника и не даст преимуществ, так как параллельное выполнение шагов внутри одного деплоя не требуется. ## ADR-004: Механизм передачи файлов - Решение: Использование протокола SFTP/SCP через встроенные возможности крейта ssh2. - Обоснование: Отказ от вызова системного rsync через std::process::Command делает утилиту самодостаточной и независимой от того, установлен ли rsync на конкретной ОС (например, на Windows утилита отработает так же успешно, как на Linux). ## ADR-005: Стратегия обработки ошибок и идемпотентность - Решение: Реализовать стратегию Fail-Fast с выводом stderr упавшей команды. Идемпотентность (как в Ansible) на первом этапе не реализуется. - Обоснование: Для хобби-проекта проверка состояния системы перед каждым шагом (идемпотентность) избыточна и сильно усложнит архитектуру. Если команда упала, пользователь просто фиксит ошибку и запускает деплой заново. ## ADR-006: Замена ssh2 (libssh2) на russh в качестве SSH-транспорта - Решение: Вместо крейта ssh2 (обёртка над libssh2) используется чисто Rust-овый russh (0.62.x, crypto-backend ring). Парсер ~/.ssh/config остаётся на ssh2-config (он не зависит от libssh2). Публичный API утилиты синхронный (ADR-003); tokio-runtime живёт внутри модуля ssh и наружу не торчит. - Обоснование: libssh2 не поддерживает шифр `chacha20-poly1305@openssh.com`, а свежие OpenSSH-серверы (9.x/10.x, в т.ч. дефолтные Ubuntu) часто предлагают только его — подключение падает с Session(-5). Утилита обязана работать с любым стоковым сервером без правки sshd_config. russh умеет chacha20-poly1305, aes-gcm и современные KEX (включая post-quantum гибриды). - Следствия: проверка host key реализована через TOFU поверх ~/.ssh/known_hosts средствами russh; ssh-agent (этап 6) доступен через встроенные agent-возможности russh; сборка не требует NASM/CMake (в отличие от aws-lc-rs дефолта russh 0.63, поэтому зафиксирован backend ring). --- ## 📈 План развития проекта (Roadmap) - MVP: Парсинг TOML, последовательный запуск локальных std::process::Command, SSH-коннект по ключу, запуск удаленных команд. - Files: Реализация копирования одиночных файлов и рекурсивного копирования папок по SFTP. - UX: Добавление красивого вывода (библиотека indicatif для progress-bar или colored для цветных логов). - Advanced: Поддержка переменных окружения (.env), интеграция с системным ssh-agent.