--- 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.