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

Upgrade to CYPEX v2.0.0

17 min read

This page is the mandatory upgrade entry point for CYPEX v2.0.0. It is written for operators who run CYPEX in production and need a single walkthrough that covers every breaking change in this release.

Audience. Read this end-to-end before opening the maintenance window. It links out to detailed pages for each topic; follow every link in the order presented.

What is changing in v2.0.0

v2.0.0 introduces seven platform-level changes. Each one is breaking or behavior-changing for at least one class of deployment.

Warning
Do not treat v2.0.0 as a routine minor upgrade. Every item below is mandatory reading; any skipped item risks a production outage or a silent tenant-data leak.
  1. Multi-tenant Organizations with PostgreSQL Row-Level Security (RLS). 37 tables gain RLS policies — 28 in cypex, 5 in cypex_log, and 4 in sso_gateway. Twelve existing tables gain an organization_id column, and the tables v2.0.0 introduces are created with one; the remainder inherit their scope through a join to their parent module or object. Isolation is enforced in the database on every read and write, not by UI filtering.
  2. Schema Access becomes an explicit control. An organization must be granted a schema (module) before its members can see anything in it — regardless of role capabilities or RLS policy. A missing grant produces an empty screen with no error.
  3. SSO Gateway is added alongside LDAP and local login. Nothing is forced to migrate: local database authentication and LDAP continue to work unchanged. The login flow is redesigned with progressive disclosure and email auto-detection. A branded icon appears for Google, Microsoft Entra, and JumpCloud providers (matched by issuer hostname); any other provider type — including GitHub — renders with a generic login icon, not a distinct brand mark.
  4. New infrastructure in the stack. The SSO Gateway and a Redis instance are new services, and two new secrets (.sso_kek, .encryption_master_key) must exist before the stack starts. See section 6.
  5. Governed External API Connector Platform. Connectors gain an allowlist, tenant-scoped secrets-at-rest, two-level execution enablement, and execution audit logging. Execution ships disabled — upgrading starts no outbound traffic. Legacy connector definitions continue to work but should be reviewed.
  6. Default password policy seeded. A new row is inserted into cypex.t_config with a very permissive policy. Existing custom policies are preserved.
  7. Roles and permissions override. cypex_user becomes SELECT-oriented on most CYPEX core tables. A new organization_admin role (NOLOGIN) gates organization-scoped admin actions. New JWT claims are required.
Info
The Authentication section of the admin menu (SSO Providers, LDAP) is gated behind an active enterprise licence, as are Extensions and Storage & Repositories. If those entries do not appear after the upgrade, check the licence before debugging the configuration.

The operator flow

Use this checklist to drive the upgrade from planning to verification. Each step links to the detailed page that explains the work and lists the checks you must perform.

1. Pre-upgrade checklist (mandatory)

Complete every item below before opening the maintenance window.

  • Full backup. Logical backup (pg_dump) plus, ideally, a filesystem snapshot. Verify the backup can be restored.
  • Export application packages. Every CYPEX application is exportable as a package from the release management panel. Export and store the packages outside the database so you have an application-layer fallback if the schema restore fails. Do this before the upgrade, not after — v2.0.0 migrates application definitions from format 17 to 20 and a v1.9.x backend cannot read a format-20 package. See Release Management and section 9.
  • Audit LDAP / SSO configuration. Inventory current LDAP settings, group mappings, and any existing SSO providers. You will need this for the SSO migration step.
  • Inventory custom RLS policies. Custom RLS on tenant-scoped tables is not removed by the v2.0.0 migrations; new policies are added on top. List them with SELECT * FROM pg_policies WHERE schemaname IN ('cypex', 'cypex_log').
  • Inventory custom password policies. The default v2.0.0 password policy uses ON CONFLICT DO NOTHING; existing policies are preserved.
  • Confirm connector definitions. Decide which legacy connector definitions will be reviewed against the new governance model.
  • Generate the two new secrets. yarn sso-kek and yarn encryption-master-key (or yarn secrets for all of them). The SSO Gateway will not start without .sso_kek. Back both up alongside .jwt_secret. See section 6.
  • Plan for the two new services. sso_gateway and cypex_redis are added to the compose stack, along with a redis_data volume. Confirm you have the ports, image pull access, and disk for them.
  • Inventory direct database consumers. Any report, ETL job, dashboard, or script that reads CYPEX tables with a non-admin role will start returning filtered results once RLS is enabled. List them now and decide which need an admin role, an organization mapping, or a rewrite.
  • Collect admin bookmarks and runbook URLs. Admin navigation and routes are reorganized in v2.0.0; platform pages moved under a system path. Saved links and runbook steps that reference admin URLs will break.
  • Schedule the maintenance window. Notify users in advance. Enable CYPEX maintenance mode if your deployment supports it.
  • Replicate to staging and run end-to-end first. See Pre-upgrade checklist for the full staging rehearsal procedure.
Warning
Rehearse before you commit to a production window. Replicate production, run the migrations end-to-end on the replica, exercise the application as a non-admin user, and time the operation.

2. RLS default-on and row visibility impact

The v2.0.0 migrations enable PostgreSQL Row-Level Security on every tenant-scoped table.

Info
RLS does not change row visibility for existing single-tenant data when the upgrade is applied as documented. The migrations create a Default Organization, map every existing role and module to it, and allow organization_id IS NULL rows to be visible to users mapped to the Default Organization. Verify this on your instance before and after with the queries on the linked page.

What you must verify on your instance:

1
2
3
4
-- Before upgrade: capture row counts
SELECT count(*) FROM cypex.t_ui;
SELECT count(*) FROM cypex.t_file;
SELECT count(*) FROM cypex.t_user;
1
2
3
4
-- After upgrade: confirm counts match and RLS is enabled
SELECT schemaname, tablename, rowsecurity
FROM pg_tables
WHERE schemaname IN ('cypex', 'cypex_log');

If any count drifts or any table shows rowsecurity = f, do not cut traffic. Investigate before proceeding.

Full procedure and pitfall list: RLS impact on existing data.

3. Roles and permissions function override

The cypex_user role is read-only on most tables after v2.0.0. New helper functions read the JWT to drive RLS predicates:

FunctionPurpose
cypex.is_organization_admin()True for organization_admin members.
cypex.is_admin()True for isSuperAdmin claim holders.
cypex.current_user_organization_ids()All org IDs the user can access.
cypex.current_organization_id()The active organization.

New required JWT claims, read from request.jwt.claims by the functions above:

ClaimTypeRead by
isSuperAdminbooleancypex.is_admin()
isOrganizationAdminbooleancypex.is_organization_admin()
org_idbigintcypex.current_organization_id()
organization_idsbigint arraycypex.current_user_organization_ids()
Warning
org_id and organization_ids are bigint, not UUID — cypex.t_organization.id is a BIGINT inherited from cypex.t_global. An external verifier that expects UUIDs will fail to parse them.

External JWT verifiers (API gateways, SSO bridges) must accept these claims. Tokens issued by v1.x do not have them and will be rejected.

Full role table and verification queries: Roles and permissions.

4. Default password policy

A new default is inserted into cypex.t_config:

1
2
3
4
5
6
7
{
  "minLength": 4,
  "minUppercase": 0,
  "minLowercase": 0,
  "minNumbers": 0,
  "minSpecial": 0
}

This is very permissive by design. It only applies if no policy already exists (ON CONFLICT (key) DO NOTHING).

Warning
The shipped default is a placeholder, not a recommendation. Tighten the policy to match your security requirements before exposing the upgraded deployment to end users.

Override procedure and verification query: Default password policy.

5. Organizations and Schema Access

What the migration does for you

The v2.0.0 migrations leave existing data on a single Default Organization (organization_domain = 'default') and, in the same step:

  • create the cypex_default virtual module and set it as the Default Organization’s primary module;
  • map every pre-existing module to the Default Organization;
  • map every role that is a member of cypex_user or cypex_admin (excluding authenticator) to the Default Organization.

That is why a single-tenant deployment keeps working without a backfill. It is also why a role created outside those two group memberships, or a module created after the migration, will have no data scope until you map it explicitly.

Schema Access is now mandatory

Warning
Schema Access is the coarsest control in the release. An organization that has not been granted a schema sees nothing in it — regardless of role capabilities, and regardless of whether the RLS policy would have allowed the row. If a correctly configured user lands on an empty screen after the upgrade, check Schema Access before anything else.

Post-upgrade, for every organization you create beyond the default:

  1. Create the organization. The backend provisions exactly one primary module for it in the same transaction.
  2. Grant Schema Access for every additional schema that organization needs. Grants are additive — adding a second schema does not drop the first — and can be applied in bulk.
  3. Assign roles and users.
  4. Verify with Access Preview before handing the environment over.

Schema Access is a System Administrator-only page (system admin visibility). An Organization Administrator cannot grant their own organization a schema.

How-to: Schema Access · concept: Organizations.

Splitting into multiple organizations

Splitting a single-tenant deployment is a separate post-upgrade procedure:

  1. Confirm the v2.0.0 upgrade is complete (verify queries in the linked page).
  2. Decide the cutover pattern: per-client organization, per-business-unit organization, or per-environment separation.
  3. Schedule a maintenance window — backfilling organization_id on large databases is a multi-hour operation.
  4. Smoke-test on staging using the canonical SQL template.
  5. Apply on production.
  6. Verify and roll back if needed.

Full procedure: Detailed organization setup.

6. SSO Gateway: new service prerequisites

v2.0.0 adds an SSO Gateway service alongside the main backend, with its own sso_gateway PostgreSQL schema and its own key material. It does not replace anything: local database authentication and LDAP continue to work unchanged.

Warning
The gateway refuses to start if it cannot resolve its key-encryption key. Provision the secrets below before bringing the stack up, or the whole compose project will fail to come healthy — including deployments that never intend to use SSO.

New services and secrets

The v2.0.0 docker-compose.yml adds two services and two secrets that did not exist in v1.9.x:

New itemKindPurpose
sso_gatewayserviceFederated identity gateway (cybertecpostgresql/cypex-sso-gateway)
cypex_redisserviceredis:7-alpine, backs SSO session and refresh-token storage; adds a redis_data volume
.sso_keksecret fileKey-encryption key for SSO provider secrets, mounted at /run/secrets/sso_kek (SSO_KEK_FILE)
.encryption_master_keysecret fileMaster key for connector secrets-at-rest, read by the backend as ENCRYPTION_MASTER_KEY_FILE

The backend also gains REDIS_URL (default redis://cypex_redis:6379) and ENCRYPTION_MASTER_KEY_FILE.

Generate the two new secrets at the repository root before starting:

1
2
3
4
5
6
# Both secrets at once, alongside the pre-existing ones
yarn secrets

# Or individually
yarn sso-kek                # writes .sso_kek
yarn encryption-master-key  # writes .encryption_master_key
Warning
.sso_kek and .encryption_master_key are the only way to decrypt SSO provider secrets and connector credentials respectively. Back them up with the same discipline as .jwt_secret. Losing .encryption_master_key makes every stored connector credential unrecoverable; losing .sso_kek makes every stored SSO provider secret unrecoverable.

Verify after the stack is up:

1
2
docker compose ps sso_gateway cypex_redis   # both should be healthy
curl -fsS http://<sso-host>:3032/health     # gateway health endpoint

Migration path for an existing LDAP deployment

The login flow is redesigned with progressive disclosure (email vs. username, database vs. SSO) and SSO brand icons. For a typical LDAP-only deployment:

  1. Inventory current LDAP configuration (host, base DN, group mappings).
  2. Identify users that should keep LDAP authentication.
  3. Identify users that should move to OIDC (typically a new provider such as GitHub, Okta, or Azure AD).
  4. Decide whether LDAP and OIDC coexist (recommended for staged migration) or whether LDAP is replaced.
  5. Configure the new SSO providers — see SSO providers (OIDC). Providers are scoped per organization, not globally.
  6. Decide the approval policy. Unless a role-mapping rule matches, a first SSO sign-in lands in a pending state and an administrator must approve it. See User lifecycle.
  7. Test the login flow on staging with both auth paths.
  8. Roll out to production.
Info
OIDC and LDAP coexist in v2.0.0. You can migrate users one team at a time and keep LDAP active until the last user has moved.

If your deployment has external JWT verifiers (an API gateway or SSO bridge that validates CYPEX tokens), update them to accept the new JWT claims listed in section 3.

7. Connector enablement prerequisites

Info
Connector execution ships disabled. Enablement is two-level — a platform-wide switch plus a per-organization row — and a run is permitted only when both agree. Absent rows count as disabled, so upgrading to v2.0.0 starts no outbound traffic anywhere. Nothing in this section is required unless you intend to turn connectors on.

The governed External API Connector Platform requires:

  • An active organization for every connector caller, resolved from the JWT’s org_id claim on every request — the same claim RLS reads via cypex.current_organization_id(). There is no separate organization session variable to configure.
  • .encryption_master_key provisioned — connector credentials are envelope-encrypted with a per-version data key wrapped by this master key. Without it, the backend cannot store or read connector secrets. See section 6.
  • An outbound allowlist entry for every host a connector calls. An entry can be global or scoped to a single organization; the effective allowlist for a run is the union of both. A call to a host outside the allowlist is blocked and the block is recorded in the connector audit.
  • Tenant-scoped credentials (configure via the admin panel; secrets are encrypted at rest and scoped to the organization, and plaintext is never shown again after save).
  • Both enablement levels switched on — the platform-wide switch and the per-organization rollout row for the calling organization.
  • Connector audit logging enabled (default in v2.0.0; verify by checking cypex_log.t_permission_audit_log after the first connector call).

Order matters: the platform enforces allowlist → credentials → definition → enablement at save time. Governance walkthrough: Connectors.

Pre-upgrade checklist for connectors:

  • Inventory existing connector definitions.
  • Identify which connector definitions should be reviewed against the new governance model.
  • Confirm that no connector definition uses cypex_user credentials directly. The v2.0.0 permission override revokes write access for cypex_user on most tables.
  • Plan for tenant-scoped secret rotation if you are switching from shared secrets.

7b. Sessions, tokens, and JWT environment

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); the session is bounded by a separate refresh token whose lifetime comes from cypex.t_config.jwt_exp — the value the admin Configuration page edits. POST /app/auth/refresh re-checks the user against the database on every renewal, which is what makes a deactivation take effect within one access-token lifetime instead of one session.

Full model: Sessions and tokens.

New and changed environment variables:

Variablev1.9.xv2.0.0Action
JWT_EXPIRES_INsession lengthaccess-token lifetime, default 15mDo not reuse your old session value here.
JWT_ISSUERcypex-sso-gatewaycypex-apiNo action — the old name stays accepted, so live sessions survive.
JWT_AUDIENCEcypex-platformMust match PGRST_JWT_AUD in docker-compose.yml.
JWT_REFRESH_EXPIRES_IN7dRefresh lifetime fallback. Precedence is cypex.t_config.jwt_exp (admin-panel session length) → this variable → built-in default. The SSO gateway reads the same variable. See Sessions and tokens.
BCRYPT_ROUNDS10Optional. Range 10–15, clamped. Raise only behind a load test.
REDIS_URLredis://cypex_redis:6379Required with SSO; leave unset without it.
Warning
JWT_AUDIENCE must equal PGRST_JWT_AUD. A mismatch is hard to diagnose because it fails asymmetrically: users authenticate, the admin panel works, and only data-API requests return 401. Refresh tokens deliberately carry a different audience (cypex-refresh) so a refresh token cannot be spent as a database credential at the data API.
Warning
Existing jwt_exp values below the new minimum will be refused on the next edit. The session length must be at least 2× the access-token lifetime — 30m at the default. Check it now: SELECT value FROM cypex.t_config WHERE key = 'jwt_exp';
Warning
Redis must persist if you use SSO. The bundled compose service runs with --appendonly yes. A Redis that loses its data signs out every SSO user on their next renewal.

Machine consumers need attention too:

  • Any service-to-service integration that logged in once and reused the token for days now breaks every 15 minutes. Either handle 401 by calling POST /app/auth/refresh, or issue the integration a token outside the interactive login flow.
  • Any client reading a token out of the login response body must change — the refresh token is cookie-only (refresh_token), never in JSON.

8. Post-upgrade verification

After the upgrade and before removing the maintenance banner:

  • Run the row-count comparison queries in RLS impact on existing data. Counts before and after must match.

  • Run pg_policies and confirm every tenant-scoped table has at least one policy. Most tables with a direct, nullable organization_id column include an organization_id IS NULL clause for legacy-row visibility — but not all: t_organization, t_module, t_role_organization, and the object-model tables (t_object, t_object_field, t_object_view, etc.) scope visibility through a join or a non-nullable column instead, and legitimately have no such clause. Don’t treat its absence there as a failure.

  • Sign in as a non-admin user and confirm the application still renders the data it rendered before the upgrade.

  • Log into the CYPEX GUI as a non-admin user and confirm:

    • Previously-visible data is still visible.
    • Direct API calls targeting another organization’s rows return 403.
    • Writes to the user’s own organization succeed.
  • Confirm the audit log is being written: SELECT count(*) FROM cypex_log.t_permission_audit_log;

  • Confirm the default password policy is in place: SELECT value FROM cypex.t_config WHERE key = 'password_policy';

  • Confirm the Organizations subsystem is populated: SELECT * FROM cypex.t_organization; Expected: at least the Default Organization row.

  • Confirm role mappings. cypex.t_role_organization stores the role as a name (role_name TEXT), not an OID:

    ```sql
    SELECT ro.role_name, o.organization_domain
    FROM cypex.t_role_organization ro
    JOIN cypex.t_organization o ON o.id = ro.organization_id
    ORDER BY o.organization_domain, ro.role_name;
    ```
    
    Expected: every `cypex_user` / `cypex_admin` member role that
    existed before the upgrade is mapped to the Default Organization.
    A role missing from this table has no data scope and will see
    zero rows.
    
  • Confirm Schema Access for every organization. An organization with no schema grant sees nothing:

    ```sql
    SELECT o.organization_domain, m.module_name, mo.is_primary
    FROM cypex.t_organization o
    LEFT JOIN cypex.t_module_organization mo ON mo.organization_id = o.id
    LEFT JOIN cypex.t_module m ON m.id = mo.module_id
    ORDER BY o.organization_domain, m.module_name;
    ```
    
    Expected: the Default Organization is mapped to every pre-existing
    module plus the `cypex_default` virtual module (its primary).
    Any organization with a `NULL` module row is misconfigured.
    
  • Confirm connector execution is still off unless you deliberately enabled it: SELECT * FROM cypex.t_connector_execution_enablement; Expected on a fresh upgrade: no enabled rows. Absent rows count as disabled.

  • Tighten the password policy if the shipped default is too permissive.

If every check passes, remove the maintenance banner. If any check fails, follow the rollback procedure below.

9. Rollback constraints and limitations

The v2.0.0 migrations are forward-only. There is no automatic rollback script.

What you can roll back:

  • Disable RLS on tenant-scoped tables (ALTER TABLE … DISABLE ROW LEVEL SECURITY).
  • Drop the organization_id columns (only if no application code reads them).
  • Delete the Default Organization and the role/module mappings.

What you cannot easily roll back:

  • The password policy insert. Removing the row disables password complexity entirely; restoring from backup is the only true rollback.

  • New tables. t_organization, t_module_organization, t_role_organization, t_permission_audit_log are referenced by the v2.0.0 backend on every request.

  • Data written with organization_id set. Once the v2.0.0 backend has served traffic, new rows are stamped with organization_id. The context is lost on rollback.

  • Migrated application definitions. v2.0.0 raises the application definition format from 17 to 20 — three forward-only migrations:

    MigrationWhat it changes
    17 → 18thousandSeparator converted from boolean to string; new decimalSeparator attribute
    18 → 19Element tree normalized from a nested structure to a flat dictionary with references
    19 → 20Chart selected-expression configuration reshaped

    A v1.9.x backend only understands format 17. Once an application has been opened and saved on v2.0.0 its definition is at 20 and will not load on v1.9.x.

Warning
Export application packages before the upgrade, not after. A package exported from a v2.0.0 instance carries a format-20 definition and cannot be imported into v1.9.x. The pre-upgrade export in section 1 is only a usable fallback if it was taken before the migrations ran.
Warning
If you decide to roll back, restore the database from the pre-upgrade backup and revert the backend binary. A partial rollback is fragile and will leave the system in an inconsistent state.

Recommended rollback procedure and decision criteria: Rollback constraints.

Quick reference

TopicPage
Pre-upgrade checklistPre-upgrade checklist
Conceptual overviewConceptual overview
Breaking changesBreaking changes
Behavior changesBehavior changes
Additive changesAdditive changes
RLS impact on existing dataRLS impact on existing data
Roles and permissionsRoles and permissions
Default password policyDefault password policy
Rollback constraintsRollback constraints
Test matrixTest matrix
Detailed organization setupDetailed organization setup
What is an OrganizationWhat is an Organization
Capabilities vs Data ScopeCapabilities vs data scope
Schema Access (admin)Schema Access
Roles & Capabilities (admin)Roles & Capabilities
SSO providers (OIDC)SSO providers
SSO user lifecycle / approval queueUser lifecycle
Connector governanceConnectors
Release notes for v2.0.0v2.0.0 release notes

See also

  • Migrations — full migrations section in the docs.
  • CYPEX internals — for the underlying platform architecture.
  • User management — for the user and role model that Organizations extends.
  • Organizations — conceptual reference for what an Organization is, how the JWT claim flows into RLS, and where audit evidence lives.
  • Release Management — for exporting application packages and per-application version control.