What problem does this solve?
Routerly has a permission system (project:read/write, model:read/write, user:read/write, report:read) and three built-in roles (admin, operator, viewer). The RoleConfig type supports custom roles, but roles.json ships empty and there is no dashboard UI to manage them. Several important actions have no dedicated permission at all, meaning access control is binary (admin vs. non-admin) for settings, notification config, token management, and audit data.
Proposed solution
1. Fill the permission gaps
Add missing permissions to Permission type and enforce them on the relevant API endpoints:
| New permission |
Covers |
settings:read |
View global settings |
settings:write |
Modify global settings (ports, storage, channels) |
notification:write |
Add/edit/delete notification channels and rules |
token:read |
List project tokens (currently: anyone with project:read) |
token:write |
Create/delete/edit project tokens |
role:write |
Create/edit/delete custom roles |
audit:read |
Access audit log |
2. Complete custom roles
- Dashboard UI: Roles page (already exists as
RolesPage.tsx) should allow creating, editing, and deleting custom roles
- On user creation/edit, allow assigning any role from
roles.json, not just the three built-ins
- Validate that built-in roles (
admin, operator, viewer) cannot be deleted
3. Project-level role enforcement
ProjectMember already has viewer | editor | admin role, but it is unclear if this is enforced server-side for per-project API calls. Verify and enforce: a project viewer cannot call project:write endpoints for their project; a project admin cannot affect other projects.
4. Audit log
Record all write operations to a tamper-evident append-only log:
- Who (userId, email), what (endpoint + action), when (timestamp), result (success/forbidden)
- Exposed via
/api/audit with audit:read permission
- Dashboard: Audit Logs page with filter by user, action type, date range
- Retention: configurable (default 90 days)
5. Credential hygiene
- Tokens in
projects.json are stored in plaintext — consider storing SHA-256 hashes (show once on creation, like GitHub PATs)
- Add token expiry support: optional
expiresAt field on ProjectToken
- Add token last-used timestamp so stale tokens can be identified and rotated
Alternatives you've considered
Keeping the current three-role model and documenting its limits. Acceptable for single-user deployments, not for teams.
Who would benefit from this?
Any team deployment where multiple people share a Routerly instance. Required for SOC 2 / ISO 27001 compliance (access control + audit trail are explicit requirements).
Additional context
The resolvePermissions() function in routes/api.ts already supports arbitrary permission arrays — the infrastructure is in place. This issue is primarily about filling the gaps, wiring the UI, and adding the audit trail.
What problem does this solve?
Routerly has a permission system (
project:read/write,model:read/write,user:read/write,report:read) and three built-in roles (admin,operator,viewer). TheRoleConfigtype supports custom roles, butroles.jsonships empty and there is no dashboard UI to manage them. Several important actions have no dedicated permission at all, meaning access control is binary (admin vs. non-admin) for settings, notification config, token management, and audit data.Proposed solution
1. Fill the permission gaps
Add missing permissions to
Permissiontype and enforce them on the relevant API endpoints:settings:readsettings:writenotification:writetoken:readproject:read)token:writerole:writeaudit:read2. Complete custom roles
RolesPage.tsx) should allow creating, editing, and deleting custom rolesroles.json, not just the three built-insadmin,operator,viewer) cannot be deleted3. Project-level role enforcement
ProjectMemberalready hasviewer | editor | adminrole, but it is unclear if this is enforced server-side for per-project API calls. Verify and enforce: a projectviewercannot callproject:writeendpoints for their project; a projectadmincannot affect other projects.4. Audit log
Record all write operations to a tamper-evident append-only log:
/api/auditwithaudit:readpermission5. Credential hygiene
projects.jsonare stored in plaintext — consider storing SHA-256 hashes (show once on creation, like GitHub PATs)expiresAtfield onProjectTokenAlternatives you've considered
Keeping the current three-role model and documenting its limits. Acceptable for single-user deployments, not for teams.
Who would benefit from this?
Any team deployment where multiple people share a Routerly instance. Required for SOC 2 / ISO 27001 compliance (access control + audit trail are explicit requirements).
Additional context
The
resolvePermissions()function inroutes/api.tsalready supports arbitrary permission arrays — the infrastructure is in place. This issue is primarily about filling the gaps, wiring the UI, and adding the audit trail.