--- type: review work_item_id: ORCH-048 verdict: APPROVED version: 1 --- # Review ORCH-048 ## Summary Фикс достоверности staging-чека B6: реестр проектов теперь читается по HTTP у живого инстанса (новый read-only `GET /projects`), а не локальным импортом `src.projects` в process-env скрипта (host-path хак `/repos/orchestrator` + `importlib.reload`), который давал ложный FAIL на каноническом host-запуске деплоера. Выбран вариант (а) из 02-trz §4, обоснован в ADR-001. Реализация чистая, defensive, полностью покрыта тестами; вся обязательная документация обновлена в том же PR. **APPROVED.** Проверены 4 оси: соответствие ТЗ, соответствие ADR, качество кода, качество тестов — плюс обновление документации. Замечаний уровня P0/P1 нет. ## Соответствие ТЗ (02-trz / 03-acceptance-criteria) - **TR-1 / AC-1** ✓ B6 получает known id из `GET /projects` живого инстанса (порт 8501) — источник отражает реестр процесса, реально обслуживающего webhooks; локальный импорт убран. - **TR-2** ✓ Контракт вердикта неизменен: PASS ⟺ `SANDBOX ∈ known ∧ PROD_ET ∉ known ∧ PROD_ORCH ∉ known`; те же константы. - **TR-3** ✓ Формат `Results.add(label, passed, detail)` сохранён (`sandbox=…, prod-ET=…, prod-ORCH=…`). - **TR-4 / AC-1** ✓ Недоступность источника (network error / не-200 / нет ключа / битый тип) → детерминированный FAIL без необработанного исключения и без ложного PASS. Покрыто TC-07a–d. - **TR-5** ✓ Stdlib-only: B6 использует тот же `_get(...)`, что A/B4/B5/C. - **TR-6** ✓ Удалены `sys.path.insert(0, "/repos/orchestrator")` и `importlib.reload`; статический guard в TC-06. - **AC-2** ✓ `_evaluate_b6(known)` — чистая функция; оба исхода (clean→PASS, polluted→FAIL) покрыты юнитами без поднятия инстанса/docker (TC-01…TC-05). - **AC-3** ✓ `git diff` не трогает `src/projects.py`, `.env*`. Прод-логика — только additive read-only роут `GET /projects`; существующие роуты неизменны; блоки A/B4/B5/C функционально не тронуты (изменение `block_b(base, results)` — необходимая проброска base-url, не меняет логику остальных чеков). - **AC-4** ✓ `pytest tests/ -q` → 476 passed. - **AC-5** ✓ Документация обновлена (см. ниже). ## Соответствие ADR - ADR-001 (per-work-item): реализация точно соответствует решению — вариант (а), эндпоинт с заявленной схемой ответа (`known_plane_project_ids` + `projects[{id,repo,prefix,name}]`, без секретов), B6 на HTTP, чистая `_evaluate_b6`, детерминированный FAIL. - ADR-0003 (staging-гейт `check_staging_status`): поведение гейта не меняется — повышается лишь достоверность одного чека suite. Нарушений нет. - Self-hosting: изменение additive/read-only, прод-поведение существующих роутов неизменно; доставка через штатный staging-гейт без внепланового рестарта прод-контейнера. ## Findings ### P0 — Blocker - нет ### P1 — Must fix - нет ### P2 — Should fix - нет ### P3 — Nice-to-have - `GET /projects` импортирует `known_plane_project_ids`/`PROJECTS` внутри функции (lazy import); стилистически — на уровне модуля было бы единообразнее, но текущий вариант корректен и безопасен (registry строится при импорте `src.projects`). Не блокирует. ## Документация Обновлена полностью в том же PR, согласована с кодом: - `docs/architecture/README.md` — добавлена строка `GET /projects` в таблицу API; описана механика B6 (чтение реестра по HTTP) в секции про условный staging-гейт; футер отмечает ORCH-048. - `CHANGELOG.md` — запись в `[Unreleased] / Added` о новом эндпоинте и фиксе B6. - `docs/operations/STAGING_CHECK.md` — обновлены таблица блоков, врезка про инвариантность B6 к способу запуска и строка «Изолированность от прода». - ADR `docs/work-items/ORCH-048/06-adr/ADR-001-b6-registry-via-http-endpoint.md` — заведён, обосновывает выбор варианта (а) против (б)/(в). Требование «изменён `src/` → обновлена документация» выполнено.