Files

212 lines
23 KiB
Markdown
Raw Permalink 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-102
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-10
model_used: claude-opus-4-8
---
# 01 — BRD: ORCH-102 — ORCH-10a Lite-тираж: перенос орк+watchdog + полная инструкция донастройки окружения
Work Item: **ORCH-102** · Repo: **orchestrator** (self-hosting) · Стадия: analysis
Заказчик: Слава · Эпик: **ORCH-10** (домен D5 «Масштаб», `docs/epics/self-evolution.md`) · Тип: **A — Lite**
---
## 1. Бизнес-контекст и проблема
### 1.1. Цель эпика ORCH-10
Тираж платформы — РАЗДАЧА текущей функциональности нескольким заказчикам **на тест**.
Решения Владельца 10.06 (приняты как требования, см. §1.4): ДВА типа тиража, ОБА **stateless**
(наши задачи/данные/секреты НЕ переносим — чистый старт):
- **Тип A (Lite)** — переносим ТОЛЬКО орк+watchdog на новую инфру; окружение
(Plane / Gitea / LLM / Telegram) заказчик донастраивает сам **по чёткой инструкции**.
- **Тип B (Bundled)** — весь стек одним комплектом (отдельная задача эпика, вне ORCH-102).
### 1.2. Проблема, которую закрывает ORCH-102
Фундамент **10-common (ORCH-101) уже в `main`**: все хост-значения параметризованы env
(`docker compose config` без переменных = боевое поведение 1:1), секреты выпускаются заново
(`scripts/gen_secrets.py`), есть smoke-процедура с PASS/FAIL (`docs/operations/REPLICATION.md` §4)
и анти-регресс `tests/test_no_host_hardcodes.py`. **Технически** платформа разворачивается на
чужом хосте без правки кода.
**Операционно** — нет: знания размазаны по 4+ документам, каждый из которых писался для
оператора НАШЕГО хоста, а не для заказчика на чистой инфре:
| Документ | Что покрывает | Чего не хватает для Lite |
|----------|---------------|--------------------------|
| `docs/operations/REPLICATION.md` | карта env, секреты, smoke | явно НЕ описывает установку/подключение Plane/Gitea (анти-скоуп Р-5 ORCH-101) |
| `docs/operations/ONBOARDING.md` | онбординг проекта (статусы/лейблы/репо/kit/реестр) | предполагает уже работающий оркестратор и наш хост |
| `docs/operations/SETUP_WEBHOOKS.md` | формат вебхуков Plane/Gitea | примеры с боевыми URL (`mva154`), не generic |
| `docs/operations/INFRA.md` | топология/рестарты нашего хоста | не инструкция «с нуля» |
Заказчик сегодня **не может развернуть Lite без доп-вопросов** — отсутствует единый сквозной
маршрут «голый хост → работающий конвейер». Главный продукт ORCH-102 — **ИНСТРУКЦИЯ**
`docs/deployment/LITE_SETUP.md` (golden source в репо), закрывающая этот разрыв.
### 1.3. Установленные факты (проверено по репо, не изобретать)
- **ORCH-101 смержен** (`git log`: merge #122) — ветка задачи уже содержит фундамент: env-карта
§2 REPLICATION.md, `gen_secrets.py`, `.env.example` = канон 100% ключей старта (включая блок
`WATCHDOG_*`), smoke §4, тесты `test_no_host_hardcodes/test_infra_parametrization/test_secrets_gen/test_replication_smoke`.
- **`docker-compose.yml` УЖЕ является compose-подмножеством Lite:** ровно три сервиса —
`orchestrator`, `orchestrator-watchdog`, `orchestrator-staging` (последний строго за
`profiles: [staging]`); сервисов Plane/Gitea в compose НЕТ. Дефолтный `docker compose up -d`
поднимает ровно орк+watchdog. AC-2 достижим без форка compose — нужны фиксация в доке и
анти-дрейф тест.
- **Plane CE не отдаёт webhook через публичный API** — на нашем хосте webhook создан напрямую в
PostgreSQL / через UI (`SETUP_WEBHOOKS.md`). Инструкция Lite обязана дать заказчику оба пути
(UI и DB) для ЕГО инсталляции Plane.
- **Точная модель статусов**: 22 канонических имени с группами (источник —
`plane_sync._PLANE_NAME_TO_KEY`; таблица — `ONBOARDING.md` §1; создаёт
`scripts/onboard_project.py apply`). Код-критичные fail-closed: `Confirm Deploy`, `STOP`
(группа `cancelled`); в терминальных группах — только Done/Cancelled/STOP.
- **Branch protection на `main` нормативно ЗАПРЕЩЁН** (ORCH-009 ADR D10: required-approvals /
status-checks ломают PR-merge API merge-актора → ложные HOLD). **Pre-receive хуков в платформе
НЕТ** — защита держится конвенцией + скоупом токенов. Формулировка бизнес-запроса
«pre-receive хуки» конфликтует с этим нормативом → вопрос архитектору (ТЗ §3.8 А-1);
рекомендация: раздел Gitea фиксирует канон (репо+токен+webhook+«protection НЕ включать»).
- **Гэп watchdog-конфига:** compose читает `.env.watchdog` (`required: false`), но
`.env.watchdog.example` в репо НЕТ (есть только `.env.example`/`.env.staging.example`);
ключи `WATCHDOG_*` задокументированы внутри `.env.example`. Инструкции нужен однозначный
рецепт настройки watchdog-бота (форма — вопрос архитектору А-4).
- **Платформенные конвенции тиража** (REPLICATION.md §1, нормативно): репо платформы обязан
называться `orchestrator` (`SELF_HOSTING_REPO`); имена сервисов/профиля — константы;
контейнерный layout (`/app/data`, `/repos`, `/opt/claude-code`) не параметризуется.
- **Прецедент приёмки smoke**: ORCH-101 AC-3 — воспроизводимость подтверждается прогоном на
текущей инфре (staging-песочница `ORCH_STAGING_PORT`=8501 + sandbox-проект), без нового железа.
### 1.4. Решения Владельца (10.06) — приняты как требования
| # | Решение |
|---|---------|
| D-1 | Тиражей ДВА типа: A (Lite) и B (Bundled); ORCH-102 реализует ТОЛЬКО A. |
| D-2 | Оба типа **stateless**: наши задачи/данные/секреты не переносятся; на целевой инфре чистый старт. |
| D-3 | Lite = перенос ТОЛЬКО орк+watchdog; окружение (Plane/Gitea/LLM/Telegram) заказчик донастраивает по инструкции. |
| D-4 | Главный продукт задачи = **инструкция** `docs/deployment/LITE_SETUP.md` — golden source в репо. |
| D-5 | Зависимость: ORCH-102 ← **10-common (ORCH-101)** — выполнена (смержен), блокеров нет. |
---
## 2. Объём (scope)
### 2.1. В объёме
- **Инструкция `docs/deployment/LITE_SETUP.md`** — полная пошаговая (каждый шаг = команда +
проверка), покрывающая сквозной маршрут: предусловия хоста (зависимости, uid/gid) → перенос
кода орк+watchdog → конфиг (`.env` с нуля + секреты) → подключение Plane (workspace/проект,
точная модель статусов, API-токен, webhook+HMAC) → подключение Gitea (репо, токен, webhook,
норматив защиты `main`) → LLM-доступ (claude CLI / ключи моделей) → Telegram (бот трекера +
watchdog-бот + chat-id) → запуск compose-подмножества → регистрация проекта
(`ORCH_PROJECTS_JSON`, `src/projects.py`) → health-чек → smoke (из 10-common) → траблшутинг.
- **Фиксация compose-подмножества** (AC-2): документировано и защищено структурным тестом, что
дефолтный запуск = ровно орк+watchdog, без Plane/Gitea-контейнеров.
- **Stateless-нормативы** в инструкции (AC-3): чистая БД, новые секреты, явный запрет переноса
наших задач/данных/секретов.
- **Smoke на чистом окружении** (AC-4): воспроизводимая процедура/чек-лист (переиспользование
REPLICATION.md §4) + зафиксированный приёмочный прогон.
- **Анти-дрейф тесты** структуры/полноты инструкции и compose-подмножества; полный pytest
зелёный; `CHANGELOG.md`; перекрёстные ссылки (REPLICATION.md §1 границы, README — по объёму).
### 2.2. Вне объёма (явно, не делать)
- **Тип B (Bundled)** — весь стек одним комплектом: отдельная задача эпика.
- **Установка самих Plane / Gitea / Telegram / LLM-аккаунтов** — заказчик ставит по официальной
документации вендоров; ORCH-102 покрывает только ПОДКЛЮЧЕНИЕ к оркестратору (анти-скоуп-крип,
зеркало Р-5 ORCH-101).
- **Изменения рантайма/конвейера**: ожидаемый объём — docs+tests; `src/**` не трогается;
`STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict ключи / схема БД — байт-в-байт.
- **Перенос данных**: ни БД, ни задач, ни worktree, ни секретов (D-2).
- **Новая автоматизация** поверх существующих CLI (`gen_secrets.py`, `onboard_project.py`):
новые скрипты не вводятся без решения архитектора.
- **Коммерческая механика раздачи** (доступ заказчика к коду, лицензии, поддержка) —
операторский/владельческий уровень; в инструкции — параметризованный источник кода.
- **Введение pre-receive хуков / branch protection** — запрещено действующим нормативом
ORCH-009 ADR D10 (см. §1.3); пересмотр только явным ADR архитектора.
---
## 3. Заинтересованные стороны
- **Владелец (Слава)** — раздаёт платформу заказчикам на тест; принимает инструкцию как продукт.
- **Заказчик-тестер (новый оператор)** — целевой читатель LITE_SETUP.md: разворачивает Lite на
своей инфре без доп-вопросов; технически грамотен (linux/docker), платформу видит впервые.
- **Оператор текущего прода** — прогоняет приёмочный smoke на staging-песочнице; его прод
(общий для enduro-trails) не должен быть затронут.
- **Будущая задача 10b (Bundled)** — переиспользует разделы Lite-инструкции; границы фиксируются
в REPLICATION.md §1.
---
## 4. Бизнес-требования (BR)
| ID | Требование | Связь |
|----|------------|-------|
| BR-1 | Существует `docs/deployment/LITE_SETUP.md`**полная пошаговая** инструкция Lite-тиража: по ней человек, не видевший платформу, разворачивает орк+watchdog и донастраивает окружение **без доп-вопросов**; **каждый шаг несёт команду и проверку** (ожидаемый результат / PASS-FAIL). | AC-1, FR-1, D-4 |
| BR-2 | Инструкция покрывает ВСЕ системы донастройки: Plane (workspace/проект, точная модель статусов — 22 имени с группами, API-токен, webhook+HMAC с учётом ограничения Plane CE), Gitea (репо, токен с нужными scope, per-repo webhook, норматив «branch protection `main` НЕ включать»), LLM (claude CLI: дистрибутив/node/аутентификация/`ORCH_CLAUDE_BIN`/модели), Telegram (бот трекера + ОТДЕЛЬНЫЙ watchdog-бот + получение chat-id), регистрацию проекта (`ORCH_PROJECTS_JSON` через `onboard_project.py`), health-чек, smoke. | AC-1, FR-4 |
| BR-3 | Разворачивается **compose-подмножество только орк+watchdog**: дефолтный `docker compose up -d` поднимает ровно `orchestrator`+`orchestrator-watchdog`; Plane/Gitea-контейнеров в compose нет; staging-сервис — строго за профилем. Свойство зафиксировано в доке и защищено структурным тестом. | AC-2, FR-2 |
| BR-4 | **Stateless**: инструкция предписывает чистую БД (создаётся пустой при первом старте), выпуск НОВОГО комплекта секретов (`gen_secrets.py` + чек-лист внешних токенов), и нигде не предписывает перенос наших задач/данных/секретов; в самой доке — только плейсхолдеры, ни одного реального секрета/боевого токена. | AC-3, FR-3 |
| BR-5 | **Smoke на чистом окружении** существует как воспроизводимая процедура/чек-лист с PASS/FAIL (переиспользование REPLICATION.md §4, без форка); приёмочный прогон выполнен на чистом контуре (минимум — staging-песочница + sandbox-проект, прецедент ORCH-101 AC-3) и зафиксирован в артефактах задачи. | AC-4, FR-5 |
| BR-6 | **Канон не форкается**: канонические таблицы (модель статусов, карта env, формат вебхуков) инструкция даёт ссылкой на golden source (`ONBOARDING.md`/`REPLICATION.md`/`SETUP_WEBHOOKS.md`) либо с анти-дрейф тестом при неизбежном дублировании; копируемые команды инструкции — generic (плейсхолдеры вместо боевых URL/путей). | AC-1/AC-6, FR-4, NFR-4 |
| BR-7 | Полный `pytest tests/ -q` зелёный; запись в `CHANGELOG.md`; перекрёстные доки обновлены (REPLICATION.md §1 «границы» — строка Type A → ссылка/статус; README/CLAUDE.md — по фактическому объёму, правило агентов №2/№6). | AC-5, FR-6/FR-7 |
| BR-8 | Полнота/структура инструкции защищена **структурным pytest** (анти-дрейф, по образцу `tests/test_replication_smoke.py`): исчезновение обязательного раздела/кирпича/env-ключа из дока или дрейф compose-подмножества ломает CI. | AC-6, FR-6 |
---
## 5. Нефункциональные требования (NFR)
| ID | Требование |
|----|------------|
| NFR-1 | **Self-hosting безопасность:** задача docs+tests; прод-контейнер `orchestrator` не перезапускается; прод-выкат — только штатным конвейером (staging 8501 → ручной Confirm Deploy). |
| NFR-2 | **Нулевая регрессия:** поведение рантайма не меняется (ожидаемо ноль изменений `src/**`); `STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/machine-verdict/схема БД — байт-в-байт; существующие тесты (включая `test_no_host_hardcodes`, `test_replication_smoke`) остаются зелёными. |
| NFR-3 | **Секрет-гигиена:** ни в инструкции, ни в тестах — ни одного реального секрета/токена/боевого webhook-секрета; только плейсхолдеры и ссылки на `gen_secrets.py`; security-гейт (ORCH-022) зелёный. |
| NFR-4 | **Единый источник истины:** инструкция — маршрутизатор поверх канонов, не их копия; неизбежные дубли защищены анти-дрейф тестом (сверка с кодом/каноном импортом, не строкой). |
| NFR-5 | **Поддерживаемость golden source:** LITE_SETUP.md версионируется в репо и поддерживается агентами при каждой доработке, меняющей шаги тиража (правило агентов №2 — дока в том же PR). |
| NFR-6 | **Копируемость команд:** каждый код-блок инструкции выполняется на чистом хосте дословно после подстановки явно перечисленных плейсхолдеров (`<...>`); никаких неявных «подразумевается, что…». |
---
## 6. Допущения и ограничения
- **Поддерживаемый контур** (фиксируется в предусловиях инструкции): Linux x86_64, Docker Engine +
Compose v2, git, python3; пользователь с правами docker; диск/память по минимальным требованиям
(значения уточнит архитектор/инструкция). Иные ОС/архитектуры — вне гарантии Lite.
- **Заказчик сам ставит** Plane CE, Gitea, заводит Telegram-ботов и LLM-доступ (Claude
CLI-аутентификация / ключи) — по официальным докам вендоров; наша инструкция начинается с
«системы установлены и доступны по сети».
- **Имя репо платформы — `orchestrator`** (норматив REPLICATION.md §1 / `SELF_HOSTING_REPO`);
инструкция не предлагает его менять.
- **Источник кода** для заказчика (clone-URL/архив) — решение Владельца; в инструкции —
параметризованный шаг (А-6 в ТЗ).
- «Без доп-вопросов» (AC-1) операционализируется проверяемо: (а) каждый шаг несёт
команду+проверку, (б) приёмочный smoke-прогон по инструкции на чистом контуре зафиксирован,
(в) траблшутинг покрывает типовые отказы первичной настройки.
- Терминология бизнес-запроса «pre-receive хуки» трактуется по факту платформы (§1.3):
канонический механизм защиты — конвенция + скоуп токенов + запрет branch protection;
окончательная формулировка раздела Gitea — за архитектором (А-1).
---
## 7. Критерии успеха (резюме; детали — 03-acceptance-criteria.md)
- AC-1: `docs/deployment/LITE_SETUP.md` — полная пошаговая, человек разворачивает без
доп-вопросов (каждый шаг — команда/проверка).
- AC-2: compose-подмножество только орк+watchdog (без Plane/Gitea-контейнеров).
- AC-3: stateless — чистая БД, ни одной нашей задачи/секрета.
- AC-4: smoke на чистом окружении проходит (минимум — воспроизводимая процедура/чек-лист).
- AC-5: pytest зелёный; CHANGELOG.
- AC-6 (детализация): анти-дрейф тесты структуры дока/compose; канон не форкается.
- AC-7 (детализация): self-hosting безопасность, инварианты конвейера не тронуты.
---
## 8. Риски (детали — 10-tech-risks.md, заполняет архитектор)
- R-1 — **Дрейф инструкции**: платформа развивается, шаги устаревают → структурные тесты (BR-8)
+ правило golden source (NFR-5).
- R-2 — **Форк канона**: скопированная таблица статусов/env разъедется с кодом → ссылки/анти-дрейф
(BR-6, NFR-4).
- R-3 — **Непроверяемость «без доп-вопросов»** → операционализация через §6 (команда+проверка,
smoke-прогон, траблшутинг).
- R-4 — **Гетерогенность хостов заказчиков** (rootless docker, иной uid, нет node) → явный
поддерживаемый контур + предусловия с проверками (`getent group docker`, владение
`ORCH_HOST_REPOS_DIR`).
- R-5 — **Конфликт «pre-receive» с нормативом ADR D10** → вопрос А-1 архитектору; до решения —
канон платформы.
- R-6 — **Утечка секрета через примеры дока** → NFR-3, security-гейт, тест на отсутствие
секретоподобных значений.