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
    Recipes

    Temporal Access

    Rules with validity windows and automatic expiry.

    Situation. A locum physician joins Clinique Valmont Nord for the summer. Separately, an external firm audits invoices during one week in September. Both accesses must switch themselves off, with nobody remembering to revoke.

    Assumes the shared Valmont setup.

    Rules carry their own validity window

    Every rule store has valid_from and valid_until:

    INSERT INTO morbac.rules
        (org_id, role_id, activity, view, context_id, modality, valid_from, valid_until)
    SELECT o.id, r.id, 'read', 'patients',
           (SELECT id FROM morbac.contexts WHERE name = 'always'), 'permission',
           '2026-07-01 00:00+02', '2026-09-01 00:00+02'
    FROM morbac.orgs o JOIN morbac.roles r ON r.org_id = o.id AND r.name = 'physician'
    WHERE o.name = 'Clinique Valmont Nord'
    ON CONFLICT DO NOTHING;

    A BEFORE trigger maintains the is_active column on write, and morbac.is_rule_valid(valid_from, valid_until) is re-evaluated inside every uncached decision. Expiry is therefore exact at read time: no cron job, no sweeper, no risk of a forgotten grant.

    SELECT id, is_active, valid_from, valid_until FROM morbac.rules
    WHERE view = 'patients' AND valid_until IS NOT NULL;

    The one-week audit

    The same columns exist on cross_org_rules and user_rules, which is the natural fit for an external auditor who has no role at Valmont:

    INSERT INTO morbac.user_rules
        (user_id, org_id, activity, view, context_id, modality, valid_from, valid_until)
    SELECT '77777777-7777-4777-8777-777777777777', o.id, 'read', 'invoices',
           (SELECT id FROM morbac.contexts WHERE name = 'always'), 'permission',
           '2026-09-07 00:00+02', '2026-09-14 00:00+02'
    FROM morbac.orgs o WHERE o.name = 'Clinique Valmont Nord'
    ON CONFLICT DO NOTHING;

    Before and after that week the row is inert; during it, access is exactly read on invoices in one org.

    Temporal delegation

    For handing over an existing role rather than granting a new capability, use a delegation: it is time-bounded in the same way and stays tied to the delegator's own grant.

    Windows versus contexts

    NeedUse
    fixed calendar intervalvalid_from / valid_until
    recurring or computed condition (office hours, on-call shift)context

    Recurring rules belong in a context evaluator, because a validity window is a single interval, not a schedule.

    Caching caveat

    The decision cache has a TTL (300 seconds by default). A grant that expires mid-TTL can survive in cache until the entry ages out. Lower cache_ttl_seconds if your windows must close to the second, or flush explicitly at the boundary:

    SELECT morbac.invalidate_cache();

    Reviewing what is about to change

    SELECT 'rule' AS kind, id, activity, view, valid_until FROM morbac.rules
    WHERE valid_until IS NOT NULL AND valid_until > now()
    UNION ALL
    SELECT 'user_rule', id, activity, view, valid_until FROM morbac.user_rules
    WHERE valid_until IS NOT NULL AND valid_until > now()
    ORDER BY valid_until;
    PreviousObligations & RecommendationsNext Fastify
    pgmorbac - Multi-OrBAC permission engine for PostgreSQL
    DocumentationDownloadGitea