From ddf90c8819937286aae3a4a099b4525da7c0f68d Mon Sep 17 00:00:00 2001 From: Benjamin Smidt Date: Mon, 8 Jun 2026 20:07:12 -0700 Subject: [PATCH 1/4] docs(users): replace roles page with access control Document the workspace and group role model. Add the access control page covering tiers, workspace roles (viewer/operator/provisioner/ publisher), and group roles (viewer/operator/provisioner/manager), swap it into the Users nav, and remove the superseded roles page. --- docs/admin/users/access-control.mdx | 108 ++++++++++++++++++++++++++++ docs/admin/users/roles.mdx | 54 -------------- docs/docs.json | 2 +- 3 files changed, 109 insertions(+), 55 deletions(-) create mode 100644 docs/admin/users/access-control.mdx delete mode 100644 docs/admin/users/roles.mdx diff --git a/docs/admin/users/access-control.mdx b/docs/admin/users/access-control.mdx new file mode 100644 index 0000000..7bb385e --- /dev/null +++ b/docs/admin/users/access-control.mdx @@ -0,0 +1,108 @@ +--- +title: "Access control" +--- + +import { OwnerBadge, MemberBadge, ViewerBadge, OperatorBadge, ProvisionerBadge, PublisherBadge, GroupManagerBadge } from '/snippets/components/role-badges.jsx'; + +There are two access control mechanisms for users in a workspace: **tiers** and **roles**. + +## Tiers + +Tiers are the access levels of a user in a workspace. Below is a summary of the tiers and their permissions. + +| Tier | Description | +| -------- | ----------------------------------------------------------------------------------- | +| `owner` | Complete control over the workspace; exactly one per workspace | +| `admin` | Administrative and application access to the workspace; is subordinate to the owner | +| `member` | Application access to the workspace, but no administrative privileges | + +### Administrators + +Owners and admins hold administrative privileges, granting them the following permissions, which are unavailable to members: + +**API Keys** +- Create a new API key +- Delete an existing API key + +**Groups** +- Create a new group +- Update an existing group +- Delete an existing group +- Move a device to a different group + +**Invites** +- Send an invite +- Resend an invite +- Revoke an invite + +**Members** +- Suspend a member +- Update another member's role + +**Workspace** +- Update the workspace + +Of course, owners have some special immunity from the above permissions to prevent unwanted privilege escalation: + +- Owners cannot be suspended +- Owners cannot have their role changed by another user + +### Owners + +A workspace must have exactly one owner. As such, owners cannot leave their workspace or be suspended. + +However, owners can transfer ownership to another member. Thus, in addition to the admin permissions above, owners also have a special permission for transferring workspace ownership to another member. + +### Members + +Members hold application access to the workspace but no administrative privileges. Unlike owners and admins, a member is not granted blanket access — what a member can actually do is determined by their **roles**. + +Every member starts as a viewer with read-only access to the workspace. From there, [workspace roles](#workspace-roles) and [group roles](#group-roles) grant the write access needed to create devices, deploy configurations, publish releases, and more. + +## Roles + +Tiers decide whether a user is an administrator. **Roles** decide what a member can actually do. Because owners and admins already have full access to the workspace, roles only apply to members. + +A member's access comes from two independent sources: + +- **Workspace roles** apply across the entire workspace. +- **Group roles** apply inside a single [group](/learn/groups) and every group beneath it. + +A member can hold any combination of both. Permissions are always **additive** — Miru allows an action if any of the member's roles permit it, and one role never removes access granted by another. + +### Workspace roles + +A workspace role grants a member permissions across the **entire workspace**. Every member is at least a viewer, with read-only access to all resources; the other roles add write access on top of that baseline. A member can hold several workspace roles at once. + +- **Viewer** — Read-only access to every resource in the workspace. This is the baseline that every member has. +- **Operator** — Stage, deploy, and remove deployments. +- **Provisioner** — Create and activate devices. +- **Publisher** — Create and edit config types, schemas, and releases — the publishing pipeline. + +| Resource | Viewer | Operator | Provisioner | Publisher | +| -------- | :----: | :------: | :---------: | :-------: | +| **Deployments** — stage, deploy, remove | Read | Write | Read | Read | +| **Devices** — create, activate | Read | Read | Write | Read | +| **Config types, releases & schemas** — publishing pipeline | Read | Read | Read | Write | +| **Groups** — tree structure & membership | Read | Read | Read | Read | + +Managing the group tree, members, and billing are administrative actions — they belong to owners and admins, not to workspace roles. See [Tiers](#tiers). + +### Group roles + +A group role grants permissions inside one [group](/learn/groups) **and every group beneath it**. Because a device belongs to every group above it in the tree, a role granted on a group cascades down to all of its subgroups and devices. + +Group roles mirror the workspace roles, scoped to the group: + +- **Viewer** — Read-only access to the group's resources. The baseline for every group member. +- **Operator** — Stage, deploy, and remove deployments within the group. +- **Provisioner** — Create and activate devices within the group. +- **Manager** — Manage the group's members and their grants, and create subgroups. Includes everything the operator and provisioner roles can do. + +| Resource | Viewer | Operator | Provisioner | Manager | +| -------- | :----: | :------: | :---------: | :-----: | +| **Deployments** — stage, deploy, remove | Read | Write | Read | Write | +| **Devices** — create, activate | Read | Read | Write | Write | +| **Groups** — subgroups & membership | Read | Read | Read | Write | + +A member's effective permissions are the union of their workspace roles and every group role they hold. For example, a member with the workspace viewer role plus the manager role on a `production` group can read everything in the workspace and fully manage `production` and all of its descendants. diff --git a/docs/admin/users/roles.mdx b/docs/admin/users/roles.mdx deleted file mode 100644 index 9a02bdc..0000000 --- a/docs/admin/users/roles.mdx +++ /dev/null @@ -1,54 +0,0 @@ ---- -title: "Roles" ---- - -Roles are the access levels of a user in a workspace. Below is a summary of the roles and their permissions. - -| Role | Description | -| -------- | ----------------------------------------------------------------------------------- | -| `owner` | Complete control over the workspace; exactly one per workspace | -| `admin` | Administrative and application access to the workspace; is subordinate to the owner | -| `member` | Application access to the workspace, but no administrative privileges | - -### Admin permissions - -Owners and admins hold administrative privileges, granting them the following permissions, which are unavailable to members: - -**API Keys** -- Create a new API key -- Delete an existing API key - -**Groups** -- Create a new group -- Update an existing group -- Delete an existing group -- Move a device to a different group - -**Invites** -- Send an invite -- Resend an invite -- Revoke an invite - -**Members** -- Suspend a member -- Update another member's role - -**Workspace** -- Update the workspace - -Of course, owners have some special immunity from the above permissions to prevent unwanted privilege escalation: - -- Owners cannot be suspended -- Owners cannot have their role changed by another user - -### Owner permissions - -A workspace must have exactly one owner. As such, owners cannot leave their workspace or be suspended. - -However, owners can transfer ownership to another member. Thus, in addition to the admin permissions above, owners also have a special permission for transferring workspace ownership to another member. - -### Member permissions - -Members hold application access to the workspace but no administrative privileges. - -We won't detail every permission here — suffice it to say, members can perform any action that is not administrative or owner-only. This includes creating devices, deploying configurations, etc. diff --git a/docs/docs.json b/docs/docs.json index b0557c3..589ba8d 100644 --- a/docs/docs.json +++ b/docs/docs.json @@ -162,9 +162,9 @@ "group": "Users", "pages": [ "admin/users/overview", - "admin/users/roles", "admin/users/invites", "admin/users/profile", + "admin/users/access-control", "admin/users/manage" ] } From b7ea845cd025b846605602c4e917fe2cf2044194 Mon Sep 17 00:00:00 2001 From: Benjamin Smidt Date: Mon, 8 Jun 2026 20:07:12 -0700 Subject: [PATCH 2/4] docs(users): add member badge and point role links to access control Add the MemberBadge component used by the access control page and repoint the role badge/link targets from the removed /admin/users/roles path to /admin/users/access-control. --- docs/admin/users/overview.mdx | 2 +- docs/snippets/components/role-badges.jsx | 81 ++++++++++++++++++++++-- docs/snippets/components/users/roles.jsx | 6 +- 3 files changed, 81 insertions(+), 8 deletions(-) diff --git a/docs/admin/users/overview.mdx b/docs/admin/users/overview.mdx index 47738ed..5323367 100644 --- a/docs/admin/users/overview.mdx +++ b/docs/admin/users/overview.mdx @@ -39,7 +39,7 @@ import UserDef from '/snippets/definitions/user.mdx'; - The user's [access role](/admin/users/roles) in the workspace. + The user's [access role](/admin/users/access-control) in the workspace. Allowed values: - `member` diff --git a/docs/snippets/components/role-badges.jsx b/docs/snippets/components/role-badges.jsx index d1a06c0..4b55a2b 100644 --- a/docs/snippets/components/role-badges.jsx +++ b/docs/snippets/components/role-badges.jsx @@ -3,21 +3,94 @@ export const OwnerBadge = ({ size = "md" }) => { owner ); }; +export const MemberBadge = ({ size = "md" }) => { + return ( + + member + + ); +}; + export const AdminBadge = ({ size = "md" }) => { return ( admin ); -}; \ No newline at end of file +}; + +export const GroupManagerBadge = ({ size = "md" }) => { + return ( + + group manager + + ); +}; + +export const PublisherBadge = ({ size = "md" }) => { + return ( + + publisher + + ); +}; + +export const ProvisionerBadge = ({ size = "md" }) => { + return ( + + provisioner + + ); +}; + +export const OperatorBadge = ({ size = "md" }) => { + return ( + + operator + + ); +}; + +export const ViewerBadge = ({ size = "md" }) => { + return ( + + viewer + + ); +}; + diff --git a/docs/snippets/components/users/roles.jsx b/docs/snippets/components/users/roles.jsx index b83acab..a11fda9 100644 --- a/docs/snippets/components/users/roles.jsx +++ b/docs/snippets/components/users/roles.jsx @@ -1,18 +1,18 @@ export const ROLE_TOOLTIP = { tip: "The access role of the user in the workspace.", cta: "Learn more", - href: "/admin/users/roles" + href: "/admin/users/access-control" }; export const ADMIN_TOOLTIP = { tip: "A user with administrative and application access to the workspace; subordinate to the owner.", cta: "Learn more", - href: "/admin/users/roles" + href: "/admin/users/access-control" }; export const OWNER_TOOLTIP = { tip: "A user with complete control over the workspace; exactly one per workspace.", cta: "Learn more", - href: "/admin/users/roles" + href: "/admin/users/access-control" }; \ No newline at end of file From e004e5a687bda56fd605ae2ff48c498237709917 Mon Sep 17 00:00:00 2001 From: Benjamin Smidt Date: Mon, 8 Jun 2026 20:10:42 -0700 Subject: [PATCH 3/4] docs(users): rename tiers to user types Use 'user types' instead of 'tiers' to match the backend UserType model (owner/admin/member), including the section heading, table header, and the cross-reference anchor. --- docs/admin/users/access-control.mdx | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/admin/users/access-control.mdx b/docs/admin/users/access-control.mdx index 7bb385e..8777473 100644 --- a/docs/admin/users/access-control.mdx +++ b/docs/admin/users/access-control.mdx @@ -4,13 +4,13 @@ title: "Access control" import { OwnerBadge, MemberBadge, ViewerBadge, OperatorBadge, ProvisionerBadge, PublisherBadge, GroupManagerBadge } from '/snippets/components/role-badges.jsx'; -There are two access control mechanisms for users in a workspace: **tiers** and **roles**. +There are two access control mechanisms for users in a workspace: **user types** and **roles**. -## Tiers +## User types -Tiers are the access levels of a user in a workspace. Below is a summary of the tiers and their permissions. +User types are the access levels of a user in a workspace. Below is a summary of the user types and their permissions. -| Tier | Description | +| User type | Description | | -------- | ----------------------------------------------------------------------------------- | | `owner` | Complete control over the workspace; exactly one per workspace | | `admin` | Administrative and application access to the workspace; is subordinate to the owner | @@ -49,9 +49,9 @@ Of course, owners have some special immunity from the above permissions to preve ### Owners -A workspace must have exactly one owner. As such, owners cannot leave their workspace or be suspended. +A workspace must have exactly one owner—owners cannot leave their workspace or be suspended. -However, owners can transfer ownership to another member. Thus, in addition to the admin permissions above, owners also have a special permission for transferring workspace ownership to another member. +Of course, owners can transfer ownership to another member. Thus, in addition to the admin permissions above, owners also have a special permission for transferring workspace ownership to another member. ### Members @@ -61,7 +61,7 @@ Every member starts as a viewer with read-only access to the workspace. From the ## Roles -Tiers decide whether a user is an administrator. **Roles** decide what a member can actually do. Because owners and admins already have full access to the workspace, roles only apply to members. +A user's type decides whether they are an administrator. **Roles** decide what a member can actually do. Because owners and admins already have full access to the workspace, roles only apply to members. A member's access comes from two independent sources: @@ -86,7 +86,7 @@ A workspace role grants a member permissions across the **entire workspace**. Ev | **Config types, releases & schemas** — publishing pipeline | Read | Read | Read | Write | | **Groups** — tree structure & membership | Read | Read | Read | Read | -Managing the group tree, members, and billing are administrative actions — they belong to owners and admins, not to workspace roles. See [Tiers](#tiers). +Managing the group tree, members, and billing are administrative actions — they belong to owners and admins, not to workspace roles. See [User types](#user-types). ### Group roles From dd7a88e3b77ef8ee79caf410b363d5a9715dea98 Mon Sep 17 00:00:00 2001 From: Benjamin Smidt Date: Tue, 9 Jun 2026 09:21:50 -0700 Subject: [PATCH 4/4] docs(users): reformat group roles to match workspace roles Replace the group-role badge list and permissions matrix with per-role subsections (viewer/operator/provisioner/manager), each with a prose description and linked operation lists, matching the workspace roles format. Also fix a double dash and a typo in the administrative privileges intro. --- docs/admin/users/access-control.mdx | 175 +++++++++++++++++++--------- 1 file changed, 119 insertions(+), 56 deletions(-) diff --git a/docs/admin/users/access-control.mdx b/docs/admin/users/access-control.mdx index 8777473..88e3cc0 100644 --- a/docs/admin/users/access-control.mdx +++ b/docs/admin/users/access-control.mdx @@ -2,107 +2,170 @@ title: "Access control" --- -import { OwnerBadge, MemberBadge, ViewerBadge, OperatorBadge, ProvisionerBadge, PublisherBadge, GroupManagerBadge } from '/snippets/components/role-badges.jsx'; +import { OwnerBadge, AdminBadge, MemberBadge, ViewerBadge, OperatorBadge, ProvisionerBadge, PublisherBadge, GroupManagerBadge } from '/snippets/components/role-badges.jsx'; There are two access control mechanisms for users in a workspace: **user types** and **roles**. ## User types -User types are the access levels of a user in a workspace. Below is a summary of the user types and their permissions. +User types determine the broad access levels of a user. Below is a summary of the user types and their functions. -| User type | Description | -| -------- | ----------------------------------------------------------------------------------- | -| `owner` | Complete control over the workspace; exactly one per workspace | -| `admin` | Administrative and application access to the workspace; is subordinate to the owner | -| `member` | Application access to the workspace, but no administrative privileges | + - complete control over the workspace; exactly one per workspace -### Administrators + - complete administrative and application access; is subordinate to the owner -Owners and admins hold administrative privileges, granting them the following permissions, which are unavailable to members: + - limited application access to the workspace with no administrative privileges -**API Keys** +Owners have unrestricted access to the workspace with the ability to execute any action. Administrators hold nearly the same access as owners, but are unable to escalate themselves to be the workspace owner. + +Members are the only user type that can be granted fine-grained access to the workspace through [roles](#roles). Administrators and owners cannot be given any roles since they already have complete access to the workspace. + +### Administrative privileges + +There are a variety of privileges which are only available to owners and administrators — no roles exist that can grant members these privileges: + +[API Keys](/admin/apikeys) - Create a new API key -- Delete an existing API key +- Delete an API key -**Groups** -- Create a new group -- Update an existing group -- Delete an existing group +[Groups](/learn/groups) +- Create a group +- Update a group +- Delete a group - Move a device to a different group -**Invites** +[Invites](/admin/users/invites) - Send an invite - Resend an invite - Revoke an invite -**Members** +[Members](/admin/users/manage) - Suspend a member - Update another member's role -**Workspace** +[Workspace](/admin/workspace) - Update the workspace -Of course, owners have some special immunity from the above permissions to prevent unwanted privilege escalation: +## Roles -- Owners cannot be suspended -- Owners cannot have their role changed by another user +While a user's type determines broad access and administrative capabilities, **roles** grant fine-grained access to the workspace. Because owners and admins already have full access to the workspace, roles can only be granted to members. -### Owners +A member's roles are defined in two independent sources: -A workspace must have exactly one owner—owners cannot leave their workspace or be suspended. +- **Workspace roles** apply across the entire workspace +- **Group roles** apply to a [group](/learn/groups) and all of its subgroups -Of course, owners can transfer ownership to another member. Thus, in addition to the admin permissions above, owners also have a special permission for transferring workspace ownership to another member. +A member can hold any combination of both. Permissions are always **additive** — Miru allows an action if any of the member's roles permit it, and one role never removes access granted by another. -### Members +### Workspace roles -Members hold application access to the workspace but no administrative privileges. Unlike owners and admins, a member is not granted blanket access — what a member can actually do is determined by their **roles**. +A workspace role grants a member permissions across the **entire workspace**. Every member is at least a viewer, with read-only access to the entire application. -Every member starts as a viewer with read-only access to the workspace. From there, [workspace roles](#workspace-roles) and [group roles](#group-roles) grant the write access needed to create devices, deploy configurations, publish releases, and more. +Beyond viewer, the other roles permit write access to specific resources. A member can hold multiple workspace roles at once. -## Roles +#### Viewer -A user's type decides whether they are an administrator. **Roles** decide what a member can actually do. Because owners and admins already have full access to the workspace, roles only apply to members. +Viewers hold read-only access to the entire application. It is not possible to restrict read access to specific resources. -A member's access comes from two independent sources: +#### Operator -- **Workspace roles** apply across the entire workspace. -- **Group roles** apply inside a single [group](/learn/groups) and every group beneath it. +The operator role allows members to deploy configurations to devices in the workspace. The operator role grants access to the following operations: -A member can hold any combination of both. Permissions are always **additive** — Miru allows an action if any of the member's roles permit it, and one role never removes access granted by another. +[Config editor](/learn/devices/config-editor) -### Workspace roles +- Deploy configurations to devices + +[Release staging area](/learn/releases/staging-area) + +- Stage a deployment +- Patch a deployment +- Review a deployment +- Deploy a deployment +- Archive a deployment + +#### Provisioner + +The provisioner role allows members to create and activate devices in the workspace. The provisioner role grants access to the following operations: + +[Manage devices](/learn/devices/manage) + +- Create a device +- Edit a device +- Delete a device + +[Provision devices](/learn/devices/provision/dashboard) + +- Provision a device +- Reprovision a device + +#### Publisher -A workspace role grants a member permissions across the **entire workspace**. Every member is at least a viewer, with read-only access to all resources; the other roles add write access on top of that baseline. A member can hold several workspace roles at once. +The publisher role allows members to create and edit config types, schemas, and releases (all the resources needed to publish a release). The publisher role grants access to the following operations: -- **Viewer** — Read-only access to every resource in the workspace. This is the baseline that every member has. -- **Operator** — Stage, deploy, and remove deployments. -- **Provisioner** — Create and activate devices. -- **Publisher** — Create and edit config types, schemas, and releases — the publishing pipeline. +[Config types](/learn/config-types) -| Resource | Viewer | Operator | Provisioner | Publisher | -| -------- | :----: | :------: | :---------: | :-------: | -| **Deployments** — stage, deploy, remove | Read | Write | Read | Read | -| **Devices** — create, activate | Read | Read | Write | Read | -| **Config types, releases & schemas** — publishing pipeline | Read | Read | Read | Write | -| **Groups** — tree structure & membership | Read | Read | Read | Read | +- Create a config type +- Edit a config type -Managing the group tree, members, and billing are administrative actions — they belong to owners and admins, not to workspace roles. See [User types](#user-types). +[Config schemas](/learn/schemas/manage) + +- Create a config schema + +[Releases](/learn/releases/create) + +- Create a release +- [Duplicate a release](/learn/releases/manage#duplicate-a-release) ### Group roles A group role grants permissions inside one [group](/learn/groups) **and every group beneath it**. Because a device belongs to every group above it in the tree, a role granted on a group cascades down to all of its subgroups and devices. -Group roles mirror the workspace roles, scoped to the group: +Group roles mirror the workspace roles, scoped to a single group. A member can hold multiple group roles at once. + +#### Viewer + +Viewers hold read-only access to all of the group's resources. + +#### Operator + +The operator role allows members to deploy configurations to devices in the group. The operator role grants access to the following operations: + +[Config editor](/learn/devices/config-editor) + +- Deploy configurations to devices + +[Release staging area](/learn/releases/staging-area) + +- Stage a deployment +- Patch a deployment +- Review a deployment +- Deploy a deployment +- Archive a deployment + +#### Provisioner + +The provisioner role allows members to create and activate devices in the group. The provisioner role grants access to the following operations: + +[Manage devices](/learn/devices/manage) + +- Create a device +- Edit a device +- Delete a device + +[Provision devices](/learn/devices/provision/dashboard) + +- Provision a device +- Reprovision a device + +#### Manager + +The manager role allows members to manage a group's members, their grants, and its subgroups. It includes everything the operator and provisioner roles can do, along with the following operations: -- **Viewer** — Read-only access to the group's resources. The baseline for every group member. -- **Operator** — Stage, deploy, and remove deployments within the group. -- **Provisioner** — Create and activate devices within the group. -- **Manager** — Manage the group's members and their grants, and create subgroups. Includes everything the operator and provisioner roles can do. +[Groups](/learn/groups) -| Resource | Viewer | Operator | Provisioner | Manager | -| -------- | :----: | :------: | :---------: | :-----: | -| **Deployments** — stage, deploy, remove | Read | Write | Read | Write | -| **Devices** — create, activate | Read | Read | Write | Write | -| **Groups** — subgroups & membership | Read | Read | Read | Write | +- Create a subgroup +- Edit a group +- Move a device +- Delete a group A member's effective permissions are the union of their workspace roles and every group role they hold. For example, a member with the workspace viewer role plus the manager role on a `production` group can read everything in the workspace and fully manage `production` and all of its descendants.