fix: TimeRegistration findings #51–#55 (ALTER-PAGE assoc binding, microflow check false-positives, workflow-action describe) - #55
Merged
Conversation
… bindings (FINDINGS #55) ALTER PAGE INSERT/REPLACE into a ListView bound `from association` produced a widget whose Attribute binding pointed at the wrong entity — the outer data view's entity instead of the association's destination — or no binding at all. `mxcli check` passed; the Mendix build then failed with CE1613 "The selected attribute 'Module.OuterEntity.Attr' no longer exists", and DESCRIBE masked it by printing only the short attribute name. Root cause: the page mutator read the enclosing entity from DataSource.EntityRef.Entity, which is only populated for a DIRECT entity ref (database source). An AssociationSource stores its destination on the last DomainModels$EntityRefStep of an IndirectEntityRef, so the mutator saw no entity for the list and left the context at the outer data view's entity; the inserted bare attribute then resolved against that outer entity. Fix: extractEntityFromDataSource now also reads the IndirectEntityRef's last EntityRefStep.DestinationEntity (new lastStepDestinationEntity helper), so a list bound `from association` reports its correct child entity to INSERT/REPLACE. Verified on real mxbuild 11.12.1: the nested dataview→association-listview→insert and →replace cases now `mx check` with 0 errors (CE1613 before). Unit guard TestEnclosingEntity_AssociationSource; repro mdl-examples/bug-tests/55-alter-page-insert-assoc-binding.mdl. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…ore workflow-action describe (FINDINGS #51–54) Four findings from the TimeRegistration retest, all verified against real mxbuild 11.12.1: #53 — MDL048 rejected `retrieve … where [id = '[%CurrentUser%]']`, the standard signed-in-user idiom (mx check → 0 errors). checkXPathIdConstraint now skips a `'[%…%]'` server-token operand; a real stored-id value is still flagged. #52 — MDL045 rejected division whose divisor is an association-attribute path, e.g. `round($a div $obj/Attr * 100)`. The grammar parses div/*/`/` at one precedence level, so `$a div $obj/Attr` mis-nests as `($a div $obj) / Attr` with `Attr` a bare identifier; MDL045 saw the `/` as division. Mendix has no `/` division operator and re-parses the raw `$obj/Attr` as a path — the serialized output preserves the `/` and mx check passes. exprHasSlashDivision now ignores a `/` whose right operand is a bare IdentifierExpr (member navigation). #54 — `describe microflow` printed `-- Empty action` for `set task outcome` (and open user task / notify workflow) under the default modelsdk engine, so a describe→drop→exec round-trip silently dropped it. The write path and describe formatter already handled these; only the modelsdk read case (actionFromGen) was missing. Added SetTaskOutcome/OpenUserTask/NotifyWorkflow read cases. #51 — `create association` erroring on re-run is correct SQL-shaped semantics (not idempotent); the idempotent form `create or modify association` was undiscoverable. Improved the "already exists" error to name it (and `drop association …`). (#50 daysBetween sign and #52's dateTime-literal restriction are genuine Mendix platform behavior — the latter is already surfaced by MDL046 — so no code change.) Tests: TestValidateMicroflow_XPathIdConstraint (CurrentUser token), TestValidateMicroflow_SlashDivision (div-by-assoc), TestActionFromGen_WorkflowActions. Repros: mdl-examples/bug-tests/{52-53-microflow-check-false-positives,54-describe-set-task-outcome,51-create-or-modify-association}.mdl. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…ERT/REPLACE bindings (FINDINGS #55) Retest of #55 showed the association + database datasource cases are fixed, but a microflow/nanoflow datasource still bound nothing: inserting/replacing a data-bound widget in a list bound `datasource: microflow …` produced an unbound attribute (mx check CE0402 "No value specified" / CE1613). Unlike a database (direct EntityRef) or association (IndirectEntityRef) source, a MicroflowSource/NanoflowSource stores no entity in its own BSON — the entity is the flow's RETURN type, which lives in the flow document. So the mutator's BSON walk yielded "" and the bare inserted attribute resolved against nothing. Fix: the page mutator's new EnclosingDataSourceFlow returns the qualified name of the microflow/nanoflow governing the target's context — the nearest ENCLOSING datasource for sibling INSERT/REPLACE, or the widget's OWN datasource for INSERT INTO — via findNearestDataSourceDoc, which returns the nearest datasource *doc* so a nearer non-flow source (database/association) correctly shadows an outer flow. The executor (resolveDataSourceFlowEntity) then resolves that qualified name to the flow's return entity via the existing getMicroflowReturnEntityName / getNanoflowReturnEntityName, and uses it as the widget's entity context when the BSON walk found none. Verified on real mxbuild 11.12.1: INSERT and REPLACE into a microflow-sourced ListView now mx check with 0 errors (CE0402 before). New EnclosingDataSourceFlow interface method + mock/mcp impls (mcp is a no-op — its model resolves entities directly). Unit guard TestEnclosingDataSourceFlow (incl. nearer-source shadowing); repro extended in mdl-examples/bug-tests/55-alter-page-insert-assoc-binding.mdl. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
…ct arg (write is correct) Investigation of FINDINGS #56 ("describe page omits a show_page action's arguments"), verified against mxbuild 11.12.1: A widget button's show_page stores FormSettings.ParameterMappings as an empty list [2] and Mendix infers the current-row object for each unmapped page parameter. Storing an explicit `Argument: "$currentObject"` mapping makes mxbuild report CE0115 "arguments do not match" — the original issue mendixlabs#296, re-confirmed here. So the empty-mapping write is REQUIRED for a building app. Consequence: `show_page X` and `show_page X($p = $currentObject)` serialize to identical BSON, so describe→drop→exec re-produces a byte-identical valid page — the round-trip is functionally lossless; only the redundant $currentObject annotation is not echoed. No writer change (a fix there reintroduces CE0115); clarified the serializer comment and added a bug-test documenting the verified behavior and the boundary (a non-$currentObject widget page arg needs a Studio-Pro WidgetValue reference to encode). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01JXnEgoc2NQP1Y2TWMCMXC4
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes five findings from the
ako/mxcli-timeregistrationretest. Every fix was verified against real mxbuild 11.12.1 (not justmxcli check), and each has a regression test + amdl-examples/bug-tests/repro + afix-issue.mdsymptom row.Findings addressed
#55 —
ALTER PAGE INSERT/REPLACEdropped a widget's attribute binding in a non-database-sourced list (c663f7af,a91e7329)Inserting/replacing a data-bound widget into a list whose datasource was
from associationordatasource: microflow/nanoflowbound the new widget'sAttributeto the wrong entity, or to nothing —mxcli checkpassed but the Mendix build failed CE1613 / CE0402, and DESCRIBE masked it by printing only the short attribute name. Root cause: the page mutator read the enclosing entity fromDataSource.EntityRef.Entity, which is only populated for a direct ref (database).c663f7af): the destination lives on the lastEntityRefStepof anIndirectEntityRef.extractEntityFromDataSourcenow reads it.a91e7329): a flow source stores no entity in its BSON — its entity is the flow's return type (in the flow document). The mutator's newEnclosingDataSourceFlowreturns the governing flow's qualified name (nearest-enclosing for sibling INSERT/REPLACE, or own for INSERT INTO; a nearer non-flow source shadows an outer flow), and the executor resolves the return entity viagetMicroflowReturnEntityName/getNanoflowReturnEntityName.Verified: nested dataview→assoc-listview, and microflow-sourced listview, both INSERT and REPLACE →
mx check0 errors (CE1613/CE0402 before). This also closes the remaining half of #49.#53 — MDL048 false-positive on
[id = '[%CurrentUser%]'](25b02acd)The standard signed-in-user idiom (mx-check clean) was rejected.
checkXPathIdConstraintnow skips a'[%…%]'server-token operand; real stored-id values ([id = $Id]) are still flagged.#52 — MDL045 false-positive on division by an association-attribute path (
25b02acd)round($a div $obj/Attr * 100)was rejected. The grammar parsesdiv/*//at one precedence level, so$a div $obj/Attrmis-nests as($a div $obj) / Attr; Mendix has no/-division operator and re-parses the raw$obj/Attras a path (serialized output preserves the/, somx check→ 0 errors).exprHasSlashDivisionnow ignores a/whose right operand is a bareIdentifierExpr.#54 —
describe microflowrenderedset task outcomeas-- Empty action(25b02acd)Under the default (modelsdk) engine,
set task outcome/open user task/notify workflowread back as-- Empty action, so a describe→drop→exec round-trip silently dropped them. Added the three read cases toactionFromGen, mirroring the legacy parsers.#51 —
create associationnot idempotent (25b02acd)The corrupting cascade was already fixed (mendixlabs#90).
create associationerroring on re-run is correct SQL-shaped semantics; the idempotent formcreate or modify associationwas undiscoverable. Improved the "already exists" error to name it (anddrop association …).Not code changes: #50 (
daysBetweensign) is Mendix runtime behavior with no mxcli surface; #52'sdateTime()-literal restriction is genuine platform behavior already surfaced by MDL046.Testing
TestEnclosingEntity_AssociationSource,TestEnclosingDataSourceFlow(incl. nearer-source shadowing),TestValidateMicroflow_XPathIdConstraint(CurrentUser token),TestValidateMicroflow_SlashDivision(div-by-assoc),TestActionFromGen_WorkflowActions.mdl-examples/bug-tests/{55-alter-page-insert-assoc-binding,52-53-microflow-check-false-positives,54-describe-set-task-outcome,51-create-or-modify-association}.mdl.go build ./...,go vet, and themdl/executor+mdl/backend/{modelsdk,pagemutator,mcp}suites all pass.mx create-project(11.12.1) and confirmed withmx check→ 0 errors.🤖 Generated with Claude Code