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

## Цель

Сквозной технический аудит портала: найти **скрытые** дефекты качества и безопасности,
которых нет ни в документации, ни в TODO-метках — упавшие тесты, нарушения статанализа,
уязвимости, известные CVE в зависимостях, мёртвый код, дрейф схемы. Аудит **только читает
и измеряет** (наблюдательный прогон); правок продукта на этом этапе нет. Каждая команда
аудита даёт измеримый сигнал (код возврата + вывод), по которому классифицируется находка.

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

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

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

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

**Конвенция:** инструменты запускаются из каталога приложения `app/` (composer-скрипты
`pint:test`, `stan`, `audit-offline`); порог Larastan — текущий baseline проекта.

## Статанализ 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`.

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

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

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

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

## Pre-prod инвентарь {#D4}

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

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

**Конвенция:** read-only artisan-команды, выполняются с указанием пути `app/artisan`.

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

**Контракт:** прогнать backend-тесты (Pest `--parallel --recreate-databases`), frontend-тесты
(Vitest `run`), сборку фронтенда (Vite `build`) — последняя одновременно проверяет целостность
бандла и отсутствие ошибок компиляции.

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

**Конвенция:** Pest/Vitest из `app/`; пересоздание тестовых БД для изоляции; сборка пишет
артефакты в build-каталог приложения (ожидаемый побочный эффект, не правка исходников).

## Security {#D6}

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

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

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

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

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

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

**Конвенция:** knip из каталога `app/`.

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

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

```verified-context-json
[
  {"id":"C1","kind":"EXTRACTED","ref":"app/composer.json","anchor":"\"test:parallel\": \"@php vendor/bin/pest"},
  {"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("}
]
```
