Team
The /team page is admin-only. It lists every user under your tenant — both active members and pending invites — and lets admins change roles, send new invites, and remove users.
Roles
Three tiers cover the common needs (full breakdown on the overview):
- admin — everything, including managing other admins.
- developer — read everything, mint / revoke test-mode keys.
- viewer — read-only across audit, usage, settings.
A tenant must always have at least one admin. The page enforces this by greying out the "Remove" action on a row if removing it would leave the tenant with zero admins, and by disabling the "Demote to developer" action on the same row.
Inviting a teammate
- Click Invite user.
- Enter the email address and pick a role.
- Submit. The dashboard sends an email with a setup link of the form
dashboard.drukverify.com/setup?invite=<token>. - The invited user lands on a page that shows the tenant name they're joining; they set a password, enroll TOTP, and save backup codes — same flow as initial-admin setup, just pre-bound to the role you picked.
Pending invites appear in the team list with a "Pending" badge until the invitee completes setup. Invite tokens expire after 7 days. If the invitee never accepts, the row stays "Pending" — re-send (a new token replaces the old one) or remove the row.
Changing a role
Click the role dropdown on any non-self row and pick a new value. The change is immediate — the affected user sees their permissions update on their next dashboard page load. Existing sessions are not invalidated (a viewer demoted from admin still holds an active cookie; they just can't act on it anymore).
You cannot change your own role. The dropdown is disabled on the row matching your user id. Ask another admin to do it, or — if you're the only admin and want to step down — invite a new admin first, then have them demote you.
Removing a user
Click Remove. The user's sessions are invalidated immediately (their dv_dash cookie stops working), their API keys keep working (revoke them separately on /keys if needed), and their dashboard access is gone. The row drops off the team list.
You cannot remove yourself. Same reason as the role dropdown — if you're leaving, an admin teammate handles it.
The removal is recorded in the audit log under the admin who performed it.
Self-protection guardrails (summary)
| Action | On your own row | On the last-admin row |
|---|---|---|
| Change role | Disabled (greyed out) | Disabled (greyed out — applies to anyone, including the last-admin's own row) |
| Remove | Disabled (greyed out) | Disabled (greyed out) |
The same guardrails apply at the API layer — a hand-crafted DELETE against your own user id returns a 403 with error.type = "cannot_modify_self", and removing the last admin returns 422 with error.type = "would_orphan_tenant".
Last login
The team list shows the last time each user signed into the dashboard. Useful for credential hygiene — a user who hasn't logged in for 90 days is a credible removal candidate.