RBAC across 10+ roles without a permissions mess
How module-scoped permissions kept an admin panel maintainable as roles multiplied.
1 min read#full-stack#auth#react
SealMyIdea's admin panel started with three roles. It now has more than ten, spread across a 1000+ user base, and the permission model still hasn't turned into spaghetti — because we scoped permissions to modules, not to roles.
Roles are just named bundles
Instead of writing if (role === 'finance_admin') checks scattered through the codebase, every permission check asks "can this user perform this action in this module?" A role is nothing more than a named bundle of module-scoped permissions. Adding a new role means composing existing permission bundles, not writing new conditional logic.
Route middleware, not component-level checks
Permission checks happen once, at the route middleware layer, not re-implemented in every component that happens to render a sensitive button. The UI reads the same permission set to decide what to show — one source of truth, checked server-side and mirrored client-side for UX, never the other way around.
Where it still gets hard
Module-scoped permissions handle "can you see this" cleanly. They handle "can you see this specific record" (row-level authorization) less cleanly — that still needs explicit checks per resource. The next iteration folds row-level rules into the same permission bundle format instead of leaving them as one-off checks in route handlers.