Skip to main content
CYPEX Documentation
Support
v2.0.0 Latest stable release View changelog ->

Capabilities vs data scope (admin UI)

5 min read
Info
This page is the admin-panel walkthrough: where each dimension lives in the GUI, and how they combine at query time. For the full conceptual write-up (JWT claims, RLS SQL, the roleType API contract), see Capabilities vs Data Scope under Organizations.

The v2.0.0 access model has two independent dimensions. A request only returns rows when both agree:

DimensionQuestion answeredWhere it’s configured
CapabilitiesWhat is this user allowed to do?PostgreSQL role grants (SELECT/INSERT/UPDATE/DELETE, EXECUTE)
Data ScopeWhich rows is this user allowed to act on?Organization assignment + Row-Level Security

A role with broad capabilities but no organization mapped sees no tenant rows. A role mapped to an organization but with read-only capabilities sees all of that organization’s rows but can’t change them. Neither dimension substitutes for the other.

Capabilities UI: role → PostgreSQL role mapping

Capabilities are configured on Roles & Capabilities, under Role Details:

Role Details — Role Attributes

PostgreSQL role attributes (Superuser, Can Login, Create Roles, Create Databases, …) define what this role can do at the database level.

PostgreSQL role attributes (Superuser, Can Login, Create Roles, Create Databases, …) define what this role can do at the database level.

Role Details — Capabilities

Schema-level permissions (e.g. eshop: USAGE). Object-level permissions on views, functions, and state transitions are assigned separately; review the resolved outcome on the Access Preview page.

Schema-level permissions (e.g. eshop: USAGE). Object-level permissions on views, functions, and state transitions are assigned separately; review the resolved outcome on the Access Preview page.

Data Scope UI: role → organization visibility

Data Scope is configured on the same Role Details panel, under the Organizations tab, and at role-creation time:

Role Details — Organizations

Organization Boundaries: users holding this role can only access data within the organizations assigned here.

Organization Boundaries: users holding this role can only access data within the organizations assigned here.

Create Role — Organization Assignments

For Organization Administrator and Organization Member role types, at least one organization must be assigned here before the role can be saved.

For Organization Administrator and Organization Member role types, at least one organization must be assigned here before the role can be saved.

A role with capabilities but zero organizations assigned is flagged No Scope in the role list — see Roles & Capabilities — User-Defined Roles.

How they combine at query time

flowchart LR
    req["Incoming request<br/>role + org_id claim"]
    cap{"Capability check<br/>PostgreSQL role grant"}
    scope{"Data Scope check<br/>RLS policy on org_id"}
    deny["No rows / operation denied"]
    allow["Rows returned"]

    req --> cap
    cap -->|"denied"| deny
    cap -->|"allowed"| scope
    scope -->|"no match"| deny
    scope -->|"match"| allow

Both checks run on every request. Capabilities are enforced by the PostgreSQL role the session runs as; Data Scope is enforced by RLS policies keyed on the org_id JWT claim (wired by the v2.0.0 upgrade’s Organizations migrations). Neither layer knows about the other — that separation is intentional, so granting a capability and assigning an organization remain independent operations.

Capability × Data Scope matrix

No organization assignedAssigned to Org A onlyAssigned to Org A + Org B
Organization Member (cypex_user)No rows visible (No Scope)SELECT-only, Org A rowsSELECT-only, Org A + Org B rows
Organization AdministratorNo rows visible (No Scope)Full CRUD, Org A rowsFull CRUD, Org A + Org B rows
System Administrator (cypex_admin)Full CRUD, all organizations — every policy admits the role via cypex.is_admin(); organization assignment doesn’t applysamesame

Every capability or data-scope change — role create/update, capability grant, organization assignment — is written to cypex_log.t_permission_audit_log (action, entity_typerole / organization / view / function / state_transition —, before_state, after_state). It’s queryable via:

GET /admin/audit/permissions
Info
There is no dedicated admin-panel page for this log yet — it’s API-only, filterable by userId, action, entityType, entityId, and date range. See Governance evidence for the full evidence trail (write-path service calls and doc-side approvals).

Contrast with the legacy model

Before Organizations, app rendering in CYPEX was single-dimension: Applications predicts an application for a chosen owner user, and CYPEX renders only the tables, forms, and buttons that user’s role permits — capabilities alone decided the outcome, because there was no separate data-scope concept to layer on top.

v2.0.0 keeps that capability-driven prediction unchanged, but adds Data Scope as a second, independent axis: the same predicted app now also filters rows by the viewing user’s organization membership at query time via RLS. Two users with the identical role see the identical app shape (same capabilities), but different data (different data scope) if they belong to different organizations.

Info
Coming from Oracle APEX? The two security concepts on this page have direct APEX equivalents — useful shorthand if you’re mapping a migrated application’s access model.
Oracle APEX conceptCYPEX equivalent
Authorization SchemePostgreSQL role grant (Capabilities, this page’s first dimension)
Workspace / App GroupOrganization (Data Scope, this page’s second dimension), enforced via RLS instead of an application-level check

APEX evaluates both as PL/SQL conditions inside the application; CYPEX evaluates the same two questions as PostgreSQL role grants and RLS policies at the database layer, so the access rules hold regardless of which client queries the data.

See also