176 lines
17 KiB
Markdown
176 lines
17 KiB
Markdown
---
|
||
work_item: ORCH-101
|
||
stage: analysis
|
||
author_agent: analyst
|
||
status: ready-for-review
|
||
created_at: 2026-06-10
|
||
model_used: claude-opus-4-8
|
||
---
|
||
|
||
# 01 — BRD (бизнес-требования): ORCH-101 — ORCH-10-common: расхардкод + секреты + smoke (фундамент тиража)
|
||
|
||
Work Item: **ORCH-101** · Repo: **orchestrator** · Стадия: analysis
|
||
|
||
## 1. Бизнес-контекст и проблема
|
||
|
||
Эпик **ORCH-10** (домен 📈 D5 «Масштаб», `docs/epics/self-evolution.md`, D5.3) — тираж платформы
|
||
для раздачи **текущей** функциональности нескольким заказчикам **на тест**. Решения Славы 10.06:
|
||
|
||
- **Два типа тиража, оба stateless** (наши задачи/данные НЕ переносятся, чистый старт):
|
||
- **Тип A (Lite):** перенос орк + watchdog на новую инфру; окружение донастраивается по чёткой
|
||
инструкции.
|
||
- **Тип B (Bundled):** весь стек (Plane/Gitea/орк) одним комплектом.
|
||
- **ORCH-101 = 10-common** — общий фундамент **обоих** типов. Без него ни Lite, ни Bundled не поедут.
|
||
|
||
**Проблема.** Платформа фактически прибита гвоздями к хосту `mva154`:
|
||
|
||
1. **Хардкоды хоста/окружения.** Аудит репо (стадия analysis, см. реестр в `02-trz.md` §3.1)
|
||
подтвердил: в `src/**` есть код, который **обходит конфиг** — внешний URL Gitea
|
||
`http://git.mva154.duckdns.org` зашит в `src/plane_sync.py`, `HOME=/home/slin` и git-идентичность
|
||
`*@mva154.local` зашиты в трёх местах (`launcher`/`self_deploy`/`post_deploy`); в
|
||
`docker-compose.yml` зашиты пути `/home/slin/...`, gid docker-группы `999`, uid `1000:1000`,
|
||
node-пути; в `Dockerfile` — `useradd … -d /home/slin slin` и порт CMD; в
|
||
`scripts/orchestrator-deploy-hook.sh` — `REPO=/home/slin/repos/orchestrator`. На новом хосте
|
||
(другой пользователь, другие пути, другой gid docker, другие URL) платформа не заведётся без
|
||
правки кода — это блокер тиража.
|
||
2. **Секреты.** Боевые секреты (`.env`) копировать на чужую инфраструктуру нельзя (общий
|
||
webhook-secret = чужой хост сможет слать нам валидные вебхуки; утечка токенов). Механизма
|
||
«сгенерировать НОВЫЙ комплект секретов на новом хосте» нет; `.env.example` не имеет чек-листа
|
||
«что обязан заполнить оператор».
|
||
3. **Верификация.** Нет процедуры убедиться, что развёрнутая копия платформы **жива**: «завести
|
||
тестовый проект + задачу → конвейер доехал». Без неё каждый тираж — слепой деплой.
|
||
|
||
**Ценность:** после ORCH-101 платформа разворачивается на новой инфре конфигурацией (env), с
|
||
собственными секретами и проверяется воспроизводимым smoke-прогоном. Это критический путь всего
|
||
эпика ORCH-10.
|
||
|
||
## 2. Объём (scope)
|
||
|
||
### В объёме
|
||
|
||
1. **Расхардкод** — вынести все хардкоды хоста/окружения в конфиг/env **с дефолтами, равными
|
||
текущим значениям**: IP/hostname (`82.22.50.71`, `mva154`, `*.duckdns.org`), пути
|
||
(`/home/slin/...`, `/repos`), порты (8500/8501/3000/8091), gid docker `999`, uid `1000`, имена
|
||
контейнеров/сервисов/образов, URL Plane/Gitea, git-идентичность агентов. Зоны:
|
||
`src/**`, `watchdog/**`, `docker-compose.yml`, `Dockerfile`, `scripts/`, `.env.example`.
|
||
Аудит — **весь репо** (нормативный реестр находок — `02-trz.md` §3.1).
|
||
2. **Секреты** — механизм генерации **новых** секретов на новом хосте (webhook-секреты —
|
||
криптослучайная генерация на месте; внешние токены Plane/Gitea/Telegram — выпуск на целевых
|
||
системах по чек-листу). Полный шаблон `.env.example` с плейсхолдерами + чек-лист «что заполнить».
|
||
Боевые секреты не покидают текущий хост.
|
||
3. **Smoke-верификация** — документированная воспроизводимая процедура (и/или скрипт-обвязка):
|
||
«завести тестовый проект + задачу → конвейер доехал», с чёткими критериями PASS/FAIL.
|
||
4. **Анти-регресс** — структурный тест (grep-тест по образцу `tests/test_agent_prompts_canon.py`),
|
||
запрещающий возврат хост-хардкодов в `src/**`.
|
||
5. **Доки** — deployment-раздел (параметризация, карта новых env-ключей, чек-лист секретов,
|
||
smoke-процедура) + обновление карты env в `docs/operations/INFRA.md` + `CHANGELOG.md`.
|
||
|
||
### Вне объёма
|
||
|
||
- **Сама инструкция тиража Типа A (Lite) end-to-end** и **сборка комплекта Типа B (Bundled)** —
|
||
отдельные задачи эпика ORCH-10; 10-common даёт им фундамент.
|
||
- **Перенос данных/задач/истории** — тираж stateless по решению Славы 10.06 (чистый старт).
|
||
- **Мультитенантность** (D5.6), горизонтальный воркер-пул (D5.4), IaC-автоматизация
|
||
(Terraform/Ansible) — не сейчас.
|
||
- **Изменение конвейера**: `STAGE_TRANSITIONS` / `QG_CHECKS` / `check_*` / machine-verdict ключи /
|
||
схема БД — не трогаются (задача конфигурационная, не процессная).
|
||
- **Расхардкод исторических документов** `docs/**`, `memory/**`, `CHANGELOG.md` — историческая
|
||
правда не переписывается; аудит судит **код и инфра-файлы**, не архив.
|
||
- **`tests/**`** — тестам разрешены литералы как фикстуры/ожидания.
|
||
- **Onboarding-kit** (`onboarding/`, ORCH-009) — уже параметризован плейсхолдерами `{{NAME}}`;
|
||
правится только при необходимости согласовать новые env-ключи.
|
||
|
||
## 3. Заинтересованные стороны
|
||
|
||
- **Слава (Owner)** — заказчик эпика ORCH-10; принимает BRD (гейт Approved) и прод-деплой
|
||
(Confirm Deploy).
|
||
- **Будущие заказчики-тестеры** — потребители тиража Типов A/B (получают платформу на своей инфре).
|
||
- **Стрим** — оператор тиража: выполняет инструкцию, генерирует секреты, гоняет smoke.
|
||
- **Последующие задачи эпика ORCH-10 (Lite/Bundled)** — прямые потребители фундамента.
|
||
- **Агенты конвейера / self-hosting** — изменения катятся через общий прод-инстанс; регресс на
|
||
текущем хосте недопустим (обслуживает и enduro-trails).
|
||
|
||
## 4. Бизнес-требования (BR)
|
||
|
||
- **BR-1 (расхардкод src)** — в `src/**` и `watchdog/**` не остаётся хост-специфичных литералов
|
||
(IP/hostname/пути/порты/URL/идентичности), **обходящих конфиг**: каждое такое значение читается
|
||
из `Settings` (env `ORCH_*` / `WATCHDOG_*`) с дефолтом, равным текущему боевому значению.
|
||
Дефолты в `src/config.py` / `watchdog/config.py` — легитимное место значений по умолчанию.
|
||
- **BR-2 (расхардкод инфра-файлов)** — `docker-compose.yml`, `Dockerfile`,
|
||
`scripts/orchestrator-deploy-hook.sh` параметризованы (compose-интерполяция `${VAR:-default}`,
|
||
`ARG`, env-override соответственно); без заданных переменных конфигурация резолвится в текущие
|
||
значения 1:1.
|
||
- **BR-3 (секреты)** — существует механизм получения **нового** комплекта секретов на новом хосте:
|
||
генерируемые локально (webhook-секреты) создаются криптослучайно; выпускаемые внешними системами
|
||
(токены Plane/Gitea/Telegram) перечислены в чек-листе с указанием, где их выпустить.
|
||
`.env.example` покрывает 100% обязательных ключей. Копирование боевых секретов не требуется ни
|
||
на одном шаге.
|
||
- **BR-4 (smoke)** — существует документированная воспроизводимая процедура верификации тиража:
|
||
«развёрнутый инстанс → тестовый проект + задача → конвейер доехал», с момента старта до явного
|
||
PASS/FAIL-критерия; воспроизводимость подтверждена прогоном на текущей инфре (staging-песочница
|
||
8501 / sandbox-проект).
|
||
- **BR-5 (zero-regression)** — на текущем хосте поведение 1:1: все новые параметры имеют дефолты =
|
||
сегодняшним значениям; пустой/неизменённый `.env` даёт байт-в-байт текущее поведение; полный
|
||
`pytest tests/ -q` зелёный.
|
||
- **BR-6 (анти-регресс)** — возврат хост-хардкода в `src/**` ломает CI: структурный тест
|
||
сканирует код (вне комментариев/докстрингов) на запрещённые литералы.
|
||
- **BR-7 (доки)** — deployment-раздел + карта env + чек-лист секретов + smoke-процедура
|
||
опубликованы в `docs/operations/`; `CHANGELOG.md` обновлён (правило агентов №2).
|
||
|
||
## 5. Нефункциональные требования (NFR)
|
||
|
||
- **NFR-1 (self-hosting safety)** — задача не перезапускает и не роняет прод-контейнер
|
||
`orchestrator`; правки `docker-compose.yml`/`Dockerfile` инертны до следующего штатного деплоя
|
||
через конвейер (staging 8501 → Confirm Deploy). Никаких push/force-push в `main` мимо PR.
|
||
- **NFR-2 (обратимость)** — «kill-switch природа» параметризации: отсутствие новых env-переменных
|
||
= текущее поведение. Отдельный функциональный kill-switch не требуется — дефолты и есть откат.
|
||
- **NFR-3 (секреты вне гита)** — реальные значения только в `.env`/`.env.staging` на хосте
|
||
(правило агентов №8); в гит попадают только шаблоны/плейсхолдеры; генератор секретов никогда не
|
||
перезаписывает существующий `.env` молча.
|
||
- **NFR-4 (инварианты соседних задач, правило №9)** — параметризация не ослабляет зафиксированные
|
||
инварианты: ORCH-058 «freshness-путь целится ТОЛЬКО в staging, никогда в прод 8500»; ORCH-040
|
||
«uid 1000 + group_add 999 (МИНА 1 — не удалять) + HOME согласован с маунтами»; INV-4 «мерж только
|
||
через Gitea PR-merge API». Затронутые маркеры читаются перед правкой.
|
||
- **NFR-5 (стабильность анти-регресс теста)** — grep-тест детерминирован и не флапает: судит код,
|
||
исключает комментарии/докстринги/`tests/**`/`docs/**`; список запрещённых литералов
|
||
централизован в самом тесте.
|
||
- **NFR-6 (конвейер не трогаем)** — `STAGE_TRANSITIONS`, состав `QG_CHECKS`, семантика `check_*`,
|
||
machine-verdict ключи, схема БД — байт-в-байт прежние.
|
||
|
||
## 6. Допущения и ограничения
|
||
|
||
- Целевой хост тиража: Linux + Docker + Compose; Plane и Gitea доступны (для Типа A — донастройка
|
||
по инструкции Lite-задачи; их URL/токены подаются через env). Claude CLI присутствует на хосте
|
||
(пути маунтов параметризуются).
|
||
- Тираж — **single-tenant**: один инстанс платформы на заказчика; общая мультитенантная топология
|
||
вне объёма.
|
||
- Имя self-hosting репо платформы (`orchestrator`) — платформенная конвенция; делать ли его
|
||
конфигурируемым (`SELF_HOSTING_REPO`) — решение архитектора (см. `02-trz.md` §3.4, вопрос А-2).
|
||
- Встроенный fallback-реестр проектов (`src/projects.py::_DEFAULT_PROJECTS`) содержит UUID'ы Plane
|
||
текущего хоста; на новом хосте обязателен `ORCH_PROJECTS_JSON` — фиксируется в чек-листе, сами
|
||
UUID'ы в дефолте безвредны (не сматчатся) и остаются как документированный fallback.
|
||
- Историческая документация и комментарии кода могут упоминать `mva154`/пути — это не хардкоды
|
||
поведения и аудитом кода не считаются.
|
||
|
||
## 7. Критерии успеха
|
||
|
||
Платформа разворачивается на чужой инфре **без правки кода** — только env/конфиг; секреты
|
||
выпускаются заново по чек-листу; smoke-прогон даёт явный PASS; на текущем хосте — ноль изменений
|
||
поведения и зелёный полный регресс. Детальные условия PASS/FAIL — `03-acceptance-criteria.md`
|
||
(AC-1…AC-8); прослеживаемость BR ↔ AC — в сводной матрице там же.
|
||
|
||
## 8. Риски
|
||
|
||
Кратко (детально — `10-tech-risks.md`, заполняет архитектор):
|
||
|
||
- **Р-1: скрытый регресс при параметризации горячих путей** (`launcher` env агентов, compose
|
||
volumes) — митигируется дефолтами = текущим значениям + полным регрессом + staging-прогоном.
|
||
- **Р-2: ослабление инварианта ORCH-058** при конфигуризации staging-порта (`_STAGING_PORT`) —
|
||
митигируется guard-условием «staging-порт ≠ прод-порт» и решением архитектора (возможно,
|
||
оставить константой с обоснованием).
|
||
- **Р-3: флап анти-регресс grep-теста** (ложные срабатывания на комментарии) — митигируется
|
||
правилами исключений NFR-5.
|
||
- **Р-4: неполный аудит** (пропущенный хардкод всплывает на первом реальном тираже) — митигируется
|
||
нормативным реестром §3.1 ТЗ + smoke-процедурой как последней линией обнаружения.
|
||
- **Р-5: расползание скоупа в Lite/Bundled** — митигируется явным «вне объёма» §2.
|