86 lines
6.5 KiB
Markdown
86 lines
6.5 KiB
Markdown
# Требования к модулю: m08-admin-web
|
||
|
||
> Модуль — административная консоль владельца (Ф-9, решение владельца
|
||
> 2026-10-17): бэкенд — admin REST API `/api/admin/*` в
|
||
> `Server.WatchBody.Web`; UI — Flutter Web-приложение
|
||
> `3-app\3-web\admin-web` (SDK 3.47.7 — `C:\tools\flutter`), сборка
|
||
> отдаётся сервером из `wwwroot\admin\`. Аутентификация владельца —
|
||
> логин/пароль (`Admin.Login` / `Admin.PasswordHash`, PBKDF2) →
|
||
> Bearer-токен сессии; атлеты к консоли доступа не имеют (🛡
|
||
> изменение vision 1.2). Самодостаточная копия требований (d-dev-6).
|
||
|
||
## 1. Назначение и границы
|
||
|
||
**В границах модуля (backend REST):**
|
||
|
||
- аутентификация: `POST /api/admin/login` (логин+пароль →
|
||
`pbkdf2$...`-проверка → Bearer-токен, in-memory сессия, TTL 8 ч);
|
||
все `/api/admin/*` кроме login — только с валидным токеном (401);
|
||
- атлеты (Ф-9.1): список; создание (имя → сервер генерирует API-ключ,
|
||
возвращается один раз, в БД — только хэш); смена ключа; блокировка/
|
||
разблокировка (заблокированный ключ → 401 на API телефонов);
|
||
- тренировки (Ф-9.2): таблица по всем атлетам (фильтр атлет/дата,
|
||
пагинация); карточка (подходы, план/факт, `facts_json`: таймлайн
|
||
Lap + пульс Record, средний/пиковый пульс подхода, отдых);
|
||
CSV-выгрузка текущей выборки (КУ-4, формат tech-req 2.4: `;`,
|
||
UTF-8 BOM, `athlete;date;duration_min;avg_hr;sets;exercises;
|
||
adherence_pct`);
|
||
- программы (Ф-9.3): версии атлета (статусы/автор/даты/body);
|
||
активация draft (ProgramStore.Activate); применение предложения
|
||
правил из консоли — новая версия `author=admin` с телом rules-draft,
|
||
затем активация (🛡 неизменяемость версений, Ф-9.3);
|
||
- метрики (Ф-9.4): выборка `workout_metrics` атлета за период;
|
||
- планы тренировок (Ф-9.5): сводка план/факт по неделям активной
|
||
версии (запланировано сессий / выполнено / пропущено; доля);
|
||
- отдача статики Flutter-сборки `wwwroot\admin\` (если каталог есть) —
|
||
UI хостится тем же Kestrel.
|
||
|
||
**Вне границ модуля:** Flutter Web UI `3-app\3-web\admin-web`
|
||
(отдельный этап — требует Flutter SDK, решение гейта 1.3), редактор
|
||
body версий (v1: просмотр + активация; правка — телефон m09/импорт
|
||
m06), LLM-контур (v2), выгрузка АД-журнала CSV (v3).
|
||
|
||
## 2. Сессии и токены
|
||
|
||
- пароль проверяется по `Admin.PasswordHash` (PBKDF2 100k, соль в
|
||
хэше, префикс `pbkdf2$`; формат — `<login>-salt` || PBKDF2-SHA256);
|
||
несовпадение → 401 без указания, что именно неверно;
|
||
- токен: 256-bit random (base64url), in-memory словарь
|
||
`token → (expiresAt)`; перезапуск сервера — сессии сбрасываются
|
||
(владелец входит заново); TTL 8 ч; logout — удаление из словаря;
|
||
- 🛡 токены/пароли в логи не пишутся; `Admin.PasswordHash` не
|
||
возвращается никаким эндпоинтом.
|
||
|
||
## 3. Инварианты (🛡 — нарушять запрещено)
|
||
|
||
1. **Только владелец** — `/api/admin/*` недоступен атлетам: их
|
||
`X-Api-Key` не принимается, изолированный контур (`/api/v1/*`
|
||
не меняется).
|
||
2. **Тайны** — API-ключ атлета возвращается только при создании/смене;
|
||
хэши, пароли, токены — не возвращаются и не логируются.
|
||
3. **Запись только управляющая** — admin API не пишет факт-данные
|
||
(тренировки/подходы/метрики): только атлеты (create/block/key),
|
||
статусы версий программ и author=admin-копии предложений.
|
||
4. **Неизменяемость версий** — активация через ProgramStore;
|
||
author=admin-копия создаётся CreateDraft, оригинал rules-draft
|
||
не меняется.
|
||
5. **Формат CSV** — точно tech-req 2.4 (разделитель `;`, UTF-8 BOM).
|
||
|
||
## 4. Критерии приёмки модуля
|
||
|
||
1. Логин: верный пароль → токен (последующие запросы с Bearer — 200);
|
||
неверный → 401; без токена/с токеном атлета (X-Api-Key) → 401.
|
||
2. Атлеты: создание возвращает ключ (в БД только хэш, повторный
|
||
запрос ключ не отдаёт); смена ключа; блокировка → sync телефона
|
||
с тем ключом получает 401; разблокировка → снова 200.
|
||
3. Тренировки: список всех атлетов с фильтрами/пагинацией; карточка
|
||
с подходами и план/факт; CSV выборки соответствует формату.
|
||
4. Программы: версии атлета; активация draft меняет active (прежняя —
|
||
archived); применение rules-предложения → активна версия
|
||
author=admin с телом предложения.
|
||
5. Метрики и план/факт: выборка метрик за период; сводка недель
|
||
(запланировано/выполнено/пропущено) сходится с фактическими
|
||
тренировками.
|
||
6. Тесты интеграционные против docker `watchbody-pg` — зелёные;
|
||
сборка решения без ошибок.
|