# План: route-level rate-limit (Laravel Throttle) на auth-эндпоинтах

## Цель

Через TDD добавить именованные rate-лимитеры `auth-login` / `auth-2fa` /
`auth-password` (`perMinute(20)->by(ip)`) в `AppServiceProvider::boot` и применить
`throttle:`-middleware к маршрутам login / forgot / reset-password / 2fa/verify /
2fa/recovery-use. Сначала падающий поведенческий Pest-тест на `forgot` (21-й
запрос с одного IP → 429 от middleware), затем реализация до зелёного, затем
прогон всего каталога auth-тестов на отсутствие регрессии. Прогон — из каталога
`app`, где автозагрузка и Pest.

```skills-json
["test-driven-development"]
```

```steps-json
[
  {"op": "Bash", "object": "cd \"c:/моя/проекты/портал crm/Документация/app\"", "ref": "D5"},
  {"op": "Write", "object": "c:/моя/проекты/портал crm/Документация/app/tests/Feature/Auth/AuthRouteThrottleTest.php", "ref": "D5"},
  {"op": "Bash", "object": "php artisan test tests/Feature/Auth/AuthRouteThrottleTest.php", "ref": "D5"},
  {"op": "Edit", "object": "c:/моя/проекты/портал crm/Документация/app/app/Providers/AppServiceProvider.php", "ref": "D2"},
  {"op": "Edit", "object": "c:/моя/проекты/портал crm/Документация/app/routes/web.php", "ref": "D2"},
  {"op": "Bash", "object": "php artisan test tests/Feature/Auth", "ref": "D5"},
  {"op": "Write", "object": "c:/моя/проекты/портал crm/Документация/docs/superpowers/runbooks/2026-06-17-auth-throttle-limits.md", "ref": "D2"}
]
```

```verified-context-json
[
  {
    "id": "ctx-route-forgot",
    "kind": "EXTRACTED",
    "ref": "app/routes/web.php",
    "anchor": "Route::post('/forgot', 'App\\Http\\Controllers\\Api\\PasswordResetController@forgotPassword');"
  }
]
```

## Переговоры

### Круг 1

Довод по реализации: лимитеры именованные ради изоляции счётчиков login/2fa/password
(общий `throttle:N,1` делил бы per-IP счётчик между всеми маршрутами домена).
Значение 20/мин выбрано выше максимума запросов любого существующего auth-теста к
одному маршруту в одном методе (login 11, forgot 7, 2fa 6) — поэтому существующие
тесты не ломаются; финальный шаг прогоняет весь каталог `tests/Feature/Auth` для
подтверждения отсутствия регрессии. Поведенческий тест ставится на `forgot`,
потому что разные unknown-email обходят контроллерный per-email лимит и оставляют
единственным ограничителем именно route-throttle. Прошу наставника зафиксировать
forward-рекомендацию по достаточности покрытия (forgot как репрезентативный
маршрут) и по стартовому значению лимита.
