Team and roles
Invite colleagues with their own logins, each with a role that controls what they can do.
A reseller account used to have exactly one login, the owner's. A finance person and two support staff who shared that password had no way to tell who did what, and no way to lose access without changing it for everyone. Team members fix that: every colleague gets their own login and a role that limits what it can do.
Roles
Five roles cover a reseller's team, fixed for now; a colleague holds exactly one. Owner and admin can do nearly everything — managing colleagues is the one thing left to owners alone. Finance holds the wallet, invoices, price lists and sales, and can see everything else. Support handles the day-to-day work — customers, orders, domains, numbers and licences — with no access to money or API keys. Read-only can see everything a colleague can see and change nothing. The full list is in the permission table below.
Inviting a colleague
From Settings → Team, Invite a colleague sends an email with a role attached.
- The invitation expires after 7 days. An owner or admin can revoke it at any time before it is accepted, and can send a new one once it has expired or been revoked.
- The invitee follows the link in the email and sets their own password there; nobody else ever sees it.
- A colleague's role can be changed, and the colleague removed, from the same page.
The last owner
An account always has at least one owner. The API refuses to demote or remove the last owner, whatever role change or removal is attempted, so an account can never end up with nobody able to manage it.
API keys are the account's, not a person's
API keys are unchanged by this: a key belongs to the account, not to whoever created it, and keeps the access it always had. Creating or revoking a key is restricted to the owner and admin roles, same as before — a finance, support or read-only colleague can see keys exist (where their role permits) but cannot mint or revoke one.
Enforced by the API
Roles are not a dashboard-only convenience. Every cookie-authenticated route checks the member's role against one table in the API, so a colleague who finds a way to call a route their role does not cover still gets:
{ "error": "insufficient_role" }with an HTTP 403, regardless of what the dashboard shows or hides.
Removing someone
Removing a colleague ends their sessions immediately — they are signed out everywhere, not just left to expire naturally.
The permission table
Generated from apps/api/src/permissions.ts by pnpm --filter @rhq/api roles-table, so this
table and the code that enforces it can never drift apart.
- owner — Everything, including colleagues and closing the account.
- admin — Everything except inviting, changing or removing colleagues.
- finance — The wallet, invoices, price lists and sales. Read-only elsewhere.
- support — Customers, orders, domains, numbers and licences. No money, no API keys.
- read-only — Can see everything a colleague can see, and change nothing.
| Permission | What it allows | owner | admin | finance | support | read-only |
|---|---|---|---|---|---|---|
account.read | See the account, its products and its billing details | ✓ | ✓ | ✓ | ✓ | ✓ |
account.manage | Change billing details and the default registrant | ✓ | ✓ | ✓ | ||
wallet.read | See the wallet balance and its transactions | ✓ | ✓ | ✓ | ✓ | |
customer.read | See customers and their contacts | ✓ | ✓ | ✓ | ✓ | ✓ |
customer.manage | Add and edit customers | ✓ | ✓ | ✓ | ||
order.read | See orders | ✓ | ✓ | ✓ | ✓ | ✓ |
product.read | See what is on offer, and the numbers, domains and licences you hold | ✓ | ✓ | ✓ | ✓ | ✓ |
number.manage | Buy, change, renew and cancel phone numbers | ✓ | ✓ | ✓ | ||
domain.manage | Register, change and renew domains | ✓ | ✓ | ✓ | ||
licence.manage | Buy, change and cancel mailbox licences | ✓ | ✓ | ✓ | ||
pricing.read | See price lists, contract prices and quotes | ✓ | ✓ | ✓ | ✓ | |
pricing.manage | Create and change price lists and contract prices | ✓ | ✓ | ✓ | ||
sale.read | See sales and their summary | ✓ | ✓ | ✓ | ✓ | |
invoice.read | See invoices and what a customer owes | ✓ | ✓ | ✓ | ✓ | |
invoice.manage | Raise, pay, void and share invoices, and run billing | ✓ | ✓ | ✓ | ||
webhook.read | See webhook endpoints | ✓ | ✓ | ✓ | ✓ | ✓ |
webhook.manage | Add and remove webhook endpoints | ✓ | ✓ | |||
apikey.read | See API keys | ✓ | ✓ | |||
apikey.manage | Create and revoke API keys | ✓ | ✓ | |||
sandbox.use | Top up the sandbox wallet and simulate test traffic | ✓ | ✓ | ✓ | ✓ | |
team.read | See colleagues and pending invitations | ✓ | ✓ | ✓ | ✓ | ✓ |
team.manage | Invite, change the role of and remove colleagues | ✓ |