Files
orchestrator/docs/work-items/ORCH-102/02-trz.md

271 lines
24 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-102
stage: analysis
author_agent: analyst
status: ready-for-review
created_at: 2026-06-10
model_used: claude-opus-4-8
---
# 02 — ТЗ (TRZ): ORCH-102 — ORCH-10a Lite-тираж: перенос орк+watchdog + полная инструкция донастройки окружения
Work Item: **ORCH-102** · Repo: **orchestrator** · Стадия: analysis
> ТЗ описывает **что** должно измениться и **где** (документы/контракты/тесты), выведено из BRD и
> фактического кода (аудит выполнен по репо на ветке задачи; ORCH-101 уже в `main`). **Как**
> (точная разбивка разделов дока, форма анти-дрейф тестов, исходы вопросов §3.8) — решает
> архитектор в `06-adr/`.
---
## 1. Сводка изменения
**Docs-first задача** (паттерн ORCH-077/092: документы + тесты, рантайм не трогается).
Создаётся главный продукт — инструкция `docs/deployment/LITE_SETUP.md` (golden source Lite-тиража,
новый раздел `docs/deployment/`), которая собирает существующие кирпичи 10-common
(REPLICATION/ONBOARDING/SETUP_WEBHOOKS/INFRA, `gen_secrets.py`, `onboard_project.py`, smoke §4)
в один сквозной маршрут «голый хост → работающий конвейер» для заказчика. Дополнительно:
структурные анти-дрейф тесты (полнота дока, compose-подмножество, stateless/секрет-гигиена),
перекрёстные ссылки и CHANGELOG.
Ожидаемый дифф: `docs/**`, `tests/**`, `CHANGELOG.md` (+ опционально `.env.watchdog.example`
исход А-4). **`src/**` — ноль изменений**; конвейер
(`STAGE_TRANSITIONS`/`QG_CHECKS`/`check_*`/machine-verdict/схема БД) — байт-в-байт.
---
## 2. Задействованные модули / пути
| Путь | Действие |
|------|----------|
| `docs/deployment/LITE_SETUP.md` | **создать** — главный продукт (полная пошаговая инструкция Lite; новый каталог `docs/deployment/`) |
| `docs/operations/REPLICATION.md` | изменить: §1 таблица границ — строка «Type A — Lite» → статус ✅ ORCH-102 + ссылка на LITE_SETUP.md |
| `tests/test_lite_setup_doc.py` | **создать** — структурные анти-дрейф проверки дока + compose-подмножества (образец: `tests/test_replication_smoke.py`) |
| `.env.watchdog.example` | создать **по исходу А-4** (канон конфигурации sidecar-watchdog для нового хоста; сейчас примера нет, compose читает `.env.watchdog` `required: false`) |
| `docs/operations/INFRA.md` | изменить при необходимости: перекрёстная ссылка на deployment-раздел (по фактическому объёму) |
| `README.md` | изменить: обзорный док — способность Lite-тиража (правило агентов №6: не выдавать открытое за решённое и наоборот) |
| `CLAUDE.md` | изменить: блок ORCH-102 в паспорте — по фактическому объёму (правило №2) |
| `CHANGELOG.md` | изменить: запись ORCH-102 |
| `src/**`, `docker-compose.yml`, `Dockerfile`, `scripts/**` | **НЕ менять** (читаются инструкцией/тестами как источник истины; любое отклонение — только через ADR архитектора) |
Кирпичи, которые инструкция **переиспользует по ссылке** (не форкает, BR-6/NFR-4):
`docs/operations/REPLICATION.md` (карта env §2, секреты §3, smoke §4),
`docs/operations/ONBOARDING.md` (статусы §1, слои Gitea/kit/реестр §25),
`docs/operations/SETUP_WEBHOOKS.md` (формат вебхуков, Plane CE-каверза),
`scripts/gen_secrets.py`, `scripts/onboard_project.py` (plan/apply/verify),
`.env.example` (канон 100% ключей), `GET /health|/queue|/metrics`.
---
## 3. Функциональные требования
### FR-1 — Документ `docs/deployment/LITE_SETUP.md`: состав и форма
Привязка: BR-1, BR-2. Нормативный перечень разделов (порядок = маршрут оператора; финальную
разбивку/нумерацию решает архитектор, состав — обязательный минимум):
1. **Рамка Lite** — что разворачиваем (орк+watchdog), что заказчик ставит сам (Plane/Gitea/
Telegram/LLM), границы vs 10-common vs Bundled (ссылка на REPLICATION.md §1), платформенные
конвенции (репо `orchestrator`, имена сервисов, контейнерный layout — не менять).
2. **Предусловия хоста** («зависимости, uid/gid» из бизнес-запроса): поддерживаемый контур
(Linux x86_64, Docker Engine + Compose v2, git, python3); node + дистрибутив claude-code на
хосте (`ORCH_HOST_NODE_BIN`, `ORCH_HOST_CLAUDE_CODE_DIR` — пути под маунты); пользователь и
владение каталогами: `ORCH_RUN_UID/GID` = uid владельца `ORCH_HOST_REPOS_DIR` (инвариант
ORCH-040), `ORCH_DOCKER_GID``getent group docker`; ssh-ключи деплой-хука
(`ORCH_HOST_SSH_DIR`); свободные порты (`ORCH_DEPLOY_PROD_TARGET_PORT`=8500,
`ORCH_STAGING_PORT`=8501). Каждое предусловие — команда проверки.
3. **Перенос кода орк+watchdog**: получение чекаута репо `orchestrator` на хост в
`ORCH_DEPLOY_HOST_REPO_PATH` (источник кода — параметризованный шаг, исход А-6); НИКАКИХ
данных/БД/`.env` с боевого хоста (D-2). Watchdog отдельно не переносится — код в `watchdog/`
того же репо, образ собирается локально compose'ом.
4. **Конфигурация**: `.env` строится с нуля от `.env.example` (канон); webhook-секреты —
`python3 scripts/gen_secrets.py [--write]`; карта переменных — ссылкой на REPLICATION.md §2;
в доке явно — **обязательные ключи нового хоста**: `ORCH_PLANE_API_URL/WEB_URL/WORKSPACE_SLUG`,
`ORCH_PLANE_API_TOKEN`, `ORCH_GITEA_URL/PUBLIC_URL/OWNER`, `ORCH_GITEA_TOKEN`, оба
webhook-секрета, `ORCH_TELEGRAM_BOT_TOKEN/CHAT_ID`, `ORCH_PROJECTS_JSON` (обязателен:
встроенный fallback несёт UUID исходного хоста), хост-параметры `ORCH_AGENT_HOME_DIR`/
`ORCH_HOST_*`/`ORCH_RUN_*`/`ORCH_DOCKER_GID`, когерентность портов
(`ORCH_DEPLOY_PROD_TARGET_PORT``WATCHDOG_METRICS_URL``ORCH_POST_DEPLOY_BASE_URL`).
5. **Подключение Plane** (инсталляция заказчика): создать workspace/проект; **точная модель
статусов** — 22 канонических имени с группами: создаёт `onboard_project.py apply`, таблица —
ссылкой на ONBOARDING.md §1 (без форка; fail-closed `Confirm Deploy`/`STOP` упомянуть явно);
выпуск API-токена (Workspace Settings → API tokens) + команда проверки; **webhook+HMAC**:
URL `…/webhook/plane`, секрет из `gen_secrets.py`, заголовок `X-Plane-Signature`; каверза
Plane CE «webhook не экспонирован в /api/v1» — оба пути (UI и прямой SQL, generic-вариант
команд SETUP_WEBHOOKS.md с плейсхолдерами).
6. **Подключение Gitea** (инсталляция заказчика): репо (`onboard_project.py` или вручную),
токен (scope `repo`, `admin:repo_hook`) + проверка, per-repo webhook (events
`push`/`pull_request`/`status`, `X-Gitea-Signature`, **ОДИН глобальный секрет на все репо**);
норматив защиты `main` — по исходу А-1 (канон: branch protection НЕ включать, ORCH-009 ADR D10).
7. **LLM-доступ (claude CLI)**: дистрибутив claude-code и node на хосте (пути = маунты compose),
`ORCH_CLAUDE_BIN`; аутентификация CLI на хосте (каталог `ORCH_HOST_CLAUDE_DIR` +
`ORCH_HOST_CLAUDE_JSON` — монтируются в контейнер; команда первичного логина/проверки —
`claude --version` / минимальный вызов); конфигурация моделей — `ORCH_AGENT_MODEL_*` /
`ORCH_AGENT_EFFORT_*` (резолв ORCH-41; дефолты канона — в `.env.example`).
8. **Telegram**: бот трекера (BotFather `/newbot``ORCH_TELEGRAM_BOT_TOKEN`), получение
`chat_id` (воспроизводимая команда, например через `getUpdates`), проверка `getMe`;
**отдельный** watchdog-бот (`WATCHDOG_TG_BOT_TOKEN/CHAT_ID` — независимый канал, C-1
ORCH-100, токен орка переиспользовать запрещено) — размещение ключей по исходу А-4
(`.env.watchdog`).
9. **Запуск compose-подмножества**: `docker compose config` (резолв без ошибок) →
`docker compose up -d --build` → поднимаются ровно `orchestrator` + `orchestrator-watchdog`
(AC-2); staging-профиль — опционально/когда нужен (исход А-5); health-чек:
`GET /health` → 200 `"status":"ok"`, `GET /queue`/`GET /metrics` → штатный JSON
(`schema_version: 1`).
10. **Регистрация проекта заказчика**: `onboard_project.py plan → apply → verify`
(Plane-проект+статусы+лейблы `autoApprove`/`autoDeploy`/`Bug`, Gitea-репо+webhook, kit,
merged `ORCH_PROJECTS_JSON`) → внести строку в `.env` → управляемый рестарт → проверка
`/health`+`/queue` (маршрут ONBOARDING.md, ссылкой; в Lite-доке — последовательность команд).
11. **Smoke** (AC-4): чек-лист REPLICATION.md §4 (шаги 05, опционально 6 до `done`) —
переиспользовать ссылкой + Lite-специфичные предусловия; критерий «конвейер доехал»:
задача в БД → analyst-job в `/queue` → артефакты `0104` в ветке задачи.
12. **Stateless-проверка** (AC-3): первый старт создаёт пустую БД (`data/` чист); `GET /queue`
нулевые счётчики, ни одной задачи `ORCH-*`/`ET-*`; явная нормативная строка «данные/задачи/
секреты боевого хоста НЕ переносятся».
13. **Траблшутинг** первичной настройки: минимум — webhook 401/HMAC mismatch; «задача не
появилась» (реестр/`ORCH_PROJECTS_JSON`/webhook); claude CLI не аутентифицирован/не найден;
`docker.sock` permission denied (`ORCH_DOCKER_GID`); права `/repos` (uid mismatch,
ORCH-040/057); Telegram молчит (токен/chat-id). Каждый пункт — симптом → команда
диагностики → лечение.
**Форма (NFR-6, BR-1):** каждый шаг — исполняемая команда (fenced code block) + явная проверка
(«Проверка:» / PASS-FAIL / ожидаемый вывод); все хост-специфичные значения в командах — только
плейсхолдеры `<...>` или `$ENV_VAR` (боевые `mva154`/`82.22.50.71`/реальные токены — запрещены);
язык — русский (канон доков платформы).
### FR-2 — Compose-подмножество (AC-2)
Привязка: BR-3. Зафиксировать (в доке + тестом), что Lite-развёртывание использует
существующий `docker-compose.yml` БЕЗ форка:
- множество сервисов файла — ровно `{orchestrator, orchestrator-watchdog, orchestrator-staging}`;
- `orchestrator-staging` строго за `profiles: [staging]` → дефолтный `docker compose up -d`
поднимает ровно орк+watchdog;
- сервисов/образов Plane/Gitea в compose НЕТ (и тест не даст появиться молча);
- форма фиксации (существующий файл vs отдельный lite-вариант) — исход А-2; ТЗ-рекомендация:
существующий файл (он уже является подмножеством — факт BRD §1.3), отдельный файл не плодить.
### FR-3 — Stateless-нормативы (AC-3)
Привязка: BR-4. Инструкция обязана: (а) предписывать чистый старт — пустой `data/` (БД создаётся
`init_db()` при первом старте), `.env` только с нуля; (б) предписывать выпуск НОВЫХ секретов
(`gen_secrets.py` + чек-лист REPLICATION.md §3.2) и нести норматив «боевые секреты/данные/задачи
не копируются»; (в) содержать проверку чистоты (FR-1 п.12); (г) сама не содержать реальных
секретов (NFR-3; проверяется тестом FR-6 и security-гейтом ORCH-022).
### FR-4 — Покрытие донастройки окружения без форка канона (AC-1)
Привязка: BR-2, BR-6. Per-system разделы FR-1 п.58 обязаны быть полными (заказчик не ходит за
ответами вовне репо), при этом канонические данные даются ссылкой на golden source:
| Данные | Golden source | В LITE_SETUP.md |
|--------|---------------|------------------|
| 22 статуса + группы | `plane_sync._PLANE_NAME_TO_KEY` / ONBOARDING.md §1 | ссылка + критичные fail-closed имена (`Confirm Deploy`, `STOP`) |
| Карта env / хост-параметры | REPLICATION.md §2 / `.env.example` | ссылка + список обязательных ключей нового хоста |
| Формат вебхуков / Plane CE-каверза | SETUP_WEBHOOKS.md | ссылка + generic-команды с плейсхолдерами |
| Онбординг проекта | ONBOARDING.md / `onboard_project.py` | ссылка + последовательность команд Lite-маршрута |
| Smoke | REPLICATION.md §4 | ссылка + Lite-предусловия |
Если архитектор решит дублировать таблицу (читаемость) — дубль защищается анти-дрейф тестом
(сверка импортом из `src/plane_sync.py` / парсингом `.env.example`), не строковой копией.
### FR-5 — Smoke на чистом окружении (AC-4)
Привязка: BR-5. Состав: (а) в LITE_SETUP.md — smoke-раздел (FR-1 п.11) как воспроизводимый
чек-лист с PASS/FAIL на каждый шаг; (б) приёмочный прогон процедуры на чистом контуре — минимум
staging-песочница (порт `ORCH_STAGING_PORT`, изолированная БД `./data/staging`) + одноразовый
sandbox-проект (прецедент ORCH-101 AC-3 / ONBOARDING.md §5.2), без нового железа; (в) результат
прогона фиксируется в артефактах задачи (`13-test-report.md` / `15-staging-log.md`); (г) прогон
на реальном новом хосте — желателен, но НЕ требование приёмки (нет железа в контуре задачи).
### FR-6 — Анти-дрейф тесты (BR-8)
Привязка: BR-3, BR-6, BR-8. Новый `tests/test_lite_setup_doc.py` (структурный, без сети/LLM;
образец — `tests/test_replication_smoke.py`):
1. док существует по канонному пути; несёт обязательные разделы/кирпичи FR-1 (минимум:
`gen_secrets.py`, `onboard_project.py`, `docker compose`, `/health`, `/queue`, `/metrics`,
`ORCH_PROJECTS_JSON`, webhook-секреты, `X-Plane-Signature`/`X-Gitea-Signature`,
`getent group docker`, `Confirm Deploy`/`STOP`, Telegram-боты обоих каналов, маркеры
PASS/FAIL/«Проверка»);
2. каждый env-ключ `ORCH_*`/`WATCHDOG_*`, упомянутый в доке, существует в `.env.example`
(анти-опечатка/анти-дрейф канона);
3. compose-подмножество: парсинг `docker-compose.yml` — ровно 3 сервиса, staging за профилем,
ни одного сервиса/образа `plane*`/`gitea*` (AC-2);
4. stateless/секрет-гигиена: нормативная строка «не копиру…» присутствует; в доке нет
секретоподобных значений (эвристика по образцу security-паттернов) и боевых литералов
(`mva154`, `duckdns`, `82.22.50.71`) в копируемых код-блоках;
5. перекрёстность: REPLICATION.md §1 ссылается на LITE_SETUP.md; `CHANGELOG.md` несёт ORCH-102.
Точная нарезка по тест-модулям — за developer (план — `04-test-plan.yaml`); существующие тесты
не правятся (кроме согласованных структурных дополнений).
### FR-7 — Перекрёстная документация (BR-7)
Привязка: BR-7. REPLICATION.md §1 (строка Type A — Lite → ✅ + ссылка); README.md — способность
Lite-тиража в обзоре (правило №6); CLAUDE.md — по фактическому объёму; CHANGELOG.md — запись.
INFRA.md — ссылка на deployment-раздел при необходимости.
---
## 3.8. Вопросы архитектору (решаются в `06-adr/`, не в ТЗ)
- **А-1 — «pre-receive хуки» vs норматив ADR D10 (ORCH-009):** бизнес-запрос упоминает
pre-receive хуки, но в платформе их нет, а branch protection на `main` нормативно запрещён
(ломает PR-merge API merge-актора). Что фиксирует раздел Gitea? Рекомендация ТЗ: канон —
репо+токен+webhook+явный норматив «branch protection НЕ включать»; pre-receive не вводить;
отклонение — только отдельным ADR с анализом совместимости с merge-актором (ORCH-093/INV-4).
- **А-2 — форма compose-подмножества:** существующий `docker-compose.yml` (уже = подмножество)
+ документация/тест vs отдельный `docker-compose.lite.yml`. Рекомендация: существующий, без
форка (нулевой дрейф, AC-2 держит тест).
- **А-3 — размещение дока:** бизнес-запрос фиксирует `docs/deployment/LITE_SETUP.md` (новый
раздел `docs/deployment/`); REPLICATION.md живёт в `docs/operations/`. Подтвердить layout
(deployment как витрина тиража vs operations) и перекрёстные ссылки; отступление от пути
бизнес-запроса — только явным решением.
- **А-4 — канон watchdog-конфига нового хоста:** compose читает `.env.watchdog`
(`required: false`), примера-файла нет; ключи `WATCHDOG_*` канонизированы в `.env.example`.
Добавить `.env.watchdog.example` (симметрия с `.env.staging.example`) или документировать
шаг «создай `.env.watchdog` с двумя ключами» в LITE_SETUP? Рекомендация: example-файл +
упоминание в доке (меньше шансов перепутать файл-носитель).
- **А-5 — staging-контур в Lite-инструкции:** обязателен ли запуск `orchestrator-staging` у
заказчика? Рекомендация: опционален — нужен только если заказчик регистрирует проект
`orchestrator` (self-hosting развитие платформы); для «раздачи на тест» базовый контур =
prod-инстанс + watchdog; в доке — явная вилка.
- **А-6 — источник кода для заказчика:** clone-URL (зеркало/доступ к нашему Gitea) vs архив.
В доке — параметризованный шаг `git clone <ORCHESTRATOR_GIT_URL>`; конкретику источника
фиксирует Владелец (вне репо).
---
## 4. Изменения API
Нет. Существующие `GET /health` / `/queue` / `/metrics` переиспользуются инструкцией read-only;
новые эндпоинты не вводятся.
## 5. Изменения схемы БД
Нет.
## 6. Требования к новым/изменённым QG checks
Нет. `QG_CHECKS`/`check_*`/machine-verdict ключи не меняются. Новые структурные тесты (FR-6) —
обычный pytest: попадают в существующие гейты (`check_ci_green`/`check_tests_passed`/merge-gate
re-test/coverage-гейт ORCH-027) автоматически, без регистрации нового QG.
## 7. Совместимость / регресс
- **Нулевая регрессия (NFR-2):** дифф — docs+tests (+опц. `.env.watchdog.example`); рантайм не
меняется; kill-switch не требуется (нечего выключать); полный `pytest tests/ -q` зелёный,
существующие структурные тесты (`test_no_host_hardcodes`, `test_replication_smoke`,
`test_infra_parametrization`, `test_onboarding_*`) не ослабляются.
- **Обратимость:** удаление дока/тестов возвращает состояние 1:1 (никаких миграций/состояния).
- **Self-hosting (NFR-1):** прод-контейнер не рестартится; выкат — штатный конвейер
(deploy-staging 8501 → ручной Confirm Deploy). Для enduro-trails изменение инертно.
- **Секрет-гигиена (NFR-3):** в доке/тестах только плейсхолдеры; security-гейт (ORCH-022,
`17-security-report.md`) обязан остаться `PASS`.
- **Инварианты соседних маркеров (правило №9):** ORCH-101 (дефолт = боевое значение; канон
`.env.example`; конвенции тиража REPLICATION §1), ORCH-009 (ADR D10 — без branch protection;
onboarding-CLI ничего не удаляет), ORCH-100 (независимый Telegram-канал watchdog, C-1),
ORCH-040 (uid/gid/HOME группа), ORCH-058 (staging ≠ прод-порт), INV-4 (мерж только через
PR-merge API) — инструкция обязана им следовать, а не противоречить.