Interfaces by Role and Access
1) Principles
1. Security = UX task. The user must clearly understand what he can and cannot do without "gray areas."
2. Minimum necessary rights. From display to actions, everything is limited to role tasks.
3. Signal instead of ban. If there is no access, we explain why and how to get (request, application, training).
4. Duplication on the server. UI guards never replace server checks.
5. Transparent audit. Each sensitive action leaves a readable mark.
2) Access control models
RBAC (Role-Based): fixed roles: Player, Support, Finance, Risk/Compliance, Affiliate Manager, Moderator, Admin.
ABAC (Attribute-Based): attribute-based policy (jurisdiction, brand, time zone, VIP level, team, shift).
ReBAC (Relationship-Based): access by relationship (player handler, ticket holder, partner manager).
SoD (Segregation of Duties) - separation of critical tasks (created ≠ approved).
Practice: RBAC as a basis, ABAC for fine tuning (brand/region), SoD for finance/limits, ReBAC - point (curated portfolios).
3) Function map by role (example iGaming)
4) UX patterns for rights and roles
4. 1 Navigation and visibility
Hide inaccessible sections from navigation (noise reduction), but show informational "blank" cards if this helps to understand the possibilities.
For temporarily unavailable - "Lock" with a hint: reason, requirements, CTA "Request access."
4. 2 States of action
Disabled + tooltip: "Finance role required. Request Access.
Read-only mode: fields "under the glass," an explicit marker "Read-only."
Escalation - Click Submit for Approval instead of Apply.
4. 3 Masking and Editing
PII (email, phone, address) - 'user @.', '+ 380 90' for other people's records.
PAN/IBAN - only tokens/last 4.
Show Full radio button - owning role only/by audit event.
5) Permission architecture in UI
Policy context on the client: permission cache (TTL short) + subscription to updates.
Route guards: inaccessible routs → 403-page with explanation and CTA.
Component guards: 'Can ({action:' approve _ within ', resource:' payout '})'.
Ficheflags: experimental/seasonal things - separate from rights.
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) Server> Client
Any action is confirmed by the server by a token with marks (role, attributes).
Policies are centralized (PDP/OPA/Cedar/Zanzibar-like), UI only gets the solution.
All critical operations - two-factor confirmation + audit.
7) Masking and red data zones
Data categories:- PII: name, email, phone, address, date of birth.
- Finance: PAN/IBAN/crypto wallets, amounts, limits, bonus balances.
- Documents: passports/ID/selfies (KYC).
- Gaming: Betting history/winnings/patterns.
- Full - owning role/record owner.
- Masked - support, finance (not owner).
- Aggregated - Analytics (no IDs).
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 and SoD flows
Four eyes: initiator ≠ approver.
Multistage routes (for example, amounts> X → 2nd line).
Validity of applications, SLA, escalation.
Magazine: who created, who changed, who approved, when and from where.
Examples: confirmation of withdrawal, change in player limits, KYC verdict, removal of sanction flag.
9) The specifics of iGaming
Limits and self-exclusion: change only with SoD and mandatory user notification.
KYC/AML: document access - narrow role; preview of thumbnails, full size - by a separate action with the log.
Sanctions/RAP flags: visible to the risk team; support - only the status "need verification."
Payments/Outputs: Post/Reject - Financial Accounting role only; amounts above the threshold - double confirmation.
Betting logs: Support reads but does not edit; adjustments - a separate function with investigation.
10) Localization, A11y, RTL
The "no access" texts are localized and contain valid paths (application/training).
Focus control: do not transfer the user to a "blank" page without explanation.
RTL mode is supported for roles in respective regions.
A11y: 'aria-disabled' + explanation, keyboard escalation availability.
11) Conditions and errors
403 (Ineligible): Friendly page with role context and "Request Access" CTA.
404 (no resource): do not reveal the existence of hidden objects.
413/422 (too much/validation): do not leak policy details, formulate neutrally.
Rate-limits/locks: Explain the timer/unlock condition.
12) Metrics
Access Denied Rate: failure rate by role/screen (bad IA or policy signal).
Approval SLA: median approval time by flow (output, limits, KYC).
Mask Reveal Events: PII "reveal" rate (expected small and justified).
Error-to-Resolution: time from 403 to the granted access.
Least-Privilege Drift: roles with redundant rights (detectability by use).
13) Anti-patterns
Hide errors under "nothing happened."
Show empty buttons without explanation.
Mask the owner with his own data.
Rely on UI guards without server policies.
Mix ficheflags with accesses (different tasks).
Give the support "god-mode" for the sake of convenience.
14) Design system tokens (example)
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) Snippets UI
Route guard: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/>;
}
No access card with CTA:
html
<article class="no-access">
<h3>Недостаточно прав</h3>
<p>Доступ к разделу «Выплаты» доступен ролям: Финансы/Админ.</p>
<button class="btn" data-open-request>Запросить доступ</button>
</article>
Audit log (abbreviated):
json
{
"ts": "2025-11-03T18:45:12Z",
"actor": "u_5412",
"action": "payout.approve",
"target": "withdraw#w_91822",
"ip": "194...12",
"result": "success"
}
16) QA checklist
Navigation and IA
- Unavailable sections do not make noise in the menu.
- There are clear "no access" pages/cards with CTA.
Actions and guards
- Buttons without rights - 'disabled' + tooltip/text.
- Routs protected; direct URL → 403 with an explanation.
- The server confirms each action.
Data
- PII/PAN/KYC are masked by policy.
- Logs of "disclosures" are written and reviewed.
- Export/Reports correspond to role (aggregates for analysis).
SoD/Approvals
- The initiator cannot approve his application.
- Threshold amounts → multistage routes.
А11у/Localization
- "No access" is localized; keyboard navigation works.
- Contrast/focus rings correspond to AA.
Reliability
- Permission cache with short TTL; disability when changing roles.
- PDP drop → UI is in default-safe mode.
17) Documentation in the design system
Компоненты: `GuardedRoute`, `Can`, `NoAccessCard`, `ApprovalBanner`, `Redact`.
Policies: role/action matrix, SoD rules, masking levels.
Process: access request, training/certification of roles, revision of rights once every N weeks.
Do/Don't gallery: "empty buttons for no reason," "disguise to the owner," "UI without server checks" vs "explained restrictions and CTA."
Brief summary
Role interfaces are clear information architecture + strict policies + friendly explanations. Show only what you need, mask sensitive data, protect routes and actions with guards, record every critical event in the audit and share responsibilities where it affects money and compliance. In iGaming, this not only reduces risks, but also makes teams faster and calmer.