Интерфейсы по ролям и доступам
1) Принципы
1. Безопасность = UX-задача. Пользователь должен ясно понимать, что он может и не может делать, без «серых зон».
2. Минимально необходимые права. От отображения до действий — все ограничено задачами роли.
3. Сигнал вместо запрета. Если доступа нет — объясняем почему и как получить (запрос, заявка, обучение).
4. Дублирование на сервере. UI-гварды никогда не заменяют серверные проверки.
5. Прозрачный аудит. Каждое чувствительное действие оставляет читаемый след.
2) Модели управления доступом
RBAC (Role-Based): фиксированные роли: Игрок, Саппорт, Финансы, Риск/Комплаенс, Аффилиат-менеджер, Модератор, Админ.
ABAC (Attribute-Based): политика на основе атрибутов (юрисдикция, бренд, часовой пояс, VIP-уровень, команда, смена).
ReBAC (Relationship-Based): доступ по отношениям (куратор игрока, владелец тикета, менеджер партнера).
SoD (Segregation of Duties): разделение критичных задач (создал ≠ утвердил).
Практика: RBAC как базис, ABAC для тонкой настройки (бренд/регион), SoD для финансов/лимитов, ReBAC — точечно (курируемые портфели).
3) Карта функций по ролям (пример iGaming)
4) UX-паттерны для прав и ролей
4.1 Навигация и видимость
Скрывайте недоступные разделы из навигации (уменьшение шума), но показывайте информационные «пустые» карточки, если это помогает понять возможности.
Для временно недоступного — «Замок» с подсказкой: причина, требования, CTA «Запросить доступ».
4.2 Состояния действий
Disabled + tooltip: «Требуется роль Финансы. Запросить доступ».
Read-only режим: поля «под стеклом», явный маркер «Только чтение».
Эскалация: кнопка «Отправить на утверждение» вместо «Применить».
4.3 Маскирование и редактирование
PII (email, телефон, адрес) — `user@.`, `+380 90` для чужих записей.
PAN/IBAN — только токены/последние 4.
Переключатель «Показать полностью» — только для владеющей роли/по событию с аудитом.
5) Архитектура разрешений в UI
Policy-контекст на клиенте: кеш разрешений (TTL короткий) + подписка на обновления.
Гварды маршрутов: недоступные роуты → 403-страница с объяснением и CTA.
Гварды компонентов: `Can({ action:'approve_withdrawal', resource:'payout' })`.
Фичефлаги: экспериментальные/сезонные вещи — отдельно от прав.
tsx type Permission = string; // 'payout.approve', 'kyc.view_masked'
type Policy = { has:(p:Permission)=>boolean };
const PolicyCtx = React.createContext<Policy>({ has:()=>false });
export const Can: React.FC<{perm:Permission, children:React.ReactNode, fallback?:React.ReactNode}>
= ({perm, children, fallback=null}) => {
const { has } = React.useContext(PolicyCtx);
return has(perm)? <>{children}</>: <>{fallback}</>;
};
6) Сервер > Клиент
Любое действие подтверждается сервером по токену с клеймами (роль, атрибуты).
Политики централизованы (PDP/OPA/Cedar/Zanzibar-подобные), UI получает только решение.
Все критичные операции — двухфакторное подтверждение + аудит.
7) Маскирование и красные зоны данных
Категории данных:- PII: имя, email, телефон, адрес, дата рождения.
- Финансы: PAN/IBAN/криптокошельки, суммы, лимиты, бонусные балансы.
- Документы: паспорта/ID/селфи (KYC).
- Игровые: история ставок/выигрыши/паттерны.
- Полное — владеющая роль/владелец записи.
- Маскировано — саппорт, финансы (не владелец).
- Агрегировано — аналитика (без идентификаторов).
tsx function Redact({text, perm}:{text:string, perm:Permission}){
const { has } = React.useContext(PolicyCtx);
return <span>{has(perm)? text: text.replace(/.(?=.{4})/g,'•')}</span>;
}
8) Потоки утверждений (Approvals) и SoD
Четыре глаза: инициатор ≠ утверждающий.
Многоступенчатые маршруты (например, суммы > X → 2-я линия).
Срок действия заявок, SLA, эскалации.
Журнал: кто создал, кто изменил, кто утвердил, когда и откуда.
Примеры: подтверждение вывода, изменение лимитов игрока, вердикт KYC, снятие санкционного флага.
9) Специфика iGaming
Лимиты и самоисключение: изменение только с SoD и обязательным уведомлением пользователя.
KYC/AML: доступ к документам — узкая роль; предпросмотр миниатюр, полноразмер — по отдельному действию с логом.
Санкционные/PEP-флаги: видны риск-команде; саппорту — только статус «нужна проверка».
Платежи/выводы: «провести/отклонить» — только роль Финансы; суммы свыше порога — двойное подтверждение.
Журналы ставок: саппорт читает, но не редактирует; корректировки — отдельная функция с расследованием.
10) Локализация, A11y, RTL
Тексты «нет доступа» локализуются и содержат действующие пути (заявка/обучение).
Управление фокусом: не переносить пользователя на «пустую» страницу без объяснений.
RTL-режим поддержан для ролей в соответствующих регионах.
A11y: `aria-disabled` + пояснение, клавиатурная доступность эскалации.
11) Состояния и ошибки
403 (нет прав): дружелюбная страница с контекстом роли и CTA «Запросить доступ».
404 (нет ресурса): не раскрывать существование скрытых объектов.
413/422 (слишком много/валидация): не сливать детали политики, формулируйте нейтрально.
Rate-limits/блокировки: объясняйте таймер/условие разблокировки.
12) Метрики
Access Denied Rate: доля отказов по ролям/экранам (сигнал о плохой IA или политике).
Approval SLA: медиана времени утверждения по потокам (вывод, лимиты, KYC).
Mask Reveal Events: частота «раскрытий» PII (ожидаемо мала и обоснована).
Error-to-Resolution: время от 403 до выданного доступа.
Least-Privilege Drift: роли с избыточными правами (детект по использованию).
13) Анти-паттерны
Скрывать ошибки под «ничего не произошло».
Показывать пустые кнопки без объяснений.
Маскировать владельцу его собственные данные.
Полагаться на UI-гварды без серверных политик.
Смешивать фичефлаги с доступами (разные задачи).
Давать саппорту «god-mode» ради удобства.
14) Токены дизайн-системы (пример)
json
{
"access": {
"badge": { "viewer":"#607D8B", "editor":"#4CAF50", "approver":"#FF9800", "admin":"#9C27B0" },
"lockColor": "#9E9E9E",
"maskChar": "•"
},
"states": {
"noAccess": { "bg":"var(--bg-elev)", "border":"var(--border)", "icon":"#9E9E9E" },
"approval": { "pending":"#FFC107", "approved":"#4CAF50", "rejected":"#F44336" }
},
"a11y": { "ariaDisabled": true, "explainDenial": true }
}
15) Сниппеты UI
Маршрутный гвард:tsx import { Navigate, Outlet } from 'react-router-dom';
function GuardedRoute({perm}:{perm:Permission}){
const { has } = React.useContext(PolicyCtx);
if (has(perm)) return <Outlet/>;
return <Navigate to={`/403?perm=${encodeURIComponent(perm)}`} replace/>;
}
Карточка «нет доступа» с CTA:
html
<article class="no-access">
<h3>Недостаточно прав</h3>
<p>Доступ к разделу «Выплаты» доступен ролям: Финансы/Админ.</p>
<button class="btn" data-open-request>Запросить доступ</button>
</article>
Журнал аудита (сокращенно):
json
{
"ts": "2025-11-03T18:45:12Z",
"actor": "u_5412",
"action": "payout.approve",
"target": "withdraw#w_91822",
"ip": "194...12",
"result": "success"
}
16) QA-чек-лист
Навигация и IA
- Недоступные разделы не шумят в меню.
- Есть понятные страницы/карточки «нет доступа» с CTA.
Действия и гварды
- Кнопки без прав — `disabled` + tooltip/текст.
- Роуты защищены; прямой URL → 403 с объяснением.
- Сервер подтверждает каждое действие.
Данные
- PII/PAN/KYC маскируются по политике.
- Логи «раскрытий» пишутся и ревьюятся.
- Экспорт/отчеты соответствуют роли (агрегаты для аналитики).
SoD/Approvals
- Инициатор не может утвердить свою заявку.
- Пороговые суммы → многоступенчатые маршруты.
A11y/Локализация
- «Нет доступа» локализовано; клавиатурная навигация работает.
- Контраст/фокус-кольца соответствуют AA.
Надежность
- Кеш разрешений с коротким TTL; инвалидация при смене роли.
- Падение PDP → UI работает в режиме «дефолт-безопасно».
17) Документация в дизайн-системе
Компоненты: `GuardedRoute`, `Can`, `NoAccessCard`, `ApprovalBanner`, `Redact`.
Политики: матрица ролей/действий, SoD-правила, уровни маскировки.
Процесс: запрос доступа, обучение/сертификация ролей, ревизия прав раз в N недель.
Do/Don’t-галерея: «пустые кнопки без причин», «маскировка владельцу», «UI без серверных проверок» vs «объясненные ограничения и CTA».
Краткое резюме
Ролевые интерфейсы — это понятная информационная архитектура + строгие политики + дружелюбные объяснения. Показывайте только нужное, маскируйте чувствительные данные, защищайте маршруты и действия гвардами, фиксируйте каждое критичное событие в аудите и разделяйте обязанности там, где это влияет на деньги и комплаенс. В iGaming это не только снижает риски, но и делает работу команд быстрее и спокойнее.