How pgmorbac compares
RBAC, OrBAC, Multi-OrBAC, ABAC, PBAC, ReBAC: what each decides on and where this fits.
Access control models are often presented as competitors. They are better read as a progression: each one adds a dimension the previous could not express.
At a glance
| Model | Decides on | Answers | Strength | Cost |
|---|---|---|---|---|
| ACL | identity per object | "is this user on the list?" | trivial to understand | unmanageable at scale, no structure |
| RBAC | role | "does this role have this permission?" | matches job titles, easy to audit | one flat namespace, no where |
| OrBAC | organization + role + activity + view + context | "in this organization, may this role do this here and now?" | abstraction and context, policy separated from implementation | more concepts to learn |
| Multi-OrBAC | the above, across an organization tree | "and what about subsidiaries, delegation and cross-org access?" | native multi-tenancy and hierarchy | needs a real engine |
| ABAC | arbitrary attributes | "do the attributes satisfy the policy?" | maximum expressiveness | hard to audit, hard to answer "who can do X?" |
| PBAC | centrally authored policies | "what does the policy engine say?" | governance and central control | usually a separate service to run |
| ReBAC | relationships in a graph | "is there a path from user to object?" | natural for sharing and ownership graphs | graph queries, harder to reason about statically |
Capability by capability
No model wins every row. Each was designed around a different question, so the honest comparison is about fit: what is native, what is reachable with extra work, and what a model was simply never meant to do.
| Capability | RBAC | OrBAC | ABAC | PBAC | ReBAC | Multi-OrBAC |
|---|---|---|---|---|---|---|
Roles as the primary grant | yes | yes | partial | partial | partial | yes |
Organization as a first-class dimension rules attached to an org, not just a role | no | yes | partial | partial | partial | yes |
Organization hierarchy / subtree scope one rule covering a whole branch of the tree | no | partial | no | partial | partial | yes |
Decisions from arbitrary attributes time of day, request risk, resource labels | no | partial | yes | yes | no | partial |
Relationship / graph reasoning "shared with people you follow" | no | no | partial | partial | yes | partial |
Explicit deny that overrides allow | no | yes | yes | yes | partial | yes |
Separation of duty & role limits | yes | yes | partial | partial | no | yes |
Time-bounded grants & delegation | no | partial | partial | partial | partial | yes |
Central, auditable policy answer "who can do X?" statically | yes | yes | no | yes | partial | yes |
Runs without a separate service | partial | partial | no | no | no | yes |
pgmorbac is strong where the decision is organizational and belongs in the database. It is not the sharpest tool for attribute-driven decisions (an ABAC engine is) or for deep relationship graphs (ReBAC is), and it can reach into both only with extra machinery. Pick the row that matters most to you.
Where pgmorbac sits
pgmorbac implements Multi-OrBAC, and deliberately borrows from its neighbours:
- From RBAC: roles, role hierarchy, separation of duty and cardinality constraints. Anyone who knows RBAC is already productive.
- From OrBAC: the organization as a first-class dimension, abstract activities and views, contexts, and four deontic modalities (permission, prohibition, obligation, recommendation).
- From ABAC: context evaluators are arbitrary SQL predicates, so attributes of the user, the time or the environment can gate a rule.
- From ReBAC: derived roles compute membership from your own relational data, so "head of this department" is a query, not an assignment.
- From PBAC: policy lives in one place with a single decision function, except that place is your database rather than a separate service.
Concretely: the same requirement in each model
"Nurses may read patient records at Clinique Valmont Nord and its departments, but never at Clinique Valmont Sud."
| Model | What you write |
|---|---|
| RBAC | a distinct role per site (nurse-north, nurse-south), duplicated for every new site |
| OrBAC | a rule per site: role nurse may read patients at that org, repeated for each hospital and department |
| ABAC | a policy comparing a site attribute on the user with one on the record, plus attribute plumbing everywhere |
| PBAC | a central policy document enumerating site membership, evaluated by a separate decision service |
| ReBAC | a member-of edge per user and site, plus a traversal rule |
| Multi-OrBAC | one rule: role nurse, activity read, view patients, org Clinique Valmont Nord, scope subtree |
The Multi-OrBAC version covers departments created next year with no further writes, and the isolation from Sud needs no rule at all: the absence of a grant is the isolation.
When pgmorbac is not the right tool
Be honest about the fit:
- Single-tenant with three roles and no hierarchy. Plain RBAC in your application is simpler and enough.
- Decisions driven mostly by request attributes (IP ranges, device posture, risk score) rather than organizational structure. A dedicated ABAC or PBAC engine fits better; you can still keep pgmorbac for the organizational half.
- Deeply relational sharing ("users can see documents shared with people they follow"). That is ReBAC's home ground.
- Data lives outside PostgreSQL. pgmorbac decides inside the database; if the database is not in the request path, its main advantage disappears.
Why in the database at all
Most engines answer in the application layer, which leaves every query one forgotten check away from a leak. pgmorbac's decisions are reachable from SQL, so row-level security policies enforce them per row for every client that connects, including psql and analytics tools. That is the argument in one line: the last line of defence should be the layer nothing bypasses.