Every morbac helper function alongside is_allowed: org traversal, roles, cache, audit, config.
morbac.is_allowed is the front door, but it is built on a family of helper
functions you can call directly, whether to compose your own checks, to debug
a decision, or to drive an admin UI. Every function lives in the morbac
schema.
Decision
Function
Returns
Purpose
is_allowed(user, org, activity, view)
boolean
The cached decision. The one you call in normal use. org is a specific organization, or NULL when the object is unattributed.
is_allowed_nocache(user, org, activity, view)
boolean
The same decision computed from scratch, for debugging.
has_permission(user, activity, view)
boolean
Capability probe: is the user allowed anywhere at all. For gating UI, not for authorizing an object.
rls_check(activity, view)
boolean
Row-level-security entry point for tables with no org column; reads session context.
rls_check(activity, view, row_org[, row_user])
boolean
Row-scoped entry point. row_org NULL means the record is unattributed. See row-level security.
is_rule_valid(valid_from, valid_until)
boolean
Whether a validity window covers now. The temporal test every store applies.
Organizations
Function
Returns
Purpose
get_org_ancestors(org)
rows of (org_id, depth)
The org and every ancestor.
get_org_descendants(org)
rows of (org_id, depth)
The org and every descendant.
get_org_scope(org, scope, max_depth)
rows of (org_id, depth)
A named slice of the tree: self, children, descendants, subtree, parent, ancestors, lineage, root, plus all (every org) and unattributed (no rows, since no-org is not an org).
org_in_scope(asked, rule_org, scope)
boolean
Whether a rule at rule_org with scope covers asked. asked NULL is covered only by unattributed and all.
Roles
Function
Returns
Purpose
get_comprehensive_roles(user, org)
rows of (role_id, source, depth)
Every effective role: direct, delegated, derived, inherited.
get_effective_roles(user, org)
rows of (role_id, depth)
Direct plus inherited roles.
get_inherited_roles(role)
role ids
Roles a given role inherits through the hierarchy.
user_roles_in_org(user, org)
role ids
The user's directly assigned roles in an org.
user_has_role(user, org, role_name)
boolean
A quick membership check.
assign_role(user, role, org)
void
Assign a role, enforcing separation of duty and cardinality.
revoke_role(user, role, org)
void
Remove a role assignment.
Activities and views
Function
Returns
Purpose
get_effective_activities(activity)
activity names
The activity plus every senior activity that implies it.
Rules that the given tuple would permanently override, by modality precedence. Only rules sharing the same scope compete, since different scopes target different records. A trigger reports these as warnings on write.
get_config(key) / set_config(key, value)
text / void
Read or change runtime settings such as cache_ttl_seconds and schema_version.
All of these are plain SQL functions: call them from any language, or from
psql, exactly like is_allowed.
The schema also defines trigger functions the engine wires up itself:
rules_set_is_active, global_rules_set_is_active, invalidate_cache_on_*,
refresh_on_hierarchy_change, trg_check_activity_view_binding,
trg_warn_rule_conflicts, raise_if_system_principal*, audit_trigger, plus
the evaluators context_always and eval_derived_role. They are not part of
the API you call; they are listed here so an unexpected name in a stack trace or
an EXPLAIN is identifiable.