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
    Concepts

    Contexts

    Predicate functions that decide when a rule applies.

    A context is a named predicate that decides when a rule applies. Every rule references exactly one context; the engine calls its evaluator function at decision time and skips the rule when it returns false.

    pgmorbac ships one context, always:

    SELECT name, evaluator FROM morbac.contexts;
    --  always | morbac.context_always

    Writing a custom context

    An evaluator is any zero-argument SQL function returning boolean. Valmont Clinique Valmont Nord wants prescriptions writable only during staffed hours:

    CREATE OR REPLACE FUNCTION app.context_business_hours()
    RETURNS BOOLEAN LANGUAGE sql STABLE AS $$
        SELECT EXTRACT(hour FROM now() AT TIME ZONE 'Europe/Paris') BETWEEN 7 AND 19
    $$;
     
    INSERT INTO morbac.contexts (name, description, evaluator)
    VALUES ('business-hours', 'Staffed hours at Valmont sites',
            'app.context_business_hours'::regproc);

    Attach it to a rule instead of always:

    INSERT INTO morbac.rules (org_id, role_id, activity, view, context_id, modality)
    VALUES (:nord_id, :nurse_id, 'update', 'patients',
            (SELECT id FROM morbac.contexts WHERE name = 'business-hours'),
            'permission');

    Outside 07:00-19:00 the rule simply does not exist as far as is_allowed is concerned.

    Session-dependent contexts

    Evaluators can read the RLS session variables to react to who is asking:

    CREATE OR REPLACE FUNCTION app.context_own_shift()
    RETURNS BOOLEAN LANGUAGE sql STABLE AS $$
        SELECT EXISTS (
            SELECT 1 FROM app.shifts s
            WHERE s.user_id = morbac.current_user_id()
              AND now() BETWEEN s.starts_at AND s.ends_at
        )
    $$;

    Rules for evaluators

    • Keep them STABLE and fast: they run inside every uncached is_allowed call that reaches the rule.
    • They must never write. A context is a question, not an action.
    • Failure semantics are fail-closed: an evaluator returning NULL counts as false.
    • For pure time windows, prefer the built-in valid_from / valid_until columns on the rule itself (temporal access); contexts are for conditions that need logic.
    PreviousViewsNext Rules & Modalities
    pgmorbac - Multi-OrBAC permission engine for PostgreSQL
    DocumentationDownloadGitea