The problem
EMS is a corporate expense-management system sold to many enterprises at once. Each one wants a different shape of access, and some permissions only make sense together with others. Role checks hard-coded screen by screen drift apart the moment a new screen ships.
The approach
The permission catalog lives in the database, not in code, and an enterprise can switch individual permissions off for itself.
Permissions declare their dependencies. Granting one auto-grants what it needs, transitively; downgrading a permission that others depend on is blocked instead of silently leaving a broken role behind.
The admin side has role, assignment and matrix screens — the matrix drawn as a tree by dependency — plus a "view as user" screen to see exactly what someone else sees.
On the frontend, route guarding and the sidebar both read from one shared
ROUTE_ACCESS table, so a page cannot be reachable while its menu entry is
hidden, or the other way round. Individual buttons are guarded through a
useCan hook rather than ad-hoc checks.
The result
About 5,490 frontend tests green. A permission map covering roughly 300 endpoints is prepared for backend enforcement — written down and ready, so switching the server side on is a deliberate step rather than a rewrite.