How to Design Roles and Permissions Before the UI

Permissions look like a settings problem. They are really a product model—and if that model is vague, every screen inherits the ambiguity.

How to Design Roles and Permissions Before the UI — Troiana insight cover

In short

Design permissions as explicit rules before designing the interface. Define the product's resources and actions, assign permissions to roles, add scope and exceptions, then test the model with real scenarios. The UI should explain and enforce that system; it should never be the system itself.

Start with actions, not job titles

Teams often begin with a familiar list: owner, administrator, manager, member, viewer. The names feel complete because everybody recognizes them. They are not complete until each one answers a harder question: what can this person do, to which resource, and under what conditions?

Write the verbs first. Can someone view a project, create it, edit its settings, invite another person, approve a change, export its data, archive it, or delete it? A role is a named bundle of those permissions. Starting with actions exposes ambiguity that role names hide.

"Manager" might mean someone who can manage work, manage people, manage billing, or all three. Those are materially different products.

Build a permission matrix

Create a table with roles on one axis and actions on the other. Use explicit values—allowed, denied, or conditional—rather than assumptions.

The matrix should include destructive and administrative actions, not only the happy path. Exporting data, changing ownership, removing a teammate, viewing private records, and deleting an account are where vague models become dangerous.

For each conditional permission, record its scope:

  • Own: the person can act only on records they created or own.
  • Team: the person can act within their team or workspace.
  • Assigned: the person can act on records explicitly assigned to them.
  • Organisation: the person can act across the whole account.

Scope is often more important than the role name. Two people may both be editors while one can edit only assigned projects and the other can edit everything in the workspace.

Separate visibility from authority

Hiding a button is useful interface feedback. It is not access control.

The server must validate permission on every request, including requests that never came through the intended interface. Otherwise a person can bypass a hidden control by calling the endpoint directly or changing an identifier. The interface and the backend should read from the same permission model, but the backend makes the final decision.

A good interface still communicates the rule. If someone can see a setting but cannot change it, explain why and who can. If the information itself is sensitive, do not render it at all. Disabled, hidden, and read-only are different product decisions.

Design the denied state

Permission design is incomplete until the denied state is designed.

There are several distinct cases:

  • The action is never available to this role.
  • The action is available, but not for this resource.
  • The action requires approval.
  • The person's access changed while the screen was open.
  • The resource exists, but revealing that fact would disclose sensitive information.

These cases should not all produce "Something went wrong." A useful denial says what cannot happen, why when it is safe to explain, and what the person can do next. That might be requesting access, contacting an owner, switching workspace, or returning to the previous page.

Test scenarios, not only rows

A matrix proves that individual rules exist. Scenarios prove that the rules work together.

Test stories such as: a manager creates a project, transfers ownership, leaves the organisation, and is later invited back as a viewer. Who owns the project now? Can the former manager still reach an old export link? What happens to approvals waiting on them?

Include role changes, removed users, suspended accounts, shared links, archived records, and cross-workspace access. These are the moments when permissions stop being a settings table and become product behaviour.

Default to less access

New roles, new features, and unmatched rules should begin denied. Grant access deliberately once the product can explain why it is needed.

This is safer than trying to predict every future exception, and easier to review. Adding a justified permission is usually straightforward. Discovering that a broad default exposed years of customer data is not.

Primary references

Common questions

Should every product use role-based access control?

No. Simple products may need only an owner and members. Products where access depends on ownership, geography, account tier, record state, or relationships may need attribute- or relationship-based rules alongside roles.

Should unavailable actions be hidden or disabled?

Hide actions a person will never be allowed to use or should not know exist. Disable actions that are normally available but temporarily unavailable, and explain what condition must change.

Where should permissions be enforced?

Enforce them on the server for every request. The interface should reflect the same rules so people receive clear feedback, but hiding interface controls is not a security boundary.

Have something worth building right?