Files
orchestrator/docs/work-items/ORCH-104/01-brd.md
claude-bot be90632068
All checks were successful
CI / test (push) Successful in 58s
analyst(ET): auto-commit from analyst run_id=653
2026-06-12 10:29:36 +03:00

188 lines
20 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-12
model_used: claude-opus-4-8
---
# 01 — BRD (бизнес-требования): ORCH-104 — Установочный скрипт для Lite
Work Item: **ORCH-104** · Repo: **orchestrator** (self-hosting) · Стадия: analysis
Тип: FEATURE — UX/онбординг тиража (Type A эпика ORCH-10), поверх ORCH-102 (LITE_SETUP.md)
> ⚠️ **Объём заморожен (2026-06-12).** Один интерактивный установщик, автоматизирующий
> ручной маршрут `docs/deployment/LITE_SETUP.md`. Это **scripts + docs + tests**-изменение:
> рантайм/конвейер (`src/**`, `STAGE_TRANSITIONS`, `QG_CHECKS`, схема БД) — **не трогаются**
> (см. §2 «Вне объёма», NFR-1). Установщик НЕ форкает каноны: секреты — кирпичом
> `gen_secrets.py`, онбординг — кирпичом `onboard_project.py`, env — из `.env.example`.
---
## 1. Бизнес-контекст и проблема
### 1.1. Цель
Максимально упростить установку оркестратора в Lite-режиме на чужой хост: свести
тринадцатишаговую ручную инструкцию к **одному запускаемому файлу**, который сам сканирует
систему, подсказывает чего не хватает, запрашивает у оператора только действительно
неизвестные данные (токены/URL) и доводит инсталляцию до работающего конвейера.
### 1.2. Корневая боль (установленный факт)
`docs/deployment/LITE_SETUP.md` (ORCH-102) — золотой источник Lite-тиража, но это **ручной
runbook из 13 разделов**. Оператор вручную: проверяет предусловия хоста (§2), клонирует код (§3),
копирует `.env.example`, гоняет `gen_secrets.py`, **заполняет ~20 ключей `.env`** по четырём
группам (Plane/Gitea/Telegram/хост-порты, §4), настраивает webhook Plane (иногда **прямым SQL в
Postgres**, §5.4 путь Б), выпускает токен и webhook Gitea (§6), ставит claude CLI (§7), заводит
**два** Telegram-бота (§8), поднимает compose (§9), регистрирует проект `onboard_project.py` (§10),
гоняет smoke (§11). Это долго, легко ошибиться (опечатка в секрете → 401 HMAC; неверный uid →
worktree не пишется; занятый порт; пропущенный fail-closed статус `Confirm Deploy`/`STOP`), и
ошибка часто всплывает поздно — на `docker compose up`, а не в момент ввода.
### 1.3. Почему именно установщик (а не «ещё инструкция»)
Ручной маршрут уже задокументирован и стабилен (ORCH-102). Ценность ORCH-104 — **автоматизация
happy-path и ранняя валидация**: авто-детект всего детектируемого (uid/gid/docker-gid, свободные
порты, node/claude, **существующие инсталляции Plane/Gitea**), живая проверка каждого введённого
секрета ДО записи в `.env`, идемпотентный безопасный повтор. LITE_SETUP.md остаётся справочником
и фолбэком для траблшутинга — установщик его не заменяет, а исполняет.
### 1.4. Установленные факты (переиспользуемые кирпичи — НЕ изобретать)
- **`scripts/bootstrap_bundle.py` (ORCH-103)** — ближайший прецедент: step-движок `check→ensure`,
режимы `plan`/`apply`/`verify`, exit-коды `0/2/1`, честные `manual_checkpoint` с
`input()`/`getpass()`, stdlib-only, секреты не печатаются, **delete-операций нет вообще**,
каноны переиспользуются субпроцессами. Установщик Lite — его «connect-only»-сородич: bundle
*поднимает* Plane/Gitea, Lite *подключается* к уже существующим.
- **`scripts/gen_secrets.py` (ORCH-101)** — выпуск webhook-секретов (`secrets.token_hex(32)`),
отказ перезаписи без `--force`. Единственный легитимный источник секретов.
- **`scripts/onboard_project.py` (ORCH-009)** — регистрация проекта (22 статуса с точными
именами, лейблы `autoApprove`/`autoDeploy`/`Bug`, репо+webhook), `plan`/`apply`/`verify`,
идемпотентно, exit `0/2/1`.
- **`.env.example` / `.env.watchdog.example`** — канон 100% ключей старта (дефолт каждого ключа =
боевому значению, ORCH-101); установщик рендерит `.env` из них, не выдумывая ключи.
- **`docker-compose.yml`** — сам по себе является Lite-подмножеством (дефолтный `up -d` поднимает
ровно `orchestrator` + `orchestrator-watchdog`; `orchestrator-staging` за профилем `staging`).
### 1.5. Решения владельца (Owner decisions)
Предложены Владельцу как рекомендованные дефолты 2026-06-12; приняты для старта анализа,
пересматриваемы на review.
| ID | Решение | Дата |
|----|---------|------|
| D-1 | **Установка зависимостей = детект + управляемая установка.** Установщик сканирует, показывает чего не хватает, печатает **точную команду** под обнаруженный дистрибутив и предлагает выполнить безопасные с явного согласия (`y/N`). Системные пакеты под root — только с подтверждением, **никогда молча**. (Совпадает с self-hosting-этосом и каноном `bootstrap_bundle.py`.) | 2026-06-12 |
| D-2 | **Plane/Gitea = только подключение (Lite = Type A).** Установщик **детектит существующие** инсталляции; при нескольких — показывает нумерованный список и даёт выбрать; ручной ввод URL — всегда фолбэк. Если их нет вовсе → инструктирует поставить самостоятельно либо указывает на Bundled-тираж (ORCH-103). Установщик их **не поднимает**. | 2026-06-12 |
| D-3 | **Режимы = интерактивный мастер + `plan`/`apply`/`verify`.** Канон `bootstrap_bundle.py`: `plan` (дефолт, ноль мутаций) / `apply` / `verify`; exit `0/2/1`; без TTY → fail-closed exit 2 с инструкцией; идемпотентный повтор. Скрипт пригоден и для повторного/CI-прогона. | 2026-06-12 |
---
## 2. Объём (scope)
### В объёме
- **FR-1** — Единый entry-point `scripts/install_lite.py` с режимами `plan`/`apply`/`verify`.
- **FR-2** — Скан-предусловий хоста (детект docker/compose/git/python3/node/claude CLI/портов/
uid/gid/docker-gid/каталогов) с понятным списком «чего не хватает».
- **FR-3** — Управляемая установка недостающих зависимостей (детект дистрибутива → точная команда →
выполнение безопасных с согласия; D-1).
- **FR-4** — Детект существующих инсталляций Plane/Gitea на хосте + выбор при нескольких + ручной
фолбэк (D-2).
- **FR-5** — Интерактивный сбор данных оператора (Plane/Gitea/Telegram токены/URL) с **живой
верификацией каждого ДО записи** и скрытым вводом секретов.
- **FR-6** — Выпуск webhook-секретов строго кирпичом `gen_secrets.py`.
- **FR-7** — Сборка `.env` / `.env.watchdog` из канона `.env.example` / `.env.watchdog.example`
(идемпотентный рендер, права 600, без молчаливой перезаписи).
- **FR-8** — Подъём `orchestrator` + `orchestrator-watchdog` (`docker compose up`) + ожидание
готовности.
- **FR-9** — Регистрация проекта строго кирпичом `onboard_project.py apply`/`verify` + запись
`ORCH_PROJECTS_JSON`.
- **FR-10** — Health-верификация (`/health` / `/queue` / `/metrics`) + итоговая сводка PASS/FAIL.
- **FR-11** — Синхронизация документации (указатель LITE_SETUP.md на установщик; CLAUDE/README/
overview/CHANGELOG).
### Вне объёма
-**Любые изменения рантайма/конвейера**`src/**`, `STAGE_TRANSITIONS`, `QG_CHECKS`, `check_*`,
machine-verdict ключи, схема БД (NFR-1; установщик вне процесса орка и вне конвейера QG).
-**Подъём самих Plane/Gitea** — это Bundled-тираж (ORCH-103); Lite только подключается (D-2).
-**Полный безусловный авто-install системных пакетов под root без согласия** (D-1 отвергает).
-**Teardown / удаление** — установщик не несёт delete-операций (NFR-4); снос — документированная
процедура.
-**Замена LITE_SETUP.md** — runbook остаётся золотым источником и фолбэком (дополняем, не
выкидываем).
-**Форк канонов** — секреты/онбординг/env/compose не реимплементируются (NFR-7).
-**Автоматизация интерактивного логина claude CLI** — это поток Anthropic; остаётся
верифицируемым manual-step (OQ-6).
---
## 3. Заинтересованные стороны
- **Заказчик/инициатор:** Владелец (Слава) — цель «максимально упростить установку для пользователей».
- **Прямой пользователь:** внешний оператор/заказчик платформы, разворачивающий Lite на своём хосте.
- **Затрагиваемые:** сопровождающие LITE_SETUP.md (норматив синхронизации, BR-9); агенты
пайплайна (reviewer — проверка doc-sync; tester — прогон новых тестов).
- **Принимает результат:** reviewer (стадия review) + tester (стадия testing) по критериям §03.
---
## 4. Бизнес-требования (BR)
| ID | Требование | Связь |
|----|------------|-------|
| **BR-1** | Один запускаемый файл проводит оператора от «код склонирован» до «работающий Lite-конвейер», автоматизируя LITE_SETUP.md §2§11. | FR-1, AC-1 |
| **BR-2** | Установщик сканирует хост и выдаёт чёткий список отсутствующих предусловий (что есть / чего не хватает). | FR-2, AC-2 |
| **BR-3** | Для каждого недостающего предусловия — точная команда установки под обнаруженный дистрибутив + предложение выполнить безопасные с явного согласия (никогда молча, D-1). | FR-3, AC-3 |
| **BR-4** | Данные, которые знает только оператор (токены/URL Plane, Gitea, Telegram), запрашиваются интерактивно в момент установки, **каждое — с живой проверкой ДО записи**; секреты вводятся скрыто и не логируются. | FR-5, AC-5, AC-6 |
| **BR-5** | Установщик детектит существующие инсталляции Plane и Gitea; при нескольких — показывает список и даёт выбрать; ручной ввод URL — всегда доступный фолбэк (D-2). | FR-4, AC-4 |
| **BR-6** | Каноны не форкаются: webhook-секреты — `gen_secrets.py`, регистрация проекта — `onboard_project.py`, env — из `.env.example`/`.env.watchdog.example`, стек — из `docker-compose.yml`. | FR-6, FR-7, FR-9, AC-7 |
| **BR-7** | Идемпотентность и наблюдаемость: режимы `plan`(дефолт)/`apply`/`verify`; повтор пропускает завершённые шаги; exit `0/2/1`; без TTY → fail-closed exit 2 с инструкцией; финальная сводка PASS/FAIL. | FR-1, FR-10, AC-8, AC-11 |
| **BR-8** | Self-hosting-безопасность: установщик — только scripts/docs/tests; никогда не правит `src/**`/конвейер/схему; исполняется на хосте заказчика; говорит только с локальным хостом и собственными Plane/Gitea/Telegram заказчика; delete-операций нет. | NFR-1, NFR-4, AC-9, AC-10 |
| **BR-9** | Норматив сопровождения: установщик автоматизирует LITE_SETUP.md → оба держатся в синхроне (меняешь шаги установки → обнови LITE_SETUP.md в том же PR; держит анти-дрейф тест). | FR-11, AC-12 |
---
## 5. Нефункциональные требования (NFR)
| ID | Требование |
|----|------------|
| **NFR-1** | **Рантайм байт-в-байт.** `src/**`, `STAGE_TRANSITIONS`, `QG_CHECKS`, `check_*`, machine-verdict ключи, схема БД — не трогаются. Kill-switch не нужен: активация = только явный запуск оператором (паттерн ORCH-009/102/103). |
| **NFR-2** | **Гигиена секретов.** Значения секретов никогда не печатаются в stdout/логи; `.env`/`.env.watchdog` пишутся правами 600; существующие секреты не перетираются без явного согласия/`--force`. |
| **NFR-3** | **Never-raise в детекте.** Сбой любой эвристики обнаружения/пробы деградирует на ручной ввод и не роняет установщик и не блокирует прогон (best-effort, fail-safe). |
| **NFR-4** | **Нет delete-операций** нигде в скрипте (teardown — только документированная процедура; зеркало ORCH-103 D9). |
| **NFR-5** | **Идемпотентный ensure.** Каждый шаг `check→ensure`; повтор безопасен; валидный существующий конфиг пропускается; дублей проекта/webhook не создаётся. |
| **NFR-6** | **stdlib-only.** Никаких новых зависимостей платформы — работает на голом `python3` целевого хоста ДО первого `docker compose up` (как `gen_secrets.py`/`bootstrap_bundle.py`). Каноны-знания — только субпроцессами кирпичей. |
| **NFR-7** | **Детерминированные анти-дрейф тесты.** В unit-тестах — без сети/docker/subprocess/LLM; чистые функции изолированы; HTTP/процессы — через инъекцию фейков. |
| **NFR-8** | **Кросс-дистрибутив.** Детект и команды установки работают на распространённых Linux (Debian/Ubuntu `apt`, RHEL/Fedora `dnf`); неизвестный дистрибутив → деградация на «инструктировать». |
---
## 6. Допущения и ограничения
- **Контур Lite** (LITE_SETUP §1§2): Linux x86_64, у оператора есть root/sudo для установки
системных пакетов (или он ставит их сам). Вне контура — вне гарантии.
- **Plane и Gitea — собственные инсталляции заказчика** (Type A). Установщик к ним подключается,
не управляет их жизненным циклом.
- **Plane CE не даёт API первичной инициализации/иногда webhook** (LITE_SETUP §5.4): такие шаги
остаются честными manual-step с верификацией результата (контракт `manual_checkpoint`).
- **Интерактивный логин claude CLI** не автоматизируется (поток Anthropic) — manual-step (OQ-6).
- **Платформенные конвенции (не менять):** репо обязан называться `orchestrator`
(`SELF_HOSTING_REPO`); имена compose-сервисов/профиля — константы; `ORCH_STAGING_PORT`
прод-порт (fail-closed guard ORCH-058).
---
## 7. Критерии успеха (резюме)
Оператор на свежем хосте запускает один файл, отвечает на минимум вопросов (только то, что
система не может определить сама), и получает поднятый Lite-контур с зарегистрированным проектом и
зелёными `/health` `/queue` `/metrics`. Повторный запуск безопасен и пропускает сделанное. Рантайм
не изменён. Детальные PASS/FAIL — в `03-acceptance-criteria.md`.
---
## 8. Риски (кратко; детали — 10-tech-risks.md, заполняет архитектор)
- **R-1** — Эвристика детекта Plane/Gitea ложно-положительна/отрицательна (нестандартные имена
контейнеров/порты) → митигируется ручным фолбэком (NFR-3) и живой верификацией URL (BR-4).
- **R-2** — Авто-install системных пакетов небезопасен/дистрибутиво-зависим → митигируется D-1
(только с согласия, точная команда, неизвестный дистрибутив → инструктировать).
- **R-3** — Дрейф установщик ↔ LITE_SETUP.md при будущих правках → митигируется BR-9 + анти-дрейф
тестом.
- **R-4** — Случайная утечка секрета в лог/перетирание `.env` → митигируется NFR-2 (маскирование,
600, без silent overwrite), покрыто AC-6.
- **R-5** — Дублирование логики `bootstrap_bundle.py` (parse_env/render_env/manual_checkpoint) →
архитектурный вопрос «общий модуль vs самодостаточный файл» (OQ-4), не блокирует анализ.