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

Release Notes v2.0.0

18 min read

v2.0.0 is the release in which CYPEX becomes a multi-tenant PostgreSQL application platform. Tenancy is a first-class object (Organizations), isolation is enforced in the database (Row-Level Security), authorization is two-dimensional (Capabilities × Data Scope), schema exposure is explicit (Schema Access), identity can be federated (SSO Gateway), and outbound integrations are governed (allowlist, credentials, enablement, audit).

Warning
This is not a drop-in patch. v2.0.0 changes the permission and tenancy model. Read the Upgrade to v2.0.0 operator guide before planning a maintenance window, then the Upgrading to v2.0.0 technical reference for the database detail.

At a glance

AreaWhat changed
OrganizationsMultiple tenants in one deployment, isolated by PostgreSQL RLS on 37 tables
RolesThree role types; Capabilities and Data Scope configured as separate concerns
Schema AccessPer-organization control over which database schemas (modules) are available
Admin panelNew information architecture, role-aware navigation, Setup Guide, Access Preview
SSODedicated SSO Gateway service, five provider types, pending-approval gate; LDAP and local login unchanged
ConnectorsAllowlist, encrypted credentials, connector builder, two-level enablement, execution audit
Breaking changesRLS, role semantics, Schema Access, new service, route changes

Organizations

A CYPEX deployment can serve more than one tenant — an Organization — from the same PostgreSQL database. Isolation is enforced by Row-Level Security in the database, not by UI filtering.

  • 37 tables gained RLS policies in this release — 28 in cypex, 5 in cypex_log, and 4 in sso_gateway — covering applications, the data model, workflows, modules, files, reports, notifications, export/import jobs, translations, the log tables, and SSO provider and user-mapping tables. Policies apply on every query that goes through PostgREST and the CYPEX data path.
  • Twelve existing tables gained an organization_id column (t_ui, t_notification, t_file, t_report, t_query_group, t_export_job, t_import_job, t_function_metadata, cypex_log.t_log, cypex_log.t_log_api, cypex_log.t_permission_audit_log, cypex_log.t_user). Tables new in v2.0.0 — the mapping tables, the connector tables, and the SSO tables — are created with the column. The remainder inherit their scope through a join to their parent module or object.
Warning
If you write your own policies or queries against CYPEX tables, do not assume organization_id exists on all of them. It does not. See RLS impact on existing data.

Access is two-dimensional and both dimensions must agree before a row is returned:

  • Capability — what operations a role may perform (SELECT / INSERT / UPDATE / DELETE / EXECUTE)
  • Data Scope — which organization’s rows that role can see

A capability without a data scope produces a user who can run SELECT and gets zero rows. A data scope without the capability produces a user authorized for data they cannot query. See Capabilities vs data scope.

Supporting database objects:

  • Helper functions cypex.is_admin(), cypex.is_organization_admin(), cypex.current_user_organization_ids(), and cypex.current_organization_id(), all reading request.jwt.claims.
  • cypex.validate_root_table_organization(), a function intended to reject a write that would stamp a row with an organization the caller is not acting for. It ships unattached — no trigger invokes it in v2.0.0, so organization_id is set by the application, not enforced by the database.
  • cypex_log.t_permission_audit_log, which records backend permission decisions so “why did this user see that row” has a queryable answer. The actor column is nullable — a system-triggered action is audited with no human actor attached.

Existing single-tenant deployments are not left behind: the upgrade creates a Default Organization and a cypex_default virtual module, maps every existing module and every cypex_user / cypex_admin member role to it, and leaves pre-existing data visible without a manual backfill.

Conceptual reference: Organizations.

Roles

Roles remain PostgreSQL roles. What changes is how CYPEX helps you create and reason about them. Every role now has a type, chosen at creation:

Role typePostgreSQL layerScopeIntended use
System Administratorcypex_admin, isSuperAdmin claimGlobalPlatform-wide administration. Every policy admits this role through cypex.is_admin(), so it reads every row without being exempt from RLS. Organization assignment does not apply and is rejected if supplied. Only an existing System Administrator can create another.
Organization Administratorcypex_admin + organization_admin, isOrganizationAdmin claimOne or more organizations (required)Full administration inside mapped organizations. Policies admit this role through cypex.is_organization_admin() for its mapped organizations only; everything outside them is invisible.
Organization Membercypex_userOne or more organizations (required)Default for application users. Subject to every RLS policy. On CYPEX core tables this role is SELECT-oriented, with full CRUD retained where users create and own content (reports, files, notifications).

Capabilities and organization (data) scope are configured separately, under the Capabilities and Organizations tabs on the role detail screen. Choosing a role type sets the right inheritance and validation rules at creation time; it does not collapse the two dimensions into one switch.

The default for new roles is Organization Member — least privilege unless you deliberately choose broader access. Creating an Organization Administrator or Organization Member without at least one organization is rejected by the API. This is a backend rule, not a database constraint, so it is enforced on the API path and not on direct SQL.

Two supporting screens are new alongside the role list:

  • Unmapped Related Roles — PostgreSQL roles CYPEX can see that carry no organization data scope, with an adopt action that assigns a role type and organizations without recreating the role. This is where you clean up after an upgrade, since the migration only maps roles that are members of cypex_user or cypex_admin.
  • Stale mappings — role↔organization mappings whose role or organization no longer exists, listable and purgeable in bulk. System Administrator only.

Admin how-to: Roles & Capabilities.

Sessions and tokens

v2.0.0 replaces the single long-lived JWT with an access token / refresh token pair.

  • The access token is short-lived — JWT_EXPIRES_IN, default 15m — and carries audience cypex-platform, the value PostgREST requires.
  • The refresh token bounds the session. Its lifetime comes from cypex.t_config.jwt_exp, the value the admin Configuration page edits. It is cookie-only, never returned in a JSON body, and carries a different audience (cypex-refresh) so it cannot be spent as a database credential at the data API.
  • POST /app/auth/refresh re-checks the user against the database on every renewal — still active, role unchanged. Revoking a user now takes effect within one access-token lifetime instead of one session.
  • Sessions are synchronised across browser tabs; logout clears both cookies; SSO session revocation is honoured through Redis.

New and changed environment variables: JWT_AUDIENCE (must match PGRST_JWT_AUD), BCRYPT_ROUNDS (default 10, range 10–15), REDIS_URL, and JWT_ISSUER (default changed from cypex-sso-gateway to cypex-api; the old name is still accepted, so live sessions survive the upgrade).

Warning
The Session length setting (Platform Admin → Configuration) is the session length, not the access-token lifetime, and must now be at least 2× the access TTL (30m at the default). Existing values below that are refused on the next edit.

Full model: Sessions and tokens.

Schema Access

Which schemas an organization may use is now an explicit admin control rather than an implicit side effect of grants.

  • In CYPEX, module and schema name the same operational idea: a database schema exposed to the platform. Database identifiers still say module; the UI and these docs say Schema Access.
  • Schema Access enables or disables schemas per organization. The page is System Administrator only.
  • Grants are additive — assigning a second schema does not silently drop the first — and can be applied in bulk across an organization.
  • Each organization has an explicit primary module, which determines where that organization’s generated objects land.
  • Internal CYPEX schemas are excluded and are not assignable.
Warning
Schema Access is the coarsest control in the release and the most consequential. An organization that has not been granted a schema sees nothing in it, regardless of role capabilities or RLS policy. When a correctly configured user still lands on an empty screen, check Schema Access first.

Admin how-to: Schema Access.

Admin panel overhaul

v1.9.x grouped identity under a single Authentication section (Users, Roles, Login Settings, LDAP) and kept system tasks under System Maintenance. There was no Organizations, Schema Access, SSO Providers, or Integrations area. v2.0.0 introduces a clearer map:

SectionItems
BuilderDatabase, Applications, Repository Applications
Access ControlRoles & Capabilities, Users, Access Preview; under Advanced (System admin): Organizations, Schema Access
AuthenticationSSO Providers, LDAP
IntegrationsConnector Execution, Allowlist, Credentials, Connectors
Data & ContentREST API, Internal API, Files, User Reports
Monitor & AuditUser Audit Trail, Table Audit History, Connector Audit
Platform AdminConfiguration, Database Migrations, Storage & Repositories, Internal Schema Browser
ExtensionsEnterprise extensions

Menu visibility follows role and licence. v1.9.x had a single enterprise/non-enterprise flag; v2.0.0 applies four visibility levels per item:

LevelWho sees the item
publicEvery authenticated user
adminSystem Administrators and Organization Administrators
system adminSystem Administrators only
enterpriseOnly when an enterprise licence is active

A System Administrator and an Organization Administrator therefore see structurally different navigation. Note that the whole Authentication section (SSO Providers, LDAP) is enterprise, as are Extensions and Storage & Repositories — they do not appear without an active enterprise licence.

PostgreSQL terms are explained in place: menu items and page titles carry tooltips that name the underlying concept — Schema Access explains that module and schema are the same thing, Organizations explains Row-Level Security, Roles & Capabilities explains PostgreSQL roles.

Section map: Administration panel.

Setup Guide

The dashboard carries a Setup Guide that tracks progress against real deployment state rather than a manually ticked checklist, and can be skipped. It renders two paths.

System Administrator (6 steps):

Organizations → Roles & Capabilities → Schema Access → Data Model → Users → Applications

Administrator without platform scope (4 steps):

Roles & Capabilities → Data Model → Users → Applications

The order is tenancy-first: establish the tenant, decide who may act in it, and decide which schemas it may use — then build inside that boundary. Organization Admin and Organization Member roles cannot be created without an organization, and Schema Access decides whether a tenant can see a schema at all, regardless of what the data model contains. Organizations and Schema Access are omitted from the shorter path because they are configured for that administrator by a System Administrator, not by them — which is also why that path starts at the data model.

Walkthrough: Setup Guide.

Access Preview

Access Preview is new in v2.0.0. It shows what a given user or role can actually do and see, combining capabilities with data scope, so permission errors surface before deployment rather than in a support ticket. A companion object-level view covers individual queries (views), functions, and state transitions.

See Access Preview.

Day-to-day UX

  • Organization filter bars on organization-scoped screens (SSO, connectors, applications, and related flows). For org-scoped operators the filter is not cosmetic — it reflects what the backend already allows.
  • Role screens that explain Capabilities vs Organizations in plain language.
  • Related-page links between Organizations, Schema Access, Roles, and Access Preview.
  • Dedicated Pending and Rejected panels on the Users page for the SSO approval queue.
  • Redesigned login experience (see below).
  • Typography and Material UI modernization across admin and applications.

Single Sign-On

v2.0.0 introduces a dedicated SSO Gateway service alongside the main backend, with its own encryption key material and its own sso_gateway PostgreSQL schema. Local database login and LDAP both continue to work alongside it — nothing is forced to migrate.

Provider typeProtocolWhat it covers
Generic OIDCOIDCAny OpenID Connect–compliant IdP — Microsoft Entra, Keycloak, Auth0, JumpCloud and others — through one configuration screen with discovery-document support
Generic OAuth2OAuth2Any spec-compliant OAuth2 provider configured by endpoint
GoogleOIDCDedicated Google provider strategy
MicrosoftOIDCDedicated Microsoft provider strategy
GitHubOAuth2Dedicated GitHub provider strategy

How login behaves:

  • Progressive disclosure — typing an email resolves the matching SSO provider by domain; a plain username stays on local authentication.
  • Organization-aware provider selection — providers are scoped per organization, not as one global list, so different business units on one deployment can federate with different identity providers.
  • Brand detection for Google, Microsoft Entra, and JumpCloud based on issuer hostname. Every other provider, GitHub included, renders a generic icon. This is cosmetic only.
  • First successful SSO sign-in does not silently grant access. Unless a role-mapping rule matches, the new identity lands in a pending state and an administrator must approve or reject it before the user can do anything. Every approve, reject, and un-reject decision is written to an audit trail.

Role mapping works as it does for LDAP: identity-provider claims map to CYPEX roles with exact, prefix, suffix, contains, or regex matching, and each provider can declare a default role for identities that match nothing.

What this looks like to the person signing in — the organization picker, the provider buttons, and the two “your identity was verified, but…” messages — is covered in Signing in.

The pending gate is deliberate. An identity provider you federate with can create accounts; this is where you decide whether those accounts become CYPEX users.

Warning
The SSO Gateway is a new service in the stack. It requires a key-encryption key (.sso_kek) and a Redis instance, and will not start without them. See SSO Gateway prerequisites.

Configuration: Single Sign-On.

External API connectors

v2.0.0 ships the first production-ready External API connector platform on the admin panel. Operators can govern outbound REST integrations without writing custom backend code per API. The platform enforces this order at save time:

  1. Allowlist — declare which outbound hosts connectors may call. An entry can be global or scoped to a single organization; the effective allowlist for a run is the union of both.
  2. Credentials — envelope-encrypted, organization-scoped secrets. Each version carries its own data key. The same connector definition can hold a different upstream account per tenant, with no path for one tenant’s secret to reach another. Revoked versions stay visible for audit; plaintext is never shown again after save.
  3. Connectors — author drafts, validate, optionally dry-run, then publish immutable versions. Definitions are validated JSONB holding a pre-compiled mapping structure, which the runtime evaluates directly rather than re-parsing on every call.
  4. Connector Execution — two-level enablement: a platform-wide arm/disarm switch plus per-organization rollout. A run is enabled only when both agree.
  5. Connector Audit — execution history with organization, actor, connector, outcome, and timestamp, on success, failure, and policy block alike.
Info
Connector execution ships disabled. Absent enablement rows count as off, so upgrading to v2.0.0 turns on no outbound traffic anywhere until someone deliberately enables it.

Credentials and definitions live in PostgreSQL under organization isolation and are not exposed through the PostgREST public API surface. There is no REST route to them, so a misconfigured view grant cannot leak connector secrets.

Scope boundary for v2.0.0

The administration side is complete in v2.0.0. The Application Designer side is a first implementation.

Works in v2.0.0:

  • Connector data sources on the Table, Form, and Autocomplete elements
  • Connector-backed data renders in tables
  • Forms read and write through a connector — field values resolve from literals or custom expressions on save
  • Columns are generated automatically from the connector’s response shape

Not yet available on connector-backed elements:

  • List element connector sources (List remains view-backed in this release)
  • The table filter builder, simple search, and default sort
  • User-facing allowed-filter controls
  • The table’s create button

These table controls compile to PostgREST query parameters, which the connector runtime does not accept in this release. Rather than present a control that would be silently ignored, the editor hides them when a connector source is selected. A connector-backed table therefore displays and pages its data, but cannot yet be sorted, searched, or filtered from the designer.

Filter support, List connectors, and further element types are scheduled for v2.0.1. Plan integrations accordingly: stand up governance and connector definitions now, build read-and-display and form-driven flows today, and hold anything that depends on designer-side filtering or List connectors until the follow-up release.

Governance walkthrough: Connectors · designer how-to: Connector data sources.

Also in this release

  • List element in the Application Designer — renders each row with a layout you design instead of a column grid, sharing all its data logic with the Table element
  • Visual filter builder for fixed table and list filters — build rules from dropdowns in a draggable dialog, or switch to the expression editor (view-backed sources only; see the connector scope boundary above)
  • Ctrl+S quick-save, with save descriptions pre-filled from a timestamp plus a generated summary of what changed — which elements, pages, menu items, and theme keys
  • Editor performance work: the element tree is now a flat dictionary with references rather than a deeply nested structure, cutting re-render cost on large applications
  • Autocomplete refinements — dynamic-height virtual list items and decimal value support
  • Database session and connection-pool hardening on the backend, with integration tests for the pool-escalation path
  • Material UI modernized from v5 to v9 (Material and MUI X) across the product UI
  • TypeScript upgraded to 5.9; CodeMirror updated; OpenAPI spec consistency enforced in CI
  • Configurable thousand and decimal separators on number fields (free-form characters rather than an on/off toggle)
  • Payments workshop sample model for demos and evaluations
  • Organization Administrators can again fetch queries during export/import
  • Non-administrator sessions no longer hit permission denied when loading the application UI after the multi-tenant user-table changes

Breaking changes

ChangeImpactWhat to do
RLS enabled on 37 tablesQueries, scripts, and integrations reading CYPEX tables directly with a non-admin role now return filtered resultsAudit direct database consumers before upgrading. Verify row counts before and after.
Organization Member is SELECT-oriented on core tablesApplications relying on cypex_user write access outside reports, files, and notifications will failIdentify affected applications; reassign the role type or move the write path behind a function.
Every role now has a typeExisting roles are migrated, but the semantics are newReview every role after upgrade and confirm its type and organization assignments match intent.
Schema Access must be grantedAn organization with no schema assignment sees nothing, regardless of role, and no error is raisedConfirm schema assignments for every organization post-upgrade.
New JWT claims requiredExternal JWT verifiers (API gateways, SSO bridges) reject or mis-scope tokens without themAccept isSuperAdmin, isOrganizationAdmin, org_id (bigint), and organization_ids (bigint array). Tokens issued by v1.x lack them.
Object-to-module resolution changedCustom SQL resolving a physical schema through t_object.module_id alone may resolve incorrectly for organization-attributed objectsUpdate custom queries against t_object to account for the source-module reference.
SSO Gateway is a new serviceThe stack gains a service, a key-encryption key, and a Redis dependencyProvision .sso_kek and Redis before starting the stack; the gateway will not start without them.
Admin navigation and routes reorganizedBookmarks and runbooks pointing at admin URLs break — platform pages moved under a system pathUpdate internal runbooks and saved links.
Access tokens now expire in 15 minutesService-to-service integrations that logged in once and reused a token for days break every 15 minutesHandle 401 by calling POST /app/auth/refresh, or issue the integration a token outside the interactive login flow. The refresh token is cookie-only, never in the JSON body.
JWT_AUDIENCE must match PGRST_JWT_AUDA mismatch authenticates users and passes the admin panel, but returns 401 from the data API onlySet both to cypex-platform.
Session length minimum raisedcypex.t_config.jwt_exp below 2× the access-token lifetime is refused on the next editCheck SELECT value FROM cypex.t_config WHERE key = 'jwt_exp'; — 30m minimum at the default.
Application definitions migrated 17 → 20A definition saved on v2.0.0 will not load on v1.9.x; packages exported after the upgrade cannot be imported into v1.9.xExport application packages before upgrading, not after.
Material UI v5 → v9Custom CSS targeting internal MUI class names may breakPrefer theme tokens over class-name selectors.

What does not break:

  • Existing single-tenant data is preserved and assigned to the Default Organization automatically — no backfill
  • Local database authentication and LDAP continue to work unchanged
  • Connector execution ships disabled; upgrading starts no outbound traffic
  • Legacy objects without an organization attribution continue to resolve as before

Full classification: Breaking changes · Behavior changes · Additive changes.

Known limitations

  • Application Designer connector binding covers the Table, Form, and Autocomplete elements. The List element remains view-backed. Sorting, search, the filter builder, allowed filters, and the create button are unavailable on connector-backed tables. Scheduled for v2.0.1. The administration side is complete in v2.0.0.
  • Non-branded SSO issuers render a generic login icon. Google, Microsoft Entra, and JumpCloud are matched by issuer hostname and show their own mark. Cosmetic only.
  • Legacy connector definitions may still run but should be reviewed against allowlist, credentials, and enablement before being relied on in production.
  • TypeORM remains on the 0.2.x line. A 0.3 upgrade was completed and explicitly reverted, deferred to a dedicated change window. Applications depending on 0.3-only behaviour need a follow-up release.
  • Custom CSS targeting internal Material UI class names may need adjustment after the UI modernization; prefer theme tokens.
  • The default password policy shipped in this release is deliberately permissive (minLength: 4, no character-class requirements) and is inserted only when no policy exists. Tighten it before exposing the upgraded deployment to end users. See Default password policy.

Upgrade path

  1. Read the Upgrade to v2.0.0 operator guide end to end. It covers every breaking change in one walkthrough.
  2. Complete the pre-upgrade checklist.
  3. Rehearse on a staging environment that mirrors production, and time the operation.
  4. Run the row-visibility verification queries before and after — this is the check that catches a bad migration.
  5. Provision SSO key material and confirm the gateway starts, if you adopt SSO.
  6. Decide whether you stay on a single Default Organization or split tenants after upgrade.

If that rehearsal is not ready, remain on v1.9.x until it is.

Version history