# A8 infosec-tooling Implementation Plan

> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. Project wrapper: `.claude/skills/subagent-driven-development/` (git-safety per Pravila §15.1).

**Goal:** Наполнить раздел A8 «Информационная безопасность» шестью узлами (#68 OWASP ZAP MCP, #69 Nuclei MCP, #70 Enlightn — внешние; #71 скил ПДн/152-ФЗ, #72 скил моделирование угроз, #73 скил прогон перед публикацией — self-authored) с полным footprint роутера, наблюдателя, карты и серверным слоем как открытыми вопросами.

**Architecture:** Off-phase tooling integration в изолированном worktree (паттерн A1/A11/C10/finance). ZAP/Nuclei — MCP-серверы (`.mcp.json`, READ-only сканеры, таргет по умолчанию локальный); Enlightn — Composer dev-dep + конфиг (on-demand/CI, не блокирующий); три self-authored project-скила. Каждый внешний инструмент проходит провенанс-вет (IS9) ДО установки. Нормативка bump-ится атомарным набором (cross-ref-checker C2 STRICT).

**Tech Stack:** PHP 8.3 / Laravel 13 / Composer / Node MCP / Java (ZAP) / Go (Nuclei) / lefthook / PostgreSQL 16 / Markdown-нормативка / vis.js карта.

**Spec:** `docs/superpowers/specs/2026-05-21-a8-infosec-tooling-design.md`

> **ПОПРАВКА 2026-05-21 (узел #70):** Enlightn → **Ward** (`Eljakani/ward`, Go-бинарь, MIT) после Task 1 IS9-вета (Enlightn abandoned + не поддерживает Laravel 13). Task 4 переписан под Ward: скачать `ward` Go-бинарь (pin по commit SHA — релизов нет), `ward scan` по корню `app/`, документировать в `docs/security/ward-setup.md`, постура on-demand (не lefthook). Ward — CLI-бинарь (как Nuclei/gitleaks), НЕ Composer dev-dep и НЕ MCP-сервер → `.mcp.json`/l1-watcher alias для #70 не нужны. Обоснование — `docs/security/infosec-vet.md` §«ПЕРЕСМОТР #70». «Enlightn» в слоте #70 ниже читать как «Ward».

---

## Pre-flight (исполнитель — перед Task 1)

- Worktree от свежего `origin/main` через `superpowers:using-git-worktrees`. После создания скопировать gitignored-файлы (учёт Sprint 4): `app/.env`, `app/storage/`, `app/vendor/`, `app/node_modules/`, `bin/*.exe`, `лендинг/` — иначе composer/тесты/lefthook не запустятся.
- `git fetch && git log HEAD..origin/main --oneline` — pre-flight sync 8 нормативных файлов (Pravila §15.2).
- Закоммитить уже написанные spec (`docs/superpowers/specs/2026-05-21-a8-infosec-tooling-design.md`) + этот план первым коммитом.
- Создать home-директорию раздела: `docs/security/` (отчёты ПДн/угроз/go-live + вет-документ).

---

## File Structure

| Файл | Ответственность | Задача |
|---|---|---|
| `docs/security/infosec-vet.md` | провенанс-вет 3 внешних (IS9) + выбор источников | 1 |
| `.mcp.json` | блоки `zap` + `nuclei` (READ-only сканеры) | 2, 3 |
| `tools/.l1-watcher-aliases.txt` | alias MCP-имён ZAP/Nuclei → имена в Tooling | 2, 3 |
| `docs/security/zap-setup.md` | запуск ZAP на native-Windows + локальный таргет (IS8) | 2 |
| `docs/security/nuclei-setup.md` | запуск Nuclei + шаблоны | 3 |
| `app/composer.json` | dev-dep `enlightn/enlightn` | 4 |
| `app/config/enlightn.php` | конфиг Enlightn (60 OSS-проверок) | 4 |
| `.claude/skills/pdn-152fz-audit/SKILL.md` + `references/` + `evals/` | аудит ПДн + чек-лист 152-ФЗ | 5 |
| `.claude/skills/threat-model/SKILL.md` + `references/` + `evals/` | STRIDE под портал, going-public | 6 |
| `.claude/skills/security-go-live/SKILL.md` + `references/` + `evals/` | go-live security-gate (оркестратор) | 7 |
| `docs/adr/ADR-014-infosec-tooling.md` | границы узлов + IS1–IS9 | 8 |
| `docs/routing-off-phase.md` | +6 строк routing + связка L15 | 9 |
| `docs/router-procedure.md` | bump cross-ref | 9 |
| `docs/Tooling_v8_3.md` | §4.43–4.48 (9-атрибутные блоки) + §0 счётчик + header | 10 |
| `docs/Plugin_stack_rules_v1.md` | R10.1 +6 строк + header | 10 |
| `docs/Pravila_raboty_Claude_v1_1.md` | §13.2 +абзац + header | 10 |
| `CLAUDE.md` | §3.3 +#68–73, §6 +абзац, §9 +запись, header | 10 |
| `docs/automation-graph-data.js` | +6 узлов NODE_SECTION (A8) + рёбра + версии-метки | 11 |
| `docs/Открытые_вопросы_v8_3.md` | +7 записей серверного слоя (привязка Б-1) | 12 |

---

## Phase 0 — Провенанс-вет (IS9, ДО установки)

### Task 1: Вет 3 внешних инструментов + выбор источников

**Files:**

- Create: `docs/security/infosec-vet.md`

- [ ] **Step 1: Прочитать процедуру attack-surface**

Прочитать `docs/audit/` (ручная процедура attack-surface тулчейна, ADR-003) — расширяем её на 3 новых внешних.

- [ ] **Step 2: Вет OWASP ZAP MCP-кандидата**

Для каждого кандидата собрать: владелец/провенанс, лицензия, звёзды/активность, последний релиз, что исполняет (читать README + ключевые исходники через WebFetch / `gh`).

- Кандидат A: официальный ZAP «MCP Integration» add-on (`zaproxy.org/blog/2026-04-02-zap-mcp-server`) — провенанс OWASP (предпочтительно).
- Кандидат B: `dtkmn/mcp-zap-server` (Apache-2.0, Spring Boot).

Записать выбор + обоснование в `infosec-vet.md`.

- [ ] **Step 3: Вет Nuclei MCP-wrapper**

Движок `projectdiscovery/nuclei` (MIT, провенанс ProjectDiscovery — чистый). Wrapper-кандидаты: `cyproxio/mcp-for-security` (nuclei-mcp), `addcontent/nuclei-mcp`. Выбрать wrapper с лучшим провенансом ИЛИ решить запускать `nuclei.exe` через тонкую собственную обвязку (без чужого wrapper'а — минимизация surface). Записать.

- [ ] **Step 4: Вет Enlightn**

`enlightn/enlightn` (LGPL; security-checker MIT) — подтвердить OSS-уровень (60 проверок), отсутствие телеметрии наружу, активность. Записать.

- [ ] **Step 5: Зафиксировать verdict по каждому**

В `infosec-vet.md`: таблица «инструмент / источник / лицензия / вердикт (принят/отклонён) / pin-версия». Любой кандидат с непрозрачным провенансом — отклонить (ADR-003, риск ToxicSkills). Минимум один принятый на каждый из трёх слотов #68/#69/#70.

- [ ] **Step 6: Commit**

```bash
git add docs/security/infosec-vet.md
git commit -m "docs(security): provenance vet of ZAP/Nuclei/Enlightn (IS9)"
```

---

## Phase 1 — Внешние движки (#68–70)

### Task 2: OWASP ZAP MCP — установка + native-Windows + локальный таргет smoke

**Files:**

- Modify: `.mcp.json`
- Modify: `tools/.l1-watcher-aliases.txt`
- Create: `docs/security/zap-setup.md`

- [ ] **Step 1: Установить ZAP + MCP-сервер (по вердикту Task 1)**

Установить ZAP (Java-приложение) на native-Windows + выбранный MCP-вариант. Зафиксировать команды в `docs/security/zap-setup.md`. Проверить наличие Java-рантайма (`java -version`); если нет — записать как пред-требование.

- [ ] **Step 2: Зарегистрировать MCP-сервер (READ-only сканер, локальный таргет по умолчанию)**

В `.mcp.json` добавить блок `zap`. В конфиге/обвязке зафиксировать дефолтный таргет = локальная копия портала (`http://localhost:<dev-port>`) — гард IS8 (бой только осознанно).

- [ ] **Step 3: Alias для l1-watcher (C1 STRICT)**

В `tools/.l1-watcher-aliases.txt` добавить alias MCP-имени `zap` → имя узла в Tooling Прил. Н (#68), иначе C1 заблокирует коммит нормативки.

- [ ] **Step 4: Smoke — пассивный скан локального портала**

Запустить локальный портал (dev). Через MCP запустить ZAP spider + passive scan по `http://localhost:<dev-port>`. Expected: ZAP отвечает, возвращает список endpoint'ов/alert'ов без падения. Скриншот/лог в `zap-setup.md`. **Active scan не запускать в smoke** (тяжёлый) — только проверка связности.

- [ ] **Step 5: Commit**

```bash
git add .mcp.json tools/.l1-watcher-aliases.txt docs/security/zap-setup.md
git commit -m "feat(security): OWASP ZAP MCP — setup + local-target guard + smoke (#68)"
```

---

### Task 3: Nuclei MCP — установка + smoke

**Files:**

- Modify: `.mcp.json`
- Modify: `tools/.l1-watcher-aliases.txt`
- Create: `docs/security/nuclei-setup.md`

- [ ] **Step 1: Установить nuclei + (опц.) wrapper (по вердикту Task 1)**

Установить `nuclei.exe` (Go-бинарь) на native-Windows + выбранный MCP-вариант (wrapper или собственная обвязка). Обновить шаблоны (`nuclei -update-templates`). Зафиксировать в `docs/security/nuclei-setup.md`.

- [ ] **Step 2: Зарегистрировать MCP-сервер (локальный таргет по умолчанию)**

В `.mcp.json` добавить блок `nuclei` (READ-only). Дефолтный таргет — локальная копия (гард IS8).

- [ ] **Step 3: Alias для l1-watcher (C1 STRICT)**

В `tools/.l1-watcher-aliases.txt` alias `nuclei` → имя узла Tooling (#69).

- [ ] **Step 4: Smoke — прогон шаблонов по локальному таргету**

Через MCP запустить nuclei с лёгким набором тегов (напр. `-tags tech,exposure`) по `http://localhost:<dev-port>`. Expected: nuclei отвечает, возвращает findings (или «no results») без падения. Лог в `nuclei-setup.md`.

- [ ] **Step 5: Commit**

```bash
git add .mcp.json tools/.l1-watcher-aliases.txt docs/security/nuclei-setup.md
git commit -m "feat(security): Nuclei MCP — setup + local-target guard + smoke (#69)"
```

---

### Task 4: Enlightn — установка + baseline + конфиг

**Files:**

- Modify: `app/composer.json` (require-dev)
- Create: `app/config/enlightn.php`

- [ ] **Step 1: Установить Enlightn (OSS)**

Run (root `app/`):

```bash
composer require enlightn/enlightn --dev
```

Expected: `enlightn/enlightn` в `require-dev`.

- [ ] **Step 2: Опубликовать конфиг**

Run (root `app/`):

```bash
php artisan vendor:publish --tag=enlightn
```

Expected: создан `config/enlightn.php`.

- [ ] **Step 3: Baseline-прогон**

Run (root `app/`):

```bash
php artisan enlightn --no-interaction
```

Expected: отчёт по 60 OSS-проверкам (Security / Performance / Reliability). **Записать число fail/warn по Security-категории** в коммит-сообщение.

- [ ] **Step 4: Настроить конфиг под проект**

В `config/enlightn.php`: ограничить анализаторы Security-категорией (либо оставить все, но в #73-скиле приоритезировать Security); исключить ложноположительные под native-Windows стек (если baseline покажет, напр. проверки, ожидающие конкретный веб-сервер). Не маскировать реальные находки — только явные FP.

- [ ] **Step 5: Зафиксировать постуру (не блокирующий lefthook)**

Enlightn — on-demand/CI (`php artisan enlightn`), **НЕ в lefthook** (паттерн Rector/PHP Insights, IS3). Зафиксировать в коммит-сообщении.

- [ ] **Step 6: Commit**

```bash
git add app/composer.json app/composer.lock app/config/enlightn.php
git commit -m "feat(security): Enlightn OSS setup + baseline (Security fails=<N>); on-demand posture (#70)"
```

---

## Phase 2 — Self-authored скилы (#71–73)

### Task 5: Скил «ПДн / 152-ФЗ» (#71)

**Files:**

- Create: `.claude/skills/pdn-152fz-audit/SKILL.md`
- Create: `.claude/skills/pdn-152fz-audit/references/checklist.md`
- Create: `.claude/skills/pdn-152fz-audit/evals/evals.json`

- [ ] **Step 1: Написать SKILL.md (frontmatter + тело)**

```markdown
---
name: pdn-152fz-audit
description: Аудит защиты персональных данных Лидерры и соответствие 152-ФЗ. Режим 1 — техника (где лежат ПДн в схеме/коде, RLS, маскирование pg_anonymizer, утечки в логах/Sentry/CSV-экспортах, шифрование). Режим 2 — закон (хранение в РФ, согласия, сроки/удаление, реестр обработки, уведомление РКН, права субъекта pd_subject_request). Используй при «проверь ПДн», «утекают ли персональные данные», «соответствие 152-ФЗ», «где хранятся телефоны лидов», «маскируются ли данные в дампах». НЕ для денежной корректности (billing-audit), security-аудита кода (D3/Semgrep), юридического оформления договоров/политик (D2 право), generic-угроз (threat-model #72).
---

# ПДн / 152-ФЗ аудит — Лидерра

[Тело: 2 режима, для каждого — шаги проверки со ссылками на reference и реальные артефакты проекта.]
```

- [ ] **Step 2: Написать references/checklist.md — заземлено в схему и код**

Прочитать `db/schema.sql` (таблицы с ПДн), `db/CHANGELOG_schema.md`, найти: pg_anonymizer #29 правила маскирования, RLS-политики, функцию `set_pd_subject_request_deadline` + таблицу `pd_subject_request`. Записать чек-лист:

- *Техника:* перечень таблиц/колонок с ПДн (телефоны лидов, данные клиентов); под RLS ли; маскируются ли в дампах; не пишутся ли в `import_log`/логи/Sentry/CSV-экспорты в открытом виде; шифрование at-rest.
- *152-ФЗ:* хранение в РФ (Yandex Cloud `ru-central1` ✓), согласия, сроки хранения и удаление, реестр обработки, уведомление РКН, реализация прав субъекта (выгрузка/удаление через `pd_subject_request`).

Каждый пункт — со ссылкой на конкретный файл/таблицу проекта.

- [ ] **Step 3: Написать evals/evals.json (trigger + near-miss)**

```json
{
  "skill": "pdn-152fz-audit",
  "cases": [
    {"prompt": "проверь, не утекают ли телефоны лидов в логи", "should_trigger": true},
    {"prompt": "соответствует ли портал 152-ФЗ перед запуском", "should_trigger": true},
    {"prompt": "проверь, не теряются ли копейки в списании", "should_trigger": false, "expected": "billing-audit"},
    {"prompt": "смоделируй угрозы при выходе портала в интернет", "should_trigger": false, "expected": "threat-model"},
    {"prompt": "составь договор обработки персональных данных", "should_trigger": false, "expected": "D2 право"}
  ]
}
```

- [ ] **Step 4: Прогнать классификацию + lint**

Прогнать евал-кейсы (skill-creator eval-режим или ручная проверка `description`). Expected: trigger → pdn-152fz-audit; near-miss → корректный сосед. Если перетягивает — уточнить границу в `description`.

```bash
npx markdownlint-cli2 ".claude/skills/pdn-152fz-audit/**/*.md"
```

Expected: 0 ошибок.

- [ ] **Step 5: Commit**

```bash
git add .claude/skills/pdn-152fz-audit/
git commit -m "feat(security): pdn-152fz-audit skill — ПДн + 152-ФЗ checklist (#71)"
```

---

### Task 6: Скил «Моделирование угроз» (#72)

**Files:**

- Create: `.claude/skills/threat-model/SKILL.md`
- Create: `.claude/skills/threat-model/references/stride-portal.md`
- Create: `.claude/skills/threat-model/evals/evals.json`

- [ ] **Step 1: Написать SKILL.md (frontmatter + тело)**

```markdown
---
name: threat-model
description: Моделирование угроз портала Лидерра по STRIDE — карта точек входа, что меняется при выходе в интернет, приоритизация защиты. Используй при «смоделируй угрозы», «откуда могут атаковать», «что защищать в первую очередь перед публикацией», «карта точек входа», «threat model / STRIDE». НЕ для аудита ПДн/152-ФЗ (pdn-152fz-audit #71), статического security-аудита кода (D3/Semgrep/Trail of Bits), generic архитектурных паттернов (architecture-patterns), go-live прогона (security-go-live #73).
---

# Моделирование угроз — Лидерра (STRIDE)

[Тело: процедура STRIDE под портал, со ссылкой на reference карты точек входа.]
```

- [ ] **Step 2: Написать references/stride-portal.md — заземлено в реальные точки входа**

Прочитать `app/routes/` (web.php/api.php) + контроллеры, выявить точки входа: форма входа, регистрация/2FA/recovery, вебхуки поставщика лидов (HMAC), deals API, админка, impersonation, импорт CSV. Для каждой — STRIDE-разбор (Spoofing/Tampering/Repudiation/Information disclosure/DoS/Elevation) + что меняется при публичной экспозиции (раньше контур своих → теперь произвольный внешний актор). Приоритизация по риску.

- [ ] **Step 3: Написать evals/evals.json**

```json
{
  "skill": "threat-model",
  "cases": [
    {"prompt": "смоделируй угрозы при выходе портала в интернет", "should_trigger": true},
    {"prompt": "что защищать в первую очередь перед публикацией", "should_trigger": true},
    {"prompt": "проверь соответствие 152-ФЗ", "should_trigger": false, "expected": "pdn-152fz-audit"},
    {"prompt": "прогони все проверки безопасности перед релизом", "should_trigger": false, "expected": "security-go-live"},
    {"prompt": "просканируй код на уязвимости семгрепом", "should_trigger": false, "expected": "D3/Semgrep"}
  ]
}
```

- [ ] **Step 4: Прогнать классификацию + lint**

Как Task 5 Step 4 (для `.claude/skills/threat-model/`).

- [ ] **Step 5: Commit**

```bash
git add .claude/skills/threat-model/
git commit -m "feat(security): threat-model skill — STRIDE going-public (#72)"
```

---

### Task 7: Скил «Прогон перед публикацией» (#73, оркестратор)

**Files:**

- Create: `.claude/skills/security-go-live/SKILL.md`
- Create: `.claude/skills/security-go-live/references/gate.md`
- Create: `.claude/skills/security-go-live/evals/evals.json`

- [ ] **Step 1: Написать SKILL.md (frontmatter + тело)**

```markdown
---
name: security-go-live
description: Единый go-live security-gate Лидерры перед публикацией в интернете — один воспроизводимый прогон всех проверок безопасности и вердикт «можно/нельзя в прод». Оркеструет ZAP (#68), Nuclei (#69), Enlightn (#70), pdn-152fz-audit (#71), threat-model (#72) + Semgrep #25 / Trivy #26 / gitleaks #8 / Trail of Bits #39. Используй при «прогон безопасности перед релизом», «можно ли выкатывать», «go-live security check», «финальная проверка безопасности». НЕ для полного 14-фазного аудита портала (audit-portal), отдельной проверки ПДн (pdn-152fz-audit #71) или угроз (threat-model #72).
---

# Security go-live gate — Лидерра

[Тело: порядок прогона инструментов, сбор findings, формат вердикта.]
```

- [ ] **Step 2: Написать references/gate.md — порядок и вердикт**

Описать порядок: статика (Semgrep/gitleaks/Enlightn/Trail of Bits) → ПДн (#71) → угрозы (#72) → динамика (Nuclei breadth → ZAP depth, **только локальный таргет по умолчанию**, IS8) → сбор findings по серьёзности → вердикт GO / NO-GO с перечнем блокеров. Гард IS8 явно: бой только по явной команде заказчика. Граница IS7: это security-only gate, не подменяет audit-portal.

- [ ] **Step 3: Написать evals/evals.json**

```json
{
  "skill": "security-go-live",
  "cases": [
    {"prompt": "прогони все проверки безопасности перед релизом", "should_trigger": true},
    {"prompt": "можно ли выкатывать портал в прод по безопасности", "should_trigger": true},
    {"prompt": "проведи полный аудит портала", "should_trigger": false, "expected": "audit-portal"},
    {"prompt": "проверь только персональные данные", "should_trigger": false, "expected": "pdn-152fz-audit"},
    {"prompt": "смоделируй угрозы", "should_trigger": false, "expected": "threat-model"}
  ]
}
```

- [ ] **Step 4: Прогнать классификацию + lint**

Как Task 5 Step 4 (для `.claude/skills/security-go-live/`). Особое внимание near-miss с `audit-portal` (IS7).

- [ ] **Step 5: Commit**

```bash
git add .claude/skills/security-go-live/
git commit -m "feat(security): security-go-live skill — go-live gate orchestrator (#73)"
```

---

## Phase 3 — ADR + роутер

### Task 8: ADR-014

**Files:**

- Create: `docs/adr/ADR-014-infosec-tooling.md`

- [ ] **Step 1: Прочитать шаблон ADR**

Прочитать `docs/adr/013-backend-tooling.md` (последний) как шаблон структуры (Status / Context / Decision / Alternatives / Consequences / Related / References).

- [ ] **Step 2: Написать ADR-014**

Содержание: Decision — 6 узлов infosec-tooling + границы; Alternatives — отброшенные готовые threat-model/compliance-скилы (ToxicSkills) + платные tiers + dedicated dependency-tool (дубль); Consequences — IS1–IS9 (§8 спеки) + bus-factor/supply-chain (мит. вет IS9 + pin) + DAST-safety IS8; Related — ADR-002 (RLS, драйвер ПДн-скила), ADR-003 (D3 граница). Включить серверный слой как «out of scope, отдельные открытые вопросы».

- [ ] **Step 3: Проверить adr-judge не падает**

Run (root):

```bash
git diff --cached --unified=0 | python -X utf8 tools/adr-judge.py --diff - --adr-dir docs/adr/
```

Expected: нет нарушений на собственном диффе.

- [ ] **Step 4: Commit**

```bash
git add docs/adr/ADR-014-infosec-tooling.md
git commit -m "docs(adr): ADR-014 infosec-tooling boundaries (IS1-IS9)"
```

---

### Task 9: routing-off-phase.md + router-procedure.md

**Files:**

- Modify: `docs/routing-off-phase.md`
- Modify: `docs/router-procedure.md`

- [ ] **Step 1: Прочитать текущие файлы**

Прочитать `docs/routing-off-phase.md` (формат routing-таблицы + связки L1–L14, версия v1.3) и `docs/router-procedure.md` (header v1.2).

- [ ] **Step 2: Добавить 6 строк routing-таблицы**

Для #68–73 — строки «триггер → узел» (значения routing-trigger из спеки §3 / атрибутов Task 10). Bump version routing-off-phase v1.3 → **v1.4**.

- [ ] **Step 3: Добавить каноническую связку L15**

L15 «security go-live chain»: #73 (оркестратор) → #68 ZAP / #69 Nuclei / #70 Enlightn / #71 ПДн / #72 угрозы + D3 (#39/#25/#26/#8/#40). Anti-pattern: не запускать ZAP/Nuclei в pre-commit хук (тяжёлые, требуют таргета); не путать #73 (security-only go-live) с `audit-portal` (полный аудит).

- [ ] **Step 4: Bump router-procedure.md**

router-procedure v1.2 → **v1.3**: процедура не меняется, обновить cross-ref-строку/счётчик узлов под новый набор.

- [ ] **Step 5: Verify lychee + commit**

```bash
./bin/lychee.exe --config .lychee.toml "docs/routing-off-phase.md" "docs/router-procedure.md"
git add docs/routing-off-phase.md docs/router-procedure.md
git commit -m "docs(router): +6 infosec nodes routing + L15 chain (routing-off-phase v1.4, router-procedure v1.3)"
```

---

## Phase 4 — Нормативка (АТОМАРНЫЙ набор — C2 STRICT)

### Task 10: Tooling + PSR_v1 + Pravila + CLAUDE.md — один атомарный коммит

> **Критично:** cross-ref-checker (C2, lefthook job 12) STRICT — все §0/header cross-refs между этими 4 файлами должны совпасть. Поэтому **все 4 файла редактируются и коммитятся ОДНИМ коммитом.** l1-watcher (C1, job 11) проверит формализацию MCP-серверов ZAP/Nuclei (см. alias Task 2/3).

**Files:**

- Modify: `docs/Tooling_v8_3.md`
- Modify: `docs/Plugin_stack_rules_v1.md`
- Modify: `docs/Pravila_raboty_Claude_v1_1.md`
- Modify: `CLAUDE.md`

- [ ] **Step 1: Tooling Прил. Н — §4.43–4.48 (9-атрибутные блоки)**

Прочитать §4.36 (finance plugin) как канонический шаблон 9-attribute блока, реплицировать для 6 узлов:

- **§4.43 #68 OWASP ZAP** — name@source per Task 1 вердикт; category: infosec-tooling (off-phase, 17-я); install: ZAP + MCP per `docs/security/zap-setup.md` + `.mcp.json` блок `zap`; activation: on-demand, READ-only сканер, локальный таргет (IS8); conflicts: IS1/IS2 (ADR-014); dormant: false; routing-trigger: «боевая проверка работающего портала», обход входа/инъекции/XSS; cost: 0 LLM.
- **§4.44 #69 Nuclei** — @ projectdiscovery/nuclei + wrapper per Task 1; infosec-tooling; install: `docs/security/nuclei-setup.md` + `.mcp.json` блок `nuclei`; activation: on-demand, локальный таргет (IS8); conflicts: IS2 (ADR-014); dormant: false; routing-trigger: «известные дыры/открытые двери/слабый TLS снаружи»; cost: 0 LLM.
- **§4.45 #70 Enlightn** — @ enlightn/enlightn (Composer dev-dep); infosec-tooling; install: `composer require enlightn/enlightn --dev` + `config/enlightn.php`; activation: on-demand/CI (`php artisan enlightn`), НЕ lefthook (IS3); conflicts: IS3 (ADR-014); dormant: false; routing-trigger: «безопасность настроек Laravel», заголовки/режим отладки/cookie; cost: 0 LLM.
- **§4.46 #71 pdn-152fz-audit** — @ self-authored (`.claude/skills/`); infosec-tooling; install: project skill auto-discovered; activation: trigger-based; conflicts: IS4/IS5 (ADR-014); dormant: false; routing-trigger: «проверь ПДн», «соответствие 152-ФЗ», утечки персональных данных; cost: skill inference.
- **§4.47 #72 threat-model** — @ self-authored; infosec-tooling; activation: trigger-based; conflicts: IS6 (ADR-014); dormant: false; routing-trigger: «смоделируй угрозы», «откуда атакуют», STRIDE going-public; cost: skill inference.
- **§4.48 #73 security-go-live** — @ self-authored; infosec-tooling; activation: trigger-based (оркеструет #68–72 + D3); conflicts: IS7 (ADR-014); dormant: false; routing-trigger: «прогон безопасности перед релизом», go/no-go; cost: skill inference.

§0 счётчик: 67 → **73**; добавить 17-ю off-phase подкатегорию «infosec-tooling». Header Прил. Н: v2.19 → **v2.20** + наследие-строка.

- [ ] **Step 2: PSR_v1 — R10.1 +6 строк + header**

R10.1 Блок 1 (project-скилы #71/#72/#73) + Блок 3 (MCP-серверы #68/#69) + строка Enlightn (#70, Composer dev-dep, не marketplace) с категорией infosec-tooling (не UI → вне R6/R14). Header v3.19 → **v3.20** + наследие.

- [ ] **Step 3: Pravila — §13.2 +абзац + header**

§13.2: +абзац «Off-phase infosec-tooling» (#68 ZAP / #69 Nuclei / #70 Enlightn / #71 pdn-152fz-audit / #72 threat-model / #73 security-go-live — 17-я подкатегория; счётчики — пин на Tooling Прил. Н §0; провенанс-вет IS9 обязателен для внешних). Header v1.35 → **v1.36** + §10 changelog.

- [ ] **Step 4: CLAUDE.md — §3.3 + §6 + §9 + header**

- §3.3: +6 строк #68–73 (однострочный индекс, пин на Tooling §4.43–4.48).
- §6: +абзац «2026-05-21 A8 infosec-tooling integration» сверху (+серверный слой → открытые вопросы).
- §9: +запись v2.23.
- §0 cross-refs: Pravila v1.36 / PSR_v1 v3.20 / Tooling Прил.Н v2.20.
- Header: v2.22 → **v2.23**.
(Прямой Edit — worktree-эксцепшн §5 п.10.)

- [ ] **Step 5: Verify cross-refs локально перед коммитом**

Run (root):

```bash
node tools/cross-ref-checker.mjs
node tools/l1-watcher.mjs
```

Expected: оба чисто (нет version drift; MCP ZAP/Nuclei формализованы/aliased).

- [ ] **Step 6: Атомарный commit (все 4 файла вместе)**

```bash
git add docs/Tooling_v8_3.md docs/Plugin_stack_rules_v1.md docs/Pravila_raboty_Claude_v1_1.md CLAUDE.md
git commit -m "docs(normative): A8 infosec-tooling #68-73 — Tooling v2.20/PSR v3.20/Pravila v1.36/CLAUDE v2.23"
```

---

## Phase 5 — Карта

### Task 11: automation-graph-data.js +6 узлов + рёбра + версии

**Files:**

- Modify: `docs/automation-graph-data.js`

- [ ] **Step 1: Прочитать текущее состояние карты**

Прочитать блок finance (`finance_plugin`/`billing_audit`/`ru_tax`) + backend (`rector`/`php_insights`/...) как образцы. **Зафиксировать текущий счётчик узлов/рёбер** из шапки/`NODES` (для commit-сообщения N→N+6).

- [ ] **Step 2: Добавить 6 узлов в NODES + NODE_SECTION (все A8)**

Узлы `mcp_zap`, `mcp_nuclei`, `enlightn`, `sk_pdn_152fz`, `sk_threat_model`, `sk_security_golive` в `NODES` (group: mcp / lefthook-нет / skills_proj) + в `NODE_SECTION` все 6 → `'A8'`. Reuse через `NODE_SECTION_SECONDARY` — нет (оставить только A8).

- [ ] **Step 3: Добавить рёбра**

Рёбра L15-цепочки: `sk_security_golive` → `mcp_zap`/`mcp_nuclei`/`enlightn`/`sk_pdn_152fz`/`sk_threat_model` + reuse-связи (`sk_security_golive` ↔ `mcp_semgrep`/`lh_gitleaks`/`trivy`(если есть узел)/Trail of Bits; `sk_pdn_152fz` ↔ pg_anonymizer-узел если есть). Обновить версии-метки шапки карты (v1.36/v2.23/v3.20/v2.20) + счётчики узлов/рёбер.

- [ ] **Step 4: Browser-smoke карты**

Открыть `docs/automation-graph.html` через Playwright MCP, проверить: 6 новых узлов рендерятся в секторе A8, рёбра присутствуют, нет JS-ошибок в консоли. Скриншот.

- [ ] **Step 5: Commit**

```bash
git add docs/automation-graph-data.js
git commit -m "feat(map): +6 A8 infosec-tooling nodes + L15 chain (N→N+6 nodes)"
```

---

## Phase 6 — Серверный слой (открытые вопросы)

### Task 12: Открытые_вопросы — +7 записей серверной защиты

**Files:**

- Modify: `docs/Открытые_вопросы_v8_3.md`

- [ ] **Step 1: Прочитать формат реестра**

Прочитать `docs/Открытые_вопросы_v8_3.md` (формат записи, префиксы, сводка §0). Выбрать префикс для серверной безопасности (новый `SEC-` или существующий `DO-` DevOps — по факту формата).

- [ ] **Step 2: Добавить 7 записей (только ДОБАВИТЬ — ничего не закрывать)**

7 записей серверного слоя (§9 спеки), каждая со статусом «открыт» и привязкой к Б-1 где уместно:

1. WAF (Yandex Smart Web Security / Coraza/ModSecurity).
2. Anti-brute-force / rate-limit (Laravel throttle + серверный).
3. DDoS-защита (Yandex Cloud DDoS Protection).
4. Мониторинг вторжений (Sentry #34 pending Б-1 + алерты).
5. Хранилище секретов (Yandex Lockbox).
6. TLS/HSTS/CSP на бою.
7. Бэкапы + IR-runbook (реюз operations:runbook #51).

Обновить сводку §0 (счётчики открытых вопросов). **Не закрывать никаких существующих вопросов** (правило §2.2 / economy).

- [ ] **Step 3: Verify lychee + commit**

```bash
./bin/lychee.exe --config .lychee.toml "docs/Открытые_вопросы_v8_3.md"
git add docs/Открытые_вопросы_v8_3.md
git commit -m "docs(open-questions): +7 server-side security items (A8 server layer, Б-1)"
```

---

## Phase 7 — Финал

### Task 13: Полная регрессия + finishing

**Files:** (нет правок)

- [ ] **Step 1: Полная регрессия**

Run (root `app/`):

```bash
composer pint -- --test
composer stan
php vendor/bin/pest --parallel --recreate-databases
```

Запустить Vitest, если затронут frontend (не затронут — пропустить). Expected: Pint 0, Larastan 0 above baseline, Pest GREEN (выписать точные числа passed/failed с file:line при падении).

- [ ] **Step 2: Pre-push проверки**

Run (root):

```bash
./bin/gitleaks.exe detect --source . --no-banner --config .gitleaks.toml --redact
./bin/lychee.exe --config .lychee.toml "docs/**/*.md" "*.md"
```

Expected: gitleaks 0; lychee 0 broken (untracked setup-доки `docs/security/*` — если ломают, добавить в exclude или закоммичены ранее).

- [ ] **Step 3: finishing-a-development-branch**

Использовать `superpowers:finishing-a-development-branch` — представить заказчику опции (push в main / PR / cleanup). Push паттерн `git push origin <ветка>:main` (memory reference_github).

---

## Self-Review (исполнено при написании плана)

**Spec coverage:**

- Спека §2 (6 узлов + out-of-scope) → Tasks 2/3/4 (внешние), 5/6/7 (скилы); out-of-scope зафиксирован в ADR Task 8 + серверный слой Task 12. ✅
- Спека §3 (детали узлов + границы) → Tasks 2–7 + ADR Task 8. ✅
- Спека §4 (роутер) → Task 9. ✅
- Спека §5 (наблюдатель: 9-атрибуты + C1/C2) → Task 10 (9-атрибуты §4.43–48, C1/C2 verify Step 5). ✅
- Спека §6 (нормативка атомарно) → Task 10. ✅
- Спека §7 (карта) → Task 11. ✅
- Спека §8 (IS1–IS9) → Task 8 ADR + заземление IS9 в Task 1, IS8 в Task 2/3/7. ✅
- Спека §9 (серверный слой) → Task 12. ✅
- Спека §10 (spikes) → Task 1 (IS9-вет) + smoke Task 2/3 + baseline Task 4. ✅
- Спека §11 (worktree subagent-driven) → Pre-flight + execution handoff. ✅
- Спека §12 (решения заказчика) → отражены в ADR Task 8 + гарды IS8/IS9. ✅

**Placeholder scan:** `<N>`/`<dev-port>` — намеренные spike/runtime-выходы (заполняются в Task 2/4), не placeholder-долги. Условные элементы (выбор источника per Task 1 вердикт) явно помечены ветвлением. ✅

**Type consistency:** имена узлов карты (`mcp_zap`/`mcp_nuclei`/`enlightn`/`sk_pdn_152fz`/`sk_threat_model`/`sk_security_golive`), номера (#68–73), §4.43–4.48, версии (v1.36/v3.20/v2.20/v2.23), коды IS1–IS9, связка L15, имена скилов (pdn-152fz-audit/threat-model/security-go-live) — единообразны across задач. ✅
