Skip to content

v0.27.0

Choose a tag to compare

@github-actions github-actions released this 15 Oct 13:52
· 1585 commits to main since this release

[0.27.0] - 2026-10-15

Headline: exec is all or nothing: when a statement fails at write time, the whole run is rolled back, so a script never leaves a project half-changed. Alongside it: a wave of describe → check → exec fixes from round-trip runs over real apps (the Siemens FSM template, the GenAI showcase, Marketplace modules), Mendix 9 projects can take microflows, nanoflows and pluggable widgets again, check -p resolves many more of the references exec and the build would refuse, the classic filemanager widget and role-based Visible: roles (…) are in MDL, and the companion draws a module's domain model. The MongoDB driver is upgraded for the October 2026 BSON advisories.

Added

  • mxcli search --fail-on-match turns the search into a gate — a pipeline that must refuse a change when a forbidden word turns up in the project's text had no exit status to read: search exited 0 whether it found something or not. With the flag it exits 1 when there is at least one hit and 0 when there is none, printing the results as before (a JSON array under --json). A search that cannot run, such as an unbalanced " or an unknown project, exits 2 so that 1 always means a match; the SEARCH statement still answers an unrunnable query with "No matches found.". Without the flag a hit exits 0 as before. Rules: docs-site "Full-Text Search".
  • filemanager — the classic file manager (Forms$FileManager) in MDL (#151) — filemanager fileManager1 (Label: 'File', Type: Upload, MaxFileSize: 10, AllowedExtensions: '.xlsx', ShowFileInBrowser: false) inside a data view on a System.FileDocument specialization. Before, there was no way to author one: pluggablewidget 'Forms$FileManager' had no definition, the bare keyword was refused as MDL-WIDGET25, and describe page printed a stored one as a NOT re-executable comment, so describe → exec dropped it. Omitted properties take Studio Pro's defaults (Both, 5 MB, any file, false); the written BSON has the property set of a Studio Pro-authored file manager. alter page … set changes all four properties. A file manager in no data container is MDL-WIDGET45 at check, and one in a data view on an entity that is not a FileDocument is refused by exec — both were mxbuild's CE6810 after a clean exec.
  • A module's domain model as SVG, in the companion and on the command line — mxcli describe --format svg domainmodel <Module> writes a finished SVG: entities at the positions the model stores, coloured by kind, with attributes, associations, multiplicities and generalizations. Boxes are sized to fit every name, pulling the stored layout apart just enough instead of clipping. In the Claude Code companion, selecting a module's Domain Model node in the desktop app or VS Code shows it at actual size, with pan, Fit and a full-width view; the terminal lists the entities as before.
  • Visible: roles (Mod.A, …) — role-based widget visibility (#1460) — Studio Pro's "visible for module roles" was never read by describe, had no MDL spelling, was written empty and was dropped by alter … set Visible. It is now read, written and combinable with an expression or attribute condition, on widgets, tab pages and navigation list items. A tab page's (#1465) and a layout grid row's Visible: (#1461) are now written too; describe → exec used to make a Studio Pro row always visible.
  • += / -= for reference-set members inside change (#1473) — change $Obj (Name = 'x', Mod.Assoc += $Item): a Change object activity that mixes an Add or Remove with other members had no spelling, and describe printed the Add as =, which replaces the set.
  • ALTER PAGE addresses navigation list items and widgets inside pluggable widgets — nav item('Home'), nav item(t1) and nav item@2 name an item by its text, a widget in it, or its position; insert into navList1 { item … } adds one (#1388). Widgets inside an Accordion group or a pop-up menu item, legacy DataGrid columns and search fields, and a file manager's own properties can be set and dropped (#891, #1459, #151). set also writes a text box's Placeholder, Password and Validation (#414), a static image's Image (#1464), and a Label on an input that showed none (#292).
  • Image: $currentObject binds the Image widget to an uploaded image (#1476) — no MDL form bound the pluggable Image widget to the object in context; it is refused outside a data container or over an entity that does not extend System.Image.
  • describe module --all (#1435) — the describe module subcommand printed only the module and its roles although the help promised "all contents"; --all runs describe module … with all, and the help says what each form does. with all now emits every document type, where it skipped nanoflows, snippets, JavaScript actions, mappings, task queues and image collections without an error (#1421).
  • mxcli test --app-port / --admin-port / --serve-port — test --local hard-coded its ports, so a machine with 8081 taken could not run tests. A taken port fails up front, naming the port, its role and the flag that moves it.
  • mxcli layout --only-overlapping (#1479) — and a new entity without @Position takes the first grid slot that clears every entity and annotation in the module, so an entity with many attributes no longer overlaps the one below.
  • SEC010 flags page data widgets their roles cannot read — a list view, data grid, reference selector or pluggable combo box over an entity none of a page's roles can read renders empty, with check, mxbuild and the runtime log all clean. SEC010 now asks, per user role that can open the page, whether any of its module roles has a read rule, using the System module's access rules measured from a built model, and reports a System.User list that only ever shows the current user.
  • mxcli syntax microflow workflow-actions — a topic for the microflow statements that start and manage workflows.

Changed

  • mxcli no longer creates a module role on its own (#1474) — a new page, microflow or nanoflow in a module with no module roles used to create <Module>.User ("Auto-created default role for mxcli document access") and grant the document to it, so a security role appeared that nobody chose, open to every user role later mapped to it. A new document now starts with no allowed roles in every module, and move maps a document's roles to same-named roles of the target module without creating any. Breaking for scripts that granted to <Module>.User without creating it: add create module role <Module>.User; — check --references and exec both report "module role … does not exist", and MDL-SEC21 names the fix for a flow a page uses. Roles and grants an earlier mxcli created are left as they are; create module role M.User still adopts such a role.
  • check -p resolves many more references before exec would refuse them (#1472) — each of these passed check and failed exec or the build (CE1613, CE0174):
    • ALTER PAGE targets and the flows, pages, snippets and entities inserted widgets name, and DataGrid 2 column attributes against the grid's entity;
    • the members an access rule's where names (case-insensitively, as Mendix does), an entity event handler's microflow, enumeration keys named in expressions, and the entities a view entity's OQL reads from;
    • image references against image collections the script creates (#1419), and calls to flows the script creates, including mutually recursive ones, which no statement order could check before (#1405);
    • object-list item properties that would be dropped (group g1 (Caption: …) in an Accordion, whose header is headerText), and a file manager outside a System.FileDocument data view (CE6810);
    • a change or member path over a list retrieve (MDL-RETRIEVE03, #1422), show message … type ok (MDL-SHOWMSG01), import from mapping without a result entity, which made the project unloadable (#1418), and alter settings JavaVersion on a Mendix 9 model, which stores none (#1438).
  • A multi-file check ends on a verdict for the whole set (#1431) — "N of M files failed: …" or "All M files passed", where the last line used to be the last file's verdict, which could read "Check passed!" with exit code 1.
  • Commands without -p name the project they auto-detected (#1444) — the notice gives the absolute path and how to choose another, and with several .mpr files in the directory it lists them and asks for -p instead of only saying -p is required.
  • Studio Pro document names in describe --help and the catalog (#1395) — consumedrestservice, publishedodataservice, taskqueue, aimodel, appsecurity, …, and catalog views consumed_rest_services, published_odata_services, task_queues, …. Every old keyword and view name still works.
  • mxcli syntax resolves statement verbs and stops teaching deprecated spellings (#1389) — mxcli syntax grant (and revoke, refresh) found no topic, and several examples used spellings check flags as MDL-DEPRnnn.
  • One-shot mxbuild runs have a timeout and a stall watchdog — mxcli new and docker build could hang forever behind a Gradle build that stopped making progress. They now stop after MXCLI_MXBUILD_TIMEOUT (30 minutes) or MXCLI_MXBUILD_STALL_TIMEOUT of silence (10 minutes), printing the last output lines and the Java home used.
  • mxcli init titles the generated docs after the app, not the repository folder, and the bootstrap script defaults to the release that generated it instead of nightly, and fails loudly when database provisioning fails.

Fixed

  • mxcli search and SEARCH find words that appear only in an element's documentation (#1477) — the strings index held captions, messages, URLs and the documentation of microflows and workflows, but not the documentation of entities, attributes, associations, enumerations, constants, pages and the other documents whose catalog tables carry it, so a word present only there answered "No matches found." (measured: a word in a constant's documentation was found by select … from catalog.constants where Description like … and not by search). The index now also holds those: each hit names the element (ObjectType ENTITY, ATTRIBUTE, CONSTANT, PAGE, …; an attribute is Module.Entity.Attribute) and the field (StringContext documentation), the labels microflow documentation already used, plus the parameters of microflows and Java actions and a module's domain model documentation (domain_model_documentation). A module's own rows carry the module's name in ModuleName, not the empty string the objects view holds for a module. They are read from the tables the catalog builder has just filled, not from a second walk of the model; building a catalog of a stock 11.12 app takes the same time (0.5s) and the strings table grows by about 50 rows. Enumeration values are not indexed (Mendix has no documentation field on them), nor is the summary text of a remote service's contract entities. The catalog schema version is bumped to 25, so a cached catalog is rebuilt once. Rules: docs-site "Full-Text Search".
  • search finds a microflow's log message (#1477) — only the log node name was indexed. A log message is a plain-text Microflows$StringTemplate, not a Texts$Text, so the walk that finds every translatable text never saw it, and a word present only in a log message was not found. It is now a log_message row beside the log_node one (activities inside a loop are not reached, as before for the node name).
  • check refuses a widget datasource constraint that reaches two hops off a variable (#1466) — database … where [Name = $currentObject/Mod.Assoc/Name] on a combobox, list view, data grid 2 or gallery passed check and exec, then failed the build with CE0161. MDL055 covered only microflow retrieves; it now covers page datasources too. One hop ([Mod.A = $currentObject/Mod.B]), the context object's own attribute and the inverted form all build at 0 errors on 11.13.0 and 11.14.0 and stay accepted.
  • exec rolls back when a statement fails after the pre-check (#1408) — a statement that failed at write time left every earlier statement written: a created module stayed, and a drop ahead of the failing create was not undone. A before-image journal copies the .mpr and each unit file the run touches before its first write, and restores them on failure. The message says "Nothing was written: statement N was rolled back".
  • Mendix 9 projects — microflows and nanoflows could not be created or altered in a 9.x project, and every page holding a pluggable widget failed to write, because mxcli wrote properties those versions do not have (#1410). Both are now written in the shape the project's version stores. run --local picks JDK 17 for a Mendix 9 project (#1437), and a create accepts an enumeration split of more than 16 branches, as Studio Pro 9 writes (#1416).
  • describe output that check or exec refused, found by round-trip runs over real apps:
    • an index on a system date member printed an empty column list (#1401); a parameter's separator landed inside its doc comment (#1412); a JavaScript action with type parameters and an undeclared Java action type parameter did not parse (#1404); a doc comment line starting with * lost its bullet on each round trip (#1428);
    • a native pluggable widget's child slot was printed as content { } (#1400), a Mendix 9 pluggable database source was dropped (#1399), a data view listening to a legacy data grid named a widget describe cannot emit (#1415), a data view sourced from a snippet parameter had no data source (ako#1138), and a layout built on another layout printed an empty body (#1411);
    • a decision on a rule that returns an enumeration (#1414), show page passing the page's own parameter by name (#1403), a $var/Attr text template parameter (#1406), DecimalPrecision: -1 and a primitive-array mapping root (#1407), and an aggregate whose output a later set changes (#1413) are now accepted;
    • on error is accepted, and described, on list operations, aggregates, create list, add/remove, cast, rollback and show home page (#1252);
    • describe user role always states CheckSecurity (#1427), a navigation list item keeps its class, a layout keeps its stored canvas size, and a statement whose output hits the 10,000-line limit fails instead of stopping mid-statement with exit 0 (#1425);
    • the describe subcommand describes rules (#1402) and System Java actions (#1445).
  • Model writes that passed check and broke the build or the app:
    • a multi-hop association data source wrote one step for every hop, where it stored the second association as an entity (CE1613) or made the project unloadable (#1467); a DataGrid 2 column inserted into a flow-sourced grid gets its attribute reference (#1468);
    • quoted names are stripped in a multi-predicate retrieve constraint, where ["A" = 'x'] was a string literal and the constraint always false, and in an expression slot followed by whitespace (CE0117); expose (…, "Description") in an OData service is unquoted (#1423);
    • a list sort's inherited attribute is qualified with its declaring entity (#1430), export mapping members are written in message definition order (CE5015, #1387), show message … type error is stored as Error, which the runtime showed as Information (#1280), and a module-qualified association hop in an attribute path parses;
    • create or modify entity keeps an index's GUID when its declared ID misses, where the write was refused (#1470); revoke resolves association members instead of reporting "nothing to revoke" (#1225); names with an excluded twin resolve to the live document in show access, grant, revoke, drop page and alter page, where drop could delete the live page (#1469);
    • a published REST service's authentication parameters are stated and described (#1417); create or modify javascript action keeps the file's imports and EXTRA CODE (#1429); DataGrid 2 columns with no caption or no attribute get the empty templates Studio Pro writes (CE0463); widget init no longer lets native widgets take over image and radiobuttons (#1463).
  • Marketplace — marketplace update --save-edits saves local associations into the module, which the update deleted (#1502); the reference cache keeps action sources, so an untouched module is no longer refused as locally changed (#1441); install names marketplace update for a module already present (#1442); download --output accepts a directory (#1443); a valid .mpk is no longer rejected over a data-descriptor CRC (#1488).
  • Tests and the dev loop — @throws catches errors from call java action and the other call activities (ako#1164), a FAIL carries the raised error message, test --local no longer hangs after the tests when mxbuild starts a Gradle daemon (#1396), sync-java-deps checks the version Gradle resolves when two modules declare different versions (#1450), and macOS resolves the project's JDK instead of the /usr/bin/java stub, which made mxcli new spin in Gradle.
  • diff-local names units and revisions in its headers and renders page, nanoflow and layout changes, which counted as modified and printed no hunk (#1393).
  • SEC010 counts a specialization's rule only for the members it grants, so a System.User list whose names come out blank for non-admin roles is reported.

Security

  • MongoDB driver upgraded for the October 2026 BSON advisories — go.mongodb.org/mongo-driver/v2 v2.6.0 -> v2.9.2 and go.mongodb.org/mongo-driver v1.17.9 -> v1.17.10. A customer's release scan (Sonatype Lifecycle, blocking at CVSS >= 7) refused the published .exe over CVE-2026-107324 and CVE-2026-107325 — panics in bson.Raw.Validate (a binary element declaring a length of math.MaxInt32) and bson.RawArray.Validate (a zero-length array) — and CVE-2026-81521. mxcli imports only the BSON packages, never the mongo client, so CVE-2026-81521 (Client.BulkWrite namespace confusion) was never reachable; the two Validate panics were, on bytes read from a .mpr (modelsdk/canon/attributeref.go, modelsdk/mprread/generic.go, modelsdk/mpr/reader_raw.go, cmd/mxcli/cmd_fix_hashes.go), so a malicious project file could crash the CLI — denial of service only, no code execution. v2.9.2 is the floor for all three: CVE-2026-81521 was fixed in v2.8.2, regressed out of v2.9.0 and v2.9.1, and restored in v2.9.2. The upgrade also raises the declared github.com/klauspost/compress requirement from v1.17.6 to v1.19.2, which the same scan flagged — that module is pulled in by the driver for wire-protocol compression and is compiled into no mxcli build (it has no go.sum entry and no go version -m line). No source change and no API change; BSON encoding and decoding are unaffected.

New Contributors

Full Changelog: v0.26.0...v0.27.0