Users and roles
Every person who signs in to DK Studio holds one of three roles, and the role decides what that person reaches in the product. This page introduces the three roles, how to add a colleague, how to change what they can do, and how to take their access away again.
The three roles
| Role | What it reaches in the product |
|---|---|
admin | Everything: dashboard, projects, products, environments, devices, vehicles, OEMs, test suites, test cases, test runs, executions, schedules, reports, artifacts, settings β and the administration area at /admin, where agents, licences and users are managed. |
engineer | The working platform: dashboard, projects, products, environments, devices, test suites, test cases, test runs, executions, schedules, reports, artifacts and settings. |
viewer | Read-only: dashboard, projects, test runs, reports and settings. |
The roles are fixed and live in apps/studio/lib/roles.ts: ROLES is the list of the three, and
normalizeRole maps anything else onto viewer. An account whose role is not one of the three is
therefore handled as a viewer β it sees the read-only interface and nothing of /admin.
Reach is decided by prefix match with canAccessPath(role, path): /admin covers /admin/users,
/admin/agents and /admin/licenses, and a path under one of those entries is reachable by the
role that lists it.
The role shapes two things: the interface, which renders only the navigation entries the role
allows, and the administration area, which is admin-only. A signed-in user of any other role who
asks for a path under /admin is sent to /dashboard.
Signing in and the session
{ "email": "engineer@lab.example", "password": "a-strong-password" }A successful sign-in sets two cookies:
| Cookie | Readable by JavaScript | Contents |
|---|---|---|
session | No (httpOnly) | id, email, name, role and exp β the payload the platform trusts. |
session_client | Yes | The same identity without exp, used by the interface to decide what to render. |
The session is good for seven days, and exp in the payload is set to that window. The cookie is
httpOnly and sameSite="lax", and it carries the secure flag when NODE_ENV=production.
GET /api/auth/status reports the identity the session carries, and POST /api/auth/logout clears
both cookies.
A session lasts until it expires seven days after it was issued. POST /api/auth/logout clears it
immediately, which is the right move on a shared bench.
Creating a user
Open Admin β Users. The screen counts your admins, engineers and viewers, lists every account
with its role and timestamps, and creates accounts through the Add User action. The role selector
defaults to viewer.
Over the API:
{
"email": "engineer@lab.example",
"name": "Lab Engineer",
"password": "a-strong-password",
"role": "engineer"
}| Field | Required | Notes |
|---|---|---|
email | Yes | Must be unique; a second account with the same address is refused. |
name | Yes | Shown in the interface and carried in the session payload. |
password | Yes | Stored as a bcrypt hash in users.password_hash; it is never returned. |
role | No | admin, engineer or viewer. Anything else is stored as viewer. |
The response echoes the new account β id, email, name and role β and never the password.
GET /api/admin/users lists every user with the same fields plus createdAt and updatedAt, and
no hashes.
The first administrator is created by the setup wizard, which writes the account directly with the
admin role; see Setup Wizard.
Changing a role
The role column on Admin β Users is editable: open the account, pick another role, and the platform stores it on the account. The next time that person signs in, their session carries the new role, and the interface and the administration area follow it from then on.
Give the account a role that matches the work. Promote a colleague who runs campaigns to
engineer; keep viewer for anyone who only reads results; reserve admin for the people who
manage agents, licences and accounts.
The session carries the role it was issued with. After a role change, have the user sign out and sign back in so the new role is in force for the whole interface straight away.
Deactivating a user
Deactivating keeps the account and its history but stops it working: the person can no longer sign in, and an existing session stops being honoured. Reactivate the account to give access back.
Deleting is the other way to take access away, and it removes the account outright:
{ "id": "6f0eβ¦" }Deactivation is reversible and leaves the record of who did what. Deletion is not: the account is gone, and the only way back is to create it again with the same email address.
How to verify
GET /api/auth/statusreturns the identity and role of the signed-in account.- Sign in as a
viewerand check the sidebar: the administration entries and the authoring entries are absent, and a direct request for a path under/adminlands on/dashboard. GET /api/admin/usersshows the role of every account, and the time the role was last changed.
Related pages
- Setup Wizard β the first admin account.
- REST API Reference β every user endpoint.
- Security and Privacy β how the session and the API exposure fit together.
- Self-hosted Deployment β running the studio behind TLS.