# Runbook: route-throttle на auth-эндпоинтах

**Дата:** 2026-06-17 · **Зона:** `app/` (backend) · **Связано:** P1 go-live, [open-items](../../security/2026-06-17-open-items.md)

## Что сделано

Per-IP route-throttle (Laravel Throttle middleware) поверх уже существующего
прикладного per-credential rate-limit в auth-контроллерах. Закрывает пробел:
`forgot`/`2fa`/`reset` не имели per-IP объёмного предела (через разные email
можно было перебирать без преграды).

## Лимитеры (`app/app/Providers/AppServiceProvider.php::boot`)

| Лимитер | Маршруты | Значение |
|---|---|---|
| `auth-login` | `POST /api/auth/login` | `perMinute(20)->by(ip)` |
| `auth-2fa` | `POST /api/auth/2fa/verify`, `/2fa/recovery-use` | `perMinute(20)->by(ip)` |
| `auth-password` | `POST /api/auth/forgot`, `/reset-password` | `perMinute(20)->by(ip)` |

Применение — `->middleware('throttle:<name>')` в `app/routes/web.php`.
`register` намеренно без throttle (вне P1-перечня).

## Тюнинг

- **20/мин** — стартовое значение, выбрано выше максимума тестовых циклов
  (login 11, forgot 7, 2fa 6), чтобы не ломать существующие auth-тесты.
- Для anti-enumeration на `forgot` значение можно **снизить** (например до 10/мин)
  после наблюдения боевого трафика — поправить число в `boot()`, прогнать
  `php artisan test tests/Feature/Auth`.
- Превышение → стандартный Laravel **429** + `Retry-After`.

## Проверка

`php artisan test tests/Feature/Auth` (из каталога `app`) — 97 тестов, включая
`AuthRouteThrottleTest` (21-й `forgot` с одного IP → 429 от middleware).
