added RBAC mock and spec to examples
This commit is contained in:
321
examples/RBAC/rbac-ui-spec.md
Normal file
321
examples/RBAC/rbac-ui-spec.md
Normal file
@@ -0,0 +1,321 @@
|
||||
# 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 parent–child 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.
|
||||
Reference in New Issue
Block a user