# Спека: деплой F-1 (CVE vendor-апдейт) на боевой liderra.ru — v3

## Цель

Закрыть 14 CVE на 9 пакетах боевого liderra.ru, обновив зависимости (`vendor`) до
пропатченных версий без выкатки кода приложения. Результат: `composer audit` на проде —
без advisories, портал отвечает, очередь без новых фатальных ошибок.

## Контекст и предусловия {#D1}

Контракт состояния перед деплоем:

- Прод крутит **уязвимые** версии (`vendor` не пересобран): laravel/framework, guzzlehttp/psr7,
  symfony/*. Локальный `composer.lock` уже пропатчен (laravel v13.15.0, guzzlehttp/psr7 2.11.0,
  symfony 7.4-патч).
- App-код прод↔`main` — паритет по хешам → код НЕ выкатываем, деплой узкий (только зависимости).
- Доступ к проду — только `ssh liderra-prod` (ProxyJump через бастион). Корень приложения и
  пользователь файлов проверяются по факту (ожидание: `/var/www/liderra/app`, `www-data`).
- **Проверка миграций lead-region:** убедиться, что фича на проде живёт — `php artisan migrate:status`
  показывает миграцию `phone_ranges` как Ran. Если миграций нет — это другой деплой, останов
  (фича live на 100%, отсутствие маловероятно).

## Доставка пропатченного lock {#D2}

Конвенция: на проде должен оказаться локальный пропатченный `composer.lock`. Способ — по факту:

- **git**, если прод-репо чист (`git status --short` пуст): `git checkout origin/main -- composer.lock`;
- **scp**, если репо грязный или проще файлом: скопировать `app/composer.lock` → заменить на проде,
  выставить владельца файла.

Edge-case: грязный прод-репо (`git status` не пуст) → git-способ небезопасен, использовать scp.
Критерий доставки: `laravel/framework` в lock на проде стал `v13.15.0`.

## Бэкап и режим обслуживания — точка отката {#D3}

Создаётся ДО любого изменения `vendor`. Без этого блока откат (D6) невыполним. Команды (точные):

- резерв lock: `cp composer.lock composer.lock.bak-f1`;
- резерв vendor: `tar czf /var/www/liderra/vendor-bak-f1.tar.gz vendor`;
- точка отката git: зафиксировать `git rev-parse HEAD`;
- проверить, что бэкап создан: `ls -lh /var/www/liderra/vendor-bak-f1.tar.gz` (ненулевой размер).

Перед необратимым шагом (D4) — увести приложение из-под нагрузки:

- режим обслуживания: `php artisan down`;
- остановить воркер очереди: `systemctl stop liderra-queue` (имя службы уточнить по факту), чтобы
  `composer install` не пересобирал автозагрузчик под работающими джобами.

Критерий блока: оба бэкап-файла существуют и ненулевые, приложение в `down`, воркер очереди
остановлен — только после этого допустим D4.

## Обновление зависимостей {#D4}

Главный (необратимый) шаг. Конвенция: `composer install` (НЕ `update`) — ставит ровно версии из
доставленного lock без дрейфа; `--no-dev` — прод без dev-зависимостей; `--optimize-autoloader`.
Полная команда: `composer install --no-dev --optimize-autoloader --no-interaction`. После установки:

- сброс кэшей: `php artisan optimize:clear`;
- перезапуск воркеров: `php artisan queue:restart` + запуск службы `systemctl start liderra-queue`;
- снять режим обслуживания: `php artisan up` (после успешного smoke D5).

## Критерий приёмки и smoke {#D5}

Признаки успеха (все обязательны), выполняются до `artisan up`:

- `composer audit --locked --no-interaction` — **без advisories**;
- `composer show laravel/framework` — версия `v13.15.0`;
- `php artisan about` — без ошибок;
- HTTP `https://liderra.ru/` — код `200`/`302`;
- журнал очереди за 5 мин — без новых фатальных ошибок.

## Откат {#D6}

Критерий отката: любой пункт smoke (D5) провалился. Действие (бэкапы созданы в D3):

- восстановить lock: `cp composer.lock.bak-f1 composer.lock`;
- удалить битый `vendor` и распаковать резерв: `rm -rf vendor` → `tar xzf /var/www/liderra/vendor-bak-f1.tar.gz`;
- вернуть владельца файлов `vendor` и `composer.lock`;
- `php artisan optimize:clear` + `php artisan up` + запуск воркера очереди.

После суток стабильности бэкап-файлы (`vendor-bak-f1.tar.gz`, `composer.lock.bak-f1`) удалить.

```verified-context-json
[
  {"id":"VC1","kind":"EXTRACTED","ref":"docs/superpowers/plans/2026-06-16-f1-cve-deploy-runbook.md","anchor":"composer install --no-dev --optimize-autoloader"},
  {"id":"VC2","kind":"EXTRACTED","ref":"docs/superpowers/plans/2026-06-16-session-close-handoff.md","anchor":"F-1 (CVE) запатчен локально"}
]
```
