--- result: PASS work_item: ORCH-117 stage: testing author_agent: tester status: pass created_at: 2026-06-15 model_used: claude-opus-4-8 type: test-report work_item_id: ORCH-117 --- # Test Report — ORCH-117 — sandbox-only fail-closed изоляция записи в Plane ## Окружение - Python: 3.12.13 - pytest: 8.3.3 (plugins: cov-5.0.0, anyio-4.13.0, asyncio-0.23.8) - Worktree: `/repos/_wt/orchestrator/feature_ORCH-117-bug-test-staging-plane-writes-` - Ветка: `feature/ORCH-117-bug-test-staging-plane-writes-` - Дата: 2026-06-15 ## Smoke API (read-only) - `GET /health` → `{"status":"ok","service":"orchestrator"}` ✅ - `GET /status` → 200, ORCH-117 (task 104) на стадии `testing`, `agent_running: null` ✅ - `GET /queue` → 200; блок `serial_gate` присутствует ✅; блок `auto_labels` присутствует ✅ (регресс смока ORCH-088 не обнаружен). ## Результаты — покрытие test-plan (04-test-plan.yaml) | TC ID | Описание | Тест | Результат | |-------|----------|------|-----------| | TC-01 | РЕГРЕСС ORCH-114: pytest-env + живой прод-токен → `notify_stage_change('ORCH-114','deploy','done')` на боевой проект делает 0 httpx.patch/post | `test_tc01_notify_stage_change_prod_makes_zero_writes` | PASS | | TC-02 | `update_issue_state` в тест-процессе с боевым проектом → блок; аудит `prod-project-in-test` | `test_tc02_update_issue_state_prod_blocked` | PASS | | TC-03 | `add_comment` в тест-процессе с боевым проектом → блок (httpx.post не вызван) | `test_tc03_add_comment_prod_blocked` | PASS | | TC-04 | `_set_issue_state_direct` + `set_issue_done` в тест-процессе с боевым проектом → блок | `test_tc04_set_issue_state_direct_prod_blocked`, `test_tc04_set_issue_done_prod_blocked` | PASS | | TC-05 | Default-deny: без opt-in запись блокируется для ЛЮБОГО проекта (вкл. sandbox) | `test_tc05_default_deny_blocks_sandbox_and_prod` | PASS | | TC-06 | Sandbox-разрешение: opt-in + SANDBOX `8c5a3025-…` → реальный httpx-вызов разрешён | `test_tc06_sandbox_optin_allows_write` | PASS | | TC-07 | Sandbox-only даже с opt-in: opt-in включён, боевой проект → блок | `test_tc07_optin_still_blocks_prod` | PASS | | TC-08 | Fail-closed при неопределённости: пустой/неразрешимый project_id → блок | `test_tc08_ambiguous_target_blocked` | PASS | | TC-09 | Устойчивость к захвату токена на импорте: гард блокирует на момент вызова | `test_tc09_blocks_regardless_of_captured_token` | PASS | | TC-10 | Нулевая регрессия боевого рантайма: НЕ-pytest → гард no-op, реальный httpx-вызов | `test_tc10_live_runtime_is_noop` | PASS | | TC-11 | Staging != pytest: staging-рантайм (sandbox) → запись проходит | `test_tc11_staging_writes_sandbox` | PASS | | TC-12 | Аудит: блок → структурный WARNING/ERROR с полями; sandbox-allow → audit-INFO | `test_tc12_block_audited_loudly`, `test_tc12_sandbox_allow_audited_info` | PASS | | TC-13 | Дефолтная autouse-страховка conftest: обычный тест не пишет в боевой Plane | `test_tc13_conftest_floor_default_deny` | PASS | | TC-14 | Kill-switch без чёрного хода: прод-запись из pytest не разрешается молча | `test_tc14_no_killswitch_backdoor` | PASS | | TC-15 | Полный регресс `tests/ -q` зелёный (autouse-фикстура не ломает существующие тесты) | `pytest tests/` | PASS | Сопоставление с `03-acceptance-criteria.md`: AC-1↔TC-01, AC-2↔TC-06, AC-3↔TC-07, AC-4↔TC-05/08, AC-5↔TC-10, AC-6↔TC-11, AC-7↔TC-09, AC-8↔TC-12, AC-9↔TC-14, AC-10 (docs/config — проверено reviewer'ом, APPROVED), AC-11↔TC-15. Все AC покрыты. ## Вывод pytest Целевой файл: ``` tests/test_orch117_plane_write_isolation.py ... 16 passed, 1 warning in 0.40s (TC-01…TC-14; TC-04 и TC-12 — по два теста) ``` Полный регресс: ``` 2068 passed, 1 warning in 88.02s (0:01:28) ``` (единственный warning — PydanticDeprecatedSince20 в `src/config.py:8`, не связан с ORCH-117.) ## Итог **PASS** — все 15 TC выполнены и сопоставлены с критериями приёмки; целевой сьют (16 тестов) и полный регресс (2068 passed) зелёные; smoke API (`/health`, `/status`, `/queue` с блоками `serial_gate`/`auto_labels`) — OK. Задача готова к переходу на `deploy-staging`.