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

22 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used
work_item stage author_agent status created_at model_used
ORCH-104 analysis analyst ready-for-review 2026-06-11 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) → выбор всегда за пользователем, ручной ввод всегда доступен, токен-верификация всё равно обязательна.