Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
b5409e4
test(backend): pin revoke create from several single-role rules (mend…
claude Oct 17, 2026
a0faea0
fix: ALTER SET writes a pluggable Boolean as "true"/"false", not "yes…
claude Oct 17, 2026
54f4dad
fix: user tasks always written with auto-assign off; add `auto assign…
claude Oct 17, 2026
3edb2b3
refactor: move the pluggable slot-keyword table into mdl/types
claude Oct 17, 2026
3b7ddae
fix: ALTER PAGE SET DataSource writes a Gallery's / Data grid 2's source
claude Oct 17, 2026
e4f85af
fix: ALTER PAGE can address a pluggable widget's slot, e.g. dataGrid1…
claude Oct 17, 2026
5b8e305
fix: ALTER PAGE reaches widgets inside legacy table cells
claude Oct 17, 2026
780f255
Merge remote-tracking branch 'origin/main' into fix/1445-user-task-au…
claude Oct 17, 2026
49b2d6c
Merge pull request #1460 from ako/fix/1454-pluggable-boolean-true-false
ako Oct 17, 2026
b31fb90
Merge remote-tracking branch 'origin/main' into fix/1445-user-task-au…
claude Oct 17, 2026
7404ba3
Merge pull request #1461 from ako/fix/1548-set-datasource-pluggable
ako Oct 17, 2026
bae4771
Merge pull request #1462 from ako/fix/957-datagrid2-controlbar-slot
ako Oct 17, 2026
bb486b1
Merge pull request #1463 from ako/fix/1453-alter-legacy-table-cells
ako Oct 17, 2026
fa3db73
fix: describe keeps statements after an if, and loop bodies, inside a…
ako Oct 17, 2026
7de4a4b
Merge pull request #1464 from ako/fix/1499-revoke-create-several-roles
ako Oct 17, 2026
81a0a01
Merge pull request #1466 from ako/fix/1445-user-task-auto-assign
ako Oct 17, 2026
3a9da86
fix: scheduled_events() empty module_name and excludeModules leak for…
claude Oct 17, 2026
d06dd92
fix: permissions() has no rows for nanoflow EXECUTE grants
claude Oct 17, 2026
14a01a9
fix(executor): refuse a statement that can never run (mendixlabs/mxcl…
claude Oct 17, 2026
974e78b
fix: documents() never returns message definitions
claude Oct 17, 2026
291d392
fix: a nanoflow's `export level api` is written, not dropped (mendixl…
claude Oct 17, 2026
257bf88
fix: user_roles() and the catalog do not expose a user role's descrip…
claude Oct 17, 2026
fd15667
fix: parse_xpath drops association paths; lint rules cannot recurse
claude Oct 17, 2026
c5ce11f
Merge remote-tracking branch 'origin/main' into fix/1491-unreachable-…
claude Oct 17, 2026
f142831
Merge remote-tracking branch 'origin/main' into fix/1498-nanoflow-exp…
claude Oct 17, 2026
bcbc5f6
Merge pull request #1469 from ako/fix/1452-scheduled-events-folder-mo…
ako Oct 17, 2026
665271b
Merge pull request #1470 from ako/fix/1434-nanoflow-permissions
ako Oct 17, 2026
f84d93c
Merge pull request #1472 from ako/fix/1442-user-role-description
ako Oct 17, 2026
495f6a2
Merge origin/main into fix/1433-documents-message-definitions
claude Oct 17, 2026
1a855e5
Merge origin/main into fix/1439-parse-xpath-assoc-paths
claude Oct 17, 2026
9630eb1
Merge pull request #1474 from ako/fix/1491-unreachable-statements
ako Oct 17, 2026
d7fe18f
Merge pull request #1475 from ako/fix/1498-nanoflow-export-level
ako Oct 17, 2026
b144644
fix: describe module prints grants after the associations they name
claude Oct 17, 2026
3f82b09
fix: import from mapping imports XML for an XML schema or web service…
claude Oct 17, 2026
758edf8
feat: sidebartoggle — author Atlas's responsive sidebar toggle
claude Oct 17, 2026
97626fe
Merge pull request #1471 from ako/fix/1433-documents-message-definitions
ako Oct 17, 2026
3d37303
Merge pull request #1473 from ako/fix/1439-parse-xpath-assoc-paths
ako Oct 17, 2026
f16b356
fix: a one-to-one association member in a message definition no longe…
claude Oct 17, 2026
67ed266
fix: create external entities names entities after the entity type, a…
claude Oct 17, 2026
8560ac7
fix: importing partnered OData navigation properties no longer fails …
claude Oct 17, 2026
2e66ad1
fix: copying an Atlas layout keeps its header bar and native parts
claude Oct 18, 2026
d9e3172
Merge remote-tracking branch 'origin/main' into claude/describe-round…
claude Oct 18, 2026
dea64cd
Merge pull request #1479 from ako/claude/integration-contract-drift-9…
ako Oct 18, 2026
7a6a603
Merge pull request #1478 from ako/claude/integration-contract-drift-9…
ako Oct 18, 2026
686c318
Merge pull request #1480 from ako/claude/integration-contract-drift-9…
ako Oct 18, 2026
b73fe8c
Merge pull request #1481 from ako/claude/describe-round-trip-gaps-fix…
ako Oct 18, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend/pagemutator", "date": "2026-10-17", "symptom": "after `drop` removed a Data grid 2's last control-bar button, describe printed no `controlbar` and every route back was refused: `insert into controlBar1` (\"widget not found\", with a DataGrid2-columns hint) and `insert into dataGrid21` (\"not a simple container\", reported as CustomWidgets$CustomWidget)", "cause": "the control bar is the grid's filtersPlaceholder widgets-property — a slot with no Name, not a widget — and no dotted address reached a pluggable widget's own slots; describe omits an empty slot, which made the drop look like it deleted the bar (it does not: Widgets [2] stays)", "file": "`mdl/backend/pagemutator/pluggableslot.go` (new), `alter_target.go`, `mutator.go` (`InsertWidget`/`ReplaceWidget`/`DropWidget`); slot keyword table moved to `mdl/types/widget_slot_keywords.go`", "insight": "The reporter called it a classic grid; the error's $Type (CustomWidgets$CustomWidget) was the tell that it is a Data grid 2 whose filtersPlaceholder describe spells `controlbar`. Diff the BSON before and after the drop before believing 'the bar was deleted' — the slot survived, describe hid it. Address a slot like a data view footer (`grid.controlbar`), resolving the keyword through the same table describe/create use (moved to mdl/types so the mutator cannot drift from it), and wire the generic ALTER resolver (ResolveAlterTarget) as well as the operation — the first end-to-end run passed the mutator tests and still failed at 'failed to resolve page target'", "refs": ["mendixlabs/mxcli#957", "ako/mxcli#1278"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend", "date": "2026-10-17", "symptom": "Re-executing a microflow with `$V = import from mapping M.Import_mapping($latestHttpResponse);` whose mapping is built on a web service operation: mx check \"The selected import mapping cannot handle content type JSON.\" Opening the activity in Studio Pro fixes it: \"This action now imports XML\"", "cause": "`importXmlActionToGen` (and the REST mapping result handling in `restResultHandlingToGen`) wrote `ImportMappingCall.ContentType` as the constant \"Json\"; the reader never read it, so even a pass-through rewrite of a stored XML import turned it into JSON", "file": "`mdl/backend/modelsdk/microflow_write.go`, `mdl/backend/modelsdk/microflow_read_actions.go` (`readMappingCall`), `mdl/executor/cmd_microflows_builder_calls.go` (`importMappingContentType`)", "insight": "The content type is a property of the MAPPING's source (XML schema or web service → Xml, JSON structure → Json), which the builder already fetches for the result entity — derive it there, and carry the stored value on read so a rewrite never re-derives what it cannot see. `call web service` already wrote Xml (microflow_webservice_write.go); grep `\"ContentType\", \"Json\"` for any other constant. Not run against mxbuild: MDL cannot author an XML schema or WSDL import and no testdata fixture has a mapping built on one (grep for `ImportedWebService` in mprcontents finds none) — the reporter's mx check on 11.12.4 is the evidence that Json is refused. Message-definition mappings stay Json, unmeasured", "refs": ["#1290", "mendixlabs/mxcli#1232"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend/pagemutator", "date": "2026-10-17", "symptom": "alter page/snippet set / insert / replace / drop on a widget inside a legacy table cell reports `widget \"X\" not found`; field scripts fell back to BSON patches", "cause": "findInWidgetChildren, findNearestDSInChildren and collectWidgetScopeInChildren walked every other child list but not a Forms$Table's Cells[].Widgets[]", "file": "`mdl/backend/pagemutator/mutator.go` (the three child walkers)", "insight": "Three walkers must learn every new child list together (the same trio #891 and #1388 each extended); a finder-only fix resolves the target but builds inserted widgets without the cell's data context. Keyed on the `Cells` list, not on $Type: a Mendix 11 cell is Forms$DbTableCell, which gen does not model (widget_list_markers.go), and Forms$Table is the only page type with a Cells list. Not yet run against a Studio Pro-authored table — none exists in testdata and MDL cannot create one; a wrong key guess fails safe as the same not-found", "refs": ["mendixlabs/mxcli#1453", "ako/mxcli#1326"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend/pagemutator", "date": "2026-10-17", "symptom": "`alter page … set (showFooter: true, clearable: false) on <combobox>` stores PrimitiveValue \"yes\" / \"no\"; mx check passes and the client reads \"yes\" as false, so a bare `true` turns the property off", "cause": "setPluggableWidgetPropertyMut spelled every Go bool as yes/no regardless of the property's declared ValueType.Type, although Studio Pro and the widget template store a Boolean as true/false", "file": "`mdl/backend/pagemutator/mutator.go` (`setPluggableWidgetPropertyMut`, new `pluggableBooleanSpelling`)", "insight": "The literal's type is not the stored type: the spelling must come from the schema (propKindMap) the same way columnValueField already picks the value field. yes/no is real only as the keys of an Enumeration that declares them (the reporter's 17.5k-unit scan: 0 yes/no among 13k Boolean values, 2.1k among enumerations), so those keep taking a boolean and any other enumeration refuses one. A unit test named TestSetWidgetProperty_PluggableWidget had pinned \"no\" on a kindless fixture — the bug's spelling was the asserted contract. mx check accepts both spellings (0 errors on fixed and unfixed builds), so only the stored bytes show it", "refs": ["mendixlabs/mxcli#1454", "ako/mxcli#1327"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/backend","date":"2026-10-17","symptom":"`revoke create on entity M.E from M.RoleA, M.RoleB, M.RoleC` printed \"Unchanged entity access: M.E (M.RoleA, M.RoleB, M.RoleC) — nothing to revoke\", exited 0, and `show access` still listed `Rights: create, read` for all three single-role rules (two with XPath, one without); check and mxbuild clean (mendixlabs/mxcli#1499).","cause":"Same as #1501: RevokeEntityMemberAccess only narrowed a rule whose role set EQUALLED the statement's, and every partial revoke — entity-level create/delete as well as member read/write — goes through that one matcher. Already fixed on main by fb0cec9c (#1501); #1499 was reported against v0.25.0, before it.","file":"mdl/backend/modelsdk/domainmodel_security_write.go (RevokeEntityMemberAccess target selection); test mdl/backend/modelsdk/revoke_create_1499_test.go","insight":"The reporter filed #1499 (create) and #1501 (write member) as separate bugs because the rights differ, and the dedupe against #1225 was right — but the variable shared by both was the multi-role statement over one-role-per-rule grants, not the right. Before fixing a revoke report, check which matcher the statement reaches: every partial revoke funnels into one target selection, so a fix there closes every right at once while its tests pin only the right the first report named. Pin the other rights with their own test; the control is restoring the `sameStringSet` equality guard, which reproduces 0 modified and create kept on all three.","refs":["mdl/backend/modelsdk/revoke_create_1499_test.go","mdl-examples/bug-tests/1499-revoke-create-from-several-roles.mdl","mendixlabs/mxcli#1501","mendixlabs/mxcli#1225"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend/pagemutator", "date": "2026-10-17", "symptom": "`alter page … set (DataSource: microflow M.F) on <gallery|datagrid2>` passes check, prints \"Altered page\", and the page unit is byte-identical; the same statement on a list view works", "cause": "SetWidgetDataSource ended with bsonnav.DSet(widget, \"DataSource\", …) and ignored its result; a CustomWidgets$CustomWidget has no top-level DataSource key (the source is Object.Properties[datasource].Value.DataSource), so DSet replaced nothing", "file": "`mdl/backend/pagemutator/mutator.go` (`SetWidgetDataSource`, new `setPluggableDataSource`, `pluggableDataSourceValue`)", "insight": "bsonnav.DSet replaces an existing key and returns false otherwise — an ignored DSet result is a silent-success generator, and grep for bare `bsonnav.DSet(` statements is a quick audit for the class. The READ side (widgetOwnDataSourceDoc, #1076) had already learned both locations; the write side had not, so the fix reuses that walk. The pluggable source is serialized with deps.SerializeCustomWidgetDataSource, the serializer CREATE/INSERT use for the same property, not serializeDataSourceBson; only microflow/nanoflow are written, and other kinds are refused with a pointer to REPLACE. check's dry run (probe.go) runs the real setter, so that refusal reaches check with no extra code", "refs": ["mendixlabs/mxcli#1548", "ako/mxcli#1446"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/backend","date":"2026-10-17","symptom":"Every user task written with AutoAssignSingleTargetUser = false; no MDL clause, not in describe, and create or modify workflow turned off a box ticked in Studio Pro — completing the task from a microflow then failed at runtime with 'it is not assigned to you'; check and mx check silent","cause":"userTaskToGen wrote addBool(g, \"AutoAssignSingleTargetUser\", false) as a constant (the MCP route sent the same literal); the reader never read the property, so the rewrite guard, which counts stored settings, had nothing to compare","file":"mdl/backend/modelsdk/workflow_write.go, mdl/backend/mcp/workflow.go, mdl/executor/validate_workflow_rewrite.go","insight":"This is the 'loss set is every constant the rebuild writes' audit from rewrite-drops-unauthored-state, missed for a property that sat one line above the guarded AwaitAllUsers: grep the writer for addBool/addStr with a literal and each hit is a candidate. Studio Pro's default for a NEW task is false (Model SDK default false; ako/TestApp 11.14.0 stores false on all three of its user tasks), so the default was right and only the reset was wrong — the fix is restate-or-refuse like await all users, not a changed default. A carry (keep stored value when omitted) was the reporter's ask but cannot work for a presence-only boolean clause: omission could then never turn it off. On mxcli-authored content the stored value IS the constant, so only a fixture with the flag set to true can show the bug.","refs":["#1445","mendixlabs/mxcli#1547"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-10-17","symptom":"Inside a custom error handler, `describe microflow` printed nothing after an `if … end if;` (\"The description goes from `end if;` straight to `end error;`\") and printed a loop as its bare header (`loop $Order in $Orders`, no begin/body/end loop). No warning; `create or modify` said Unchanged; drop + create rerouted the handler's tail into the main flow (a failed call logged `done` and returned 1), `mx check` clean. The loop shape did not parse","cause":"Two gaps in the handler walk (`collectErrorHandlerStatementSpans`), a second, smaller describer. (1) Its stop, `firstReachableErrorHandlerMerge`, was \"the first merge with more than one way in\" — and the merge closing an `if` in the handler body is exactly that, so it became the boundary and the split's continue-after-merge step was skipped (`nestedMergeID == boundary`). (2) It formatted a LoopedActivity with `formatActivity`, i.e. the header only, never calling `emitLoopBody`","file":"`mdl/executor/cmd_microflows_show_helpers.go` (`firstReachableErrorHandlerMerge`, the traverse closure in `collectErrorHandlerStatementSpans`)","insight":"The handler's exit is the first merge with a way in from OUTSIDE the handler (any origin not reachable from the handler start over normal flows), not the first multi-entry merge; the old no-op-merge rule (#1078 follow-up) is the one-way-in special case of this. Ask which walk disagrees: the main describer and the handler walk each re-implement compound statements, and every shape the handler walk lacks (loop body here, nested custom handlers still) is a silent drop there. `assertDescriptionRebuildsGraph` caught the reroute as `invented flow … -> LogMessageAction(main)` — use it for every handler shape. Controls: dropping the `joinsOutside` check fails both if-tests, disabling the loop branch fails the loop test. E2E on 11.12.4: reporter's script, describe → drop+create → describe is byte-identical, `mxcli docker check` passes. Not fixed here: an `if` without `else` in a handler still prints an empty `else` (parses, rebuilds the same graph)","refs":["#1456","mendixlabs/mxcli#1559","#1078"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-17", "symptom": "Replaying `describe` output into a second app: `Created entity: ModA.EntA` then `Error: entity ModA.EntA has no member(s) EntA_EntB; grant only names members of the entity or of an entity it inherits from`, after `check` printed \"Check passed!\". Seen in the field on `describe module` of EchoConnector and NativeNote", "cause": "`describe module … with all` called `describeEntity` per entity, which prints the entity's grants inline, and only then the associations — so a grant naming an association it owns came before the `create association`. exec resolves a grant's member list when it writes the grant. `check`'s grant pass resolved members against `g.whole.associations` (the whole script) and skipped script-declared entities altogether, so it accepted the forward reference", "file": "`mdl/executor/cmd_modules.go` (`describeModule`), `mdl/executor/cmd_entities_describe.go` (`describeEntityWith`), `mdl/executor/validate_grant_refs.go` (`memberProblem`, `laterAssociationProblem`)", "insight": "An association is a member of its FROM entity but a statement of its own, so any emitter that prints per-entity (grants with the entity) can order a member after its use. Grep for other `whole`-vs-`sc` reads in check passes: resolving against the whole script is exactly what makes check blind to ordering that exec enforces. The grant check keeps skipping a declared entity's attribute list (that would be a second copy of exec's) but an association is checked anyway, because its position is the script's choice. Controls: the new pedapp tests fail on the old code with the reported message (describe replay) and with an empty check report (agreement test). `describe entity` alone still prints its grants inline — concatenating `describe entity` before `describe association` by hand is now caught by `check -p` instead", "refs": ["#1315", "mendixlabs/mxcli#1409"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-17", "symptom": "`create external entities from M.Client into M` names a top-level entity after the OData entity SET (`ModA.Parts`) where Studio Pro names it after the entity TYPE (`ModA.Part`); a later script using `ModA.Part` fails with \"entity does not exist\"", "cause": "`createExternalEntities` chose `entitySet.Name` for every top-level entity, and the navigation-association and primitive-collection passes re-derived the same name to find their ends. `describe contract entity … format mdl` already emitted the type name, so mxcli disagreed with itself as well as with Studio Pro", "file": "`mdl/executor/cmd_contract.go` (`createExternalEntities`, `createNavigationAssociations`, `createPrimitiveCollectionNPEs`, new `importedEntityFor`)", "insight": "**The evidence for Studio Pro's naming was already in the repo**: the TripPin measurement tables in cmd_contract.go and the complex-type tests list `Person (entity set People)` — a Studio Pro-generated entity named after the type. Grep the measured tables before asking for a Studio Pro reference. **A rename of what an import produces is a re-import hazard, not just a cosmetic fix**: matching the existing entity by the NEW name makes every project imported by an older mxcli grow a type-named twin mapping the same entity set, and mx check does not complain (both entities are valid). So the upsert resolves by remote identity first (Source=Rest$ODataRemoteEntitySource + RemoteServiceName + RemoteEntitySet, all read back by the modelsdk reader) and keeps the old name, which pages and microflows already use. Name resolution happened in THREE passes; changing only the first leaves the association pass looking up the old name and silently creating no associations — a test that asserts the association exists catches it. Test fixtures need nav-property names that do not collide with entity names, or uniqueAssocName suffixes them (`Supplier_2`) and the assertion fails for an unrelated reason. Measured on 11.12.1: base build reproduces `external entity not found: Issue1432.Product`; fixed build creates Product/Category, mx check 0 errors; a project imported by the base build and re-imported by the fixed one reports `0 created, 2 updated` and keeps Products/Categories. Tests `cmd_contract_entity_name_test.go`; repro `mdl-examples/bug-tests/1432-external-entities-named-after-entity-type.mdl`", "refs": ["mendixlabs/mxcli#1432", "ako/mxcli#1319"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-17", "symptom": "A message definition member over a one-to-one association (`type Reference owner Both`) fails `mx check` with CE6524 \"The occurrence of 'Shop.CustomerProfile_Customer' has changed\" — on CREATE, on CREATE OR MODIFY of unchanged describe output, and on ALTER … ADD MEMBER; `exec` and `describe` look clean", "cause": "`resolveAssociationCardinality` returned MaxOccurs -1 for every REVERSE traversal (holder is the TO end). Owner Both on a Reference makes it one-to-one, so the reverse is a single object (1) too", "file": "`mdl/executor/cmd_messagedefinitions.go` (`resolveAssociationCardinality`)", "insight": "The cardinality table had two axes measured (direction, Reference vs ReferenceSet) and a third that the corpus never exercised: OWNER. When a rule's measurement corpus has no example of a property (no ReferenceSet then, no Owner Both now), the rule is unmeasured on that property, not exceptionless. CE6524 is a reliable oracle for the occurrence — mxbuild recomputes it from the domain model — so the fix is settled by mx check, no Studio Pro reference needed: base build 2x CE6524, fixed 0, with the forward definition in the same script as the control (clean on both). Owner is read from the association already in hand; ReferenceSet Owner Both stays -1 both ways. Tests `TestOneToOneAssociationIsSingleInBothDirections`; repro `mdl-examples/bug-tests/1386-message-definition-one-to-one-occurrence.mdl`", "refs": ["mendixlabs/mxcli#1386", "ako/mxcli#1311"], "ce": ["CE6524"]}
Loading
Loading