Skip to main content

📘 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/login
    • GET /api/v1/auth/verify
    • GET /api/v1/auth/me
    • GET /api/v1/auth/csrf
    • POST /api/v1/auth/logout
  • Session controls:
    • GET /api/v1/auth/sessions
    • POST /api/v1/auth/sessions/revoke
    • POST /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)​

  1. Backend is the source of truth for permissions. UI never infers capability from role names.
  2. Auth failures must be explicit: unauthenticated (401) vs forbidden (403) vs not-found/scope-hidden (404).
  3. Session safety before convenience: all session-revocation actions require CSRF and explicit confirmation.
  4. Role admin must be capability-first and auditable; system roles are visible but protected from destructive edits.
  5. 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:

  1. Sign in (public)
  2. Account Security (authenticated self-service)
  3. Users (directory + import)
  4. Groups (cohorts/membership)
  5. Roles & Capabilities (RBAC admin)

Navigation pattern:

  • On drawer-enabled identity surfaces, user and group references 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 message
  • 429: throttle message with retry guidance
  • 500: generic recoverable error with retry action

Flow:

  1. verify token
  2. set secure session cookie
  3. store returned csrfToken
  4. fetch /auth/me for app bootstrap

States:

  • loading
  • verified -> redirect to default app landing
  • invalid_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, orgScopeAll
  • roleIds, resolved capabilities
  • session csrfToken

UX rules:

  • capability-gate navigation from capabilities only
  • if /auth/me returns 401, 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:

  • current badge
  • orgUnitId
  • createdAt
  • lastSeenAt
  • idleExpiresAt
  • absoluteExpiresAt
  • redacted device metadata (userAgent, ip)

3.2 Session Actions​

Actions:

  • Sign out this device -> POST /auth/logout -> 204
  • Revoke selected session -> POST /auth/sessions/revoke (body sessionId) -> 204
  • Revoke all other sessions -> POST /auth/sessions/revoke-all -> 204

Requirements:

  • include X-CSRF-Token on 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-in
  • 403: 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:

  • email
  • 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-Key required for mutating operations
  • forms should map backend validation errors by field where possible
  • delete must require explicit confirmation text

4.3 User Import​

Flow:

  1. preview (POST /users/import/preview) -> show valid rows + row-level errors
  2. commit (POST /users/import/commit with Idempotency-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 isSystem badge
  • 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):

  1. org override
  2. tenant override
  3. 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 flow
  • 403: authenticated but action blocked (capability, CSRF, policy) -> explain + recover action
  • 404: 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>)
  • user and group references 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)​

  1. Auth bootstrap is fully driven by /auth/verify + /auth/me, with robust expired-link handling.
  2. Session security page supports list + revoke single + revoke all + logout with CSRF-safe behavior.
  3. Users/groups/roles CRUD flows honor Idempotency-Key requirements and show field-level validation.
  4. RBAC screens are capability-first (no hard-coded role logic in UI behavior).
  5. Unauthorized/forbidden/not-found states follow non-leaky semantics.
  6. Drawer/full-page navigation for users/groups aligns to shared link contract.
  7. Step-up-required failures render explicit remediation guidance.
  8. Language preference and capability-gated text override flows follow org -> tenant -> product fallback precedence.