# 01 — Business Requirements Document (BRD) **Work Item:** ORCH-048 **Title:** staging B6 check reads registry from host worktree, not staging container **Stage:** analysis **Author:** analyst **Date:** 2026-06-06 --- ## 1. Контекст и проблема `scripts/staging_check.py` — suite живых проверок staging-стенда orchestrator (порт 8501, ADR-0003). Деплоер запускает его на стадии `deploy-staging` и пишет `staging_status:` в `15-staging-log.md`. FAIL любого чека = откат на `development`. Блок B содержит проверку **B6 «Registry: sandbox present, prod ET/ORCH absent»** — она должна подтверждать, что в staging-реестре проектов есть только sandbox-проект и НЕТ боевых проектов (enduro-trails / orchestrator). Это страховка изоляции: staging не должен обслуживать прод-проекты. **B6 даёт ложный FAIL** (`prod-ET=YES(BAD!)`, `prod-ORCH=YES(BAD!)`), хотя сама изоляция реестра в staging РАБОТАЕТ корректно. ### Root cause (подтверждён прямым запуском, Стрим, 06.06) - Внутри контейнера `orchestrator-staging` `known_plane_project_ids()` корректно отдаёт `count=1, sandbox=True, ET=False, ORCH=False`. `.env.staging` верно задаёт `ORCH_PROJECTS_JSON` = только sandbox. **Изоляция реестра исправна.** - Все остальные чеки (A1–A3, B4, B5, блок C E2E) обращаются к работающему staging-инстансу по HTTP и **зелёные**. - **B6 — единственный чек, который не ходит по HTTP, а импортирует Python-код локально.** В блоке B6 (строки ~263–284) выполняется: ```python sys.path.insert(0, "/repos/orchestrator") # ХОСТ-worktree importlib.reload(sys.modules["src.projects"]) # подхватывает env ТЕКУЩЕГО процесса from src.projects import known_plane_project_ids ``` - Деплоер по факту запускает скрипт **с хоста** (`.openclaw/agents/deployer.md`: `python3 scripts/staging_check.py --base-url http://localhost:8501`). В env хост-процесса `ORCH_PROJECTS_JSON` НЕ задан → `src.projects` грузит встроенный `_DEFAULT_PROJECTS` (ET + ORCH) → `known_plane_project_ids()` возвращает боевые id → **ложный FAIL**. - Иными словами, B6 проверяет реестр НЕ того окружения, реестр которого реально использует staging-инстанс. Гипотеза деплоера про misconfig staging-контейнера — **опровергнута**. ## 2. Бизнес-цель B6 должен достоверно отражать реестр проектов **именно работающего staging-инстанса** (изолированное окружение), а не реестр, восстановленный из локального импорта в произвольном process-env. При этом B6 обязан по-прежнему ловить реальное нарушение изоляции. ## 3. Заинтересованные стороны | Роль | Интерес | |------|---------| | Deployer-агент | Достоверный сигнал staging-гейта; нет ложных откатов на development | | Owner / прод | Изоляция staging от прод-проектов реально проверяется (не ложно-зелёная и не ложно-красная) | | Self-hosting pipeline | `deploy-staging` — обязательная страховка перед прод-деплоем орка; ложный FAIL блокирует доставку всех ORCH-задач | ## 4. Объём (Scope) ### В объёме - Исправление блока B6 в `scripts/staging_check.py`, чтобы он читал реестр в окружении staging-инстанса. - Тест на корректность B6: оба исхода (PASS при чистой изоляции; FAIL при попадании прод-проекта в staging-реестр). - Обновление документации B6 (`docs/operations/STAGING_CHECK.md`, при необходимости `docs/architecture/README.md`/CHANGELOG) в том же PR. ### Вне объёма (НЕ ТРОГАТЬ) - `src/projects.py` — реестр работает корректно. - `.env` / `.env.staging` — конфигурация верна. - Прод-логика оркестратора. - Остальные staging-чеки B1–B5 и блок C E2E — зелёные. ## 5. Бизнес-требования | ID | Требование | |----|------------| | BR-1 | B6 на staging даёт PASS (`sandbox=YES`, `prod-ET=NO`, `prod-ORCH=NO`), читая реестр из окружения staging-инстанса, а не из локального импорта хост-worktree. | | BR-2 | B6 по-прежнему детектирует реальное нарушение изоляции: если бы прод-проект реально попал в staging-реестр, B6 обязан выдать FAIL. | | BR-3 | Остальные staging-чеки не сломаны; `src/projects.py` и `.env*` не изменяются. | | BR-4 | Существующие unit-тесты остаются зелёными (`pytest tests/ -q`). | | BR-5 | Документация B6 обновлена в том же PR (golden source). | ## 6. Допущения и ограничения - Решение должно быть минимально инвазивным и не затрагивать прод-логику. - Скрипт `scripts/staging_check.py` использует только stdlib (нет `requests`/`httpx`) — это конвенция файла, её нужно сохранить. - Способ запуска suite может варьироваться (с хоста / `docker exec` внутри контейнера) — выбранное решение должно быть корректным для канонического способа запуска деплоером и задокументировано. ## 7. Критерий успеха (бизнес) - staging-прогон `scripts/staging_check.py` → **B6 PASS** при работающей изоляции. - При искусственно нарушенной изоляции → **B6 FAIL** (проверяется тестом, без реального изменения staging). - `python -m pytest tests/ -q` — зелёный. ## 8. Открытые вопросы (для архитектора) Бизнес-запрос предлагает три варианта реализации (выбор за архитектором, см. 02-trz §4): - (а) B6 читает реестр через HTTP-эндпоинт staging-инстанса; - (б) B6 выполняет проверку через subprocess в окружении staging-контейнера (`docker exec`); - (в) staging_check запускается ВНУТРИ staging-контейнера и читает собственный process-env (убрать host-path хак). Предпочтение бизнес-запроса: минимально инвазивный вариант, не трогающий прод-логику.