pgmorbacMulti-OrBAC for PostgreSQL
    DocumentationDownloadSource
    Use cases
    • How do I...?
    Getting Started
    • Introduction
    • Quick start
    • How pgmorbac compares
    • Upgrade
    Concepts
    • Organizations
    • Roles
    • Activities
    • Views
    • Contexts
    • Rules & Modalities
    • Global Rules
    • System Principals
    • Constraints
    • Row-Level Security
    • Decision Cache
    Resolution
    • is_allowed
    Recipes
    • Org Hierarchies
    • Multi-Tenant Isolation
    • Wildcard Admin
    • Delegation
    • Service Accounts
    • Deny Rules
    • Separation of Duty
    • Derived Roles
    • Cross-Org Access
    • Obligations & Recommendations
    • Temporal Access
    Integration
    • Fastify
    • PostgREST & RLS Context
    • SQL Only
    Reference
    • Function Reference
    Getting Started

    Introduction

    What pgmorbac is and how Multi-OrBAC models access control.

    pgmorbac implements Multi-OrBAC (Organization-Based Access Control across multiple organizations) entirely inside PostgreSQL. One schema, morbac, holds the model; one function, morbac.is_allowed(user_id, org_id, activity, view), answers every authorization question.

    Why OrBAC instead of plain RBAC

    Role-based access control answers "what can this role do". It has no notion of where: a role is global, so a hospital chain with two sites either duplicates every role per site or gives every physician access to both. OrBAC adds the organization as a first-class dimension: a rule is always Rule(organization, role, activity, view, context, modality).

    Throughout this documentation we follow one running example: the Groupe Hospitalier Valmont, a French hospital network.

    Dr. Camille Rousseau is a physician at Clinique Valmont Nord. That sentence is exactly what pgmorbac stores: a row in morbac.user_roles binding her user id to the physician role in the Clinique Valmont Nord organization. She has no standing in Clinique Valmont Sud, and nothing needs to be written to make that true: absence of a rule means denial.

    The six ingredients

    ConceptTableValmont example
    Organizationmorbac.orgsClinique Valmont Nord, child of Groupe Hospitalier Valmont
    Rolemorbac.rolesphysician (scoped to Clinique Valmont Nord)
    Activitymorbac.activitiesread, prescribe
    Viewmorbac.viewsprescriptions, patients
    Contextmorbac.contextsalways, or a custom on_shift() predicate
    Rulemorbac.rulesphysicians may prescribe on prescriptions in the North subtree

    Activities and views are abstract: prescriptions is a category, not a table. Your application decides what concrete resources map to each view, and row-level security policies enforce the decision per row.

    One call decides

    SELECT morbac.is_allowed(
        '11111111-1111-4111-8111-111111111111',           -- Dr. Camille Rousseau
        (SELECT id FROM morbac.orgs WHERE name = 'Clinique Valmont Nord'),
        'prescribe',
        'prescriptions'
    );

    The engine resolves her effective roles (direct, inherited, delegated, derived), collects applicable prohibitions and permissions across four rule stores (org rules, cross-org rules, user rules, global rules), evaluates contexts and validity windows, and applies priority resolution where ties go to prohibition. The result is cached with a configurable TTL and invalidated automatically on any relevant change.

    Where to go next

    • Install pgmorbac in your database.
    • Work through the Concepts to learn each part of the model.
    • Jump straight to a Recipe if you have a concrete situation to solve.
    Next Quick start
    pgmorbac - Multi-OrBAC permission engine for PostgreSQL
    DocumentationDownloadGitea