VEU.WathBody/1-docs/4-modules/m08-admin-web/module_reqs.md

6.5 KiB
Raw Blame History

Требования к модулю: 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 — зелёные; сборка решения без ошибок.