87 lines
7.6 KiB
Markdown
87 lines
7.6 KiB
Markdown
# 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 хак).
|
||
|
||
Предпочтение бизнес-запроса: минимально инвазивный вариант, не трогающий прод-логику.
|