2026.9.0
Released on: 2026.10.19
|
-
Added the HTTP_CORS_ALLOWED_ORIGINS option to restrict which origins are allowed to make cross-origin requests (
2ecf8e8). -
Added the Blocking option to workflow prompts that wait for an answer (alert, choice, input, options and record picker); a blocking prompt dims the rest of the screen, keeps keyboard focus inside the prompt and has no close button, so it can only be closed by answering it (
b21647f,c57c35a). -
Added a visibility condition to automation block buttons, so a button can be shown or hidden with an expression evaluated against the record, user and screen, the same way page blocks are. The change was added to let one automation block act as a context-aware action toolbar instead of splitting buttons across several blocks with their own visibility conditions (
7199966). -
Added an option to the record organizer block to open records in edit mode, the same one the record list block has (
22051b9).
-
Changed the Go toolchain and server libraries to current versions without known vulnerabilities (
0ec05c2,027afbe,d5828a0,bcbbe6b). -
Changed web application libraries to versions without known vulnerabilities (
d073d83,5369059,16b17dd). -
Changed the gRPC client library used for Corredor to a version without known vulnerabilities (
acd4ba3). -
Changed charts to ECharts 6, which fixes a cross-site scripting issue; chart colours and legend positions are kept as before (
0ee6852,c535fc9). -
Changed the rich text editor library to a version without known vulnerabilities (
5b54812). -
Changed the server console build to Vite 6 (
fe413a4). -
Changed Docker image publishing to also tag
latestwhen the released version is the highest stable one (no pre-release suffix), next to the version tag and theYYYY.MMalias; a patch to an older release line does not movelatest(e53020a). -
Changed the tooltip of the sort button on record selector and user columns in a record list to explain that these columns sort by the referenced record or user ID, not by the displayed value (
fee0e4f). -
Changed the navigation block to fold the items that do not fit into a More menu on small screens, and the tabs block to switch to a tab selector above the content when its tab titles do not fit (horizontal tabs in one row, vertical tabs in half of the block’s width). The change was made so all navigation items and tabs stay reachable on phones instead of wrapping out of the block or squeezing the tab content (
89bacbd,dddd6c6,cb10f3e,99502f6,987040c). -
Changed record list summaries to be refused when they are requested together with a page cursor. The change was made because they only ever counted from that page on; the record list block requests them with the first page only (
3561186). -
Changed workflow triggers to be refused on save when their interval is not a valid crontab expression, their timestamp can not be parsed or their constraints can not be registered. The change was made because such triggers were saved but never fired, or fired more broadly than configured (
8747a80,c04a83f). -
Changed permission checks to look up user group permissions only when the user’s own roles neither allow nor deny, instead of on every check The change was made because every user is in a user group, so each check on a running server also walked the group tree; record lists with totals, reports and exports that check each record took about twice as long (
0794278). -
Changed granting permissions to update the permission index in place and save only the changed rules, instead of rebuilding the index and copying every rule on each grant The change was made because a grant slowed down with every rule already stored (8 ms at 20,000 rules, now 0.2 ms) and held up every other permission check while it ran; workflows that grant permissions per record ran about 3 times faster (
7c59455). -
Changed permission checks with contextual roles (Owner, Creator, …) to prepare the record for their expressions once per check instead of once per role The change was made because record lists, totals and reports for users who may read only some records check every record; their server time drops by about a quarter to a third (
84a73fe). -
Changed record lists with a total count to have the database count the records for users who may read every record of the module, and to skip checking those records one by one The change was made because the total was counted by reading and checking every record; on a module with 50,000 records a list with the total shown took about 3 seconds, now under 0.1 second, and with page navigation about half as long as before (
9a1be74,6875fc5). -
Changed workflow runs to look up each namespace and module (with its fields and labels) once and reuse it for up to 10 seconds, also in the subworkflows and record triggers they start, instead of reading them from the database on every record step The change was made because a loop over records repeated these lookups for every record; a run over 428 records sent about 6,150 queries, of which about 5,400 were these lookups, and now sends about 750, which halves its time on SQLite and saves a database round trip for each of those queries elsewhere (
f0ad751). -
Changed workflow steps to be numbered by a counter of their own instead of each taking an ID from the server’s ID generator The change was made because the generator issues at most about 25,000 IDs a second for the whole server; a loop of a few thousand iterations used them up, ran about 3 times slower than it could, and made every other request that needed an ID, such as saving a record, wait for one (about 5 ms per record save while a large loop ran) (
1610d0d). -
Changed workflow runs that something waits for (record triggers that run before a save, subworkflows, runs started by hand) to report that they finished as soon as their last step does, instead of on the next check, done every millisecond The change was made because those checks made up three quarters of a short run: a two-step workflow took 2 ms, now 0.5 ms, and a loop calling a subworkflow for each of 428 records went from 0.68 to 0.26 seconds together with the other workflow changes (
0dc3d71,068f032).
-
Fixed the integration gateway changing its routes and settings while serving requests, without any locking, when routes or gateway settings were saved and at server start; a route that was deleted or disabled now also stays gone when another route is saved (
ea9cd6c,49d1a17,7695c24). -
Fixed a failed workflow run reporting back to whatever waited for it (a record save, a subworkflow step, a run started by hand) before its failure was recorded, so the stacktrace returned with the error could miss the failing step (
cfde39f). -
Fixed creating a workflow through the API without
metafailing with an empty server error; it is now refused with the missing name error (db962f3). -
Fixed roles, users, modules, pages and other resources imported without timestamps (for example from YAML or by the user import) being stored with the creation date 0001-01-01, or failing to import on MSSQL; they now get the time of the import (
a6c2be0). -
Fixed record filters using TIME(), such as
TIME(start) = TIME('02:00:00'), matching nothing on MySQL 8, which read the bound time as midnight (6a0a45c). -
Fixed opening a notification on MSSQL hanging the request for good; its configuration is now read whether the database returns it as bytes or as text (
969cce8). -
Fixed modules on MSSQL with number fields stored in their own columns reporting schema changes that never go away; the precision of existing decimal columns is now read (
63f6ab3). -
Fixed listing records by a meta key without a value (records that have the key) failing on MSSQL with a syntax error (
1910c74). -
Fixed MSSQL installations failing to start after the first restart in the labels migration ("Incorrect syntax near 'JSON_OBJECT'"), and the migration turning the label value column into NVARCHAR, which made labels written afterwards unreadable; plain text label values are now wrapped as JSON with STRING_ESCAPE and the column stays VARCHAR (
507c717). -
Fixed filtering by label value on MSSQL failing with "Incorrect syntax near 'OPENJSON'", and other checks whether a JSON array holds a value (
74b89a1). -
Fixed charts on MSSQL becoming unreadable once their configuration was saved in a Unicode (NVARCHAR) column; chart configuration is now written as text (
8b0a3e1). -
Fixed workflow steps that allow, deny or inherit a permission crashing with "slice bounds out of range" for users who are not super administrators; they now check the user may grant on the component, as the permission editor does (
a9a0af4,d07df59). -
Fixed server scripts run from client scripts not returning their results to the client script, the returned values no longer need to be passed in as arguments first (
2d59923,4b0b332). -
Fixed the comments block set to show older comments first opening with the newest comment at the top, and showing it a second time at the bottom a few seconds later, when the comments were posted on different days (
52301f9). -
Fixed the server crashing with a concurrent map access error when a module, DAL connection or sensitivity level was saved while records were being read or written (
95a7709,b0d950b). -
Fixed number fields stored as a column in MSSQL and MySQL being created as a plain DECIMAL column, which dropped the decimal places configured on the field (
a64f65d). -
Fixed the integration gateway route create endpoint ignoring the meta options (debug, async, description), so they only took effect after a second update request (
9dcdb4e). -
Fixed updating a deleted sensitivity level failing with "does not exist", and the update silently undeleting it when it did go through (
806fee1). -
Fixed undeleting a sensitivity level creating a second active level with the same level value, which could then not be deleted (
806fee1). -
Fixed the connection pool and retry parameters of the database DSN (
*connMaxOpen,*connMaxIdle,*connMaxLifetime, …) being ignored, which left the pool at its 256 connection default and could exhaust PostgreSQL’s connection limit (4993022). -
Fixed namespace exports listing pages in database order instead of page tree order, so an import could end up with the pages reordered (
9c55fdd). -
Fixed deleting a user group that still had members or child groups leaving it soft-deleted while the children still pointed at it, which made the server fail to start while rebuilding the org tree. The delete is now refused up front (
a316983). -
Fixed a user group accepting itself or one of its descendants as parent, which created a cycle in the org tree (
a316983). -
Fixed the progress page block showing NaN% when the module behind it had no records; it now shows the configured default value instead (
a92df89). -
Fixed the record list bulk edit modal keeping the previously chosen fields and values when it was closed or after saving, so the next bulk edit started with stale data (
61362fd). -
Fixed the "Open builder" button on a workflow in the admin area opening /workflow/… at the domain root, which broke installations served under a path prefix (HTTP_BASE_URL) (
75786b3). -
Fixed bulk record edit (and any record update) storing 0 when a number field was cleared; an empty value now clears the field instead of setting it to 0 or [0] (
08fedeb). -
Fixed a required Bool field rejecting records where it was false; false was stored as an empty value and reported as a missing required field, so such records could only be saved while the field was true (
1e09956). -
Fixed record creation failing with a NOT NULL violation on the "values" column for modules stored in their own table once every field was moved to its own column. The JSON document column is now created nullable. Tables created before this fix keep the constraint; drop it manually if needed, for example on PostgreSQL: ALTER TABLE <table> ALTER COLUMN "values" DROP NOT NULL (
e8e1eab). -
Fixed the workflow list search in the admin area matching only the workflow handle; it now also matches the workflow name (
9c33eed). -
Fixed external (OpenID Connect) login failing with "request Content-Type isn’t multipart/form-data" when the identity provider returned a long authorization code, as Microsoft Entra ID does for synced work accounts. The auth form size guard no longer applies to callback query parameters, and an oversized form now gets a proper 413 response (
f2001fb). -
Fixed a workflow or script on a beforeCreate/beforeUpdate trigger not being able to set a field the saving user is not allowed to update; the change was re-checked against the user’s permissions and rejected with updateDenied. Fields the user changed are still checked against the user’s permissions, while changes made by before-handlers are taken as the automation’s own action (
568de7c). -
Fixed the MSSQL driver failing to upgrade the store ("Invalid object name 'INSTANCENAME.information_schema.columns'") when the DSN addresses a named server instance (sqlserver://user:pass@host/INSTANCE?database=corteza); the database name is now taken from the database parameter (
f2e9ca0). -
Fixed error messages on the auth pages (login, sign-up, change password, profile, MFA) being shown untranslated; service errors are now translated for the user’s language like they are in API responses, falling back to the original message when no translation exists (
0524490). -
Fixed a record list in inline-edit mode not warning about unsaved changes; leaving the page, navigating to another page or reloading now asks for confirmation while edited rows are not saved, like the record page does (
77e68c5). -
Fixed angle brackets and other markup being stripped from plain text fields (for example
Name <mail@example.tld>). A String field now has an "XSS Sanitization" option that can be turned off for fields holding trusted plain text; it stays on by default and cannot be turned off for rich text fields, which are always sanitized. Plain text fields are also rendered as text instead of HTML in record views (f6c708a,c2ed503). -
Fixed workflow errors not saying which parameter failed; an argument or result that cannot be evaluated is now reported with the function and parameter name (for example: function "composeRecordLookup", arguments: could not evaluate "recordID": …) (
c1b47cb). -
Fixed the message of a workflow error step being shown with a technical prefix ("workflow N step M execution failed: …"); it is now shown exactly as configured. The error step also accepts an optional title, used as the heading of the error notification in the webapps instead of the generic one, also in production where other error details are hidden (
51bdf5d,d5ca627). -
Fixed MSSQL storing non-Latin text (Arabic, Persian, Chinese, …) as question marks; text and enum columns are now created as NVARCHAR. Columns created earlier keep their VARCHAR type; alter text columns to NVARCHAR manually where such text must be stored. JSON columns stay VARCHAR; non-Latin text inside them needs a UTF-8 collation (
43ed0e1,fdfe836). -
Fixed updating resource translations crashing the request when no default language is loaded (
f6fa696). -
Fixed CSV record import keeping only the first line of multi-line text and dropping values that contain quotes (
3529f4c). -
Fixed number values that can not be parsed (for example a decimal comma in a CSV import) being stored as 0; they are now rejected as invalid (
56808a6). -
Fixed the page title running under the sidebar and its toggle in right-to-left languages (Hebrew, Arabic, …) (
fc88ddf). -
Fixed PostgreSQL connections using a schema other than public (search_path in the DSN) asking for the same schema alterations over and over and failing every record operation; table and index checks now look in the connection’s current schema (
6b136bc). -
Fixed saving a workflow failing for users who may update it but not manage its triggers; the editor now only sends triggers that were added or changed (
1a204cd). -
Fixed authentication pages (login, signup, profile, …) staying left to right in right-to-left languages such as Arabic and Hebrew; the page direction now follows the detected language (
62c477d). -
Fixed workflows triggered while the server was still starting (for example on a scheduled interval) failing with a missing record model; workflow triggers are now registered only after the compose models are loaded (
a2a8fd5). -
Fixed record filters with a list of values, such as
industry IN ('Tech', 'Retail', 'Mining'), using only the first two values, and a one-value list such asindustry IN ('Tech')being rejected as an unsupported operator (9ec8552). -
Fixed record filters written as
size BETWEEN 10 AND 20failing with a server error; they now filter the same as(size BETWEEN 10 20)(4b5f5e9). -
Fixed the API documentation at
/api/docsmissing endpoints added since 2022, such as the user group endpoints; the documents are now generated from the API definitions so they stay complete (f6fd2b0,9f72020). -
Fixed a failed record export opening a browser error page such as
ERR_INVALID_RESPONSEinstead of showing what went wrong (ba59f16). -
Fixed permission updates from the
200_federationand300_automationprovisioning folders not reaching an existing installation that has no auth client permissions; a provisioning folder that is missing is now reported and skipped instead of ending the import (a3b2e29). -
Fixed a module’s discovery settings keeping only their last language after each server restart; settings listed for several languages now keep all of them (
38a5b8a). -
Fixed a record filter with double-quoted or unclosed text failing with an unreadable
found an illegal tokenerror; it now says that text is quoted with single quotes (62d6fe0). -
Fixed listing a user’s roles or a role’s members on SQLite returning only one of them, or failing outright with
no such function: concat(4577dfb). -
Fixed filters matching a value against several values at once, such as a multi-value
INor a multi-value label filter, matching nothing on SQLite (0733b5d). -
Fixed a record dropped in front of another in a record organizer landing behind it again; it now stays where it was dropped (
aae2d30). -
Fixed a record export with resolved references failing when a record field’s referenced module is missing or not set; such a field now exports its record IDs (
fef2fd5). -
Fixed a fresh install on MySQL failing its database upgrade with "BLOB/TEXT column 'rel_resource' used in key specification without a key length" while creating the role members table (
6dfd592). -
Fixed record lists returning a different number of records depending on the sort direction for users who may read only some of a module’s records; a page is no longer cut short, and the total no longer stops counting, when a run of unreadable records follows it (
128c829). -
Fixed paging a record list sorted by a date field skipping or repeating records when stored values are in a different format (date only, with a positive UTC offset, or without a timezone); such values now also sort by the date they name instead of as empty (
6ba362f,fcbf6d0). -
Fixed bulk patch, delete and undelete by query only ever touching the first 500 matching records, patching them again on every pass until the request timed out (
3f6a228). -
Fixed system lists (users, roles and the like) on PostgreSQL losing rows when paged sorted by a column that is empty on some rows, and repeating the first page forever when sorted by a column name such as
created_at(7c54dab,7d9bbb2,f5b5929). -
Fixed record list summaries reporting 0 for the minimum or maximum, a wrong unique count or an invalid average when several summaries are requested or when a field has no values (
3561186). -
Fixed the workflow records iterator reporting a total of 0 from the second page of records on (
e1ad6be). -
Fixed report runs that aggregate by several keys splitting equal groups, joins overwriting rows that share a right-side row, links skipping a row on each next page, and paging over empty values failing or skipping rows in the Reporter (
30e5ef6,798e235,2abc9f1,18a4a16,5e1d964). -
Fixed a database query that fails midway being treated as the end of the results, which silently cut lists, exports and counts short (
ccdba89). -
Fixed the Corredor record iterator’s
undeleteaction never seeing deleted records (8de39a8). -
Fixed sorting or filtering by a date, number or ID field failing on MySQL 8 with "Character set 'utf8mb4_0900_ai_ci' cannot be used in conjunction with 'binary' in call to regexp_like" (
d4963eb). -
Fixed record export failing when a record reference field holds an empty or invalid value; such values are now skipped (
408d7b2). -
Fixed record value validation stopping at the first empty value, so the values and fields after it were saved without being validated (
4ec489f). -
Fixed a record import whose rows carry no record IDs loading every record of the module to look for existing ones (
cd08aa8). -
Fixed saving a record with a value in a unique Record or User field failing with a server error (
80df42b). -
Fixed a failing scheduled workflow stopping the other workflows scheduled for the same time from running (
add52fd). -
Fixed scheduled workflows silently no longer firing on servers whose clock drifts, as it does on some virtual machines; the scheduler now re-aligns to the clock on every cycle (
75f49ac). -
Fixed interval triggers with several intervals firing only on the first one (
8747a80). -
Fixed a failing after-save workflow or script stopping the remaining after-save handlers, and handlers that trigger events of their own, such as afterUpdate workflows on a bulk edit, blocking other events while they ran (
680c664). -
Fixed an event handler that crashed being treated as successful, so a crashing before-save workflow or script let the save go through; the crash is now logged and reported as the handler’s error (
7e0720a). -
Fixed a crash while starting or cleaning up a workflow session stopping the session watcher, after which no workflow could start until the server was restarted (
047ba29). -
Fixed the workflow editor not saying why a trigger failed to save; the trigger configurator now also shows the expected interval format (
5d01259,e32c220). -
Fixed the page builder freezing after a block was pasted twice or a Tabs block was pasted from another page, and pasted Tabs blocks taking over blocks with the same number on other pages (
663f450,e6f5a4d). -
Fixed a tall Tabs block growing past its own height instead of scrolling inside it, which hid the scrollbar of a record list inside the tabs (
72e34c2). -
Fixed SMTP host, user and sender address with surrounding whitespace being saved as typed, which made mail sending fail; the values are now trimmed by the server, the connection test and the settings form (
3f9dcbd).
-
Closed unauthenticated access to private record attachments, which could be downloaded by anyone who knew or guessed their ID, and added the missing permission checks for reading and removing Compose attachments, addressing GHSA-9qmq-7rfq-58cj and GHSA-jvjg-fj8j-x7qm (
3b68aa3). -
Validated OAuth2 redirect addresses strictly, so a crafted login link can no longer send the authorization code of a signed in user to another site and take over their account, and limited auth clients without redirect addresses to the address of the server, addressing GHSA-x253-2jqf-vx2x (
01eacf5,453d5b3,209f7aa). -
Stopped users from changing their own email, username, user group, kind and labels without permission to update users, which could be used to join any user group or to satisfy contextual role expressions, and limited those expressions to the confirmed email and labels of the user, addressing GHSA-6rpc-jwjp-vh82 (
db5be5a). -
Enforced the list of allowed roles on Corredor scripts, which was ignored and let any signed in user list and run restricted scripts, addressing GHSA-xq36-w6gr-q84q (
e71cbb7). -
Required the impersonate permission to make a workflow run as another user and the grant permission to change its owner, addressing GHSA-7gqf-f657-r6c8 (
015d4d4). -
Blocked workflow HTTP requests, workflow OAuth2 requests and API Gateway proxy requests from reaching cloud metadata and other link-local addresses, with the new HTTP_CLIENT_RESTRICTED_NETWORKS option to also block private networks, addressing GHSA-r6q3-f6xj-fpx7 (
21bc18a,718704f). -
Made module, page and page layout lookups check that the resource belongs to the requested namespace (
1b240f4). -
Required permission to manage settings, or to update the owner in case of avatars, for removing system attachments, which any signed in user could remove before (
323bd80). -
Limited the length of language tags accepted from requests and imported YAML, which let anyone exhaust the CPU of the server with a crafted Accept-Language header or lng parameter, addressing GHSA-q83v-jvj7-jq9m (
24974bc,590d0c5). -
Generated password reset, invite and confirmation tokens, email OTP codes, TOTP secrets, auth client secrets, federation pairing tokens and session IDs from the OS random source instead of a predictable one, and compared tokens in constant time, addressing GHSA-5xr2-wfj4-8cq8 (
9c15194). -
Stopped users from removing credentials of other users (
4f2726c). -
Applied network restrictions to attachments downloaded for email notifications (
4d529c7). -
Limited personal page layouts to the users that own them (
ef65145). -
Required a permission for sending email notifications over the API, which any signed in user could use to send email through the server (
09ceefb). -
Required permissions for auth client impersonation, forced roles and access to the client secret, including the impersonate permission for updating an auth client that impersonates another user or for reading and regenerating its secret (
176cba6,4b4e47b). -
Required permissions for managing federation nodes and refused pairing with an empty token (
09248d0). -
Required permission to update the workflow for reading its execution traces (
039beff). -
Stopped users from taking over reminders of other users by assigning them to themselves (
7d6de8f). -
Limited data privacy request comments to users with access to the request (
90ec5f9). -
Required permission to update the resource for changing its translations (
4fb814d). -
Stopped record scripts from being triggered on records that can not be read (
4a67252). -
Required read permissions for reading roles and role membership of other users (
77ab788,3dfe22c). -
Disabled SCIM when its secret is not set, which left it open to anyone, and required the secret in development mode as well (
25f89d2,07eab31,1deab14). -
Refused record reports over fields that can not be read, whatever letter case the field name is written in (
9b4da27,53e15a4). -
Limited paired federation nodes to the data shared with them (
dd4359c,ea2c440). -
Limited namespace import sessions to the users that created them (
12e7fae). -
Required the impersonate permission for changing the steps, paths or scope of a workflow that runs as another user; without it, permission to update the workflow was enough to run any code as that user (
d9b2210). -
Applied network restrictions to remote resources inlined into rendered templates with inlineRemote, which could be pointed at cloud metadata and other internal addresses (
1864cb3). -
Stopped page layout updates from moving the layout to another page or namespace (
5ccce02). -
Cleared the federation pairing token once the nodes are paired, so a leaked pairing URI can not be used to start the handshake over (
8ee1438). -
Stopped rich text values encoded several times over from turning back into live markup when read, which let a stored value run script in record views; entities in rich text are now decoded without ever producing new tags (
4e8ecf4). -
Limited record reports, and with them charts and metric blocks, to the records the user may read, so a user who reads only some of a module’s records, such as their own, no longer sees totals or grouped values of all of them (
62d626e,c0c43df,86bb517). -
Limited record export to the records the user may read, required the permission to search the module’s records for it, and stopped resolving reference labels of records and fields the user may not read (
f0dc505). -
Refused record list summaries over fields the user may not read, which exposed their sums and extremes (
d6cfeec). -
Hid the old and new values of fields the user may not read from record revisions (
7d4f368). -
Made the Corredor record iterator skip records the user may not read, instead of handing them to the script, and require the permission to search the module’s records (
8de39a8). -
Checked the run-as user of a workflow on each execution instead of once when the workflow was loaded, so a workflow no longer keeps running as a user that was suspended or deleted, or with roles the user no longer has (
71ae992). -
Saved a granted permission rule again when an earlier save of it failed and the same rule was granted again, instead of keeping it only in memory until the server restarted (
c1bd6cb).