Files

13 KiB
Raw Permalink Blame History

01 — BRD: Security-гейт (secret-scanning + аудит зависимостей перед мержем)

Work Item: ORCH-022 Приоритет: ★ высокий Источник: предложение Стрим, одобрено Славой (2026-06-04). Стадия: analysis.


1. Бизнес-проблема

Оркестратор — автономная мульти-агентная система: агенты (developer) пишут код без человека-фильтра по умолчанию. Перед мержем в main сейчас нет проверки на:

  • утёкший секрет — закоммиченный API-ключ / токен / пароль / приватный ключ;
  • дырявую зависимость — пакет с известной CVE;
  • (опционально) базовую уязвимость кода — типовой SAST-паттерн.

Для автономной системы это критично: ошибку, которую в обычной команде «выловили бы глазами на ревью», здесь поймать некому. Утёкший в git-историю ключ или уязвимая зависимость может уехать в прод и обслуживать все проекты (общий инстанс, self-hosting).

Прецеденты / связки

  • PR #18 (check_ci_green: красный CI → возврат на development) — задаёт целевой паттерн поведения красного гейта. Security-гейт должен вести себя так же.
  • Управление секретами (CLAUDE.md §8): секреты живут только в .env/.env.staging на хосте, канон — .env.example. Гейт — это автоматический страж этого правила.

2. Цель

Ввести security-гейт перед слиянием ветки задачи в main, который детерминированно (без LLM) проверяет diff/ветку на секреты и уязвимые зависимости и блокирует продвижение при нарушении порогов: красный security-гейт → возврат на development (developer-retry, как красный CI / merge-gate), задача не уезжает в прод.

Бизнес-ценность

  • Структурно невозможно «тихо» влить секрет или известную CVE в прод автономной системы.
  • Самоприменение правила CLAUDE.md §8 (секреты не в гит) без участия человека.
  • Расширяет уже выстроенную линию автономных страховок (CI-гейт, merge-gate ORCH-043, staging-провенанс ORCH-058, post-deploy ORCH-021).

3. Объём (Scope)

3.1 В объёме (v1) — предположение по умолчанию (A1)

  1. Secret-scanning — обязательный минимум гейта. Поиск закоммиченных секретов в ветке задачи / её diff относительно main.
  2. Dependency audit — аудит зависимостей проекта на известные CVE.
  3. Машиночитаемый артефакт-вердикт security-гейта (YAML-frontmatter — канон гейтов).
  4. Поведение красного гейта = откат на development + developer-retry (cap MAX_DEVELOPER_RETRIES = 3), наблюдаемость (Telegram + Plane-коммент).
  5. Условный раскат (kill-switch + scope репозиториев), never-raise, self-hosting (orchestrator) — первым.

3.2 Вне объёма (v1) — предположение (A2), отдельные WI

  • SAST (semgrep) — вынесен в follow-up WI: шумнее, требует policy-тюнинга правил; гейт проектируется с точкой расширения под него, но в v1 не включается.
  • Полноценный мульти-стек (JS/npm, Android) — см. A3 ниже; в v1 целевой стек — Python (сам оркестратор). Связь с ORCH-9/15 фиксируется как зависимость на будущее.
  • Ретроспективное сканирование уже существующей истории main (гейт смотрит вперёд — ветку перед мержем, не чистит прошлое).
  • Управление аллоулистом ложных срабатываний через UI/Plane (в v1 — файл в репозитории).

3.3 Зафиксированные предположения по умолчанию

⚠️ Интерактивный опрос Owner на стадии анализа не дал ответа; ниже — дефолты по конвенциям проекта. Любой из них Owner/архитектор может переопределить (для A4 предусмотрены конфиг-флаги порогов).

  • A1 (объём сканеров v1): secret-scanning + dependency-audit. SAST отложен.
  • A2 (SAST): отложен в отдельный WI; гейт оставляет точку расширения.
  • A3 (стек): Python-only сначала, реально только для self-hosting (is_self_hosting_repo / scope-CSV), как ORCH-35/43/58. Прочие репо — no-op pass. Мульти-стек (детект стека по репо) — отдельный WI.
  • A4 (пороги): секреты — всегда блок; зависимости — блок на HIGH/CRITICAL, warning на MEDIUM/LOW. Пороги вынесены в конфиг (переопределяемы без редеплоя кода).

4. Заинтересованные стороны

Роль Интерес
Owner (Слава) Прод-безопасность автономного конвейера; контроль порогов и раската.
Стрим Инициатор; снижение риска утечки/уязвимости в автономном режиме.
Агент developer Получает понятную причину красного гейта → быстрый фикс.
Агент reviewer Гейт снимает с него непосильную задачу «глазами ловить ключи».
Все проекты на инстансе Общий прод не должен получить секрет/CVE через одну задачу.

5. Бизнес-требования

ID Требование Приоритет
BR-1 Перед слиянием ветки задачи в main обязателен security-гейт (секреты + аудит зависимостей). MUST
BR-2 Найден секрет (порог A4) → гейт красный → откат на development, в прод не уходит. MUST
BR-3 Уязвимость зависимости уровня блокировки (порог A4) → гейт красный → откат на development. MUST
BR-4 Уязвимость ниже порога блокировки → warning, продвижение не блокируется, но фиксируется в артефакте. MUST
BR-5 Красный гейт ведёт себя как красный CI / merge-gate: откат на development + developer-retry (cap 3), затем эскалация (Telegram + Plane Blocked). MUST
BR-6 Вердикт гейта — машиночитаемый (YAML-frontmatter артефакта), читается гейтом ТОЛЬКО из frontmatter (канон проекта), не из прозы. MUST
BR-7 Гейт детерминированный, без LLM в критическом пути (как merge-gate / image-freshness). MUST
BR-8 Гейт never-raise: внутренняя ошибка не роняет advance_stage и не вешает конвейер всех проектов. MUST
BR-9 Условный раскат: глобальный kill-switch + scope-CSV репозиториев; пусто → реально только self-hosting (orchestrator), прочие репо — no-op pass. MUST
BR-10 Пороги блокировки конфигурируемы (env-флаги, без редеплоя кода). SHOULD
BR-11 Наблюдаемость: причина блокировки видна (Telegram + Plane-коммент + артефакт); проход — без шума. MUST
BR-12 Документация (CLAUDE.md «Артефакты задачи», docs/architecture/README.md таблица гейтов, CHANGELOG, ADR) обновлена в том же PR. MUST
BR-13 Аллоулист ложных срабатываний (заведомо-безопасные совпадения, напр. в .env.example, фикстуры тестов) поддерживается версионируемым файлом в репозитории. SHOULD
BR-14 Точка расширения под SAST и мульти-стек заложена, но в v1 не активна (A2/A3). SHOULD

6. Ограничения и риски (бизнес-уровень)

  • Self-hosting: гейт исполняется внутри инстанса, который правит сам себя. Запрет на рестарт/падение прод-контейнера в рамках задачи (CLAUDE.md §self-hosting) сохраняется — гейт ничего не деплоит и не рестартит, только читает/сканирует.
  • Ложные срабатывания (false positives) могут зациклить откат → development (прецедент ORCH-061 со staging-петлёй). Митигировано: cap retry=3 + аллоулист (BR-13)
    • конфигурируемые пороги (BR-10) + kill-switch (BR-9).
  • Внешние БД уязвимостей (CVE-фиды) — сетевая зависимость; недоступность фида не должна давать ложный красный (см. AC: degrade-поведение при недоступности фида — решение порога «fail-open vs fail-closed для аудита» закрепляется в acceptance + ADR).
  • Стоимость/время сканирования добавляется к каждому прогону задачи — должно быть ограничено таймаутом (как merge-retest).

7. Критерий успеха (бизнес)

Ветка с подсаженным тестовым секретом и/или зависимостью с известной CRITICAL-CVE не может дойти до main/прода: гейт краснеет, задача откатывается на development с понятной причиной. Чистая ветка проходит гейт без задержек и без шума. Для не-self репозиториев конвейер не меняется (no-op). Прод-контейнер не рестартится гейтом.


8. Открытые вопросы (для архитектора / Owner)

  1. Размещение гейта (решение архитектора): (а) на стадии review, либо (б) отдельный под-гейт перед мержем на ребре deploy-staging → deploy (где уже живёт merge-gate ORCH-043 / image-freshness ORCH-058). Требование BRD — «перед слиянием в main»; обе опции его удовлетворяют. См. 02-trz §4.
  2. Где запускается сканер: новый job в .gitea/workflows/ci.yml (тогда вердикт может течь через существующий check_ci_green) или отдельный QG-чек/под-гейт в src/qg. Решение — архитектор (02-trz фиксирует требования к обоим путям).
  3. Аудит зависимостей при недоступном CVE-фиде: fail-open (warning) или fail-closed (блок)? Дефолт-предложение — fail-open с громким warning (не плодить ложные завороты), закрепить в ADR.
  4. Выбор конкретных инструментов (gitleaks vs trufflehog; pip-audit vs trivy) — технологическое решение архитектора; BRD фиксирует только функцию.