22 KiB
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 (шаги 0–6 с PASS/FAIL: config-резолв →/health→/queue+/metrics→ onboard plan/apply/verify → тестовая задача → артефакты01–04→ опц. до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-stepORCH-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 проходит: тестовый проект создан, тестовая задача доезжает минимум до артефактов 01–04 в ветке (минимальный сигнал 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).