Symphony Apps Development logo — teal interlocking S monogram beside the studio wordmark
All writing

Build note: a permissions model that outgrew its first design

A simple role-based system worked for a year, then a client asked for an exception that broke the model. What we replaced it with, and why we waited.

Category
Case notes
Reading time
7 min
Published
10 Jun 2026
Topics
Case study, Architecture, Engineering

Every permissions system is correct for the requirements it was designed against. The interesting failures happen when a genuinely reasonable new requirement does not fit the shape at all.

The original design

Three roles — admin, manager, staff — each with a fixed set of permissions. It matched the client's organisation chart exactly and took an afternoon to build. For a year it needed no changes, which in hindsight should have made us suspicious rather than comfortable.

The request that broke it

A manager wanted to grant one specific staff member access to payroll reports, without promoting them to manager and without giving every staff member that access. Nothing about "admin, manager, staff" has room for an exception scoped to one person and one resource.

Why we did not rebuild immediately

The temptation was to redesign for full generality — arbitrary permissions on arbitrary resources for arbitrary users — the day the first exception appeared. We waited for a second and third request instead, because a permissions model designed around one anecdote tends to be wrong in a different, more expensive way.

What we built once the pattern was clear

  • Roles stayed as the default — most users need nothing more specific and should not have to think about it.
  • Resource-level grants were added as an explicit override, visible in the interface as a specific exception, not hidden in a config table.
  • Every override expires or is reviewed — a grant with no review date is a permission nobody remembers to revoke.

The part that took the longest

Not the schema — the audit trail. Once permissions could be layered, "why does this person have access to this" had to be answerable without reading code, because the client's compliance obligations required it. We built a plain-language log of every grant, who made it, and why, before we shipped the feature that made grants possible.

The expensive part of a flexible permissions model is rarely the flexibility. It is being able to explain, months later, why any given person can see what they can see.

What we would tell ourselves a year earlier

The original three-role system was the right call for the requirements at the time. The mistake would have been building the flexible version pre-emptively, against imagined future requirements rather than the one that actually arrived.

Tell us what you’re trying to ship

A first call is thirty minutes and costs nothing. Bring the problem, not a spec — working out what to build is the part we are good at.

Or email office@symphonyapps.ro. We reply within one business day, in English or Romanian.