📘 UX-IDENTITY-AND-ACCESS.md
This document defines UX contracts for identity, authentication sessions, and RBAC administration.
Goal:
- keep access flows simple for operators
- make permission behavior explicit and predictable
- align frontend behavior to backend-enforced capabilities, CSRF, idempotency, and RLS constraints
Capability Baseline (Validated 2026-02-25)​
Backend-live now:
- Passwordless auth flow:
POST /api/v1/auth/loginGET /api/v1/auth/verifyGET /api/v1/auth/meGET /api/v1/auth/csrfPOST /api/v1/auth/logout
- Session controls:
GET /api/v1/auth/sessionsPOST /api/v1/auth/sessions/revokePOST /api/v1/auth/sessions/revoke-all
- Identity admin:
- Users CRUD + import preview/commit
- Groups CRUD + member add/remove
- Roles/capabilities list + role CRUD + role clone + user-role assignment/removal
- Capability-based authorization and org/tenant RLS are enforced server-side.
- Step-up proofs exist in backend policy/enforcement paths for high-trust writes.
Current UX gap:
- no first-class frontend for identity/access workflows yet.
0. Doctrine (MUST)​
- Backend is the source of truth for permissions. UI never infers capability from role names.
- Auth failures must be explicit: unauthenticated (
401) vs forbidden (403) vs not-found/scope-hidden (404). - Session safety before convenience: all session-revocation actions require CSRF and explicit confirmation.
- Role admin must be capability-first and auditable; system roles are visible but protected from destructive edits.
- No scope leakage: tenant/org isolation is enforced in API responses and UI must not try to explain hidden resources.
0.1 Identity/Access Interface Guardrails (MUST)​
- Authentication and authorization errors must remain distinct in UX (
401,403,404) with deterministic guidance. - User/group/role tables and editors must be keyboard-complete and screen-reader understandable.
- High-trust actions (session revoke-all, role/capability mutation) require explicit confirmation and auditable reason where policy requires.
- Capability gating must be explicit in UI state (disabled/hidden with rationale), never inferred from role name strings.
- Mobile/iPad supports essential self-service security flows; dense RBAC administration may be desktop-optimized with explicit handoff.
- Import and bulk actions must preserve deterministic validation/error messaging for localisation.
1. Information Architecture​
Place under Governance > Identity & Access.
Primary pages:
Sign in(public)Account Security(authenticated self-service)Users(directory + import)Groups(cohorts/membership)Roles & Capabilities(RBAC admin)
Navigation pattern:
- On drawer-enabled identity surfaces,
userandgroupreferences open a read-only drawer peek on normal click, with canonical full-page fallback. - RBAC management (
roles) is full-page first.
2. Authentication UX​
2.1 Magic Link Request (POST /auth/login)​
Screen:
- single email field
- optional org/user targeting stays hidden unless explicitly needed in admin/dev tools
Success:
- show neutral confirmation: "Check your email for a sign-in link."
- never reveal whether account exists
Errors:
400: validation message429: throttle message with retry guidance500: generic recoverable error with retry action
2.2 Magic Link Verify (GET /auth/verify?token=...)​
Flow:
- verify token
- set secure session cookie
- store returned
csrfToken - fetch
/auth/mefor app bootstrap
States:
loadingverified-> redirect to default app landinginvalid_or_expired(401/400) -> show "Link expired or already used" + "Request new link"
2.3 Session Bootstrap (GET /auth/me, optional /auth/csrf)​
/auth/me drives shell state:
userId,tenantId,orgUnitId,orgScopeAllroleIds, resolvedcapabilities- session
csrfToken
UX rules:
- capability-gate navigation from
capabilitiesonly - if
/auth/mereturns401, hard-redirect to sign-in - do not cache capabilities beyond session lifecycle
3. Session Security UX​
3.1 Session List (GET /auth/sessions)​
Table columns:
currentbadgeorgUnitIdcreatedAtlastSeenAtidleExpiresAtabsoluteExpiresAt- redacted device metadata (
userAgent,ip)
3.2 Session Actions​
Actions:
Sign out this device->POST /auth/logout->204Revoke selected session->POST /auth/sessions/revoke(bodysessionId) ->204Revoke all other sessions->POST /auth/sessions/revoke-all->204
Requirements:
- include
X-CSRF-Tokenon all session mutations - optimistic row removal is allowed, but must rollback on API failure
- always confirm destructive session revocation actions
Error handling:
401: session expired -> return to sign-in403: CSRF/origin/content-type issue -> show secure retry guidance (refresh + retry)
4. Users UX​
4.1 Users Directory (GET /users)​
Contract:
- paginated list with stable sorting and search/filter controls
- row click opens read-only user peek drawer on drawer-enabled surfaces; "Open full page" available
Row fields:
- full name
- status (
active,inactive,suspended) - updated timestamp
4.2 User CRUD​
Write endpoints:
- create:
POST /users - update:
PATCH /users/\{id\} - delete:
DELETE /users/\{id\}
Rules:
Idempotency-Keyrequired for mutating operations- forms should map backend validation errors by field where possible
- delete must require explicit confirmation text
4.3 User Import​
Flow:
- preview (
POST /users/import/preview) -> show valid rows + row-level errors - commit (
POST /users/import/commitwithIdempotency-Key) -> show created/updated totals
UX guardrail:
- commit button disabled until preview is successful and user confirms impact.
5. Groups UX​
5.1 Group Management​
Endpoints:
- list/create:
GET/POST /groups - detail/update/delete:
GET/PATCH/DELETE /groups/\{id\} - members:
GET/POST /groups/\{id\}/members - remove member:
DELETE /groups/\{id\}/members/\{userId\}
UX pattern:
- groups list page + read-only group detail peek drawer
- membership tab with add/remove actions and recent change timestamps
Rules:
- mutating operations require
Idempotency-Key - deleting group must require confirmation and warn about assignment/targeting impact where relevant
6. Roles & Capabilities UX​
6.1 Roles Overview​
Endpoints:
- list roles:
GET /roles - list capabilities:
GET /roles/capabilities
Required UI:
- roles table with
isSystembadge - capability count per role
- quick filter by system/custom
6.2 Custom Role Lifecycle​
Endpoints:
- create:
POST /roles - update:
PATCH /roles/\{id\} - clone:
POST /roles/\{id\}/clone - delete:
DELETE /roles/\{id\}
Rules:
- mutating actions require
Idempotency-Key - system roles are read-only in UI (edit/delete disabled)
- capability selector must group capabilities by domain
group
6.3 Role Assignment to Users​
Endpoints:
- assign:
POST /roles/users/\{id\}/roles - remove:
DELETE /roles/users/\{id\}/roles/{roleId}
UX rules:
- assignment/removal from user detail "Access" tab
- show effective role list clearly separate from profile fields
- actions require
Idempotency-Key
7. Language and Text Overrides​
7.1 Language Preference (User-Level)​
Identity UX should expose user language preference in account/security settings.
Rules:
- preference changes are immediate for UI copy where possible.
- language selection must not bypass scope/capability restrictions.
- if locale content is missing, fallback is handled by shared i18n resolver.
7.2 Text Override Mode (Capability-Gated)​
Users with localization capability (for example localization.manage) can edit translation overrides.
Scope precedence (authoritative):
- org override
- tenant override
- product default (Paraglide)
Required controls:
- scope selector (org or tenant) with clear access boundary messaging
- locale selector
- key/value edit surface with preview
- publish and rollback actions
Guardrails:
- placeholder tokens must be preserved.
- unsafe markup is rejected.
- every publish/rollback action is audit logged.
8. Step-Up and High-Trust Actions​
Backend reality:
- step-up proofs are issued during auth verification and validated in high-trust write flows.
- evaluation publish and L4 policy actions can require step-up proofs.
UX contract:
- if a write is rejected due to stronger auth requirement, show a dedicated "Additional verification required" state.
- never present this as a generic permission denial.
- until first-class frontend challenge endpoints are introduced, route user to re-authenticate and retry.
9. Permission, Scope, and Error UX Contract​
9.1 Status Code Semantics​
401: not authenticated or session expired -> re-auth flow403: authenticated but action blocked (capability, CSRF, policy) -> explain + recover action404: resource absent or hidden by scope/RLS -> same user message (no inference)
9.2 Capability Diagnostics​
Admin surfaces should include:
- current user capabilities snapshot (from
/auth/me) in a debug drawer - required capability hints on disabled action buttons when safe to disclose
9.3 Idempotency UX​
For in-scope identity mutations:
- generate one key per logical write attempt
- retry with the same key on network retry of unchanged payload
- regenerate key when payload changes
10. Shared Right-Drawer Pattern​
For identity surfaces, drawer behavior must follow shared contract docs:
- URL-as-state (
drawer=<type>:<id>) userandgroupreferences open read-only drawer peek by default on drawer-enabled surfaces- Cmd/Ctrl-click opens canonical full page
- drawer content includes:
- key profile facts
- role/group summaries
- recent activity snippet
- "Open full page" action
11. Definition of Done (Identity & Access UX)​
- Auth bootstrap is fully driven by
/auth/verify+/auth/me, with robust expired-link handling. - Session security page supports list + revoke single + revoke all + logout with CSRF-safe behavior.
- Users/groups/roles CRUD flows honor
Idempotency-Keyrequirements and show field-level validation. - RBAC screens are capability-first (no hard-coded role logic in UI behavior).
- Unauthorized/forbidden/not-found states follow non-leaky semantics.
- Drawer/full-page navigation for users/groups aligns to shared link contract.
- Step-up-required failures render explicit remediation guidance.
- Language preference and capability-gated text override flows follow org -> tenant -> product fallback precedence.