# Спецификация 02: атлеты (AdminAthletesController) Источники: Ф-9.1 (управление, вопрос 9 закрыт), 🛡2 (ключ — один раз). ## 1. Эндпоинты (все — Bearer, spec 01) | Метод | Путь | Тело → Ответ | |---|---|---| | GET | `/api/admin/athletes` | → `{"items":[{"id":1,"name":"Иван","isBlocked":false,"createdAt":"…"}]}` | | POST | `/api/admin/athletes` | `{"name":"Иван"}` → `201 {"id":…,"apiKey":"wb-…"}` | | POST | `/api/admin/athletes/{id}/key` | — → `200 {"apiKey":"wb-…"}` | | POST | `/api/admin/athletes/{id}/block` | `{"isBlocked":true}` → `200 {"id":…,"isBlocked":true}` | ## 2. Семантика - **Создание**: имя непустое (иначе 400); ключ = `"wb-" + 24 hex` (random); в БД — только `ApiKeyHash.Of(key)` (SHA-256, как m02); ключ возвращается **один раз** (повторно не выдаётся — 🛡2); дубликат имени допустим (БД не запрещает; консоль показывает id). - **Смена ключа**: новый ключ по тому же правилу; `athlete_update` (все поля, NULL-семантики нет — m01); старый ключ перестаёт работать немедленно. - **Блокировка**: `athlete_update` c `is_blocked`; заблокированный ключ → 401 на `/api/v1/*` (m02, проверяется тестом сквозняком); блокировка не удаляет данные. - Все записи — только `athlete_insert`/`athlete_update` (🛡3). ## 3. Ошибки - 400 — пустое имя; 404 — атлет не найден (id); 401 — без токена.