Інтерфейси за ролями та доступами
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: доступ до документів - вузька роль; передогляд мініатюр, повнорозмір - за окремою дією з логом.
Санкційні/РЕР-прапори: видно ризик-команді; саппорту - тільки статус «потрібна перевірка».
Платежі/висновки: «провести/відхилити» - тільки роль Фінанси; суми понад порог - подвійне підтвердження.
Журнали ставок: саппорт читає, але не редагує; коригування - окрема функція з розслідуванням.
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
- Ініціатор не може затвердити свою заявку.
- Порогові суми → багатоступінчасті маршрути.
А11у/Локалізація
- «Немає доступу» локалізовано; клавіатурна навігація працює.
- Контраст/фокус-кільця відповідають AA.
Надійність
- Кеш дозволів з коротким TTL; Інвалідація при зміні ролі.
- Падіння PDP → UI працює в режимі «дефолт-безпечно».
17) Документація в дизайн-системі
Компоненти: `GuardedRoute`, `Can`, `NoAccessCard`, `ApprovalBanner`, `Redact`.
Політики: матриця ролей/дій, SoD-правила, рівні маскування.
Процес: запит доступу, навчання/сертифікація ролей, ревізія прав раз на N тижнів.
Do/Don't-галерея: «порожні кнопки без причин», «маскування власнику», «UI без серверних перевірок» vs «пояснені обмеження і CTA».
Коротке резюме
Рольові інтерфейси - це зрозуміла інформаційна архітектура + суворі політики + доброзичливі пояснення. Показуйте тільки потрібне, маскуйте чутливі дані, захищайте маршрути і дії гвардами, фіксуйте кожну критичну подію в аудиті і поділяйте обов'язки там, де це впливає на гроші і комплаєнс. В iGaming це не тільки знижує ризики, але і робить роботу команд швидше і спокійніше.