Skip to content
PlatformPricingCreditsRolesIntegrationsSecurityAccount
Guides

Role-Based Access Control for Agencies: Why Three Roles Is Never Enough

· 11 min read · Updated 29 August 2026

Role-based access control assigns permissions to named roles rather than to individuals. Most business tools ship three roles — admin, member, read-only — which cannot express an agency where a cold caller, a closer, a media buyer and a bookkeeper each need a genuinely different view. The decisive question is not how many roles exist but where the check runs: a permission enforced only in the interface is a hidden button, not access control.

Short answer. RBAC assigns permissions to roles, then people to roles. Most tools ship three — admin, member, read-only — which cannot describe an agency. But the count is the less important half. The question that decides whether your permissions are real is where the check runs: in the interface, or in the database.

Why three roles collapses

Picture a fifteen-person agency. There is a cold caller working a list, an appointment setter qualifying replies, two closers with their own books, a head of sales who needs the whole pipeline, a media buyer running paid campaigns, a content manager, a bookkeeper, and an owner.

Now map that onto admin / member / read-only.

The owner is admin. The bookkeeper cannot be read-only, because they have to raise invoices, so they become admin too — and can now see every call recording and change anyone’s permissions. The cold caller is a member, which means they can see the full pipeline including deal values and every other closer’s accounts. The media buyer is also a member, so they can see commission figures that have nothing to do with them.

Nobody chose any of that. It is what happens when a three-role model meets an eight-job organisation: everyone is either over-privileged or blocked, and the usual resolution is to make more people admins.

The specific risks

  • Salary and commission visibility. Commission figures reveal what colleagues earn. This is the one that causes actual arguments.
  • Client list exposure. A member-level account that can export every client and contact is the standard way a client list leaves with a departing employee.
  • Call recordings. Frequently contain personal data and were recorded under a specific stated purpose. “Anyone with a login” is not that purpose.
  • Accidental edits. Over-privileged accounts break things without malice. Most permission incidents are ordinary mistakes, not attacks.

Least privilege, in practice

The principle is simple: each person gets exactly the access their job requires, and nothing else. Applying it is less simple, because it requires describing the jobs honestly rather than sorting people into seniority tiers.

Three questions define a role properly:

  1. What records? Their own, their team’s, their department’s, or the whole organisation. This is the scope axis, and it is the one most tools omit entirely.
  2. What actions? Read, create, edit, delete, export. Export deserves to be separate: reading one record is not the same as taking all of them.
  3. Which surfaces? Pipeline, calls, finance, ads, settings. A media buyer needs deep access to ads and none to finance.

Scope is what three-role systems get wrong most often. Admin and member describe power, not reach. Two closers doing identical work need identical permissions over different records, and a model with no scope axis cannot express that at all.

Where the check runs

This is the part that separates a permission system from a permission-shaped interface, and it is worth being blunt about.

Hiding a button is not access control

Plenty of systems implement permissions by rendering the interface differently: the cold caller does not see a Finance tab, so the assumption is they cannot reach finance data. But the data is still there, behind a request the browser knows how to make. Anyone who opens developer tools, or an API client, or simply guesses a URL, is not stopped by a hidden button.

The test is easy to run in a demo: create a restricted account, then try to reach a forbidden record directly. If it loads, the permissions are decoration.

Enforcement in the database

The robust version puts the rule where the data is. Row-level security means the database itself filters what a query can return, based on who is asking. A cold caller querying deals gets back only the rows their role permits — not because the application remembered to filter, but because the database will not return anything else.

The reason this matters is coverage. An application-layer check protects the one code path it was written into. A database-layer rule covers every path to that data: the main app, a CSV export, an API integration, a background job, a report someone builds later. New features inherit the rule automatically instead of needing to remember it.

Step-up authentication

Some actions deserve more than a role check, because their blast radius is large and their reversal is hard: exporting the full client database, changing someone else’s permissions, viewing complete financial records.

Step-up authentication asks for a second factor at the moment of the action rather than only at login. It closes the gap where a session left open on an unlocked laptop inherits every permission the owner has. The cost is one extra prompt on a handful of actions per month, which is a trade almost everyone accepts once it is explained.

The audit trail

Permissions decide what can happen. An audit trail records what did. Without one, the answer to “who changed this deal value” is a guess, and a permission system you cannot verify is a permission system you are trusting on faith.

A trail worth having records who, what, when, and the values on both sides of a change — and cannot be edited by the people it logs.

Designing roles without over-engineering

The failure mode in the other direction is real too: fifty bespoke roles nobody can reason about, each created for one person, none documented. A workable process:

  1. List the jobs, not the people. Roles describe functions. If a role only ever fits one individual, it is probably a person-shaped exception rather than a role.
  2. Write the sentence. For each job: “A closer sees their own deals, their own commission, and the calls attached to their accounts.” If the sentence is hard to write, the role is not yet understood.
  3. Start restrictive. Adding access on request is a two-minute conversation. Removing it after someone has had it for six months is a political one.
  4. Review on change. Promotions and departures are when permissions drift. A leaver’s access should end the same day, not the same quarter.

How Openbiznis approaches it

Openbiznis ships 13 active roles for distinct jobs across sales, finance, client success and operations: cold caller, appointment setter, closer, head of sales, accountant, CFO, account manager and more. Each has a real scope — own records, team, department, or organisation — rather than a power tier.

Every one of those permissions is enforced in the database with row-level security, not in the interface. Sensitive actions require step-up MFA, and the audit trail is append-only. The practical result is that a cold caller’s account cannot reach the finance data by any route, including ones that did not exist when the role was written.

The security posture is identical on every plan, including the $37 tier. There is no security upsell here, which is a deliberate decision rather than an oversight — the full description is on the security page.

Frequently asked questions

What is role-based access control?
Role-based access control (RBAC) grants permissions to roles rather than to individual people, and then assigns people to roles. Changing what a job can do means editing one role instead of auditing every account, which is what makes permissions maintainable as a team grows.
Why are three roles not enough for an agency?
Because an agency has more than three jobs. A cold caller needs a call list but not the pipeline. A closer needs their own book but not everyone's. A media buyer needs ad spend but not commission. A bookkeeper needs invoices but not call recordings. Admin, member and read-only force most of those people into one bucket that is either too permissive or unusable.
What is the difference between hiding a button and enforcing a permission?
Hiding a button removes an option from the interface while leaving the underlying data reachable by anyone who can make a direct request. Enforcing a permission means the server or database refuses the request regardless of what the interface showed. Only the second is access control; the first is presentation.
What is row-level security?
Row-level security applies access rules in the database itself, so a query returns only the rows the requesting user is entitled to see. Because the rule lives with the data rather than in application code, every path to that data — the app, an export, an API call, a background job — is covered by the same rule.
What is step-up authentication and when should it be required?
Step-up authentication asks for a second factor at the moment a sensitive action is attempted, rather than only at login. It is appropriate for actions that are hard to reverse or that expose the whole workspace: exporting the client database, changing another user's role, or viewing full financial records.