202 lines
22 KiB
Markdown
202 lines
22 KiB
Markdown
---
|
||
work_item: ORCH-104
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-11
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# 01 — BRD: ORCH-104 — Установочный скрипт Lite-тиража (интерактивный installer)
|
||
|
||
Work Item: **ORCH-104** · Repo: **orchestrator** (self-hosting) · Стадия: analysis
|
||
Заказчик: Слава (поставщик платформы); конечный потребитель — внешний оператор Lite-тиража
|
||
|
||
---
|
||
|
||
## 1. Бизнес-контекст и проблема
|
||
|
||
### 1.1. Текущее состояние
|
||
Type A эпика ORCH-10 («Lite»: заказчик разворачивает у себя только `orchestrator` +
|
||
`orchestrator-watchdog`, подключая СВОИ Plane/Gitea/Telegram/LLM) закрыт задачей ORCH-102
|
||
**документом**: `docs/deployment/LITE_SETUP.md` — golden source из 13 нормативных разделов,
|
||
~30+ ручных fenced-команд и ~20 обязательных ключей нового хоста (§4.2 LITE_SETUP).
|
||
Маршрут полный и честный (каждый шаг несёт «Проверка:»/PASS/FAIL), но **порог входа высокий**:
|
||
|
||
- оператор вручную собирает и переносит в `.env` значения, которые машина определяет сама
|
||
(uid/gid владельца каталога репо, gid группы docker, пути node / дистрибутива claude-code,
|
||
занятость портов);
|
||
- ошибки конфигурации (символ в секрете, рассинхрон тройки прод-порта, ключи watchdog не в том
|
||
файле-носителе, branch protection на `main`) проявляются **поздно** — на smoke или первой
|
||
задаче, а не в момент ввода;
|
||
- каверзные шаги (webhook Plane CE без внешнего API — §5.4; два независимых Telegram-бота —
|
||
§8; статусы строго через onboarding-CLI — §5.3) требуют дисциплины чтения дока.
|
||
|
||
### 1.2. Бизнес-запрос (источник — описание задачи Plane)
|
||
Нужен **один установочный файл**, который:
|
||
1. на автомате выполняет установку Lite;
|
||
2. информацию, которую знает только пользователь (токен Plane и т.п.), **запрашивает в момент
|
||
установки**;
|
||
3. **сканирует систему**, говорит чего не хватает и **предлагает установить**;
|
||
4. если на хосте **несколько инсталляций** (например, Plane) — **показывает их и предлагает
|
||
выбрать**.
|
||
|
||
Цель — максимально упростить установку для пользователей.
|
||
|
||
### 1.3. Прецедент в платформе (переиспользовать, не изобретать)
|
||
- **Bundled (ORCH-103)** уже имеет установочный скрипт `scripts/bootstrap_bundle.py`:
|
||
режимы `plan` (дефолт) / `apply` / `verify`, step-движок check→ensure (повторный запуск =
|
||
каскад skip), exit-коды `0/2/1`, python stdlib-only, manual-checkpoint с обязательной
|
||
верификацией, **ни одной delete-операции**, секреты никогда не печатаются. **Lite такого
|
||
инструмента не имеет** — только док. ORCH-104 закрывает этот разрыв тем же выверенным
|
||
паттерном, добавляя три новых способности: интерактивный сбор данных, скан предусловий с
|
||
офером установки, discovery нескольких инсталляций с выбором.
|
||
- **Кирпичи готовы:** `scripts/gen_secrets.py` (webhook-секреты; x-mode «существующий файл →
|
||
отказ exit 2», перезапись только `--force`) и `scripts/onboard_project.py`
|
||
(`plan`/`apply`/`verify`: Plane-проект + 22 статуса + лейблы, Gitea-репо + webhook, kit,
|
||
merged-`ORCH_PROJECTS_JSON`). Канон статусов/лейблов **не форкается** — только кирпич.
|
||
|
||
### 1.4. Установленные факты (проверено по репо, не изобретать)
|
||
- Маршрут Lite = LITE_SETUP.md §2–§12; кирпичи-каноны: REPLICATION.md (карта env §2, секреты
|
||
§3, smoke §4), ONBOARDING.md (статусы §1), SETUP_WEBHOOKS.md, `.env.example` /
|
||
`.env.watchdog.example` (канон 100% ключей).
|
||
- Контур Lite: **Linux x86_64, Docker Engine + Compose v2, git, python3, node** (§2 LITE_SETUP);
|
||
вне контура — вне гарантии.
|
||
- Webhook Plane CE **не экспонирован во внешнем `/api/v1`** — настраивается через UI (если
|
||
сборка показывает) или прямым SQL в Postgres Plane (§5.4 LITE_SETUP).
|
||
- Branch protection на `main` **НЕ включать** (норматив §6.4, ADR D10 ORCH-009 / INV-4).
|
||
- Telegram-канала **два и они независимы** (C-1 ORCH-100); токен орка для watchdog
|
||
переиспользовать запрещено; sidecar читает только `.env.watchdog` (ловушка файла-носителя).
|
||
- Тираж **stateless**: данные/БД/секреты боевого хоста не переносятся; секреты — только
|
||
свежевыпущенные (§12 LITE_SETUP, REPLICATION §3/§5).
|
||
- Скрипт живёт в репо → `git clone` чекаута остаётся единственным ручным предшагом
|
||
(разрешает «курицу и яйцо» §3: к моменту запуска скрипта чекаут уже есть).
|
||
- Структуру LITE_SETUP.md пиннит анти-дрейф тест `tests/test_lite_setup_doc.py`
|
||
(«13 разделов в порядке», кирпичи, env-ключи ⊂ `.env.example`) — правка дока требует
|
||
синхронной правки теста в том же PR.
|
||
|
||
---
|
||
|
||
## 2. Объём (scope)
|
||
|
||
### 2.1. В объёме
|
||
- **Новый операторский CLI** в `scripts/` (один файл; кандидат имени — `setup_lite.py`,
|
||
финализирует архитектор), автоматизирующий маршрут LITE_SETUP §2–§12.
|
||
- **Скан предусловий** хоста (§2 + §7 LITE_SETUP) с честными вердиктами и **офером установки**
|
||
недостающего (с явного согласия; неподдерживаемый дистрибутив → manual-step).
|
||
- **Discovery инсталляций Plane/Gitea** на хосте (через локальный Docker): ≥2 → показать и
|
||
предложить выбрать; 1 → подставить по умолчанию; 0 → ручной ввод + честная подсказка.
|
||
- **Интерактивный сбор** обязательных ключей нового хоста (§4.2) с **немедленной верификацией**
|
||
каждого введённого значения фактическим вызовом (Plane API / Gitea API / Telegram getMe).
|
||
- **Автодетект хост-параметров** (uid/gid, docker gid, пути node/claude-code, порты) — то, что
|
||
машина может узнать сама, у пользователя не спрашивается.
|
||
- **Сборка `.env` / `.env.watchdog`** от канонов `.env.example` / `.env.watchdog.example`;
|
||
webhook-секреты — кирпичом `gen_secrets.py`; существующие файлы молча не перетираются.
|
||
- **Запуск Lite-контура** (ровно орк + watchdog) и health-проверки; stateless-проверка чистоты.
|
||
- **Регистрация проекта заказчика** строго кирпичом `onboard_project.py` (plan→apply→verify).
|
||
- **Итоговый отчёт** PASS/FAIL/MANUAL + exit-коды `0/2/1`; **идемпотентный повторный запуск**
|
||
(resume после manual-step).
|
||
- **Обновление `docs/deployment/LITE_SETUP.md`** (скрипт = рекомендованный быстрый путь; ручной
|
||
маршрут сохраняется как канон-fallback) + синхронные анти-дрейф тесты.
|
||
|
||
### 2.2. Вне объёма (явно, не делать)
|
||
- **Установка/администрирование Plane и Gitea** — Lite-рамка: это продукты заказчика
|
||
(§1 LITE_SETUP); кейс «нет инфраструктуры вовсе» закрыт Bundled (ORCH-103). Скрипт только
|
||
обнаруживает и подключает.
|
||
- Любые правки **`src/**`**, корневого `docker-compose.yml`, `Dockerfile`, схемы БД,
|
||
`STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` — рантайм байт-в-байт.
|
||
- Teardown / uninstall / миграция данных (stateless-канон; delete-операций в скрипте нет).
|
||
- Поддержка не-Linux платформ (контур Lite не расширяется).
|
||
- Автоматизация интерактивного OAuth-логина claude CLI (логин — по инструкции Anthropic,
|
||
вручную; скрипт только верифицирует результат).
|
||
- Самодостаточный «скачиватель» до чекаута (`curl | bash`): канал дистрибуции чекаута
|
||
согласуется с поставщиком (§3 LITE_SETUP) и не фиксирован платформой.
|
||
- Изменение `bootstrap_bundle.py` (Bundled) и `onboard_project.py` (кирпич переиспользуется
|
||
как есть).
|
||
|
||
---
|
||
|
||
## 3. Заинтересованные стороны
|
||
- **Внешний оператор/заказчик Lite** — главный потребитель: ставит платформу одной командой,
|
||
отвечая на вопросы по ходу; не обязан заранее читать 13 разделов.
|
||
- **Поставщик платформы (Слава/Owner)** — снижение стоимости каждого внедрения и числа
|
||
обращений «не взлетело»; принимает результат.
|
||
- **Платформа/конвейер** — не затрагиваются: операторский инструмент вне рантайма; прод и
|
||
enduro-trails не подвержены риску (активация — только явный запуск человеком).
|
||
|
||
---
|
||
|
||
## 4. Бизнес-требования (BR)
|
||
|
||
| ID | Требование | Связь |
|
||
|----|------------|-------|
|
||
| BR-1 | **Один входной файл:** установка Lite выполняется одной командой из корня чекаута на голом python3; каждый шаг маршрута LITE_SETUP §2–§12 либо выполняется скриптом, либо явно выдаётся как ручной чекпоинт с верификацией результата. Молчаливых пропусков нет. | FR-1/FR-10, AC-1 |
|
||
| BR-2 | **Скан системы:** скрипт определяет недостающие предусловия (docker/compose/git/python3/node/claude-code/uid-gid/docker-group/ssh/порты), честно перечисляет их и предлагает установить/исправить; установка — только с явного согласия пользователя; неподдерживаемое окружение → manual-step с готовыми командами. | FR-2, AC-2 |
|
||
| BR-3 | **Запрос данных в момент установки:** все обязательные ключи нового хоста (§4.2 LITE_SETUP) запрашиваются интерактивно тогда, когда нужны; каждый токен/URL немедленно верифицируется фактическим вызовом; ввод секретов скрытый, значения секретов нигде не печатаются. | FR-4, AC-4 |
|
||
| BR-4 | **Discovery с выбором:** при нескольких инсталляциях Plane/Gitea на хосте скрипт показывает кандидатов и предлагает выбрать; при одной — подставляет её по умолчанию; при нуле — ручной ввод и честная подсказка (Lite не ставит Plane/Gitea; «нет инфраструктуры» = маршрут Bundled). Вариант «ввести вручную» доступен всегда. | FR-3, AC-3 |
|
||
| BR-5 | **Безопасность повторного запуска и чужих сред:** повторный запуск идемпотентен (каскад skip, resume после manual-step); существующие `.env`/`.env.watchdog` не перетираются молча; скрипт не содержит delete-операций, не трогает `main`, не рестартит чужие контейнеры; каждая мутация — с явного согласия. | FR-1/FR-6, AC-5/AC-11 |
|
||
| BR-6 | **Результат — работающий Lite-контур:** ровно два контейнера (`orchestrator`, `orchestrator-watchdog`), `/health`–`/queue`–`/metrics` зелёные, stateless-чистота подтверждена, проект заказчика зарегистрирован кирпичом onboarding, smoke-инструкция выдана; итог прогона — однозначный вердикт + exit-код `0/2/1`. | FR-8/FR-9/FR-10, AC-9/AC-10 |
|
||
| BR-7 | **Канон не форкается:** скрипт автоматизирует маршрут LITE_SETUP.md и использует существующие кирпичи (`gen_secrets.py`, `onboard_project.py`); сам канон-знание (статусы, ключи, нормативы) не дублирует; изменение маршрута → обновление LITE_SETUP.md в том же PR (норматив NFR-5 ORCH-102); соответствие закреплено анти-дрейф тестами. | FR-11, AC-14 |
|
||
| BR-8 | **Рантайм не тронут:** `src/**`, корневой compose, `Dockerfile`, `STAGE_TRANSITIONS`/`QG_CHECKS`/схема БД — байт-в-байт; kill-switch не нужен (активация — только явный запуск оператором; паттерн ORCH-009/102/103). | NFR-7, AC-13 |
|
||
|
||
---
|
||
|
||
## 5. Нефункциональные требования (NFR)
|
||
|
||
| ID | Требование |
|
||
|----|------------|
|
||
| NFR-1 | **stdlib-only:** скрипт работает на голом python3 целевого хоста ДО любого venv/`docker compose up`; модули платформы (`src/**`) не импортируются; закрепляется ast-сканом в тестах (паттерн `test_bootstrap_script.py`). |
|
||
| NFR-2 | **Безопасность среды заказчика:** никаких delete/необратимых операций; мутации — только локальный хост и только с явного согласия; БД Plane заказчика мутируется (webhook, Path Б §5.4) исключительно по явному согласию с обязательной верификацией; branch protection скрипт сам НЕ удаляет (только честный FAIL с лечением). |
|
||
| NFR-3 | **Секрет-гигиена:** значения секретов не печатаются и не логируются (только имена ключей/пути файлов); ввод — скрытый; секреты — только свежевыпущенные (stateless, REPLICATION §3); боевые значения исходного хоста не используются даже как подсказки-дефолты. |
|
||
| NFR-4 | **Честность шагов:** каждый шаг — явный PASS/FAIL/MANUAL со ссылкой на соответствующий § LITE_SETUP; «молчаливый пропуск запрещён» (паттерн ORCH-103). |
|
||
| NFR-5 | **Тестируемость без TTY/сети/docker:** вся решающая логика (вердикты предусловий, классификация discovery, когерентность портов, рендер env, аргументы onboard, step-движок) — чистые функции; интерактив — за инжектируемым I/O; pytest-прогон детерминирован. |
|
||
| NFR-6 | **Идемпотентность/resume:** step-движок check→ensure; повторный запуск пропускает выполненное и продолжает с первого незавершённого шага; manual-step → exit 2 → «resume» = просто повторный запуск (паттерн bootstrap_bundle). |
|
||
| NFR-7 | **Self-hosting безопасность:** случайный запуск на хосте с живым продом не ломает ничего: ранний отказ по существующему `.env` (без force), read-only режим диагностики, никакого воздействия на уже бегущие контейнеры без согласия. |
|
||
| NFR-8 | **Поддержка канона:** LITE_SETUP.md, CHANGELOG.md, витрина `docs/overview/` (если затронуто описание тиража) обновляются в том же PR (правило агентов №2); анти-дрейф тесты дока остаются зелёными. |
|
||
|
||
---
|
||
|
||
## 6. Допущения и ограничения
|
||
- Контур — как у Lite: Linux x86_64, Docker Engine + Compose v2; скрипт контур не расширяет.
|
||
- Plane/Gitea — инсталляции заказчика, сетево доступны с хоста оркестратора; их установка —
|
||
вне задачи.
|
||
- Discovery гарантируется для **docker-инсталляций** (контейнеры с опознаваемыми
|
||
образами/метками compose); native/k8s-инсталляции честно уходят в ручной ввод URL —
|
||
это не FAIL discovery.
|
||
- Запуск — из корня чекаута репо `orchestrator`; clone чекаута — ручной предшаг (канал
|
||
дистрибуции — договорённость с поставщиком, §3 LITE_SETUP).
|
||
- Язык UX скрипта — русский (паттерн `gen_secrets.py`/`bootstrap_bundle.py`); сообщения
|
||
ссылаются на разделы LITE_SETUP.md как на полный канон.
|
||
- Интерактивный OAuth-логин claude CLI принципиально не автоматизируем скриптом —
|
||
верифицируется результат (читаемость кредов uid'ом контейнера).
|
||
|
||
---
|
||
|
||
## 7. Критерии успеха (резюме; детали — 03-acceptance-criteria.md)
|
||
- AC-1 одна команда, режимы и идемпотентный повтор;
|
||
- AC-2 скан предусловий с честными вердиктами и офером установки;
|
||
- AC-3 discovery 0/1/много с выбором и ручным fallback;
|
||
- AC-4 интерактивный сбор с немедленной верификацией и секрет-гигиеной;
|
||
- AC-5/AC-6 корректная сборка `.env` (обязательные ключи, свежие секреты, когерентные порты,
|
||
отказ перетирания);
|
||
- AC-7/AC-8 нормативы C-1 (два бота) и §6.4 (branch protection) машинно охраняются;
|
||
- AC-9 Lite-контур поднят и здоров; AC-10 проект зарегистрирован кирпичом;
|
||
- AC-11/AC-12 exit-коды, resume, stdlib-only/no-delete гигиена;
|
||
- AC-13 рантайм байт-в-байт; AC-14 документация обновлена синхронно.
|
||
|
||
---
|
||
|
||
## 8. Риски (кратко; детали — 10-tech-risks.md, заполняет архитектор)
|
||
- **R-1 Запуск на боевом хосте по ошибке** → ранний guard существующего `.env`/живого
|
||
инстанса; read-only диагностика дефолтно безопасна.
|
||
- **R-2 Офер установки пакетов** — вмешательство в систему заказчика → только явное согласие,
|
||
печать точной команды; неопределимый пакетный менеджер → manual-step.
|
||
- **R-3 SQL-вставка webhook в Postgres Plane** (Path Б §5.4) инвазивна → только согласие +
|
||
подтверждённый пользователем контейнер БД + верификация; UI-путь предпочтителен.
|
||
- **R-4 Дрейф скрипта от канона LITE_SETUP** (двойной источник истины) → норматив same-PR +
|
||
анти-дрейф тесты (ключи ⊂ `.env.example`, кирпичи, упоминание скрипта в доке).
|
||
- **R-5 Интерактивность против автоматизации** (CI/non-TTY: риск зависания) → инжектируемый
|
||
I/O, честный отказ/неинтерактивная альтернатива в non-TTY.
|
||
- **R-6 Ложноположительный discovery** (чужой контейнер опознан как Plane) → выбор всегда за
|
||
пользователем, ручной ввод всегда доступен, токен-верификация всё равно обязательна.
|