Files
orchestrator/docs/work-items/ORCH-117/03-acceptance-criteria.md

8.9 KiB
Raw Blame History

work_item, stage, author_agent, status, created_at, model_used, escalate
work_item stage author_agent status created_at model_used escalate
ORCH-117 analysis analyst ready-for-review 2026-06-15 claude-opus-4-8 full-cycle

03 — Критерии приёмки (Acceptance Criteria): ORCH-117 — sandbox-only fail-closed изоляция записи в Plane

Work Item: ORCH-117 · Repo: orchestrator · Стадия: analysis

Формат: каждый критерий имеет PASS (что должно быть истинно для приёмки) и FAIL (что считается провалом). Любой машинный/ручной reviewer проверяет их буквально по файлам репозитория.


AC-1 — Регресс ORCH-114: живой прод-токен + pytest не мутируют боевой проект (ОБЯЗАТЕЛЬНЫЙ)

Условие: В тест-процессе с живым боевым ORCH_PLANE_API_TOKEN в окружении вызывается notify_stage_change("ORCH-114", "deploy", "done") (и/или прямые update_issue_state/add_comment/ _set_issue_state_direct) с целевым боевым проектом 7a79f0a9-5278-49cd-9007-9a338f238f9c.

  • PASS: ноль реальных httpx.patch/httpx.post уходит в боевой проект (мок httpx не вызван для prod-URL или гард блокирует до сетевого вызова). Существует тест, который красный до фикса (воспроизводит запись инцидента) и зелёный после.
  • FAIL: хоть один PATCH/POST достигает боевого проекта из тест-процесса; либо регресс-тест отсутствует; либо он зелёный и до фикса (значит ничего не проверяет).

AC-2 — Sandbox-e2e сохранён: запись в SANDBOX под opt-in проходит

Условие: В тест-процессе включён явный интеграционный opt-in и целевой проект — SANDBOX 8c5a3025-4f9d-4190-b79f-fa06276bb27e.

  • PASS: примитивы записи выполняют реальный httpx-вызов в SANDBOX (в тесте — через мок, подтверждающий, что вызов разрешён и адресован sandbox-URL); scripts/staging_check.py Block C (E2E в SANDBOX) остаётся работоспособным.
  • FAIL: запись в SANDBOX заблокирована при корректном opt-in; либо sandbox-e2e сломан.

AC-3 — Sandbox-only даже с opt-in: боевой проект запрещён всегда

Условие: В тест-процессе включён opt-in, но целевой проект — боевой (7a79f0a9-… ORCH или боевой enduro-проект).

  • PASS: запись блокируется (allowlist sandbox-only) независимо от opt-in; аудит-лог фиксирует причину prod-project-in-test.
  • FAIL: включённый opt-in разрешает запись в любой проект, включая боевой.

AC-4 — Default-deny: без opt-in запись из тестов заблокирована (fail-closed)

Условие: Обычный pytest tests/ без явного opt-in; целевой проект — любой (sandbox или боевой).

  • PASS: все 3 примитива (update_issue_state, add_comment, _set_issue_state_direct) не делают реальной записи; autouse-фикстура conftest.py обеспечивает это по умолчанию во всех тестах. Неопределённый/неразрешимый целевой проект → блок (NFR-1).
  • FAIL: без opt-in возможна реальная запись в Plane; либо autouse-страховка отсутствует.

AC-5 — Нулевая регрессия боевого рантайма

Условие: Процесс — не pytest (боевой рантайм оркестратора).

  • PASS: гард — no-op; запись в Plane выполняется как до ORCH-117 (тот же URL/headers/payload). STAGE_TRANSITIONS/QG_CHECKS/check_*/machine-verdict ключи/схема БД — байт-в-байт не изменены (проверяемо diff'ом / структурными тестами).
  • FAIL: боевая запись подавлена/изменена; либо изменены гейты/схема БД.

AC-6 — Staging-рантайм пишет в SANDBOX

Условие: Процесс — staging-рантайм (8501), не pytest; сконфигурирован на sandbox-проект.

  • PASS: детект тест-процесса не срабатывает для staging → запись в SANDBOX проходит как прежде; staging не приравнивается к pytest.
  • FAIL: staging-запись в SANDBOX заблокирована (ложноположительный детект тест-процесса).

AC-7 — Устойчивость к захвату токена на импорте

Условие: PLANE_HEADERS/PROJECT_ID захвачены на импорте plane_sync (стр. 17/57); тест выполняет запись, не подменяя токен/env постфактум.

  • PASS: гард срабатывает на момент вызова примитива и блокирует прод-запись независимо от того, какой токен в PLANE_HEADERS; защита не опирается на os.environ.setdefault(...)/ подмену settings.plane_api_token.
  • FAIL: защита зависит от подмены токена/env и потому не срабатывает в проде (как было до фикса).

AC-8 — Аудит/наблюдаемость блокировок и разрешений

Условие: Происходит блокировка записи (или разрешённая sandbox-запись).

  • PASS: на блокировку эмитится структурный WARNING/ERROR с project_id, work_item, операцией и причиной; на разрешённую sandbox-запись — audit-INFO. Сообщения делают инцидент видимым.
  • FAIL: блокировка/разрешение происходят молча (нет логов с требуемыми полями).

AC-9 — Kill-switch без чёрного хода

Условие: Если введён kill-switch гарда — он выключен.

  • PASS: выключение деградирует к прежнему (до-ORCH-117) поведению, но не разрешает молча запись в боевой проект из pytest сверх того, что было; реальная sandbox-запись из тестов управляется только opt-in + allowlist (не общим kill-switch).
  • FAIL: общий kill-switch служит чёрным ходом, переоткрывающим прод-запись из тест-процесса.

AC-10 — Документация и конфиг обновлены (golden source)

Условие: PR закрывает ORCH-117.

  • PASS: обновлены .env.example (новые ORCH_* ключи с безопасными дефолтами), CLAUDE.md, docs/architecture/README.md, docs/operations/INFRA.md — описан инвариант изоляции тест/staging записи в Plane. ADR выпущен (06-adr/ADR-001-*.md).
  • FAIL: код есть, документация/конфиг не обновлены (по правилу reviewer'а ORCH — finding ≥P1).

AC-11 — Полный регресс зелёный

Условие: pytest tests/ -q после фикса.

  • PASS: весь сьют зелёный (автоматическая autouse-страховка не ломает существующие тесты).
  • FAIL: появились падения/флапы из-за внедрённого гарда/фикстуры.

Сводная матрица AC ↔ FR/BR

AC Покрывает
AC-1 BR-1 / FR-1 / FR-6 (обязательный регресс ORCH-114)
AC-2 BR-5 / FR-2
AC-3 BR-2 / FR-2
AC-4 BR-3 / BR-4 / FR-2 / FR-3 / NFR-1
AC-5 NFR-2 / FR-4
AC-6 NFR-3 / FR-4
AC-7 NFR-4 / FR-1
AC-8 BR-6 / FR-5
AC-9 NFR-6 / FR-7
AC-10 BR-7
AC-11 NFR-2 (регресс-нейтральность)