# Технический аудит портала Лидерра — Этап 2 (скрытые хвосты), v2

## Цель

Сквозной технический аудит **локальной dev-копии** портала: найти **скрытые** дефекты
качества и безопасности, которых нет ни в документации, ни в TODO-метках — упавшие тесты,
нарушения статанализа, уязвимости, известные CVE в зависимостях, мёртвый код, дрейф схемы.

**Окружение и безопасность.** Аудит идёт на локальной dev-копии (native Windows). Все
БД-операции тестов изолированы в выделенной **тестовой** БД через testing-окружение Laravel;
боевая БД `liderra.ru` из этого окружения недоступна. Аудит **наблюдательный**: он не содержит
деструктивных команд (никакого пересоздания/дропа боевых данных, миграций боевой схемы,
force-push). Единственные побочные эффекты — заполнение/миграция изолированной тестовой БД
самим тест-раннером и временные кэш-файлы; исходники и боевые данные не меняются.

Результат — перечень находок с серьёзностью P0–P3 и сверка с уже известными хвостами проекта.
Закрытие открытых вопросов реестра (Б-/CTO-/Биз-/Диз-/DO-/SEC-) в этот этап не входит.

## Статанализ backend {#D1}

**Контракт:** проверить PHP-код Лидерры — стиль (Pint в режиме проверки `--test`, без правок),
статический анализатор типов и логики (Larastan/PHPStan), известные уязвимости зависимостей
(composer audit по locked-файлу), плюс инвентарь установленных пакетов.

**Критерий находки:** ненулевой код возврата Pint = нарушения стиля (P2); сообщения Larastan
сверх baseline = типовые/логические дефекты (P1/P2); запись в выводе composer audit = CVE в
зависимости (P0/P1 по тяжести). Инвентарь пакетов — справочный (сверка с ожидаемым стеком).

**Конвенция:** инструменты запускаются для каталога приложения `app/` (composer-скрипты
`pint:test`, `stan`, `audit-offline`, `show`); все они read-only по отношению к исходникам.

## Статанализ frontend {#D2}

**Контракт:** проверить Vue/TypeScript-код — линтер (ESLint flat-config + plugin-vue), типы
(vue-tsc `--noEmit`), форматирование (Prettier в режиме проверки `--check`, без правок).

**Критерий находки:** ошибки ESLint = дефекты кода/стиля (P1/P2); ошибки vue-tsc = нарушения
типобезопасности и компиляции (P1); расхождение Prettier = неотформатированные файлы (P2).

**Конвенция:** запуск для `app/` через npm-скрипты `lint:vue`, `type-check`, `format:check`;
все три read-only.

## Статанализ документации и SQL {#D3}

**Контракт:** проверить нормативную/проектную документацию (markdownlint, орфография cspell)
и DDL-схему БД (squawk — линтер схемы PostgreSQL по `db/schema.sql`).

**Критерий находки:** ошибки markdownlint/cspell = дефекты доков (P2/P3); предупреждения squawk
= небезопасные/нестандартные конструкции DDL (P1/P2).

**Конвенция:** запуск из корня репозитория (npm-скрипты `lint:md`, `spell`, `lint:sql`),
read-only.

## Инвентарь окружения {#D4}

**Контракт:** снять справочные read-only срезы dev-окружения — список запланированных задач
(artisan `schedule:list`) и обзор подключения/таблиц тестовой БД (artisan `db:show`), чтобы
выявить расхождения с ожидаемым составом расписаний и схемой.

**Критерий находки:** пустой/неожиданный список расписаний или отсутствие ожидаемых задач = P2;
расхождение числа таблиц/подключения с эталоном схемы = сигнал к более глубокой сверке (P1/P2).

**Конвенция:** строго read-only artisan-команды (`schedule:list`, `db:show`), без мутаций;
выполняются с указанием пути `app/artisan`.

## Тестовые своды {#D5}

**Контракт:** прогнать backend-тесты (стандартный `composer test` — artisan test на testing-БД,
без пересоздания боевых данных) и frontend-тесты (Vitest `run`).

**Критерий находки:** любой упавший тест Pest/Vitest = **P1** (нарушение функциональности —
главный искомый скрытый хвост). Зелёный свод подтверждает отсутствие регрессий.

**Конвенция:** тест-раннеры пишут только в изолированную тестовую БД testing-окружения;
боевые данные недоступны и не затрагиваются. Backend из `app/` (скрипт `test`), Vitest из
`app/` (скрипт `test:vue`).

## Security {#D6}

**Контракт:** поиск секретов в репозитории (gitleaks detect) и статический анализ безопасности
кода (Semgrep по наборам правил PHP/JS/TS/secrets + локальный `.semgrep.yml`).

**Критерий находки:** найденный секрет = **P0** (инцидент безопасности); срабатывание Semgrep =
потенциальная уязвимость (P0–P2 по правилу). Semgrep тянет наборы правил из реестра — сетевая
зависимость; недоступность инструмента/сети фиксируется как «проверка не выполнена».

**Конвенция:** gitleaks из корня (бинарь `bin/gitleaks.exe`, read-only скан); Semgrep через
npm-скрипт `sast` (read-only скан).

## Мёртвый код {#D7}

**Контракт:** найти неиспользуемые экспорты, файлы и зависимости фронтенда (knip).

**Критерий находки:** сообщения knip = неиспользуемый код/зависимости (P2/P3) — кандидаты на
удаление; ложные срабатывания на намеренных заглушках отсеиваются при разборе.

**Конвенция:** knip для каталога `app/`, read-only.

## Серьёзность находок {#D8}

**P0** — блокирует production / порча данных / инцидент безопасности. **P1** — нарушение
функциональности / упавший тест / ошибка типов / уязвимость. **P2** — предупреждение / стиль /
мёртвый код / устаревший документ. **P3** — косметика. P0/P1 фиксируются как находки с
указанием места; закрытие открытых вопросов реестра — вне этого этапа (требует явного решения
владельца). Сборка фронтенда и UI-smoke (требуют поднятого сервера) и глубокая сверка
схемы боевой БД в этот наблюдательный прогон не входят — выносятся отдельно.

```verified-context-json
[
  {"id":"C1","kind":"EXTRACTED","ref":"app/composer.json","anchor":"\"test\": ["},
  {"id":"C2","kind":"EXTRACTED","ref":"package.json","anchor":"\"sast\": \"semgrep --config=p/php"},
  {"id":"C3","kind":"EXTRACTED","ref":"tools/cost-pricing.mjs","anchor":"export const PRICING = Object.freeze("}
]
```
