Journal / Security, Auth, and Compliance

Security, Auth, and Compliance

The Permission System That Scales With Your B2B Customers

A B2B permission system that scales requires a layered model: system roles, organization roles, and resource level permissions. Flat role lists collapse under enterprise requirements. I build these with RBAC as the baseline, ABAC for attribute driven rules, and a clear separation between platform level and customer configurable permissions. That combination handles the first customer and the fiftieth without a rewrite.

What you actually need to know

  • Flat role systems break at the first enterprise customer who needs custom roles. Build a role and permission join from the start.
  • Multi org context is not optional. Every permission check must carry user ID, org ID, and resource.
  • RBAC handles 80 percent of B2B use cases. ABAC is the layer for attribute driven rules that enterprise contracts demand.
  • Customer configurable roles need a boundary. Customers customize within what you define, not outside it.
  • Audit logs on every permission change are the difference between passing and failing a vendor security review.
  • In my experience, the teams that get permission systems right write down the data model before the first line of code.
Approach Flexibility Complexity Best for
Flat roles (admin/member/viewer) Low Low Early stage, single product
RBAC with join table Medium Medium Most B2B SaaS at scale
ABAC with attribute rules High High Regulated industries, enterprise contracts
ReBAC (relationship based) Very high Very high Graph structured data, document hierarchies

The core argument

The permission system is the product feature that gets the least love and causes the most enterprise sales friction. Every founder I talk to has a version of this story: a mid market deal was moving until the security questionnaire asked about custom roles. The current system has three hard coded roles. The buyer needs seven. The deal pauses. The team scrambles. The rearchitecture takes a quarter.

The reason this happens is that most early permission systems are built for the first customer, not the tenth. Three roles is a fine start. The mistake is the data model underneath. If permissions are if statements on role strings scattered across the codebase, adding a fourth role means touching every one of those statements. If permissions are rows in a join table between roles and permission constants, adding a fourth role is one database insert.

The second thing that breaks is the multi org model. Early B2B apps often store a single role per user. The user is an admin or they are not. Then the first customer wants a user to be an admin in their account and a read only viewer in a partner account. Now the data model needs an org context column on the role, which means the permission check needs to carry that context on every request.

Both of these problems have the same fix: a principled data model written before the first enterprise conversation. Role and permission joins. Org scoped assignments. Deny by default. This is not over engineering. It is the minimum viable permission architecture for anything that will talk to enterprise buyers.

The data model that actually scales

The core tables

Three tables handle most B2B permission needs. A permissions table enumerating every named permission in the system. A roles table with platform defined and customer defined roles. A role permissions join table connecting the two. A user org roles table assigning a user to a role within an org context.

The permissions table is the authority. It lists every permission as a constant string, something like reports:export or users:invite. No permissions exist that are not in this table. This is what makes audit logging complete and what makes security reviews tractable.

Platform roles versus customer roles

Platform roles are defined by you and cannot be modified by customers. They cover the cases every org needs: org admin, billing contact, read only viewer. Customer roles are scopes that the org admin can define within the permission set you expose. The org admin can create a role called "Regional Manager" and assign it reports:export and users:view. They cannot assign it billing:manage if you have not surfaced that permission for customer configurable roles.

This boundary is the important part. Enterprise buyers want flexibility. They do not want to break their own data. The boundary protects both of you.

ABAC for the rules you cannot express in roles

Some enterprise requirements cannot be expressed in a role. "Only users with department=Finance can export revenue reports." That is an attribute rule, not a role. ABAC adds an attribute evaluation layer on top of the RBAC base. The check becomes: does this user have the reports:export permission via their role, and do their attributes satisfy the policy attached to this resource?

I build this as a policy engine that evaluates at request time. Simple policies can live in a database table. Complex policies warrant a dedicated service or a library like Open Policy Agent.

What it requires

Requirement Without it With it
Role permission join table Roles are hard coded strings Adding roles is one insert
Org scoped user role assignments Users have one global role Multi org memberships work correctly
Permission constants table Permissions exist implicitly Audit log is complete and queryable
Customer role configuration UI Every new role needs an engineer Enterprise admins manage their own access
Audit log on permission changes Incidents are unrecoverable Vendor security reviews are passable

What to look for in a permission system implementation

  • A deny by default posture. Explicit grants only.
  • Permission constants defined in one authoritative place, not scattered as strings.
  • Org context on every permission check. No global user level permissions for resource access.
  • A customer role configuration interface that exposes only the permissions you intend to expose.
  • Audit log rows for every permission grant and revoke. Immutable, with actor and timestamp.
  • A test harness that exercises the permission model on every deploy. Silent regressions in auth are dangerous.
  • A clear escalation path for permission errors. Users should see a clear "access denied" with a path to request access, not a generic 500.

Expert opinion

The teams that build scalable B2B permission systems in the first sprint rarely regret it. The teams that defer it to "when we get an enterprise customer" are rebuilding it under a sales deadline, which is the worst possible time to redesign a data model. The data model cost is one sprint. The rearchitecture cost under pressure is two to four quarters of distraction.

Yashveer Singh, founder of Yashveer Labs

How this played out on a real project

A client came to me mid deal with a manufacturing enterprise. Their permission model was three enum values on a users table. The enterprise buyer needed department scoped permissions, a read only auditor role, and a custom export role for compliance staff. None of that was possible without a rewrite.

We shipped the new data model in six weeks. Role and permission joins, org scoped assignments, a customer role configuration page, and an audit log. The deal closed. The model has handled four more enterprise customers without modification since then.

The first thing we did was write the permission constants to a table. Forty three constants covering every action in the product. That table became the source of truth for the customer configuration UI, the audit log, and the test harness. The rest followed from that one decision.

For the related auth layer, see API authentication in 2026 for how authentication feeds into permission checks, and the user impersonation feature building it securely for the specific case of admin impersonation inside a B2B permission model. The compliance frame for what enterprise buyers actually ask is covered in the security gap how one missing SOC 2 control kills your enterprise deal.

Common mistakes

  1. Hard coding role checks as if statements throughout the codebase instead of a centralized permission check.
  2. No org context on permission checks. The user is an admin globally, which breaks multi org memberships.
  3. Customer configurable roles with no permission boundary. The org admin can grant billing access to anyone.
  4. No audit log on permission changes. An incident produces zero forensic evidence.
  5. Permissions as string literals scattered across five files. Changing the constant name becomes a search and replace incident.
  6. Deny by default forgotten. New users get too much access until someone notices.
  7. No test coverage on the permission model. A refactor silently breaks access control.
  8. Building custom ABAC before the RBAC model is stable. Complexity compounds on an unstable foundation.

A 30 day plan

  1. Week one. Write every action in your product to a permissions table. Group by resource type. This is the authoritative list.
  2. Week two. Build the role permission join model. Migrate any existing hard coded role checks to query the join table. Add org context to user role assignments.
  3. Week three. Build the audit log. Every permission grant and revoke writes a row. Add the customer role configuration UI restricted to the permissions you expose.
  4. Week four. Write a test harness that exercises every permission constant. Run it in CI. Pick the next highest risk gap and plan the next sprint.

For deeper reading, the threat model how to build one in two hours covers the broader security posture exercise, and vendor security assessments how to pass them quickly covers what enterprise buyers actually evaluate when they review your access control model.

FAQ

Frequently asked

  • What is the difference between RBAC and ABAC for B2B SaaS permission systems?
  • How do I design a permission system that lets enterprise customers configure their own roles?
  • What causes B2B permission systems to break under enterprise requirements?
  • How should I handle multi organization permissions in a SaaS app?
  • When should I build a custom permission system versus using a third party service like Permit.io or Cerbos?
  • How do I audit who changed a permission in a B2B system?
  • What is the right default permission posture for a new B2B organization account?

Author

The reason I write these

I write these because the writing is the proof. Yashveer Singh, founder of Yashveer Labs. The systems I build are not theoretical. They are running right now, serving real users, generating real revenue. That is the bar I hold this writing to. If you want to hire someone who can match that bar, I am the call.

Start the conversation See the work DM on Instagram