Files
orchestrator/docs/work-items/ORCH-103/01-brd.md

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-103 analysis analyst ready-for-review 2026-06-11 claude-opus-4-8

01 — BRD: ORCH-103 — ORCH-10b Bundled-тираж: весь стек одним комплектом + bootstrap-скрипт

Work Item: ORCH-103 · Repo: orchestrator (self-hosting) · Стадия: analysis Заказчик: Слава · Эпик: ORCH-10 (домен D5 «Масштаб», docs/epics/self-evolution.md) · Тип: B — Bundled


1. Бизнес-контекст и проблема

1.1. Цель эпика ORCH-10

Тираж платформы — РАЗДАЧА текущей функциональности нескольким заказчикам на тест. Решения Владельца 10.06 (приняты как требования): ДВА типа тиража, ОБА stateless (наши задачи/данные/секреты НЕ переносим — чистый старт):

  • Тип A (Lite, ORCH-102 ) — переносится ТОЛЬКО орк+watchdog; Plane/Gitea/LLM/Telegram заказчик донастраивает сам по инструкции docs/deployment/LITE_SETUP.md.
  • Тип B (Bundled, эта задача)весь стек одним комплектом (орк + watchdog + Gitea + Plane + рантайм-обвязка агентов) — «под ключ».

1.2. Проблема, которую закрывает ORCH-103

Lite предполагает, что у заказчика уже есть (или он сам поднимет) свои Plane и Gitea. Для заказчика без собственной инфраструктуры это барьер: Plane CE self-hosted — это ~14 контейнеров со своей БД/брокером/хранилищем, Gitea — отдельная установка, и поверх всего — первичная инициализация (админы, токены, workspace, 22 статуса, лейблы, вебхуки в обе стороны, git-доступ агентов). Сегодня репо не содержит ни compose-описания этого стека, ни автоматизации его доводки: разворачивание «с нуля до работающего конвейера» = многочасовая ручная работа по сторонним докам с рисками дефолтных паролей и дрейфа от канона платформы.

ORCH-103 должен дать: один compose-комплект всего стека + bootstrap-скрипт, доводящий свежеподнятый стек до рабочего состояния одной командой/визардом, + новые секреты на каждую инсталляцию + инструкцию docs/deployment/BUNDLED_SETUP.md с требованиями к хосту.

1.3. Установленные факты (проверено по репо — не изобретать)

  • Корневой docker-compose.yml защищён анти-дрейфом: ровно 3 сервиса (orchestrator, orchestrator-watchdog, orchestrator-staging за profiles: ["staging"]); tests/test_lite_setup_doc.py (TC-04) проверяет точное множество сервисов и запрещает появление в нём имён/образов с подстроками plane/gitea → bundle-компоуз обязан быть отдельным файлом, корневой compose не форкается и не расширяется.
  • Кирпичи уже в main (переиспользовать, не дублировать):
    • scripts/gen_secrets.py (ORCH-101) — криптослучайные webhook-секреты (ORCH_PLANE_WEBHOOK_SECRET/ORCH_GITEA_WEBHOOK_SECRET), печать по умолчанию, --write отказывает при существующем .env, --force — перезапись; exit 0/2.
    • scripts/onboard_project.py (ORCH-009) — plan (GET-only) / apply (идемпотентный ensure, без delete) / verify: Plane-проект + 22 статуса (read-only импорт plane_sync._PLANE_NAME_TO_KEY, fail-closed имена Confirm Deploy/STOP) + лейблы autoApprove/autoDeploy/Bug; Gitea-репо + per-repo webhook (push/pull_request/status, ОДИН глобальный ORCH_GITEA_WEBHOOK_SECRET); недоступное в Plane CE API → manual-step (fail-safe); exit 0/2/1.
    • docs/operations/REPLICATION.md (ORCH-101) — карта env (§2), чек-лист секретов (§3), smoke §4 (шаги 06 с PASS/FAIL: config-резолв → /health/queue+/metrics → onboard plan/apply/verify → тестовая задача → артефакты 0104 → опц. до done); §1 — таблица границ, где Type B помечен «отдельная задача».
    • docs/deployment/LITE_SETUP.md (ORCH-102) — канон тиражной инструкции: 13 нормативных разделов, каждый шаг = fenced-команда + явная «Проверка:» PASS/FAIL, хост-специфика только плейсхолдерами; канон не форкается — общие шаги ссылками.
    • .env.example — канон 100% ключей орка; .env.watchdog.example — канон watchdog (key-set-sync тестом, D5 ORCH-102).
  • Хост-параметризация завершена (ORCH-101): платформа разворачивается без правки кода — только env (${VAR:-default}-интерполяция compose, ARG APP_* Dockerfile); анти-регресс tests/test_no_host_hardcodes.py (FORBIDDEN-литералы: IP//home/slin/mva154/duckdns).
  • Claude CLI НЕ запечён в образ орка: монтируется с хоста (ORCH_HOST_CLAUDE_CODE_DIR/ORCH_HOST_NODE_BIN/ORCH_HOST_CLAUDE_DIR/ORCH_HOST_CLAUDE_JSON). «Агенты» в комплекте = рантайм-обвязка запуска; инсталляция Claude CLI и LLM-ключ — внешнее предусловие хоста заказчика (как Lite §7), bundle их не содержит и не генерирует.
  • Нормативы тиражной Gitea: branch protection на main НЕ включать (D10 ORCH-009 / INV-4 — мерж только через Gitea PR-merge API); pre-receive не вводится.
  • Plane CE self-hosted ≈ 14 контейнеров (web/admin/space/api/worker/beat/live/migrator + postgres/redis/mq/minio/proxy) — ресурсоёмко; часть первичной инициализации в CE недоступна по API → честные ручные чекпоинты (паттерн manual-step ORCH-009).

2. Объём (scope)

2.1. В объёме

  • Bundle-compose — отдельный compose-комплект всего стека: орк + watchdog + Gitea + Plane-стек (~14 контейнеров); пиннинг версий; чистые именованные тома; согласованная сетевая достижимость (вебхуки в обе стороны).
  • Bootstrap-скрипт — один запуск (команда/визард): поднять всё → дождаться готовности/миграций → инициализация Gitea (админ/токен) → инициализация Plane (instance/workspace/API-токен; CE-ограничения → явные manual-step чекпоинты) → онбординг sandbox-проекта (22 статуса/3 лейбла/репо/вебхуки — через onboard_project.py) → git-доступ агентов → сборка .env/.env.watchdog орка → health → smoke-подсказка.
  • Инициализация секретов — генерация НОВЫХ на каждую инсталляцию (reuse gen_secrets.py + bundle-внутренние креды: пароли БД/брокера/хранилища Plane, админ Gitea); дефолтных паролей в репо нет.
  • docs/deployment/BUNDLED_SETUP.md — инструкция запуска bundle по канону LITE_SETUP, включая требования к хосту (RAM/диск/CPU/порты).
  • Структурные анти-дрейф тесты (без docker/сети/LLM в CI) + полный зелёный pytest + CHANGELOG.
  • Отметка Type B в docs/operations/REPLICATION.md §1 (границы трёх задач эпика).

2.2. Вне объёма (явно, не делать)

  • Изменения рантайма: src/**, корневой docker-compose.yml, Dockerfile, .gitea/workflows/, STAGE_TRANSITIONS/QG_CHECKS/check_*/machine-verdict/схема БД — байт-в-байт.
  • Перенос наших задач/данных/секретов (stateless — решение Владельца 10.06).
  • Автоматическая установка Claude CLI / выдача LLM-ключей / создание Telegram-ботов — внешние предусловия заказчика (документируются, не автоматизируются).
  • HTTPS/домены/публичный reverse-proxy заказчика — за рамками bundle (документируется как ручной шаг при необходимости).
  • Процедура обновления (upgrade) развёрнутого bundle; миграция Lite→Bundled; кластерные/ multi-host топологии; мультитенантность (D5.6) и горизонтальный воркер-пул (D5.4).
  • Какая-либо активация bundle на НАШЕМ боевом хосте.

3. Заинтересованные стороны

  • Владелец (Слава) — раздаёт платформу заказчикам на тест; принимает результат.
  • Оператор заказчика — целевой читатель BUNDLED_SETUP.md: чистый Linux-хост, docker+compose, без знания внутренностей платформы.
  • Self-hosting прод (orchestrator, общий для всех проектов) — не должен быть затронут: задача — артефакты репо (compose/скрипт/доки/тесты), активируемые только явным запуском на ЦЕЛЕВОМ хосте.

4. Бизнес-требования (BR)

ID Требование Связь
BR-1 Единый bundle-compose (отдельный файл) поднимает ВЕСЬ стек одной командой: орк, watchdog, Gitea, Plane-стек. Корневой docker-compose.yml не форкается и не меняется. AC-1, AC-6, FR-1
BR-2 Bootstrap-скрипт ОДНИМ запуском (команда/визард) доводит свежеподнятый стек до рабочего состояния: готовность/миграции → init Gitea → init Plane → онбординг sandbox-проекта → git-доступ агентов → конфиг орка → health. Шаги, физически недоступные через Plane CE API, оформляются явными интерактивными manual-step чекпоинтами (fail-safe, паттерн ORCH-009) — без молчаливых пропусков. AC-1, FR-2
BR-3 После bootstrap smoke проходит: тестовый проект создан, тестовая задача доезжает минимум до артефактов 0104 в ветке (минимальный сигнал REPLICATION §4 шаг 5); расширенно — до done. Вебхуки работают в ОБЕ стороны (Plane→орк, Gitea→орк, орк→Plane/Gitea API). AC-2, FR-2/FR-6
BR-4 Stateless: каждая инсталляция стартует с чистых томов/БД (Plane, Gitea, орк) и НОВЫХ секретов (gen_secrets.py + bundle-внутренние креды). Боевые данные/секреты не используются ни на одном шаге; в репо нет ни одного реального секрета/дефолтного пароля. AC-3, FR-3
BR-5 docs/deployment/BUNDLED_SETUP.md написан по канону LITE_SETUP (fenced-команды + «Проверка:» PASS/FAIL, плейсхолдеры вместо хост-специфики, канон не форкается — общие шаги ссылками на LITE_SETUP/ONBOARDING/REPLICATION) и фиксирует требования к хосту: RAM/диск/CPU/занимаемые порты (Plane ~14 контейнеров — ресурсоёмко). AC-4, FR-4
BR-6 Переиспользование кирпичей без дублирования: секреты — gen_secrets.py; статусы/лейблы/репо/вебхуки — onboard_project.py (22 статуса — из plane_sync._PLANE_NAME_TO_KEY, нулевой дрейф); smoke — шаги REPLICATION §4. Bootstrap не реализует собственную копию этих канонов. FR-2/FR-3, AC-7
BR-7 Идемпотентность/fail-safe: повторный запуск bootstrap безопасен (ensure/skip, без delete-операций); запуск на «грязном» хосте (существующие тома/занятые порты/нехватка ресурсов) → явный отказ preflight с понятной подсказкой, а не молчаливое переиспользование чужого состояния. FR-2, AC-8
BR-8 Наш прод не затрагивается: вся задача — вне рантайма и вне конвейера; kill-switch не требуется (активация — только явный запуск человеком на целевом хосте, паттерн ORCH-009). NFR-1/NFR-2, AC-6
BR-9 Анти-дрейф: структурные тесты держат bundle-канон (compose-структура, док-канон, env-ключи, FORBIDDEN-литералы, секрет-эвристика, кросс-ссылки); существующие test_lite_setup_doc.py/test_no_host_hardcodes.py остаются зелёными; полный pytest tests/ -q зелёный; CHANGELOG обновлён. AC-5, AC-6, AC-7, FR-5

5. Нефункциональные требования (NFR)

ID Требование
NFR-1 Рантайм/конвейер байт-в-байт: src/**, корневой docker-compose.yml, Dockerfile, STAGE_TRANSITIONS, QG_CHECKS, check_*, machine-verdict ключи, схема БД орка — не тронуты. Задача — docs+scripts+compose-bundle+tests.
NFR-2 Self-hosting безопасность: ни один артефакт задачи не рестартит/не деплоит/не конфигурирует наш прод-контейнер; bundle-артефакты в нашем контуре инертны (никто их не исполняет).
NFR-3 Секрет-гигиена: в репо не попадают реальные секреты, высокоэнтропийные литералы и хост-литералы (FORBIDDEN-скан test_no_host_hardcodes.py распространяется на новые артефакты); bootstrap не печатает секреты в лог; сгенерированные файлы конфигов — только на целевом хосте, в .gitignore.
NFR-4 Переносимость: bundle не зависит от нашей инфраструктуры; вся хост-специфика — переменные/плейсхолдеры; целевая платформа — одиночный Linux x86_64 хост с docker+compose.
NFR-5 Норматив сопровождения (зеркало NFR-5 ORCH-102): изменение шагов тиража в будущих задачах → обновление BUNDLED_SETUP.md в том же PR.
NFR-6 Воспроизводимость: версии образов Gitea/Plane-стека зафиксированы (пиннинг тегов/digest, не latest); состав bundle детерминирован.
NFR-7 Без новых тяжёлых зависимостей: bootstrap — в духе существующих скриптов (stdlib-инструментарий gen_secrets.py/onboard_project.py); точный стек (bash/python) — решение архитектора.

6. Допущения и ограничения

  • Целевой хост: чистый одиночный Linux x86_64 с установленными docker + docker compose; оператор имеет sudo. Прочие ОС — вне целевой платформы (best-effort).
  • Ресурсы: Plane-стек ресурсоёмок; ориентир для проверки — не менее 4 vCPU / 8 GB RAM / 40 GB диска (финальные минимумы УТОЧНЯЮТСЯ при реализации замером на тестовом развёртывании и фиксируются в BUNDLED_SETUP.md — см. AC-4; цифры выше — гипотеза, не факт).
  • Внешние предусловия заказчика (bundle не поставляет): инсталляция/аутентификация Claude CLI
    • LLM-доступ Anthropic; Telegram-боты (трекер + watchdog) — опциональны, их отсутствие деградирует только нотификации (never-raise), не конвейер.
  • Часть инициализации Plane CE недоступна по API (instance-setup/workspace/API-токен) — допускаются документированные интерактивные шаги внутри визарда; «одной командой» означает «один запуск bootstrap с явными чекпоинтами», а не «ноль действий человека».
  • Версии upstream-образов (Plane CE/Gitea) фиксируются на момент реализации; их обновление — отдельные будущие задачи (NFR-6).

7. Критерии успеха (резюме; детали — 03-acceptance-criteria.md)

Пять AC из постановки Владельца (сохранены 1:1 как AC-1…AC-5) + производные проверяемые:

  • AC-1 единый bundle-compose поднимает ВЕСЬ стек; bootstrap доводит до рабочего состояния одной командой/визардом.
  • AC-2 после bootstrap smoke проходит (тестовый проект + задача доезжает).
  • AC-3 stateless (чистые Plane/Gitea/БД, новые секреты).
  • AC-4 BUNDLED_SETUP.md + требования к хосту (RAM/диск) задокументированы.
  • AC-5 pytest зелёный; CHANGELOG.
  • AC-6 корневой compose/рантайм не тронуты (анти-дрейф зелёный); AC-7 нулевой дрейф канонов (22 статуса/лейблы/секреты — через существующие кирпичи); AC-8 идемпотентность/fail-safe bootstrap; AC-9 секрет-гигиена новых артефактов.

8. Риски (детали — 10-tech-risks.md, заполняет архитектор)

  • R-1 Ресурсоёмкость Plane: ~14 контейнеров → OOM/медленный старт на слабом хосте; смягчение — preflight-проверка ресурсов + честные требования в доке (AC-4).
  • R-2 Дыры Plane CE API: первичная инициализация частично UI-only → ручные чекпоинты; риск — UX «одной команды» размывается; смягчение — явные manual-step с проверкой результата (паттерн ORCH-009), минимизация числа ручных шагов.
  • R-3 Дрейф upstream-образов: «плавающие» теги ломают воспроизводимость → пиннинг (NFR-6).
  • R-4 Сетевая достижимость вебхуков: орк (host network) ⟷ Plane/Gitea (bridge-сеть bundle) — двунаправленные URL должны быть согласованы bootstrap'ом; ошибка = «задача не появилась» (труднодиагностируемо); смягчение — smoke проверяет оба направления.
  • R-5 Соблазн форкнуть корневой compose (анти-дрейф TC-04 test_lite_setup_doc.py упадёт) → bundle строго отдельным файлом.
  • R-6 Утечка секретов в логи/репо при генерации bundle-кред → секрет-эвристика в тестах, запрет печати секретов (NFR-3).