# 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 фиксирует только функцию.
