chore: roles management groundwork
This commit is contained in:
1 parent
7c0ee21906
commit
44cca46d5e
11 files changed
+1255
-5
No files matched your search
@@ -0,0 +1,565 @@
|
||||
# Roles and permissions
|
||||
|
||||
Routes: `/settings/roles`, `/settings/roles/new`, `/settings/roles/:id`. `/settings/permissions` is retired and redirects (301) to `/settings/roles`. Board: `RenewCMS Screens Roles.dc.html` (frame `RolesFrame`). Every state is "Available now". Copy below is exact; `·` separates strings.
|
||||
|
||||
## 1 Roles list
|
||||
|
||||
Route: /settings/roles · API: GET /v1/role · Auth: Roles: view
|
||||
|
||||
Settings > Roles. Visible to anyone who can view roles. Owner carries a Locked badge. The row menu has Edit, Duplicate and Delete. Mobile: one card per role.
|
||||
|
||||
### Default (Available now)
|
||||
|
||||
Trigger: Owner opens /settings/roles.
|
||||
|
||||
Copy: Roles · Who can do what on this site. Each user has one role. · New role · Role · Description · Members · Type · Owner · Locked · Admin · Writer · Contributor · Content lead · Built-in · Custom
|
||||
|
||||
### Loading (Available now)
|
||||
|
||||
Trigger: First load or retry. Skeleton rows after 150 ms. New role disabled.
|
||||
|
||||
Copy: (skeleton) · New role (disabled)
|
||||
|
||||
### Only built-in roles (Available now)
|
||||
|
||||
Trigger: GET /v1/role returns the three built-ins and no custom role.
|
||||
|
||||
Copy: No custom roles yet · The three built-in roles cover most sites. Create a role when someone needs something in between. · New role
|
||||
|
||||
### Row menu: custom role (Available now)
|
||||
|
||||
Trigger: Open the row menu on Contributor.
|
||||
|
||||
Copy: Edit · Duplicate · Delete
|
||||
|
||||
### Row menu: built-in role (Available now)
|
||||
|
||||
Trigger: Open the row menu on Writer as owner. Delete is disabled and its tooltip shows on focus or hover.
|
||||
|
||||
Copy: Edit · Duplicate · Delete (disabled) · Built-in roles can't be deleted. Duplicate it to make a custom role.
|
||||
|
||||
### No permission to edit (Available now)
|
||||
|
||||
Trigger: User has Roles: view but not Roles: manage. New role is disabled with a tooltip.
|
||||
|
||||
Copy: You can see roles but not change them · Ask an owner or admin if a role needs to change. · You can see roles, but only people who manage roles can create or change them.
|
||||
|
||||
### Error (Available now)
|
||||
|
||||
Trigger: 500 or network failure.
|
||||
|
||||
Copy: Couldn't load roles · GET /v1/role failed. Check your connection and try again. · Try again
|
||||
|
||||
## 2 Role editor
|
||||
|
||||
Route: /settings/roles/new, /settings/roles/:id · API: POST /v1/role, GET/PUT /v1/role/{id} · Auth: Roles: manage (view for read-only)
|
||||
|
||||
Name and description, then Content permissions (the grid moved here from /settings/permissions) and General permissions. Desktop: the plain-language panel sits on the right. Mobile: the grid is one card per type, and a sticky bar holds "What this role can do" and Save. The old route /settings/permissions redirects here (301 to /settings/roles).
|
||||
|
||||
### New role (empty) (Available now)
|
||||
|
||||
Trigger: Owner or admin opens /settings/roles/new. Nothing is granted. Save is off until the role has a name.
|
||||
|
||||
Copy: New role · Name · For example, Contributor · Description (optional) · What this role is for · Name your role to save it · Discard · Save changes · Name Contributor · Description Creates content and edits only their own. · Content permissions · What this role can do with entries of each content type. Own means entries the person created. · Quick presets · Read only · Write own · Full content · Content type · Read · Create · Update · Delete · Publish · All content types · Sets every row · Articles · Built-in · Schema locked · None · Own · All · On · Off · General permissions · Everything outside entries. · Expand all
|
||||
|
||||
### Editing a custom role (Available now)
|
||||
|
||||
Trigger: Open Contributor. Two groups open. Case studies shows Custom with a Reset link.
|
||||
|
||||
Copy: Name Contributor · Description Creates content and edits only their own. · Content permissions · What this role can do with entries of each content type. Own means entries the person created. · Quick presets · Read only · Write own · Full content · Content type · Read · Create · Update · Delete · Publish · All content types · Sets every row · Articles · Built-in · Schema locked · None · Own · All · On · Off · General permissions · Everything outside entries. · Expand all · Custom · Reset · 4 members · Custom
|
||||
|
||||
### Built-in role, as owner (Available now)
|
||||
|
||||
Trigger: The owner opens Writer. A warning shows how many members are affected.
|
||||
|
||||
Copy: This role has 5 members · Changes apply to all of them when you save, and to the API keys they created. Built-in roles can be restored with Reset to default. · 2 unsaved changes
|
||||
|
||||
### Built-in role, as admin (read-only) (Available now)
|
||||
|
||||
Trigger: An admin opens Writer. All controls are disabled and the fields are locked.
|
||||
|
||||
Copy: Only the owner can edit built-in roles · You can read what Writer allows. To change it, duplicate it into a custom role. · Duplicate role · Built-in
|
||||
|
||||
### Owner role (locked) (Available now)
|
||||
|
||||
Trigger: Anyone with Roles: view opens Owner.
|
||||
|
||||
Copy: The Owner role is locked · It always has every permission. To hand it to someone else, transfer ownership from Users. · Go to Users · Locked
|
||||
|
||||
### General permissions (Available now)
|
||||
|
||||
Trigger: Scrolled to General permissions. Groups collapse; each shows "x of y enabled". Scoped rows use the same None / Own / All control.
|
||||
|
||||
Copy: Activity · See activity · Read the log of who did what. · Export activity · Download the log as a CSV file. · Users and invites · View users · Invite users · Change a user's role · Remove users · Settings · View settings · Edit general settings · Manage sites · See API keys · Create API keys · Revoke API keys · Delete a site · Owner only · 2 of 2 enabled
|
||||
|
||||
### Owner-only items (Available now)
|
||||
|
||||
Trigger: Roles and System groups, as an admin. Owner-only items are disabled with a lock and an Owner only tag. They stay off even for Admin.
|
||||
|
||||
Copy: Roles · View roles · See roles and what they allow. · Manage roles · Create, edit, duplicate and delete roles. · Edit roles with owner-only power · Change a role that carries owner-only abilities. · System · Apply software updates · Install a new version of RenewCMS. · Edit activity retention · How long the activity log is kept. · Transfer ownership · Make another member the owner. · Owner only
|
||||
|
||||
### Unsaved changes (Available now)
|
||||
|
||||
Trigger: Three edits. Changed cells carry a square marker and the preview tags the changed line.
|
||||
|
||||
Copy: 3 unsaved changes · Discard · Save changes · Changed
|
||||
|
||||
### Saving (Available now)
|
||||
|
||||
Trigger: PUT in flight. Fields dim; Save shows the loader.
|
||||
|
||||
Copy: Saving… · Discard (disabled)
|
||||
|
||||
### Saved (Available now)
|
||||
|
||||
Trigger: 200. The bar closes and a toast confirms.
|
||||
|
||||
Copy: Role saved · Contributor is updated for 4 members.
|
||||
|
||||
### Name required (Available now)
|
||||
|
||||
Trigger: Save with an empty name.
|
||||
|
||||
Copy: Give the role a name. · 1 problem to fix
|
||||
|
||||
### Name already taken (Available now)
|
||||
|
||||
Trigger: 409 role_name_taken on POST or PUT.
|
||||
|
||||
Copy: A role named "Writer" already exists. Choose a different name. · 1 problem to fix
|
||||
|
||||
### Escalation blocked (Available now)
|
||||
|
||||
Trigger: The editor holds Roles: manage but can publish only their own entries, so Publish: All is disabled with a lock.
|
||||
|
||||
Copy: You can only grant what your role has. Your role can publish only entries you created, so All isn't available. · All (locked)
|
||||
|
||||
### Conflict (Available now)
|
||||
|
||||
Trigger: 409 role_conflict on PUT (version mismatch).
|
||||
|
||||
Copy: This role changed while you were editing · Jonas Weber saved changes to Contributor at 11:02. Reload to see them, or review how they differ from your edits. · Reload role · Review differences · 2 unsaved changes. Save is off until you reload
|
||||
|
||||
### Permission lowered while open (403) (Available now)
|
||||
|
||||
Trigger: 403 missing_permission on PUT or on refresh. The page becomes read-only.
|
||||
|
||||
Copy: Your access changed · An owner changed your role while this page was open. You can still see roles, but you can't change them. Your edits weren't saved. · Reload page
|
||||
|
||||
## 3 Plain-language preview
|
||||
|
||||
Route: Panel inside the role editor; bottom sheet on mobile · API: None. Computed in the browser from the form · Auth: Roles: view
|
||||
|
||||
Title "What this role can do". Two parts: Content (one sentence per group of types that share the same permissions) and Everything else (one sentence per group). A last line lists areas with no access. Lines that change while editing carry a Changed tag. Sentences are built from fixed templates, never from keys.
|
||||
|
||||
### Live panel (Available now)
|
||||
|
||||
Trigger: Editing Contributor. Events: Update changed from Own to All. The first line is tagged.
|
||||
|
||||
Copy: What this role can do · Updates as you edit. · Content · All content types · Can read any entry, create entries and edit only their own. Can't delete and publish. · Everything else · Schema · Can see content types and fields. · Media · Can browse the media library and upload files. · Authors · Can see authors and edit authors, only their own. · No access to Activity, Users and invites, Settings, Roles. · Applies to 4 members, and to the API keys they created. · Changed
|
||||
|
||||
### Read-only summary (Available now)
|
||||
|
||||
Trigger: Opened from a built-in role in read-only mode. No "Updates as you edit".
|
||||
|
||||
Copy: What this role can do · A summary of what this role allows.
|
||||
|
||||
### Nothing granted (Available now)
|
||||
|
||||
Trigger: New role with every permission off.
|
||||
|
||||
Copy: Content · All content types · No access to entries. · No access to Schema, Media, Authors, Activity, Users and invites, Settings, Roles.
|
||||
|
||||
### Mobile sheet (Available now)
|
||||
|
||||
Trigger: Tap "What this role can do" in the sticky bar. 92% sheet with grabber and close.
|
||||
|
||||
Copy: What this role can do · Updates as you edit. · Close
|
||||
|
||||
## 4 Delete role
|
||||
|
||||
Route: Dialog over /settings/roles · API: POST /v1/role/{id}/reassign, DELETE /v1/role/{id} · Auth: Roles: manage
|
||||
|
||||
A role with members is blocked until they move. Choosing a target role enables a single action that moves them and deletes the role. Roles with more power than the user are disabled in the picker with a reason.
|
||||
|
||||
### Blocked: has members (Available now)
|
||||
|
||||
Trigger: Delete Contributor, 4 members.
|
||||
|
||||
Copy: Delete Contributor? · 4 members have this role. Move them to another role first. Then Contributor can be deleted. · Move members to · Choose a role · They keep their API keys. Keys follow the new role. · Cancel · Move 4 members and delete role (disabled until a role is chosen)
|
||||
|
||||
### Role picker open (Available now)
|
||||
|
||||
Trigger: The picker shows each role's summary. Admin is disabled for an admin.
|
||||
|
||||
Copy: Writer · Reads everything and writes content. Can't delete or publish. · Content lead · Edits and publishes all content. · Admin · Your role can't assign a role with more power than yours.
|
||||
|
||||
### Confirm: no members (Available now)
|
||||
|
||||
Trigger: Delete Intern, 0 members.
|
||||
|
||||
Copy: Delete Intern? · No one has this role. This can't be undone. · Deleting a role doesn't affect content. · Cancel · Delete role
|
||||
|
||||
### Built-in role (Available now)
|
||||
|
||||
Trigger: Delete is disabled in the menu. If the dialog is reached by link it shows this state.
|
||||
|
||||
Copy: Delete Writer? · Built-in roles can't be deleted. · Writer is built in · Duplicate it to make a custom role you can change or delete. · Duplicate role · Close
|
||||
|
||||
## 5 Users: roles and ownership
|
||||
|
||||
Route: /users · API: PUT /v1/user/{id}/role, POST /v1/invite, POST /v1/site/transfer-ownership · Auth: Users: view; change role, invite, remove; owner for transfer
|
||||
|
||||
The Role column shows a role badge with an icon: crown (Owner), shield (Admin), pencil (Writer), person (custom). The owner row is protected. Pending invites show their role.
|
||||
|
||||
### List with roles (Available now)
|
||||
|
||||
Trigger: Owner opens /users.
|
||||
|
||||
Copy: Users · 5 members and invites · Invite user · Name · Email · Role · Status · Owner · Admin · Writer · Contributor · Content lead · Active · Invite pending
|
||||
|
||||
### Row menu (Available now)
|
||||
|
||||
Trigger: Open the menu on Ines Duarte.
|
||||
|
||||
Copy: Change role · Send password reset · Remove user
|
||||
|
||||
### Owner row menu (Available now)
|
||||
|
||||
Trigger: Owner row: Change role and Remove are disabled; Transfer ownership appears.
|
||||
|
||||
Copy: Change role (disabled) · Transfer ownership · Remove user (disabled) · The owner can't be changed or removed. Transfer ownership first.
|
||||
|
||||
### Change role dialog (Available now)
|
||||
|
||||
Trigger: Each option shows the role's one-line summary. The current role is marked.
|
||||
|
||||
Copy: Change role for Ines Duarte · Her API keys follow the new role. · Admin · Writer · · Current · Contributor · Content lead · Cancel · Change role
|
||||
|
||||
### Change role: options blocked (Available now)
|
||||
|
||||
Trigger: An admin opens the dialog. Roles with more power are disabled with a reason.
|
||||
|
||||
Copy: Owner · There is one owner. Transfer ownership to change who it is. · Content lead · It can publish. Your role can't grant that.
|
||||
|
||||
### Invite dialog (Available now)
|
||||
|
||||
Trigger: Role picker defaults to Writer and shows its summary.
|
||||
|
||||
Copy: Invite user · They get an email with a link to set a password. · Email · Role · Writer · Writer is the default. You can change a role later. · Cancel · Send invite
|
||||
|
||||
### Transfer ownership: pick member (Available now)
|
||||
|
||||
Trigger: Owner menu > Transfer ownership. Only members can be chosen.
|
||||
|
||||
Copy: Transfer ownership · Choose who becomes the owner. Only members can be chosen. · Cancel · Continue
|
||||
|
||||
### Transfer ownership: confirm (Available now)
|
||||
|
||||
Trigger: Consequences listed. The action stays off until the email is retyped exactly.
|
||||
|
||||
Copy: Transfer ownership to Jonas Weber · This takes effect straight away. · Jonas Weber becomes the owner. · You become an Admin. You can't take ownership back unless he transfers it. · Only the owner can apply updates, delete a site and change activity retention. · Your API keys follow your new role. · Type jonas@renewbuild.example to confirm · The email must match exactly. · Back · Transfer ownership
|
||||
|
||||
### Transfer ownership: done (Available now)
|
||||
|
||||
Trigger: The former owner is now Admin. The list shows the new owner.
|
||||
|
||||
Copy: Ownership transferred · Jonas Weber is now the owner. You are an Admin.
|
||||
|
||||
## 6 Role-aware shell
|
||||
|
||||
Route: Every page · API: GET /v1/me returns role and permission keys · Auth: Any
|
||||
|
||||
Rule: hide whole areas the person can never use; disable, with a reason, an action that is blocked on something they can see; show read-only pages with a banner. Writer in these frames is the built-in Writer; Contributor shows "own" scope.
|
||||
|
||||
### The rule (Available now)
|
||||
|
||||
Trigger: Reference card used across the app.
|
||||
|
||||
Copy: Hidden · The person can never use it. · Disabled, with a reason · The person sees the thing but can't act on it. · Read-only · The person may look but not change.
|
||||
|
||||
### Writer: Articles list (Available now)
|
||||
|
||||
Trigger: Create and edit all, no delete, no publish. No Schema, Users, Integration or Settings in the sidebar.
|
||||
|
||||
Copy: Articles · You can write and edit all articles. Publishing is done by an editor. · New article · Created by · Status · Draft · Published
|
||||
|
||||
### Writer: row menu (Available now)
|
||||
|
||||
Trigger: Delete is disabled with a reason.
|
||||
|
||||
Copy: Edit · Duplicate · Delete (disabled) · Your role can't delete articles.
|
||||
|
||||
### Writer: entry editor (Available now)
|
||||
|
||||
Trigger: Publish is hidden. Status reads Draft with a hint.
|
||||
|
||||
Copy: Save draft · Status · Draft · Saved at 11:02 · Ask an editor to publish.
|
||||
|
||||
### Own scope: entry list (Available now)
|
||||
|
||||
Trigger: Contributor can edit only entries they created. Others show a View only mark.
|
||||
|
||||
Copy: Events · You can create entries and edit your own. · Entries by others are view only · Your role lets you edit entries you created. · New entry · View only
|
||||
|
||||
### Own scope: row menu (Available now)
|
||||
|
||||
Trigger: On an entry by someone else, Edit and Delete are disabled.
|
||||
|
||||
Copy: Edit (disabled) · Duplicate · Delete (disabled) · You can only edit content you created.
|
||||
|
||||
### Admin: read-only settings (Available now)
|
||||
|
||||
Trigger: An admin without Edit general settings. Fields locked, Save off.
|
||||
|
||||
Copy: You can read these settings but not change them · Ask the owner to change them, or ask for a role that can edit settings. · Save changes (disabled)
|
||||
|
||||
### Admin: owner-only settings (Available now)
|
||||
|
||||
Trigger: Software and Retention show an Owner only tag. The action stays visible and disabled.
|
||||
|
||||
Copy: Owner only · Apply update (disabled) · Only the owner can apply updates. · Keep activity for · Admins can read the log. Only the owner can change how long it is kept.
|
||||
|
||||
## 7 No access: 403 copy
|
||||
|
||||
Route: Any page · API: 403 missing_permission, 403 role_locked · Auth: Any
|
||||
|
||||
A direct link to a page the person can't use shows the page-level state with a link to a page they can use. A blocked action shows a toast.
|
||||
|
||||
### Page: no access (Available now)
|
||||
|
||||
Trigger: Contributor opens /settings/roles by link.
|
||||
|
||||
Copy: You don't have access to this page · Your role, Contributor, doesn't include it. Ask an owner or admin if you need it. · Go to Articles · See what I can do
|
||||
|
||||
### Action: missing_permission (Available now)
|
||||
|
||||
Trigger: An action was refused with 403 missing_permission.
|
||||
|
||||
Copy: You don't have permission to do that · Your role doesn't include Delete entries. Ask an owner or admin.
|
||||
|
||||
### Action: role_locked (Available now)
|
||||
|
||||
Trigger: An attempt to edit or delete the Owner role.
|
||||
|
||||
Copy: This role is locked · The Owner role can't be changed or deleted. Transfer ownership from Users instead.
|
||||
|
||||
## 8 Activity: role events
|
||||
|
||||
Route: /activity · API: GET /v1/activity · Auth: Activity: own or all
|
||||
|
||||
New event types. The detail panel summarises a role diff as Added and Removed lines using the human permission names.
|
||||
|
||||
### List with role events (Available now)
|
||||
|
||||
Trigger: Five new events.
|
||||
|
||||
Copy: Role Contributor created · Role Contributor edited · Ines Duarte's role changed from Writer to Content lead · Ownership transferred from Marta Alves to Jonas Weber · Role Intern deleted
|
||||
|
||||
### Detail: role diff (Available now)
|
||||
|
||||
Trigger: Open "Role Contributor edited".
|
||||
|
||||
Copy: Activity details · What changed · Added · Delete entries (Own) · Removed · Publish · 4 members have this role.
|
||||
|
||||
## 9 Profile: your role
|
||||
|
||||
Route: /profile · API: GET /v1/me · Auth: Any
|
||||
|
||||
The person sees their own role and a read-only summary.
|
||||
|
||||
### Role card (Available now)
|
||||
|
||||
Trigger: Any signed-in user.
|
||||
|
||||
Copy: Your role · Contributor · Assigned by Marta Alves · Creates content and edits only their own. · See what I can do · Your API keys follow this role. If your role changes, they change too.
|
||||
|
||||
### See what I can do (Available now)
|
||||
|
||||
Trigger: Opens the summary. Dialog on desktop, sheet on mobile.
|
||||
|
||||
Copy: What you can do · A summary of your role, Contributor. Read-only. · Close
|
||||
|
||||
## 10 API keys: inherited role
|
||||
|
||||
Route: /settings/api-keys · API: GET /v1/api-key · Auth: Settings: API keys
|
||||
|
||||
Keys follow their creator's role live. The fact is stated in an info alert and each row shows the creator's role.
|
||||
|
||||
### Keys follow the role (Available now)
|
||||
|
||||
Trigger: Always shown on the API keys screen.
|
||||
|
||||
Copy: Keys follow their creator's role · A key can do what its creator's role can do, today. If the person's role changes, their keys change with it. · Follows role
|
||||
|
||||
## 11 Flow: create "Contributor" in under a minute
|
||||
|
||||
Route: /settings/roles, /settings/roles/new · API: POST /v1/role · Auth: Roles: manage
|
||||
|
||||
Six steps, about 40 seconds: 1 New role. 2 Name and description. 3 Choose the preset Write own. 4 Check the preview and the Schema and Media defaults. 5 Save. 6 Done. A new role starts with nothing granted; presets fill the grid in one tap.
|
||||
|
||||
### 1 Roles list: New role (Available now)
|
||||
|
||||
Trigger: Click New role.
|
||||
|
||||
Copy: New role
|
||||
|
||||
### 2 Name it (Available now)
|
||||
|
||||
Trigger: Type a name and a one-line description.
|
||||
|
||||
Copy: Name Contributor · Description Writes posts and edits only their own
|
||||
|
||||
### 3 Tap the preset: Write own (Available now)
|
||||
|
||||
Trigger: The preset sets Read: All, Create: On, Update: Own, Delete and Publish: None for every type.
|
||||
|
||||
Copy: Write own · 7 unsaved changes
|
||||
|
||||
### 4 Check General permissions (Available now)
|
||||
|
||||
Trigger: Optional. Schema view and Media view and upload are on by default for the preset. Check the preview.
|
||||
|
||||
Copy: What this role can do · Can read any entry, create entries and edit only their own. Can't delete and publish.
|
||||
|
||||
### 5 Save (Available now)
|
||||
|
||||
Trigger: Save changes. The role appears in the list and in the invite picker.
|
||||
|
||||
Copy: Save changes
|
||||
|
||||
### 6 Done (Available now)
|
||||
|
||||
Trigger: Toast, and the bar closes.
|
||||
|
||||
Copy: Role created · Contributor is ready. Assign it from Users.
|
||||
|
||||
## Tables
|
||||
|
||||
The board lists, and this file repeats, the tables below.
|
||||
|
||||
### Permission catalogue (names shown to people)
|
||||
|
||||
| Group | Items (human name) | Scope |
|
||||
|---|---|---|
|
||||
| Content, per type | Read entries · Create entries · Update entries · Delete entries · Publish entries | None / Own / All, except Create (on or off) |
|
||||
| Schema | View content types · Create and edit content types · Delete content types | On or off |
|
||||
| Media | View the media library · Upload files · Delete files | Delete: None / Own / All |
|
||||
| Authors | View authors · Create authors · Edit authors · Delete authors | Edit: None / Own / All |
|
||||
| Activity | See activity · Export activity | See: None / Own / All |
|
||||
| Users and invites | View users · Invite users · Change a user's role · Remove users | On or off |
|
||||
| Settings | View settings · Edit general settings · Manage sites · See API keys · Create API keys · Revoke API keys · Delete a site (owner only) | API keys: None / Own / All |
|
||||
| Roles | View roles · Manage roles · Edit roles with owner-only power (owner only) | On or off |
|
||||
| System (owner only) | Apply software updates · Edit activity retention · Transfer ownership | Locked off for everyone but the owner |
|
||||
|
||||
### Built-in roles
|
||||
|
||||
| Role | What it has | Editable by |
|
||||
|---|---|---|
|
||||
| Owner | Everything. One per site. Ownership can be transferred; the former owner becomes Admin. | No one (locked) |
|
||||
| Admin | Everything except the owner-only list. Can see all settings, read-only where they can't edit. | Owner |
|
||||
| Writer | Reads schema and all content; creates and edits all content. No delete, no publish; no schema, settings, sites, users or integrations. Authors: view, edit own (assumed). | Owner (duplicate for variants) |
|
||||
|
||||
### No-escalation feedback
|
||||
|
||||
| Rule | Where it shows | Copy |
|
||||
|---|---|---|
|
||||
| Grant only what you hold | Disabled segment or switch with a lock; popover on focus or hover | You can only grant what your role has. Your role can publish only entries you created, so All isn't available. |
|
||||
| No role above yours | Disabled option in the role picker (Change role, Delete reassign, Invite) | Your role can't assign a role with more power than yours. |
|
||||
| No editing your own role | Editor opens read-only with a banner | You can't change the permissions of your own role. Ask another owner or admin. |
|
||||
| No delete while it has members | Delete dialog, blocked state | 4 members have this role. Move them to another role first. Then Contributor can be deleted. |
|
||||
| Owner-only list | Disabled item with an Owner only tag and a lock | Only the owner can apply updates. |
|
||||
|
||||
### Hidden or disabled
|
||||
|
||||
| Case | Treatment | Example |
|
||||
|---|---|---|
|
||||
| Whole area the role never has | Hidden (no sidebar item, no page card). Direct link shows the 403 page. | Schema for a Writer |
|
||||
| Action on something visible, blocked by role | Disabled with a reason in a tooltip or row text | Delete on an article for a Writer |
|
||||
| Action that only exists above their level | Hidden | Publish for a Writer; status shows Draft and "Ask an editor to publish." |
|
||||
| Row the person can read but not edit (Own) | View only mark on the row; Edit and Delete disabled in the menu | You can only edit content you created. |
|
||||
| Settings page they can read | Read-only: locked fields, banner, Save off | Admin on General without Edit general settings |
|
||||
| Owner-only action visible to an admin | Disabled, Owner only tag | Apply update |
|
||||
|
||||
### HTTP status to copy (additions)
|
||||
|
||||
| Code | Status | Title | Body |
|
||||
|---|---|---|---|
|
||||
| missing_permission | 403 | You don't have permission to do that | Your role doesn't include {permission name}. Ask an owner or admin. |
|
||||
| role_locked | 403 | This role is locked | The Owner role can't be changed or deleted. Transfer ownership from Users instead. |
|
||||
| role_has_members | 409 | Role still has members | {n} members have this role. Move them to another role first. |
|
||||
| role_name_taken | 409 | Name already used | A role named "{name}" already exists. Choose a different name. |
|
||||
| role_conflict | 409 | This role changed while you were editing | {name} saved changes to {role} at {time}. Reload to see them, or review how they differ from your edits. |
|
||||
| escalation | 403 | You can't grant that | You can only grant what your role has. |
|
||||
| (page level) | 403 | You don't have access to this page | Your role, {role}, doesn't include it. Ask an owner or admin if you need it. |
|
||||
|
||||
### Components (new) and Nuxt UI v4 mapping
|
||||
|
||||
| Component | Used for | Nuxt UI mapping |
|
||||
|---|---|---|
|
||||
| ScopeControl (tri-state) | None / Own / All in grid cells, mobile cards and general rows | URadioGroup variant="table" orientation="horizontal" size="xs", three items, in a grid cell. Selected item: sand fill, weight 600 and an underline |
|
||||
| OnOffCell | Create column and boolean rows | USwitch with visible On/Off label |
|
||||
| PermissionGrid | Content permissions | Custom grid (role="grid") of ScopeControl cells; header buttons use UDropdownMenu for bulk actions |
|
||||
| PresetPills | Read only, Write own, Full content | UButton variant="outline" size="xs", pressed state via aria-pressed |
|
||||
| PermissionGroup | Collapsible group with "x of y enabled" | UCollapsible; header UButton variant="ghost" |
|
||||
| OwnerOnlyTag | Locked owner-only items | UBadge variant="subtle" with lucide lock icon |
|
||||
| RoleBadge | Users, roles, API keys | UBadge variant="outline" with role icon (crown, shield, pencil, user-round) |
|
||||
| RolePreview | What this role can do | Card on desktop (UCard), USlideover side="bottom" on mobile |
|
||||
| RolePicker | Change role, invite, reassign on delete | URadioGroup variant="card" with description; USelectMenu for the reassign field; items disabled with a reason in description |
|
||||
| SaveBar | Unsaved changes | Sticky container with UButton color="neutral" variant="outline" and UButton color="primary" |
|
||||
| ReadOnlyBanner | Read-only pages | UAlert color="info" icon="i-lucide-lock" variant="soft" |
|
||||
| ViewOnlyMark | Own scope rows | Text with lucide lock icon and UTooltip |
|
||||
|
||||
### Accessibility: tri-state cell
|
||||
|
||||
| Item | Pattern |
|
||||
|---|---|
|
||||
| Structure | The grid is role="grid". Each cell contains a role="radiogroup" named "{Type}: {Action}" (for example "Events: Update") with three role="radio" items None, Own, All. Create is a role="switch" named "Events: Create". |
|
||||
| Keyboard | Tab moves between cells (one stop per cell). Inside a group, Left and Right (or Up and Down) move and select, Home and End jump to None and All. Arrow keys also move the roving tabindex. Space selects. Header bulk buttons open a menu with the same three values. |
|
||||
| Announcement | Selected item is aria-checked="true". A polite live region announces changes: "Events, Update, set to Own." Disabled items are aria-disabled and described by the reason ("You can only grant what your role has."). |
|
||||
| Not by color alone | Selected segment: sand fill plus weight 600 plus a 2 px underline in --ui-primary. Locked: lock icon. Changed cell: square marker. Mixed: text badge. |
|
||||
| Targets | 26 px segments on desktop, 44 px on mobile. Focus: 2 px --ui-primary outline, offset 2 px. |
|
||||
|
||||
### Needs backend
|
||||
|
||||
| Item | Detail |
|
||||
|---|---|
|
||||
| Role storage | Table role (id, name, description, built_in, locked, version) and role_permission (role_id, key, scope none|own|all). One role_id on user. Built-ins seeded and non-deletable. |
|
||||
| Endpoints | GET/POST /v1/role · GET/PUT/DELETE /v1/role/{id} · POST /v1/role/{id}/reassign · PUT /v1/user/{id}/role · POST /v1/site/transfer-ownership · GET /v1/me (role and permissions) · GET /v1/permission (catalogue) |
|
||||
| created_by | Add created_by (user id) to articles and entries so Own scope can be checked on read, update, delete and publish. Backfill from existing author or activity data. |
|
||||
| Enforcement | Server checks every call against role permissions and the no-escalation rules. API keys resolve the creator's current role on each request. |
|
||||
| Version field | role.version for the conflict state (409 role_conflict). |
|
||||
| Activity events | role.created, role.updated (with a diff of added and removed permissions), role.deleted, user.role_changed, site.ownership_transferred. |
|
||||
|
||||
### Existing screens that change
|
||||
|
||||
| Screen | Change |
|
||||
|---|---|
|
||||
| Sidebar and mobile drawer (AppFrame) | Items are listed per permission, not per fixed role. Writer sees Home, Articles, Media, Authors, Activity and Content. A Roles entry appears under Settings for people who can view roles. |
|
||||
| Settings navigation | New "Roles" item. "Permissions" is removed. |
|
||||
| /settings/permissions | Retired. 301 to /settings/roles. The grid lives in the role editor. |
|
||||
| Users (list, invite, row menu) | Role badges, Change role dialog, role picker in invite (default Writer), pending invites show the role, Transfer ownership, protected owner row. |
|
||||
| Articles list and Editor | Publish hidden for roles without it; status shows Draft with "Ask an editor to publish." Delete and Edit disabled with a reason when scope is Own and the item is someone else's. |
|
||||
| Content entry lists and editor | Same Own rules. View only mark. |
|
||||
| Settings pages | Read-only mode with banner for people who can view but not edit. Owner-only actions disabled with an Owner only tag. |
|
||||
| Schema | Hidden for roles without Schema view. Read-only for view-only roles. |
|
||||
| API keys | Info alert "Keys follow their creator's role", a Follows role column. |
|
||||
| Profile | Your role card and See what I can do. |
|
||||
| Activity and filters | New event types, role diff in the detail panel. |
|
||||
| Error and 403 copy | Two codes and the page-level state added. |
|
||||
|
||||
### Decisions to confirm
|
||||
|
||||
| # | Decision made | Alternative |
|
||||
|---|---|---|
|
||||
| 1 | Content permissions come before General permissions in the editor, because the common case (Contributor) only touches the grid. | General first, as in the brief. |
|
||||
| 2 | Writer gets Authors: view and edit own, and Activity: own. | No Authors or Activity access. |
|
||||
| 3 | A new role starts with nothing granted; presets fill the grid. | Start from a copy of Writer. |
|
||||
| 4 | Own-scope rows others created show "View only" with a lock icon, not a hidden row. | Hide other people's entries. |
|
||||
| 5 | Reset to default exists for built-in roles edited by the owner. | No reset. |
|
||||
| 6 | Activity own/all scope uses the same None / Own / All control. | Toggle plus a separate scope select. |
|
||||
| 7 | Transfer ownership takes effect at once, no email to the new owner. | The new owner must accept. |
|
||||
| 8 | A user with Roles: manage cannot edit their own role, even in a custom role. | Allow narrowing only. |
|
||||
|
||||
|
||||
State count: 61.
|
||||
Reference in new issue
Block a user