8.9 KiB
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.pyBlock 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 (регресс-нейтральность) |