work_item: ORCH-022 title: "Security-гейт: secret-scanning + dependency audit перед мержем" notes: > План тестов для security-гейта. Чистая логика выносится в leaf-модуль src/security_gate.py (never-raise) — основной предмет unit-тестов (по образцу tests для merge_gate / image_freshness / post_deploy / staging_verdict). Интеграция врезки в advance_stage и условный раскат — integration-тесты. Имена модулей тестов финализирует разработчик/архитектор по факту реализации. tests: # --- Secret-scanning (FR-1 / AC-1..AC-3) --- - id: TC-01 type: unit description: "Подсаженный тестовый секрет в diff -> вердикт FAIL, secrets_found>=1, причина называет находку." module: tests/test_security_gate.py expected: PASS - id: TC-02 type: unit description: "Чистая ветка без секретов -> вердикт PASS, secrets_found=0." module: tests/test_security_gate.py expected: PASS - id: TC-03 type: unit description: "Совпадение из аллоулиста (плейсхолдер .env.example / фикстура) НЕ даёт FAIL." module: tests/test_security_gate.py expected: PASS # --- Dependency audit + пороги (FR-2 / AC-4..AC-7) --- - id: TC-04 type: unit description: "CVE уровня HIGH/CRITICAL при пороге HIGH -> вклад в FAIL, deps_blocking>=1." module: tests/test_security_gate.py expected: PASS - id: TC-05 type: unit description: "Только MEDIUM/LOW уязвимости -> PASS, deps_warning>=1, находки в теле артефакта." module: tests/test_security_gate.py expected: PASS - id: TC-06 type: unit description: "Конфиг порога: severity=CRITICAL делает HIGH-CVE warning; severity=HIGH делает её блоком." module: tests/test_security_gate.py expected: PASS - id: TC-07 type: unit description: "Недоступный CVE-фид -> детерминированный degrade по политике ADR (дефолт fail-open + warning), без исключения и без ложного FAIL." module: tests/test_security_gate.py expected: PASS # --- Вердикт / парсер frontmatter (FR-3 / AC-8..AC-10) --- - id: TC-08 type: unit description: "Вердикт читается ТОЛЬКО из YAML-frontmatter; проза PASS/FAIL в теле не влияет; negative-токен авторитетен." module: tests/test_security_gate.py expected: PASS - id: TC-09 type: unit description: "Нет frontmatter / битый YAML / нет поля security_status -> (False, reason) (fail-closed на чтении)." module: tests/test_security_gate.py expected: PASS - id: TC-10 type: unit description: "Артефакт 17-security-report.md создаётся с валидным frontmatter (security_status, secrets_found, deps_blocking, deps_warning) и телом-списком." module: tests/test_security_gate.py expected: PASS # --- never-raise / таймаут / условность (FR-5/FR-6 / AC-14..AC-17) --- - id: TC-11 type: unit description: "Отсутствие бинаря сканера / внутреннее исключение -> (False, reason), исключение не пробрасывается (never-raise)." module: tests/test_security_gate.py expected: PASS - id: TC-12 type: unit description: "Превышение ORCH_SECURITY_SCAN_TIMEOUT_S -> корректное прерывание и детерминированный вердикт, без зависания." module: tests/test_security_gate.py expected: PASS - id: TC-13 type: unit description: "check_security_gate: не-self репо при пустом scope -> (True, 'security-gate N/A for ') мгновенно." module: tests/test_qg_security.py expected: PASS - id: TC-14 type: unit description: "check_security_gate: ORCH_SECURITY_GATE_ENABLED=false -> no-op pass (True)." module: tests/test_qg_security.py expected: PASS - id: TC-15 type: unit description: "Новый чек зарегистрирован в QG_CHECKS и корректно диспетчеризуется _run_qg." module: tests/test_qg_security.py expected: PASS # --- Откат / retry в stage_engine (FR-4 / AC-11..AC-13) --- - id: TC-16 type: integration description: "security_status FAIL -> advance_stage откатывает на development, enqueue developer, Plane-коммент + notify_qg_failure." module: tests/test_stage_engine_security_gate.py expected: PASS - id: TC-17 type: integration description: "task_desc перезапущенного developer содержит дословную причину находок (ORCH-046-паттерн), не только ссылку." module: tests/test_stage_engine_security_gate.py expected: PASS - id: TC-18 type: integration description: "После MAX_DEVELOPER_RETRIES (3) -> set_issue_blocked + Telegram-алерт; бесконечного отскока нет." module: tests/test_stage_engine_security_gate.py expected: PASS - id: TC-19 type: integration description: "security_status PASS -> advance_stage продвигает конвейер штатно (без отката, без шумных нотификаций)." module: tests/test_stage_engine_security_gate.py expected: PASS # --- Инварианты / интеграция (BR-7/BR-12 / AC-18..AC-19) --- - id: TC-20 type: integration description: "При варианте 'под-гейт ребра' STAGE_TRANSITIONS не изменён; существующие тесты стадий/гейтов остаются зелёными." module: tests/test_stages.py expected: PASS - id: TC-21 type: integration description: "Гейт не вызывает деплой-хук/рестарт прод-контейнера (self-hosting safety)." module: tests/test_stage_engine_security_gate.py expected: PASS