# Роли пользователей и права доступа

## 6 ролей

### Тренер (мобильное приложение)

- Дашборд: статистика, ближайшие занятия, рейтинг, долги
- Расписание: создание, отмена, перенос, повтор тренировок
- Клиенты: карточка, цели, травмы, запись на тренировку
- Воронка: новые -> назначенные -> проведённые
- Продажи клиентам
- График работы (синхронизация с 1С)
- Спящие клиенты (без активности > 1 месяц)
- SIP-звонки: исходящие (CallerID клуба) + журнал

### Координатор (мобильное приложение)

- Распределение клиентов по тренерам
- Передача между департаментами
- Статистика департамента и всех тренеров
- Расписание всех тренеров
- SIP-звонки + журнал

### Фитнес-менеджер (мобильное приложение + веб)

- Полная аналитика и отчёты
- Движение клиентов по воронке
- Расписание всех тренеров
- SIP-звонки

### Администратор рецепции (веб)

- Запись на ВПТ, поиск клиентов, карточки
- Распределение клиентов

### Администратор клуба (веб — club admin panel)

- Сотрудники, департаменты, залы, каталог услуг/пакетов
- Настройки уведомлений, интеграций (1С, SIP, webhooks, API-ключи)
- Email-рассылки: шаблоны, кампании, аналитика, настройки провайдера
- Лицензия, общие настройки клуба

### Суперадминистратор (веб — platform admin panel)

- Управление клубами и лицензиями
- Мониторинг платформы, audit log
- Управление темой оформления платформы (10 дизайн-китов)
- 2FA (TOTP) обязательна, IP-whitelisting

## Матрица прав доступа (полная)

| Функция                     | Тренер | Координатор | ФМ  | Админ (веб) | Админ клуба | Суперадмин |
| --------------------------- | ------ | ----------- | --- | ----------- | ----------- | ---------- |
| Главный экран (свои данные) | +      | +           | +   | —           | —           | —          |
| Статистика (своя)           | +      | x           | x   | —           | —           | —          |
| Статистика (департамента)   | x      | +           | +   | +           | —           | —          |
| Расписание (своё)           | +      | +           | —   | —           | —           | —          |
| Расписание (тренеров)       | x      | +           | +   | +           | —           | —          |
| Клиенты (свои)              | +      | x           | —   | —           | —           | —          |
| Клиенты (все)               | x      | +           | +   | +           | —           | —          |
| Воронка (своя)              | +      | x           | —   | —           | —           | —          |
| Воронка (общая)             | x      | +           | +   | +           | —           | —          |
| Распределение клиентов      | x      | +           | +   | +           | —           | —          |
| Выставить продажу           | +      | x           | +   | +           | —           | —          |
| Рейтинг                     | +      | +           | +   | —           | —           | —          |
| SIP: звонки + журнал        | +      | +           | +   | —           | —           | —          |
| Спящие клиенты              | +      | x           | —   | —           | —           | —          |
| Уведомления (push)          | +      | +           | +   | —           | —           | —          |
| График работы               | +      | x           | —   | +           | —           | —          |
| Аналитика и отчёты (веб)    | x      | x           | +   | +           | —           | —          |
| REST API (API-ключ)         | —      | —           | —   | —           | +           | +          |
| Webhooks: настройка         | —      | —           | —   | —           | +           | —          |
| Управление сотрудниками     | —      | —           | —   | —           | +           | —          |
| Управление департаментами   | —      | —           | —   | —           | +           | —          |
| Управление залами           | —      | —           | —   | —           | +           | —          |
| Каталог услуг и пакетов     | —      | —           | —   | —           | +           | —          |
| Настройки уведомлений       | —      | —           | —   | —           | +           | —          |
| Настройки интеграций        | —      | —           | —   | —           | +           | —          |
| Email: шаблоны + кампании   | —      | —           | —   | —           | +           | —          |
| Email: аналитика рассылок   | —      | —           | +   | —           | +           | —          |
| Лицензия / настройки клуба  | —      | —           | —   | —           | +           | +          |
| Управление клубами          | —      | —           | —   | —           | —           | +          |
| Управление лицензиями       | —      | —           | —   | —           | —           | +          |
| Мониторинг платформы        | —      | —           | —   | —           | —           | +          |
| Тема оформления (смена)     | —      | —           | —   | —           | —           | +          |

## Принципы UX-авторизации

### 1. Невидимость недоступного (Hide, Don't Block)

**Пользователь НЕ должен видеть то, к чему у него нет доступа.** Недоступные элементы не рендерятся — ни в меню, ни в списках, ни в карточках, ни в таблицах. Пользователь не должен натыкаться на «нет прав» при обычной работе в системе.

**Исключение**: прямой переход по URL (ссылку мог прислать коллега) — допустимо показать страницу «Контент недоступен». Но эта ссылка нигде в интерфейсе пользователя появляться не должна.

Правило распространяется на:

- **Пункты меню / навигации** — не рендерить в sidebar/tab bar, если роль не имеет доступа
- **Списки и таблицы** — недоступные записи не возвращаются API и не отображаются
- **Элементы карточек** — кнопки, ссылки, действия, колонки таблиц
- **Данные в API** — эндпоинт возвращает только доступные записи (фильтрация по роли на уровне запроса, не на уровне UI)
- **CRM-сделки** — менеджер видит только свои (assigneeId = userId), координатор — своего департамента
- **Прямой переход по URL** — страница «Этот контент вам недоступен» (не redirect, не пустая страница)

Реализация:

- **Backend**: `filterByRole()` в EntityPermissions — WHERE-условие на уровне запроса к БД
- **Frontend (Web)**: компонент `<RoleGate roles={[...]}>` — рендерит children только для указанных ролей
- **Frontend (Mobile)**: `useHasRole(role)` / `useHasPermission(permission)` хуки
- **Sidebar / Navigation**: маршруты фильтруются по `allowedRoles` из конфига навигации
- **API**: 404 (не 403) для сущности, к которой нет доступа — чтобы не раскрывать существование

### 2. Режим имперсонации для суперадмина (Role Switcher)

Суперадминистратор должен иметь возможность **переключать видимую роль** внутри системы без перелогинивания, чтобы видеть интерфейс глазами любой роли.

Механика:

- **UI**: выпадающий список ролей в header platform-admin (`Просмотр как: Суперадмин ▼`)
- **Варианты**: `Суперадмин` (по умолчанию), `Админ клуба [выбор клуба]`, `Фитнес-менеджер`, `Координатор`, `Тренер`, `Админ рецепции`
- **Backend**: `POST /v1/auth/impersonate` — возвращает временный JWT с `{ role: targetRole, impersonatedBy: realUserId, clubId }`. Все аудит-логи сохраняют `impersonatedBy`
- **Визуальная индикация**: яркий баннер вверху экрана `Вы просматриваете систему как [Роль]. Вернуться к суперадмину ×`
- **Ограничения**: запись/модификация данных в режиме имперсонации запрещена (read-only), кроме явного флага `allowWrite`
- **Выход**: клик «×» на баннере или выбор «Суперадмин» — возврат к исходному JWT
