Files
orchestrator/docs/work-items/ORCH-104/01-brd.md
claude-bot 94a3f399f2
All checks were successful
CI / test (push) Successful in 58s
analyst(ET): auto-commit from analyst run_id=638
2026-06-11 20:19:18 +03:00

202 lines
22 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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) → выбор всегда за
пользователем, ручной ввод всегда доступен, токен-верификация всё равно обязательна.