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.
v2.0.0 introduces seven platform-level changes. Each one is breaking or behavior-changing for at least one class of deployment.
WarningDo 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.
- Multi-tenant Organizations with PostgreSQL Row-Level Security (RLS).
37 tables gain RLS policies — 28 in
cypex, 5 incypex_log, and 4 insso_gateway. Twelve existing tables gain anorganization_idcolumn, 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. - 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.
- 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.
- 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. - 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.
- Default password policy seeded. A new row is inserted into
cypex.t_configwith a very permissive policy. Existing custom policies are preserved. - Roles and permissions override.
cypex_userbecomes SELECT-oriented on most CYPEX core tables. A neworganization_adminrole (NOLOGIN) gates organization-scoped admin actions. New JWT claims are required.
InfoThe 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.
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.
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-kekandyarn encryption-master-key(oryarn secretsfor 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_gatewayandcypex_redisare added to the compose stack, along with aredis_datavolume. 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.
WarningRehearse 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.
The v2.0.0 migrations enable PostgreSQL Row-Level Security on every tenant-scoped table.
InfoRLS 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 alloworganization_id IS NULLrows 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:
| |
| |
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.
The cypex_user role is read-only on most tables after v2.0.0. New
helper functions read the JWT to drive RLS predicates:
| Function | Purpose |
|---|---|
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:
| Claim | Type | Read by |
|---|---|---|
isSuperAdmin | boolean | cypex.is_admin() |
isOrganizationAdmin | boolean | cypex.is_organization_admin() |
org_id | bigint | cypex.current_organization_id() |
organization_ids | bigint array | cypex.current_user_organization_ids() |
Warningorg_idandorganization_idsare bigint, not UUID —cypex.t_organization.idis aBIGINTinherited fromcypex.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.
A new default is inserted into cypex.t_config:
| |
This is very permissive by design. It only applies if no policy
already exists (ON CONFLICT (key) DO NOTHING).
WarningThe 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.
The v2.0.0 migrations leave existing data on a single Default
Organization (organization_domain = 'default') and, in the same step:
- create the
cypex_defaultvirtual 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_userorcypex_admin(excludingauthenticator) 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.
WarningSchema 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:
- Create the organization. The backend provisions exactly one primary module for it in the same transaction.
- 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.
- Assign roles and users.
- 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 a single-tenant deployment is a separate post-upgrade procedure:
- Confirm the v2.0.0 upgrade is complete (verify queries in the linked page).
- Decide the cutover pattern: per-client organization, per-business-unit organization, or per-environment separation.
- Schedule a maintenance window — backfilling
organization_idon large databases is a multi-hour operation. - Smoke-test on staging using the canonical SQL template.
- Apply on production.
- Verify and roll back if needed.
Full procedure: Detailed organization setup.
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.
WarningThe 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.
The v2.0.0 docker-compose.yml adds two services and two secrets that
did not exist in v1.9.x:
| New item | Kind | Purpose |
|---|---|---|
sso_gateway | service | Federated identity gateway (cybertecpostgresql/cypex-sso-gateway) |
cypex_redis | service | redis:7-alpine, backs SSO session and refresh-token storage; adds a redis_data volume |
.sso_kek | secret file | Key-encryption key for SSO provider secrets, mounted at /run/secrets/sso_kek (SSO_KEK_FILE) |
.encryption_master_key | secret file | Master 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:
| |
Warning.sso_kekand.encryption_master_keyare 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_keymakes every stored connector credential unrecoverable; losing.sso_kekmakes every stored SSO provider secret unrecoverable.
Verify after the stack is up:
| |
The login flow is redesigned with progressive disclosure (email vs. username, database vs. SSO) and SSO brand icons. For a typical LDAP-only deployment:
- Inventory current LDAP configuration (host, base DN, group mappings).
- Identify users that should keep LDAP authentication.
- Identify users that should move to OIDC (typically a new provider such as GitHub, Okta, or Azure AD).
- Decide whether LDAP and OIDC coexist (recommended for staged migration) or whether LDAP is replaced.
- Configure the new SSO providers — see SSO providers (OIDC). Providers are scoped per organization, not globally.
- 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.
- Test the login flow on staging with both auth paths.
- Roll out to production.
InfoOIDC 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.
InfoConnector 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_idclaim on every request — the same claim RLS reads viacypex.current_organization_id(). There is no separate organization session variable to configure. .encryption_master_keyprovisioned — 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_logafter 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_usercredentials directly. The v2.0.0 permission override revokes write access forcypex_useron most tables. - Plan for tenant-scoped secret rotation if you are switching from shared secrets.
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:
| Variable | v1.9.x | v2.0.0 | Action |
|---|---|---|---|
JWT_EXPIRES_IN | session length | access-token lifetime, default 15m | Do not reuse your old session value here. |
JWT_ISSUER | cypex-sso-gateway | cypex-api | No action — the old name stays accepted, so live sessions survive. |
JWT_AUDIENCE | — | cypex-platform | Must match PGRST_JWT_AUD in docker-compose.yml. |
JWT_REFRESH_EXPIRES_IN | — | 7d | Refresh 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_ROUNDS | — | 10 | Optional. Range 10–15, clamped. Raise only behind a load test. |
REDIS_URL | — | redis://cypex_redis:6379 | Required with SSO; leave unset without it. |
WarningJWT_AUDIENCEmust equalPGRST_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.
WarningExistingjwt_expvalues 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';
WarningRedis 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.
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_policiesand confirm every tenant-scoped table has at least one policy. Most tables with a direct, nullableorganization_idcolumn include anorganization_id IS NULLclause 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_organizationstores 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.
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_idcolumns (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_logare referenced by the v2.0.0 backend on every request.Data written with
organization_idset. Once the v2.0.0 backend has served traffic, new rows are stamped withorganization_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:
Migration What it changes 17 → 18 thousandSeparatorconverted from boolean to string; newdecimalSeparatorattribute18 → 19 Element tree normalized from a nested structure to a flat dictionary with references 19 → 20 Chart 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.
WarningExport 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.
WarningIf 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.
| Topic | Page |
|---|---|
| Pre-upgrade checklist | Pre-upgrade checklist |
| Conceptual overview | Conceptual overview |
| Breaking changes | Breaking changes |
| Behavior changes | Behavior changes |
| Additive changes | Additive changes |
| RLS impact on existing data | RLS impact on existing data |
| Roles and permissions | Roles and permissions |
| Default password policy | Default password policy |
| Rollback constraints | Rollback constraints |
| Test matrix | Test matrix |
| Detailed organization setup | Detailed organization setup |
| What is an Organization | What is an Organization |
| Capabilities vs Data Scope | Capabilities vs data scope |
| Schema Access (admin) | Schema Access |
| Roles & Capabilities (admin) | Roles & Capabilities |
| SSO providers (OIDC) | SSO providers |
| SSO user lifecycle / approval queue | User lifecycle |
| Connector governance | Connectors |
| Release notes for v2.0.0 | v2.0.0 release notes |
- 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.