# План: доменный go-live аудит — карточки навыков в теле + чтение 8 артефактов + отчёт

## Цель

Провести доменный аудит безопасности по спеке `2026-06-15-go-live-security-audit-evidence-2.md`
(раздел D5) через прогон 4 доменных скилов с чтением исходных артефактов и записать
**промежуточный неавторизующий** отчёт. Критерии приёмки D5, раскрытые здесь:
- **Поля каждой находки:** ID; инвариант (D1–D4); `файл:строка`; приоритет `P1`/`P2`/`P3`;
  статус `закрыт`/`остаточный риск`/`открыт`; рекомендация.
- **Критерий блокера:** открытая находка `P1` = блокер публикации.
- **Минимальный охват 8 артефактов:** `routes/web.php`, `EnsureSaasAdmin.php`,
  `ResolvesAdminUserId.php`, `WebhookSettingsController.php`, `WebhookUrlGuard.php`,
  `PdErasureService.php`, `schema.sql`, `LedgerService.php` — каждый читается grep-шагом ниже.
- **Форма:** промежуточный, **не авторизация go-live**; финал go/no-go — владелец после
  полного review (live-DAST отложен). Открытые вопросы (Б-1/SEC/CTO/Биз/Диз/DO) не закрываются.

## КАРТОЧКИ НАВЫКОВ (верифицированные — дословно из `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 (портал+STRIDE vs generic deep-audit)"],"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 (аудит vs инструмент), IS5 НЕ D2 (техника vs юр.оформление)"],"preview-form":"outline","defaults":["инвентаризация ПДн в схеме/коде → проверка соответствия"],"key-decisions":["режим: техника или закон"],"acceptance-criteria":["ПДн инвентаризированы, соответствие 152-ФЗ проверено"]},
  {"skill":"billing-audit","kind":"own","needs":["код/диф биллинга для аудита денежной корректности"],"produces":["отчёт о money-инвариантах биллинга"],"constraints":["self-authored; аудит кода биллинга (bcmath/идемпотентность/tier/charge_source)","ADR-012: НЕ налоги (ru-tax), НЕ процесс (process-*), НЕ security (D3)"],"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 (только security+go-live vs полный 14-фазный аудит)"],"preview-form":"outline","defaults":["оркеструет ZAP/Nuclei/Ward/pdn-152fz/threat-model + Semgrep"],"key-decisions":["go/no-go порог"],"acceptance-criteria":["вердикт GO/NO-GO обоснован результатами проверок"]}
]
```

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

Под печатью до первого мутирующего шага (Write) вызываются все 4 объявленных скила
(threat-model → pdn-152fz-audit → billing-audit → security-go-live). Затем 8 grep-шагов
читают артефакты по доменам. Если grep даёт пустой вывод — это фиксируется в отчёте как
«артефакт не подтвердил находку» (fallback, не молчание). Финальный Write агрегирует
находки доменных скилов в отчёт по полям и критериям D5.

## Шаблон содержимого отчёта (Write-шаг)

Таблица: `| ID | инвариант (D1-D4) | файл:строка | приоритет | статус | рекомендация |` —
одна строка на находку; затем блок «промежуточный статус НЕ ГОТОВ + блокеры (открытые P1)»
и явная пометка «не авторизация go-live».

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

```steps-json
[
  {"op":"Bash","object":"grep -n api/admin app/routes/web.php","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 blockReason app/app/Support/WebhookUrlGuard.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 -n bcsub app/app/Services/Billing/LedgerService.php","ref":"D4"},
  {"op":"Write","object":"docs/superpowers/audits/2026-06-15-portal-domain-audit-findings.md","ref":"D5"}
]
```

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