Roles and Permissions
Operyn uses roles to control what users can see and do in the console and, optionally, in backend APIs. This document defines the intended personas, permissions per resource, and a role–permission matrix. Implementation can start with organization-plugin roles and a small in-code permission map; a full RBAC plugin can be added later for database-driven permissions.
Personas and Roles
| Role | Who | Purpose |
|---|
| Viewer | NOC, stakeholders, auditors | See incidents, analytics, and remediation status; no configuration or actions. |
| Responder | On-call engineers | Everything Viewer can do, plus: comment on incidents, assign, acknowledge, and approve or reject remediations. |
| Operator | SRE / platform team | Everything Responder can do, plus: create/update/delete correlation rules, manage the on-call team roster, and test notification channels. |
| Admin | Workspace owners | Everything Operator can do, plus: manage org members, configure notification channels and remediation policy, and full settings. |
| Owner | Single per organization | Same as Admin, plus: transfer ownership and delete the organization. |
Operyn natively supports these 5 roles via the better-auth organization plugin. Each role is assigned a specific set of permissions defined in lib/auth/permissions.ts (dashboard) and @operyn/shared-types (backend).
Permissions (Resource + Action)
Permissions are scoped by resource and action. This list aligns with the current Incident Engine, Remediation Engine, and Notification Service APIs.
Incidents
| Permission | Description |
|---|
incidents:view | List incidents, get by id, subscribe to SSE stream. |
incidents:create | Manually create an incident. |
incidents:update | Update incident-linked metadata actions (for MVP: link/unlink runbooks). |
incidents:update_status | Acknowledge, resolve, or change status. |
incidents:comment | Add a comment. |
incidents:assign | Assign an incident to a team member. |
Team (on-call roster)
| Permission | Description |
|---|
team:view | List members and on-call state. |
team:manage | Create or delete members, toggle on-call. |
team:assign_incident | Assign an incident (can be merged with incidents:assign or kept separate). |
Correlation rules
| Permission | Description |
|---|
correlation_rules:view | List and view rules. |
correlation_rules:create | Create a rule. |
correlation_rules:update | Update a rule. |
correlation_rules:delete | Delete a rule. |
| Permission | Description |
|---|
remediation:view | List and view remediation requests. |
remediation:approve | Approve a remediation. |
remediation:reject | Reject a remediation (optionally with reason). |
Policy (safety)
| Permission | Description |
|---|
policy:view | View remediation policy. |
policy:update | Change policy (e.g. auto-approve thresholds). |
Notifications
| Permission | Description |
|---|
notifications:view | View channel status and notification history. |
notifications:configure | Configure channels. |
notifications:test | Send a test notification. |
Organization (auth)
| Permission | Description |
|---|
org:view_members | List org/team members. |
org:invite | Invite users. |
org:remove_member | Remove a member. |
org:change_role | Change a member’s role. |
org:manage_teams | Create, rename, or delete teams within the org. |
org:delete | Delete the organization (owner only). |
org:transfer_ownership | Transfer ownership (owner only). |
Settings
| Permission | Description |
|---|
settings:view | View general, profile, and notification settings. |
settings:edit | Change settings (profile can be restricted to “own profile only”). |
Analytics
| Permission | Description |
|---|
analytics:view | View the analytics page (read-only). |
Role–Permission Matrix
| Permission | Viewer | Responder | Operator | Admin | Owner |
|---|
incidents:view, analytics:view | ✓ | ✓ | ✓ | ✓ | ✓ |
incidents:create, update, update_status, comment, assign | — | ✓ | ✓ | ✓ | ✓ |
remediation:view, approve, reject | — | ✓ | ✓ | ✓ | ✓ |
correlation_rules:* | view only | view only | full | full | full |
team:view | ✓ | ✓ | ✓ | ✓ | ✓ |
team:manage, assign_incident | — | assign only | ✓ | ✓ | ✓ |
policy:view / policy:update | view | — | view | full | full |
notifications:view / configure / test | view | — | full | full | full |
org:view_members, invite, remove, change_role, manage_teams | view | — | — | full | full |
settings:view / edit | view | own profile | full | full | full |
org:delete, org:transfer_ownership | — | — | — | — | ✓ |
- view = read-only for that resource.
- assign only = can assign incidents but not add/remove team members.
- full = create, update, delete (and test where applicable).
Implementation Architecture
Operyn uses a hybrid approach for RBAC:
- Native Better-Auth Roles: All 5 personas (
owner, admin, operator, responder, viewer) are natively registered with the better-auth organization plugin.
- Synchronous Client Checks: Role verification and permission checking on the client are handled by a
can() helper in permissions.ts.
- Backend Enforcement: Backend services (e.g. Incident Engine) use a
RolesGuard that validates the user's role from a JWT and checks it against a per-service permission map.
- Shared Contract: A shared
@operyn/shared-types library ensures that role-to-permission mappings are consistent between the dashboard and the backend.
See Authentication for how auth is integrated.