Fix inheritance handling in security, mappings, XPath rendering and the Java version dialect - #820
Merged
Conversation
…ixlabs#772) Mendix stores sibling predicate groups concatenated in one XPathConstraint field: [Reminders.Task_TaskGroup/Reminders.TaskGroup[EndDate = $EndDateLimit]] [Status != 'Completed'] [CompletionDate = empty] The grammar's xpathConstraint rule matches ONE bracket group. ParseXPathConstraint removes the error listeners, so ANTLR parsed the first group, left the rest on the token stream, and still returned ok=true. enrichXPathConstraintForDescribe read that as a full parse and re-rendered only what came back — its `if !ok { return original }` fallback never fired — so describe emitted: where Reminders.Task_TaskGroup/Reminders.TaskGroup[EndDate = $EndDateLimit]; That is worse than a crash. The output looks complete while describing a materially less restrictive query than the project contains, which makes correct defensive code read as buggy — and `describe` is what an agent reads to decide whether code is right. Fixed in two layers: 1. ParseXPathConstraint reports a partial parse as a failure (require the token stream to be at EOF). That alone stops the data loss: the caller falls back to the stored string, which the render path then splits correctly. 2. visitor.SplitXPathPredicateGroups splits a constraint into its top-level groups, and each is enriched and rendered separately — so enum enrichment reaches groups after the first, not just the first. The splitter tracks nesting depth and quoting, because the previous "][" split mangled both a nested [A/B[x = 1]] and a literal containing ']'. The render path now uses it too. Verified end-to-end on a real 11.12.2 project carrying the reported constraint shape: all three groups render, Status is enriched to its qualified enum value in the second group, the output re-parses and re-executes to an identical flow, and `mx check` reports 0 errors. A/B against a pre-fix binary on the same project reproduces the two dropped groups exactly as reported. All three guards mutation-checked. Refs mendixlabs#772
…ndixlabs#758, mendixlabs#765) Mendix models inheritance across multiple tables: a child adds attributes to the parent's, and all of the parent's are members of the child. An access rule must therefore carry a MemberAccess entry for every member — own AND inherited — or Mendix reports CE0066 "Entity access is out of date". Both the GRANT builder and ReconcileMemberAccesses enumerated only entity.Attributes. Two consequences, and the second explains why the first could not be worked around: * GRANT naming an inherited member produced no entry at all, while reporting success. * Reconciliation runs immediately after every GRANT, and on any write touching the module. An inherited reference is qualified against the entity that DECLARES it, so it never matched the child's own attribute list and was deleted as stale — removing, in the same command, what the grant had just written. That is why REVOKE + GRANT never repaired a damaged rule. The damage was masked: mx check reports CE0066 and stops, hiding the CE2729 "No read access to attribute" cascade until Studio Pro's Update security is clicked, so CLI-only workflows shipped it undetected. Two facts were established against mx check rather than inferred: 1. An inherited member's reference must be qualified against its declaring entity. Sec758.Base.SharedField validates clean; the child-qualified Sec758.Item.SharedField is CE1613 "The selected attribute no longer exists". mxcli wrote the child form. This is the same rule the change-object writer needs (mendixlabs#451). 2. System.User's members are the exception. Entities specialising it are user entities whose platform members Mendix manages: listing them turns a clean rule into CE0066 — confirmed on Mendix's own Administration.Account and on a fresh specialisation — while omitting System.FileDocument's six members is CE0066 until all are present. Fixed: * EntityMembers walks the generalization chain, qualifying each member against its declaring entity and excluding System.User's platform members. The GRANT builder uses it, and now rejects a named member that matched nothing instead of dropping it in silence. * Reconciliation strips only a reference qualified to the entity itself. An ancestor may live in another module or in System, neither of which is loaded at that layer, so an inherited reference cannot be validated there — it is preserved rather than deleted. Applied to both engines. Verified end-to-end on a real 11.12.2 project carrying all three specialisation shapes at once — same-module ancestor, System.FileDocument, and System.User — mx check reports 0 errors, and describe round-trips both members of the mixed entity. All three guards mutation-checked. Refs mendixlabs#758, mendixlabs#765
Nothing about entity inheritance appeared in any security doc, even though a specialized entity's access rule must cover its inherited members and getting it wrong is CE0066. Added to each surface the story touches: - mxcli syntax security.entity-access — an "Inherited members" block plus examples for a same-module ancestor and System.FileDocument - skills/mendix/manage-security.md — worked example, the None-rights detail, the new unknown-member error, and the System.User exception - skills/mendix/generate-domain-model.md — a pointer from EXTENDS, where a reader meets inheritance first - docs-site security/grant.md — the same as reference prose - MDL_QUICK_REFERENCE.md — the grant-entity-access row Covers what mendixlabs#758/mendixlabs#765 made work: inherited members are named exactly like the entity's own, READ */WRITE * include them, unmatched names are an error rather than a silent skip, and entities extending System.User must not grant their inherited platform members.
…ixlabs#703) Mendix inheritance is multi-table: a child adds attributes to its parent's, and all the parent's are members of the child. A mapping element bound to one must reference the entity that DECLARES it. The builder prefixed the entity being mapped, unconditionally: attr := def.Attribute if parentEntity != "" && !strings.Contains(attr, ".") { attr = parentEntity + "." + attr // always the CHILD } so every inherited field produced a reference to an attribute that entity does not have. Studio Pro shows the field unmapped — the reported symptom — and mx check reports CE1613 "The selected attribute ... no longer exists". A second, quieter defect sat next to it: resolveAttributeType scanned only the entity's own attributes and fell through to a "String" default, so an inherited Boolean or DateTime element carried the wrong DataType even once the reference was correct. That function also matched entities by name across every domain model, ignoring the module, so a same-named entity elsewhere could win; it now resolves the module by name. Both the import and export builders carried the same two lines, and both are fixed. They route through the generalization walk added for mendixlabs#758, generalised here into ResolveMemberRef (declaring-entity reference) and ResolveMemberType (type from up the chain), each falling back to the previous behaviour when the member cannot be resolved. EntityMembersFor takes the backend directly so the mapping builders, which hold no ExecContext, can use it. This closes the mapping half of the mendixlabs#765 umbrella; the same declaring-entity rule governs entity access rules (mendixlabs#758) and the change-object writer (mendixlabs#451). Verified end-to-end on a real 11.12.2 project with an entity extending another, mapping one own and two inherited attributes in both directions: before: Map703.Contract.DocName StringType -> CE1613 Map703.Contract.Confidential StringType -> CE1613 after: Map703.DocumentBase.DocName StringType Map703.DocumentBase.Confidential BooleanType mx check -> 0 errors Both halves mutation-checked, including a test at the resolveAttributeType call site rather than only on the resolver — reverting the call site alone left the resolver's own test green. Docs: inheritance was unmentioned in every mapping doc, so the syntax topic, the json-structures-and-mappings skill and docs-site create-import-mapping now cover it. Refs mendixlabs#703, mendixlabs#765
The doctype example granted read on SecTest.Customer (Notes), but the entity only declares Name, Email and IsActive. Before mendixlabs#758 an unmatched member name was dropped in silence, so the grant did nothing and the script still passed; with that silence replaced by an error the example fails, and the integration tier caught it. The example is what is wrong: its own comment says "adding Notes access preserves existing Name and Email", so it always meant to demonstrate an additive grant on a third attribute. Declaring Notes makes it do that. Fixes the build-and-test failure on main introduced by #81.
The mendixlabs#759 fix followed the JavaVersion -> JavaMajorVersion key rename but wrote the caller's value through verbatim. The rename changed the value format too: 11.6 stores the enum member "Java21", 11.12 the bare major "21". So `alter settings model JavaVersion = 'Java21'` on an 11.12 project put "Java21" into JavaMajorVersion, and mxbuild refuses to load it: System.ArgumentOutOfRangeException: Specified argument was out of the range of valid values. (Parameter 'majorVersion is an unsupported value: Java21') at Mendix.Modeler.Settings.JavaVersionExtensions.fromString This is a harder failure than the original mendixlabs#759 shape. That one wrote an unknown property, which mxbuild tolerates, so only Studio Pro broke; a wrong value for a known enum fails the whole project load, taking every check downstream of the settings unit with it. It is why the nightly went red on 14-project-settings-examples.mdl at 11.12 rather than surfacing as a user report. settingsoverlay.JavaVersionValue renders the value per stored key, so either spelling is accepted on input and stored in the project's own dialect. A value with no recognisable major version passes through untouched, so a typo surfaces as a Mendix error rather than as a silently mangled setting. Verified on real projects with mx check: 11.12.2 given 'Java21' stores '21' and checks clean on both engines (pre-fix binary reproduces the nightly error exactly); 11.6.6 given '21' stores 'Java21', 0 errors. Also routes the unused third copy in modelsdk/mpr/serialize_services.go through the same helper, so wiring it up later cannot reintroduce this. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012XR649rKk68z6gBpngu6MA
fix: write the Java version in the dialect the stored key expects
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.
Five fixes from issue triage on this fork, each verified against a real Mendix project with
mx checkand covered by a regression test plus an MDL repro fixture inmdl-examples/bug-tests/.Take this one for the red nightly. The last sync's #759 fix regressed
alter settings model JavaVersionon Mendix 11.12 — first bullet below. Until it lands,14-project-settings-examples.mdlfails on every Mendix version and both engines.The nightly regression
Java version: the rename changed the value format, not just the key. Mendix renamed
JavaVersiontoJavaMajorVersionbetween 11.6 and 11.12 and moved the value with it — 11.6 stores the enum member"Java21", 11.12 the bare major"21". The Runtime Configuration ( Create or Update ) are not fully supported #759 fix followed only the key and wrote the caller's value through verbatim, soalter settings model JavaVersion = 'Java21'put"Java21"intoJavaMajorVersionand mxbuild refuses to load the project:ArgumentOutOfRangeException ... (Parameter 'majorVersion is an unsupported value: Java21')atJavaVersionExtensions.fromString.Note the failure mode is sharper than the original Runtime Configuration ( Create or Update ) are not fully supported #759 shape. That one wrote an unknown property, which mxbuild tolerates — only Studio Pro broke, so it took a user report to surface. A wrong value for a known enum fails the whole project load, taking every check downstream of the settings unit with it.
settingsoverlay.JavaVersionValuenow renders the value in the dialect the stored key expects, so either spelling is accepted on input and one MDL statement is portable across versions. Verified withmx checkon real projects: 11.12.2 given'Java21'stores'21'and checks clean on both engines (a pre-fix binary reproduces the nightly error exactly); 11.6.6 given'21'stores'Java21', 0 errors.Inheritance: a member reference belongs to the entity that declares it
Three of these turned out to be the same rule applied in different places — the umbrella issue is #765.
Security reconciliation (UPDATE SECURITY / CREATE ASSOCIATION) strips inherited members from access rules of specialized entities; damage masked by CE0066 and unrepairable via GRANT #758 / Root cause: member/attribute enumerators don't walk the generalization chain (umbrella for #758, #703, #451) #765 — security writes stripped inherited members from access rules. Mendix inheritance is multi-table: an access rule needs a
MemberAccessentry for every member, own and inherited, each qualified against the declaring entity. Both theGRANTbuilder andReconcileMemberAccessesenumerated only the entity's own attributes, so inherited references matched nothing and were deleted as stale — and reconciliation runs immediately after everyGRANT, silently undoing what the grant had just written correctly.mx checkshowed only CE0066, hiding the CE2729 cascade until Studio Pro's "Update security" was clicked.Two facts here were established against
mx check, not inferred: the child-qualified form is CE1613 while the declaring-entity form validates clean; andSystem.Useris the exception — entities specialising it are user entities whose platform members Mendix manages, so listing them turns a clean rule into CE0066, while omittingSystem.FileDocument's six members is CE0066 until all are present.Create or modify import/export mapping silently skips attributes inherited from a generalized (parent) entity #703 — import/export mappings skipped inherited attributes. The mapping builder prefixed the mapped entity unconditionally, so every inherited field showed unmapped in Studio Pro with CE1613. Routed through the same generalization walk added for Security reconciliation (UPDATE SECURITY / CREATE ASSOCIATION) strips inherited members from access rules of specialized entities; damage masked by CE0066 and unrepairable via GRANT #758. A sibling defect came out with it:
resolveAttributeTypematched entities by name across every domain model, so a same-named entity in another module could win, and inherited Boolean/DateTime fields silently gotDataType=String.Other fixes
describe/MDL formatter silently drops trailing XPath constraint brackets on Retrieve actions #772 —
describesilently dropped trailing XPath constraint groups.ParseXPathConstraintremoved its error listeners, so ANTLR parsed the first bracket group, left the rest on the token stream and still returned ok — the output read as a complete but materially less restrictive query, making correct defensive code look buggy. Fixed at two layers: reject a partial parse by requiring EOF, and split into top-level groups (nesting- and quote-aware) so enrichment reaches groups after the first.Test fix —
SecTest.Customerin the security examples granted aNotesattribute it never declared. That had always been silently ignored; Security reconciliation (UPDATE SECURITY / CREATE ASSOCIATION) strips inherited members from access rules of specialized entities; damage masked by CE0066 and unrepairable via GRANT #758 turned it into an error, so the attribute is now declared