Access rules are often introduced as a list of job titles: cashier, supervisor, manager, administrator. The list is only the vocabulary. The real security question is whether this person may do this action to this record, in this organization, right now. A hidden button can make a screen easier to use, but it cannot make that decision safely on its own.
Start with the action
Write down the actions people perform before you create roles. Looking at a record, exporting it, approving it, changing it and deleting it are all different permissions. A role should be a named bundle of those permissions, not a shortcut that quietly grants every action in a whole area.
- Name actions as verbs: view, create, edit, approve, export or delete.
- Keep sensitive actions separate. Permission to view a payment is not permission to refund it.
- Write down which roles need each action and why, including actions that nobody should perform.
Check whose record it is before checking the action
In a system that serves several organizations, permission to edit an invoice is not enough. The invoice must also belong to an organization the person is allowed into. Look up the record behind the scenes, check whose it is, and then check the action. Never trust an organization or record number just because it arrived in a web address or a form.
In plain terms, every decision has two parts, and both must be clear: is this record within the person's area, and is this action one their role allows? Only when both answers are yes should the action go ahead. Real systems also look at the record's current state and any rule specific to the action, but these two parts are the foundation.
Check at every door, not only the front one
The system must check access everywhere protected information can be read or changed: every request, every automatic task, every export and every administration tool. A screen can hide a button that is not available, to reduce confusion, but a direct request must face exactly the same check. Otherwise someone can skip the screen and ask the system for what they want directly.
Test the refusals too
A table of who may do what is a useful design document, but it does not prove the system follows it. Turn the table into tests of what should be allowed and what should be refused. Include a person from another organization, a request from someone not signed in, a role that has since been changed, and a record whose state no longer permits the action. The tests should go through the same checks a real request goes through.
The refusals matter because access failures usually come from a missing check, or a lookup that used the wrong area. A test showing that one manager can approve an item does not show that a cashier, someone from another organization, or someone whose session has expired cannot.
Make decisions explainable
For sensitive actions, record enough to answer: who acted, what they asked to do, which record was involved, when the decision happened and whether it was allowed. Keep passwords and secrets out of that record. A record of who did what should help someone explain a decision without exposing information that is not needed for the explanation.
- List the information and actions the system protects.
- Give each role only the actions it needs.
- Include whose record it is, as well as the action, in every check behind the scenes.
- Test both permitted and refused requests automatically.
- Review changes to access and sensitive decisions through a proper record of who did what.
Roles help people understand a system. Rules checked behind the scenes are what protect it. Keeping those two jobs separate makes access easier to review, test and change as the work changes.