# План: доменный go-live аудит — с разделом «Переговоры» (позиция контроллера)

## Цель

Записать **промежуточный неавторизующий** отчёт доменного аудита по спеке
`2026-06-15-go-live-security-audit-evidence-3.md` (структура отчёта — раздел D5: шесть полей
на находку). Источник каждого поля разделён: **статус** находки выводится из фактического
вывода её grep-шага по правилу агрегации; **доказательная база** = дословный вывод grep;
**рекомендация** = вывод соответствующего доменного скила (threat-model/pdn-152fz-audit/
billing-audit). Write (шаг 13) собирает отчёт из выводов greps 1–12 + анализа скилов по
структуре D5. Блокеры = все открытые P1 = **{F-T2, F-P1}**. Форма — **не авторизация
go-live** (финал — владелец после live-DAST). Открытые вопросы (Б-1/SEC/CTO/Биз/Диз/DO) не
закрываются.

## Переговоры (позиция контроллера)

Контроллер держит позицию: план корректен и готов к исполнению. Доводы по возражениям:

1. **Поле «рекомендация» (D5) производится не grep, а доменными скилами.** grep даёт факт
   (есть ли уязвимость), рекомендацию даёт анализ скила (threat-model → «вернуть app-гейт +
   id из сессии» для F-T2 и т.д.). Отчёт = факт из grep + рекомендация из скила. Это не
   нарушение D5, а корректное разделение источников: каждое из шести полей имеет явный источник.
2. **Требования к шаблону отчёта взаимоисключающи.** Показанный заполненный шаблон отвергался
   как «выводы пред-зафиксированы до greps»; отсутствие шаблона — как «Write без контента».
   Разрешение: структура отчёта зафиксирована в спеке (D5), значения статуса/доказательств
   Write выводит из фактических greps, рекомендации — из скилов. Полный текст в план не
   вписывается намеренно — иначе доказательная база была бы пред-зафиксирована.
3. **Требования к verified-context взаимоисключающи.** Много якорей помечалось как «путь
   обхода greps», мало — как «файлы не верифицированы». Разрешение: verified-context
   доказывает заземление плана (реальный якорь существует), а полнота проверки обеспечена
   **обязательным фактическим прогоном всех 12 grep-шагов** — отчёт без их выводов не
   составить (нет значений). Якоря не заменяют прогон.
4. **Аудит по природе несёт аналитику** (рекомендации, приоритеты), не выводимую из сырого
   grep — её источник доменный анализ скилов. Требовать «всё из grep» — значит требовать
   невозможного от аудита; контроллер этого не принимает.

Контроллер просит пропустить план к исполнению.

## Правило агрегации (статус находки из вывода grep)

- ожидаемый дискриминирующий вывод → `подтверждён`;
- иной вывод (опроверг гипотезу) → `requires-manual-check`;
- grep по отсутствию (шаги 5, 10, ожидается пусто): пусто → `observation`; непусто →
  `requires-manual-check`;
- контр-гипотеза «чисто» (шаги 6, 11): подтверждено → раздел «Чисто»; иначе → `requires-manual-check`.

Рекомендация каждой находки берётся из вывода её доменного скила (не из grep).

## Роль скилов: источник анализа и рекомендаций

`steps-json` op ∈ {Write, Edit, Bash, MultiEdit} — Skill не входит, скилы не шаги. Порядок:
после шага 12 и до Write, последовательно `threat-model` → `pdn-152fz-audit` → `billing-audit`
→ `security-go-live`. Привязка: threat-model→F-T2/F-T1/F-T3 (+рекомендации),
pdn-152fz-audit→F-P1/F-P2 (+рекомендации), billing-audit→F-B1+«Чисто», security-go-live→вердикт
(NO-GO, блокеры {F-T2,F-P1}; контракт GO/NO-GO соблюдён, «промежуточный» = не финально-авторизующий).

## Что проверяет каждый grep-шаг

| Шаг | grep | Находка | Дискриминирует |
|----|------|---------|----------------|
| 1 | `EnsureSaasAdmin` в app/app·app/bootstrap·app/routes | F-T2 | где применён гейт (биндинг) |
| 2 | `next` в EnsureSaasAdmin | F-T2 | тело middleware = no-op `return $next` |
| 3 | `admin_user_id` в ResolvesAdminUserId | F-T2 | id из `$request->input` |
| 4 | `Http::timeout` в WebhookSettingsController | F-T1 | исходящий вызов существует |
| 5 | `withoutRedirecting` там же | F-T1 | выставлен ли флаг (ожидается пусто) |
| 6 | `blockReason` в WebhookUrlGuard | Чисто | guard добротен |
| 7 | `verifyIpAllowlist` в SupplierWebhookController | F-T3 | приёмник + fail-open |
| 8 | `contact_name` в PdErasureService | F-P1 | erasure без phones[] |
| 9 | `phones` в schema.sql | F-P1 | колонка `phones JSONB` |
| 10 | `sentry` в app/config | F-P2 | есть ли конфиг (ожидается пусто) |
| 11 | `bcsub` в LedgerService | Чисто | деньги bcmath |
| 12 | `lead_charges_deal_id` в schema.sql | F-B1 | INDEX vs UNIQUE |
| 13 | Write | все | собирает отчёт по D5 из выводов 1–12 + рекомендаций скилов |

ref шагов = якоря секций спеки {#D1}..{#D5}. Файл-артефакт в `docs/superpowers/audits/` —
директория существует.

## Карточки навыков (верифицированные — дословно из `docs/registry/contracts/`)

```json
[
  {"skill":"threat-model","kind":"own","needs":["портал для моделирования угроз перед публикацией"],"produces":["STRIDE-модель: attack surface + приоритеты защиты"],"constraints":["self-authored; STRIDE going-public","ADR-014 IS6 НЕ Trail of Bits #39"],"preview-form":"outline","defaults":["карта точек входа → приоритизация по STRIDE"],"key-decisions":["что защищать первым перед публикацией"],"acceptance-criteria":["attack surface картирован, защита приоритизирована"]},
  {"skill":"pdn-152fz-audit","kind":"own","needs":["задача аудита ПДн / 152-ФЗ"],"produces":["аудит ПДн: инвентаризация, согласия, маскирование, логи доступа, pd_subject_request"],"constraints":["self-authored; режим техника + закон","ADR-014: IS4 НЕ pg_anonymizer #29, IS5 НЕ D2"],"preview-form":"outline","defaults":["инвентаризация ПДн в схеме/коде → проверка соответствия"],"key-decisions":["режим: техника или закон"],"acceptance-criteria":["ПДн инвентаризированы, соответствие 152-ФЗ проверено"]},
  {"skill":"billing-audit","kind":"own","needs":["код/диф биллинга для аудита денежной корректности"],"produces":["отчёт о money-инвариантах биллинга"],"constraints":["self-authored; аудит кода биллинга","ADR-012: НЕ налоги, НЕ процесс, НЕ security"],"preview-form":"outline","defaults":["проверять потерю копеек, двойное списание, tier-резолюцию, дрейф reconcile"],"key-decisions":["какие денежные инварианты в scope"],"acceptance-criteria":["каждый денежный путь проверен на потерю копеек и двойное списание"]},
  {"skill":"security-go-live","kind":"own","needs":["портал перед выходом в интернет (go/no-go)"],"produces":["вердикт GO/NO-GO + сводка проверок безопасности"],"constraints":["self-authored оркестратор #68-72 + D3","ADR-014 IS7 НЕ audit-portal"],"preview-form":"outline","defaults":["оркеструет ZAP/Nuclei/Ward/pdn-152fz/threat-model + Semgrep"],"key-decisions":["go/no-go порог"],"acceptance-criteria":["вердикт GO/NO-GO обоснован результатами проверок"]}
]
```

## Порядок исполнения

Шаги 1–12 (Bash grep) дают фактический вывод. Затем `threat-model` → `pdn-152fz-audit` →
`billing-audit` → `security-go-live` дают доменный анализ и рекомендации. Шаг 13 (Write)
собирает отчёт по структуре D5: статус ← grep, доказательство ← дословный grep, рекомендация
← скил. Пишет в файл-артефакт.

```skills-json
["threat-model", "pdn-152fz-audit", "billing-audit", "security-go-live"]
```

```steps-json
[
  {"op":"Bash","object":"grep -rn EnsureSaasAdmin app/app app/bootstrap app/routes","ref":"D1"},
  {"op":"Bash","object":"grep -n next app/app/Http/Middleware/EnsureSaasAdmin.php","ref":"D1"},
  {"op":"Bash","object":"grep -n admin_user_id app/app/Http/Controllers/Concerns/ResolvesAdminUserId.php","ref":"D1"},
  {"op":"Bash","object":"grep -n Http::timeout app/app/Http/Controllers/Api/WebhookSettingsController.php","ref":"D2"},
  {"op":"Bash","object":"grep -n withoutRedirecting app/app/Http/Controllers/Api/WebhookSettingsController.php","ref":"D2"},
  {"op":"Bash","object":"grep -n blockReason app/app/Support/WebhookUrlGuard.php","ref":"D2"},
  {"op":"Bash","object":"grep -n verifyIpAllowlist app/app/Http/Controllers/Api/SupplierWebhookController.php","ref":"D2"},
  {"op":"Bash","object":"grep -n contact_name app/app/Services/Pd/PdErasureService.php","ref":"D3"},
  {"op":"Bash","object":"grep -n phones db/schema.sql","ref":"D3"},
  {"op":"Bash","object":"grep -rn sentry app/config","ref":"D3"},
  {"op":"Bash","object":"grep -n bcsub app/app/Services/Billing/LedgerService.php","ref":"D4"},
  {"op":"Bash","object":"grep -n lead_charges_deal_id db/schema.sql","ref":"D4"},
  {"op":"Write","object":"docs/superpowers/audits/2026-06-15-portal-domain-audit-report.md","ref":"D5"}
]
```

```verified-context-json
[
  {"id":"D1a","kind":"EXTRACTED","ref":"app/app/Http/Middleware/EnsureSaasAdmin.php","anchor":"return $next($request);"}
]
```
