271 lines
24 KiB
Markdown
271 lines
24 KiB
Markdown
---
|
||
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/реестр §2–5),
|
||
`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 (шаги 0–5, опционально 6 до `done`) —
|
||
переиспользовать ссылкой + Lite-специфичные предусловия; критерий «конвейер доехал»:
|
||
задача в БД → analyst-job в `/queue` → артефакты `01–04` в ветке задачи.
|
||
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 п.5–8 обязаны быть полными (заказчик не ходит за
|
||
ответами вовне репо), при этом канонические данные даются ссылкой на 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) — инструкция обязана им следовать, а не противоречить.
|