Files
cameleer-server/examples/RBAC/rbac-ui-spec.md
2026-03-17 16:21:25 +01:00

322 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# RBAC Management UI — Design Specification
## Overview
This document describes the Monitor RBAC management interface: its layout, navigation, entity model, visual conventions, badge/chip meanings, and inheritance behaviour. It is intended as a handoff reference for developers implementing the production version.
---
## Application layout
The app is a two-column shell with a fixed top bar.
```
┌─────────────────────────────────────────────────┐
│ Top bar (brand + environment badge + avatar) │
├──────────────┬──────────────────────────────────┤
│ │ │
│ Sidebar │ Main panel │
│ (200px) │ (fills remaining width) │
│ │ │
└──────────────┴──────────────────────────────────┘
```
### Top bar
| Element | Purpose |
|---|---|
| Brand dot (green) | Indicates a live/healthy connection to the monitoring backend |
| `Monitor RBAC` wordmark | App name |
| Environment badge (`production`, `staging`, etc.) | Reminds operators which environment they are modifying — destructive changes in production are intentional |
| User avatar circle | Current operator identity; initials derived from name |
### Sidebar
Three navigation sections:
- **Overview** — `Dashboard` (system summary + inheritance model diagram)
- **Identity** — `Users`, `Groups`, `Roles` (the three core entity types)
- **Audit** — `Audit log` (change history, out of scope for this spec)
Each identity nav item shows a **count badge** (e.g. `8`, `5`, `6`) reflecting the total number of entities of that type. The active item is indicated by a green left border accent and bold label.
---
## Panels
### Dashboard (Overview)
Displays three **stat cards** at the top:
| Card | Content |
|---|---|
| Users | Total user count + active sub-count |
| Groups | Total group count + max nesting depth |
| Roles | Total role count + note about direct vs inherited |
Below the stat cards is an **inheritance model diagram** — a three-column schematic showing how Groups → Roles on groups → Users form the inheritance chain. This is a read-only orientation aid, not interactive.
A note block (green left border) explains the inheritance rule in plain language.
---
### Users panel
Split into a **list pane** (left, ~52% width) and a **detail pane** (right).
#### List pane
Each row is a user card containing:
| Element | Description |
|---|---|
| Avatar circle | Two-letter initials; background colour varies by user for visual distinction |
| Name | Full display name |
| Meta line | Email address · primary group path (e.g. `Engineering → Backend`) |
| Tag row | Compact role and group badges (see Badge reference below) |
| Status dot | Green = active, grey = inactive/suspended |
A search input at the top filters rows by any visible text (name, email, group, role).
Clicking a row selects it (blue tint) and loads the detail pane.
#### Detail pane — user
Shows full user information organised into sections:
| Section | Contents |
|---|---|
| Header | Avatar, full name, email address |
| Fields | Status, internal ID (truncated), created date |
| Group membership | Chips for every group the user directly belongs to. Sub-groups are also shown if membership was inherited via a parent group, with a small `via GroupName` annotation. |
| Effective roles | All roles the user holds — both direct assignments and roles inherited through group membership (see Role chips below) |
| Group tree | A visual indented tree showing the ancestry path of the user's groups |
---
### Groups panel
Same split layout as Users.
#### List pane — group cards
| Element | Description |
|---|---|
| Avatar square (rounded) | Two-letter abbreviation; colour indicates domain (green = engineering, amber = ops, red = admin) |
| Name | Group display name |
| Meta line | Parent group (if nested) · member count |
| Tag row | Roles assigned directly to this group; inherited roles shown with italic/faded styling |
#### Detail pane — group
| Section | Contents |
|---|---|
| Header | Avatar, group name, hierarchy level label |
| Fields | Internal ID |
| Members (direct) | Name chips for users who are direct members of this group |
| Child groups | Chips for any groups nested inside this one |
| Assigned roles | Roles directly assigned to this group — what all members will inherit |
| Inheritance note | Plain-language explanation of how roles propagate to children |
| Group hierarchy | Indented tree showing parent → this group → children |
---
### Roles panel
Same split layout.
#### List pane — role cards
| Element | Description |
|---|---|
| Avatar square | Two-letter abbreviation of the role name |
| Name | Role identifier (lowercase slug) |
| Meta line | Short description of access level · assignment count |
| Tag row | Groups and/or users the role is directly assigned to |
#### Detail pane — role
| Section | Contents |
|---|---|
| Header | Avatar, role name, description |
| Fields | Internal ID, scope |
| Assigned to groups | Group chips where this role is directly configured |
| Assigned to users (direct) | User chips that hold this role outside of any group |
| Effective principals | All principals (users) who effectively have this role, whether directly or via group inheritance |
| Inheritance note | Explains direct vs inherited assignments |
---
## Badge and chip reference
### Role tags (amber / orange)
Appear on user and group list rows to show which roles apply.
| Style | Meaning |
|---|---|
| Solid amber background, normal text | **Direct assignment** — the role is explicitly assigned to this entity |
| Faded / italic text, dashed border | **Inherited role** — the role flows from a parent group, not assigned directly |
In the detail pane, inherited role chips include a small `↑ GroupName` annotation identifying the source group.
### Group tags (green)
Appear on user list rows and role detail panes.
| Style | Meaning |
|---|---|
| Solid green background | The entity belongs to or is assigned to this group directly |
### Status dot
| Colour | Meaning |
|---|---|
| Green (filled) | User account is active |
| Grey (filled) | User account is inactive or suspended |
### Environment badge (top bar)
| Value | Meaning |
|---|---|
| `production` | Live system — changes are immediate and real |
| `staging` | Pre-production — safe for testing |
### Count badge (sidebar nav)
Small pill next to each nav label showing the total number of entities of that type. Updates to reflect search/filter state when implemented.
---
## Inheritance model
The RBAC system implements **two inheritance axes**:
### 1. Group → child group
Groups can be nested to any depth. A child group inherits all roles assigned to its parent group. This is transitive — a role on `Engineering` propagates to `Backend` and `Frontend`, and would continue to any groups nested inside those.
```
Engineering (role: viewer)
├── Backend (role: editor, inherits: viewer)
└── Frontend (role: editor, inherits: viewer)
```
### 2. Group → member users
All roles effective on a group (direct + inherited from parent groups) are inherited by every user who is a member of that group.
```
User: Alice
Direct member of: Engineering, Backend
Effective roles:
- admin (direct on Alice)
- viewer (inherited via Engineering)
- editor (inherited via Backend)
```
### Role resolution
When checking if a user has a given role, the system should:
1. Check direct role assignments on the user.
2. For each group the user belongs to (directly or transitively), check all roles on that group.
3. Union the full set — **no role negation** in the base model (roles only grant, never deny).
This makes effective role computation a union of all reachable role sets across the user's group membership graph.
---
## Visual conventions
| Convention | Meaning |
|---|---|
| Dashed chip border | Inherited / transitive — not directly configured here |
| `↑ GroupName` annotation | Points to the source of an inherited permission |
| Green left border on nav item | Currently active section |
| Indented tree with corner connector | Shows parentchild group hierarchy |
| Green note block (left border) | Contextual explanation of inheritance behaviour — appears wherever inherited permissions could be confusing |
| Blue tint on selected list row | Currently selected entity; detail pane reflects this entity |
---
## Entity data model (for implementation reference)
### User
```ts
interface User {
id: string; // e.g. "usr_01HX…4AF"
name: string;
email: string;
status: "active" | "inactive";
createdAt: string; // ISO date
directGroups: string[]; // group IDs — direct membership only
directRoles: string[]; // role IDs — assigned directly to this user
// Computed at read time:
effectiveGroups: string[]; // all groups including transitive
effectiveRoles: string[]; // all roles including inherited
}
```
### Group
```ts
interface Group {
id: string; // e.g. "grp_02KX…9BC"
name: string;
parentGroupId?: string; // null for top-level groups
directRoles: string[]; // role IDs assigned to this group
// Computed at read time:
effectiveRoles: string[]; // direct + inherited from parent chain
memberUserIds: string[]; // direct members only
childGroupIds: string[]; // direct children only
}
```
### Role
```ts
interface Role {
id: string; // e.g. "rol_00AA…1F2"
name: string; // slug, e.g. "admin", "viewer"
description: string;
scope: string; // e.g. "system-wide", "monitoring:read"
// Computed at read time:
directGroupIds: string[]; // groups this role is assigned to
directUserIds: string[]; // users this role is assigned to directly
effectivePrincipalIds: string[]; // all users who hold this role
}
```
---
## Recommended API surface
| Method | Path | Description |
|---|---|---|
| `GET` | `/users` | List all users with effectiveRoles and effectiveGroups |
| `GET` | `/users/:id` | Single user detail |
| `POST` | `/users/:id/roles` | Assign a role directly to a user |
| `DELETE` | `/users/:id/roles/:roleId` | Remove a direct role from a user |
| `POST` | `/users/:id/groups` | Add user to a group |
| `DELETE` | `/users/:id/groups/:groupId` | Remove user from a group |
| `GET` | `/groups` | List all groups with hierarchy |
| `GET` | `/groups/:id` | Single group detail |
| `POST` | `/groups/:id/roles` | Assign a role to a group |
| `POST` | `/groups/:id/children` | Nest a child group |
| `GET` | `/roles` | List all roles with effective principals |
| `GET` | `/roles/:id` | Single role detail |
---
## Handoff notes for Claude Code
When implementing this in a production stack:
- **State management** — effective roles and groups should be computed server-side and returned in API responses. Do not compute inheritance chains in the frontend.
- **Component split** — `EntityListPane`, `UserDetail`, `GroupDetail`, `RoleDetail`, `InheritanceChip`, `GroupTree` are the natural component boundaries.
- **CSS tokens** — all colours use CSS variables (`--color-background-primary`, `--color-border-tertiary`, etc.) that map to the design system. Replace with your own token layer (Tailwind, CSS Modules, etc.).
- **Search** — currently client-side string matching. For large deployments, wire to a server-side search endpoint.
- **Inheritance note blocks** — always render these wherever inherited permissions are displayed. They prevent operator confusion when a user has a role they didn't expect.