Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
dccf72a
feat: mxcli search --exclude-marketplace leaves out Marketplace modul…
stagknee Oct 14, 2026
e425fa4
docs: search --help describes the documented elements by rule, not by…
stagknee Oct 14, 2026
27e1a1f
feat: mxcli marketplace package exports a module as a .mpk (closes #1…
stagknee Oct 11, 2026
ac909ae
fix: marketplace package refuses an mx of another Mendix version, and…
stagknee Oct 15, 2026
1d87679
fix(mcp): resolve a foldered document's module through its folder chain
claude Oct 20, 2026
0906ee5
test(mcp): group imports in the foldered-document tests
claude Oct 20, 2026
1b6ae1d
Merge remote-tracking branch 'origin/main' into claude/mxcli-issue-15…
claude Oct 20, 2026
8d8ed36
feat: export level on entities, attributes, associations and enumerat…
claude Oct 20, 2026
3c2854c
Merge mendixlabs/mxcli#1493: docs: search --help describes the docume…
claude Oct 20, 2026
b38512c
Merge mendixlabs/mxcli#1383: fix: marketplace package refuses an mx o…
claude Oct 20, 2026
64e93cb
Merge pull request #1501 from ako/claude/mxcli-issue-1593-mgbb67
ako Oct 20, 2026
b35336e
docs(search): say which elements' documentation is searched, and wher…
claude Oct 20, 2026
2083d7b
docs(skills): regenerate the download-marketplace-content section index
claude Oct 20, 2026
decf528
Merge main into integrate/wave3-upstream-prs
claude Oct 20, 2026
2a321aa
Merge pull request #1517 from ako/integrate/wave3-upstream-prs
ako Oct 20, 2026
2d6ad98
Merge remote-tracking branch 'origin/main' into fix/1498-domain-model…
claude Oct 21, 2026
d8f0371
Merge branch 'mendixlabs:main' into main
ako Oct 21, 2026
1b88baf
fix: keep a @curve written inside a loop or while body (mendixlabs/mx…
claude Oct 21, 2026
f1c347b
fix: describe prints persistent for a specialization of a non-persist…
claude Oct 21, 2026
36d1c13
fix: check the annotations in an alter microflow fragment (mendixlabs…
claude Oct 21, 2026
add6693
fix(visitor): strip identifier quotes in widget expression slots
claude Oct 21, 2026
b5b87ce
fix(xpath): keep the line breaks an author gives an XPath constraint
claude Oct 21, 2026
08f6ac3
refactor(executor): extract the --references variable-typing walk (wa…
claude Oct 21, 2026
4849e24
fix(executor): check a flow's use of Hidden members of a Protected mo…
claude Oct 21, 2026
4f4d239
fix(check): refuse an association path as a return value or loop list
claude Oct 21, 2026
10e9d6f
fix: pluggable attribute outside the data view entity — refuse the mi…
claude Oct 21, 2026
c59fe00
fix: describe keeps a gallery's sort when its source runs over an ass…
claude Oct 21, 2026
3240d49
fix: describe prints a combo box's and a data grid filter's settings …
claude Oct 21, 2026
bdd7973
test: bug-test for describe of a snippet's root data source (mendixla…
claude Oct 21, 2026
ca5f477
fix: set a Java action parameter's description and the return value n…
claude Oct 21, 2026
df0a607
docs(changelog): restore the entries the wave-3 merge dropped
claude Oct 21, 2026
06f9adc
fix(check): MDL-WIDGET42 judges a known-but-unmapped key by its templ…
claude Oct 21, 2026
d32fb5e
fix(deps): keep the klauspost/compress floor across go mod tidy
claude Oct 21, 2026
7baaa5e
Merge pull request #1518 from ako/fix/1498-domain-model-export-levels
ako Oct 21, 2026
e9be8b2
docs(skills): make the retrieve-over-association pitfall example a wh…
claude Oct 21, 2026
7f8e0ee
fix: check accepts ALTER ENTITY on an entity an earlier MOVE or RENAM…
claude Oct 21, 2026
e97b376
fix: page data-source XPath sees members the same script adds
claude Oct 21, 2026
6d48b67
fix: check resolves an ALTER PAGE column address no earlier operation…
claude Oct 21, 2026
36f59f7
fix: control-bar SHOW PAGE can pass the grid's selection
claude Oct 21, 2026
21be71b
ci(deps): bump Go toolchain 1.27.2 → 1.27.3 for GO-2026-6809
claude Oct 21, 2026
e9bfd00
ci(deps): bump Go toolchain 1.27.2 → 1.27.3 for GO-2026-6809
claude Oct 21, 2026
32aa807
Merge remote-tracking branch 'origin/main' into claude/sharp-bell-300jcx
claude Oct 21, 2026
742af8d
Merge remote-tracking branch 'origin/main' into claude/gracious-brown…
claude Oct 21, 2026
4dfa773
Merge remote-tracking branch 'origin/main' into claude/check-referenc…
claude Oct 21, 2026
c45af5d
Merge remote-tracking branch 'origin/main' into claude/nice-hawking-j…
claude Oct 21, 2026
a3b33a8
build: move to Go 1.27.3 for govulncheck (GO-2026-6809)
claude Oct 21, 2026
72aef78
Merge remote-tracking branch 'origin/main' into fix/1498-protected-me…
claude Oct 21, 2026
1272e6d
build: move to Go 1.27.3 for govulncheck (GO-2026-6809)
claude Oct 21, 2026
b07f7d9
test(roundtrip): a combo box's named datasource keeps `database from …
claude Oct 21, 2026
3751ce7
build: move to Go 1.27.3 for govulncheck (GO-2026-6809)
claude Oct 21, 2026
865be72
build: move to Go 1.27.3 for govulncheck (GO-2026-6809)
claude Oct 21, 2026
d64eb56
fix(xpath): describe a grant constraint with a trailing line break in…
claude Oct 21, 2026
2794e9f
build: move to Go 1.27.3 for govulncheck (GO-2026-6809)
claude Oct 21, 2026
826caf7
Merge pull request #1520 from ako/claude/mxcli-dev-upstream-pr-wm0592
ako Oct 21, 2026
adebd38
Merge remote-tracking branch 'origin/main' into claude/sharp-bell-300jcx
claude Oct 21, 2026
c3929fe
Merge remote-tracking branch 'origin/main' into claude/nice-hawking-j…
claude Oct 21, 2026
e8b9d5c
Merge remote-tracking branch 'origin/main' into claude/check-referenc…
claude Oct 21, 2026
dc2f733
Merge pull request #1522 from ako/claude/trusting-darwin-q2q31j
ako Oct 21, 2026
08cea76
Merge pull request #1527 from ako/fix/go-1.27.3-govulncheck
ako Oct 21, 2026
8354dd2
Merge pull request #1519 from ako/fix/1498-protected-member-refs
ako Oct 21, 2026
0a0e622
Merge origin/main into claude/busy-mayer-5677nr
claude Oct 21, 2026
90d802f
Merge pull request #1523 from ako/claude/gracious-brown-c46qr9
ako Oct 21, 2026
d036ecc
feat(lint): configurable QUAL004 and CUSTOM002 prefixes via lint-conf…
claude Oct 21, 2026
039473b
Merge pull request #1525 from ako/claude/nice-hawking-j6wtss
ako Oct 21, 2026
b864314
Merge pull request #1526 from ako/claude/check-references-issues-1qh811
ako Oct 21, 2026
d784f9c
Merge pull request #1524 from ako/claude/sharp-bell-300jcx
ako Oct 21, 2026
826e4f5
feat(check,lint): warn when a snippet call carries Class/Style/design…
claude Oct 21, 2026
38d68c5
feat(workflow): boundary events on call workflow (mendixlabs/mxcli#1532)
claude Oct 21, 2026
a904e74
feat(lint): CONV020 reports a created object never committed or passe…
claude Oct 21, 2026
218be6f
fix(mdl): let MDL document mappings, published REST services and data…
claude Oct 21, 2026
ff2eeb0
fix(check): MDL089 no longer sends a create's doc comment to the next…
claude Oct 21, 2026
1221fcb
Merge pull request #1521 from ako/claude/busy-mayer-5677nr
ako Oct 21, 2026
b21e897
Merge pull request #1530 from ako/feature/1532-call-workflow-boundary…
ako Oct 21, 2026
c7dfd8d
Merge pull request #1529 from ako/feature/1511-snippetcall-class-styl…
ako Oct 21, 2026
6a59151
Merge pull request #1532 from ako/feature/1518-lint-created-object-ne…
ako Oct 21, 2026
5b063fb
Merge origin/main into feature/1509-lint-configurable-prefixes
claude Oct 21, 2026
97d23bc
Merge pull request #1533 from ako/feature/1510-documentation-for-mapp…
ako Oct 21, 2026
2d25ffe
Merge pull request #1531 from ako/feature/1509-lint-configurable-pref…
ako Oct 21, 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
2 changes: 2 additions & 0 deletions .claude/commands/mendix/lint.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ mxcli lint -p app.mpr --exclude System --exclude Administration
| MPR006 | quality | EmptyContainer - Empty layout containers |
| MPR007 | security | PageNavigationSecurity - Navigation pages need allowed roles (CE0557); every user role must be able to open its home page (at Production security, else CE2729 per widget) |
| MPR012 | correctness | LegacyImageWidget - staticimage/dynamicimage are unsupported by the React client (CE0582) |
| MPR013 | correctness | SnippetCallAppearance - Class/Style/DynamicClasses/design properties on a snippet call never reach the page (it renders no element) |
| SEC001 | security | NoEntityAccessRules - Persistent entities need access rules |
| SEC002 | security | WeakPasswordPolicy - Password minimum length should be 8+ |
| SEC003 | security | DemoUsersActive - Demo users should be off at Production security |
Expand All @@ -49,6 +50,7 @@ mxcli lint -p app.mpr --exclude System --exclude Administration
| CONV012 | quality | ExclusiveSplitCaption - Exclusive splits need meaningful captions |
| CONV013 | quality | ErrorHandlingOnCalls - External calls (REST/WS/Java) need custom error handling |
| CONV014 | quality | NoContinueErrorHandling - Don't silently swallow errors with Continue |
| CONV020 | quality | CreatedObjectNeverPersisted - A microflow creates a persistent object without commit and never commits, returns or passes it on, so it is discarded |

## Bundled Starlark Rules

Expand Down
17 changes: 13 additions & 4 deletions .claude/lint-rules/example_microflow.star
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,15 @@
# VAL_ - Validation microflows
# SCH_ - Scheduled event microflows
#
# Customize the prefixes and patterns to match your project standards.
# Customize the prefixes in lint-config.yaml rather than here (`mxcli init`
# rewrites this file):
#
# rules:
# CUSTOM002:
# options:
# valid_prefixes: [ACT_, SUB_, DS_, TEST_] # or "ACT_, SUB_, DS_, TEST_"
#
# The option replaces VALID_PREFIXES below; unset keeps it.
#
# Microflow properties:
# .id - Document ID
Expand All @@ -28,21 +36,22 @@ DESCRIPTION = "Microflows should have standard naming prefixes (ACT_, SUB_, DS_,
CATEGORY = "naming"
SEVERITY = "info"

# Define valid prefixes - customize for your project
# Built-in valid prefixes, used when the valid_prefixes option is unset
VALID_PREFIXES = ["ACT_", "SUB_", "DS_", "VAL_", "SCH_", "IVK_", "OCH_"]

def check():
"""
Check that microflows use standard naming prefixes.
"""
violations = []
valid_prefixes = get_list_option("valid_prefixes", VALID_PREFIXES)

for mf in microflows():
name = mf.name # Simple name

# Check if name starts with any valid prefix
has_valid_prefix = False
for prefix in VALID_PREFIXES:
for prefix in valid_prefixes:
if name.startswith(prefix):
has_valid_prefix = True
break
Expand All @@ -57,7 +66,7 @@ def check():
message="{} '{}' should start with a standard prefix ({})".format(
mf.document_noun_title,
name,
", ".join(VALID_PREFIXES)
", ".join(valid_prefixes)
),
location=loc
)
Expand Down
20 changes: 15 additions & 5 deletions .claude/lint-rules/orphaned_elements.star
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,22 @@
# - Entities with no references at all
#
# This rule requires REFRESH CATALOG FULL to populate the refs table.
#
# Options (lint-config.yaml, rules.QUAL004.options):
# entry_point_prefixes - microflow name prefixes that mark an entry point,
# as a YAML list or comma-separated text. Replaces
# the built-in list below; unset keeps it.
#
# Edit the option, not this file: `mxcli init` rewrites the shipped rules.

RULE_ID = "QUAL004"
RULE_NAME = "Orphaned Elements"
DESCRIPTION = "Elements should be referenced somewhere in the project or marked as entry points"
CATEGORY = "quality"
SEVERITY = "info"

# Prefixes for microflows that are expected to be entry points
# Prefixes for microflows that are expected to be entry points, unless the
# entry_point_prefixes option says otherwise
ENTRY_POINT_PREFIXES = ["ACT_", "SCH_", "WS_", "REST_", "OData_"]

# Page name patterns that are likely entry points
Expand All @@ -33,9 +41,9 @@ MICROFLOW_ENTRY_KINDS = ["call", "schedule", "publish", "datasource", "action",
# Reference kinds that mean "something opens this page".
PAGE_ENTRY_KINDS = ["show_page", "home_page", "login_page", "menu_item", "action"]

def is_entry_point_microflow(name):
def is_entry_point_microflow(name, prefixes):
"""Check if a microflow name suggests it's a UI/scheduled entry point."""
for prefix in ENTRY_POINT_PREFIXES:
for prefix in prefixes:
if name.startswith(prefix):
return True
return False
Expand All @@ -52,11 +60,13 @@ def check():
Check for orphaned elements that have no incoming references.
"""
violations = []
entry_prefixes = get_list_option("entry_point_prefixes", ENTRY_POINT_PREFIXES)
rename_hint = "/".join(entry_prefixes[:2]) if entry_prefixes else "an entry-point"

# Check microflows
for mf in microflows():
# Skip entry point microflows
if is_entry_point_microflow(mf.name):
if is_entry_point_microflow(mf.name, entry_prefixes):
continue

# Get references to this microflow
Expand Down Expand Up @@ -95,7 +105,7 @@ def check():
v = violation(
message="{} '{}' is not called from anywhere.".format(mf.document_noun_title, mf.name),
location=loc,
suggestion="Remove if unused, or rename with ACT_/SCH_ prefix if it's an entry point."
suggestion="Remove if unused, rename with {} prefix if it's an entry point, or add its prefix to rules.QUAL004.options.entry_point_prefixes in lint-config.yaml.".format(rename_hint)
)
violations.append(v)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl-backend", "date": "2026-10-20", "symptom": "`alter page` over the MCP backend (Studio Pro 11.12.5) fails for every page inside a folder with `failed to open page for mutation: module not found: <uuid>` — the uuid is the page's parent FOLDER — while the same statement on a module-root page succeeds; `check --references` passes and the trace shows no PED call before the error", "cause": "`resolvePageUnit` (MCP page mutator) resolved the module with `GetModule(page.ContainerID)`, and a page's ContainerID is its immediate parent, a folder for most Studio Pro pages. The backend already had the folder-aware answer, `moduleNameForContainer` (walks `resolveDocContainer` up the folder chain), used by CreatePage, DeleteConstant, the microflow mutator and others. `UpdateConstant` and `UpdateWorkflow` (CREATE OR MODIFY on a foldered document) and `forgetSessionConstant` / `forgetSessionEnum` (DROP cleanup; silently left the entry registered) had the same direct lookup", "file": "`mdl/backend/mcp/page_mutator.go` (`resolvePageUnit`), `mdl/backend/mcp/constant.go`, `mdl/backend/mcp/workflow.go`, `mdl/backend/mcp/enumeration.go`", "insight": "When an error says `<kind> not found: <id>` and the id is NOT an id of that kind, it is the caller passing the wrong id — map the id to what it actually is (here a folder) before reading any resolver. For containers: `GetModule(x.ContainerID)` is correct only for a domain model or a folder's own walk; for any other document grep the package for that exact pattern — a folder-aware helper usually already exists and the bug is the call sites that bypass it (this is the MCP-backend recurrence of #976/#1071 in the executor). The modelsdk engine never had it, so running the bug-test MDL without `--mcp` proves nothing about the fix; the evidence is `mdl/backend/mcp/page_mutator_folder_test.go`, whose fake reader returns `module not found: <id>` for any non-module id exactly as the codec does. Control: production change stashed → `OpenPageForMutation: module not found: fPages` plus the three sibling failures. Repro `mdl-examples/bug-tests/1593-mcp-alter-page-in-folder.mdl`. Issue #1593", "refs": ["#1593", "#1071", "#976"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend", "date": "2026-10-21", "symptom": "`describe entity Probe.Child` printed `create or modify persistent entity Probe.Child extends Probe.Base (` when Probe.Base is non-persistent; check and exec were clean, and the same wrong flag reached the catalog's EntityType, mermaid/ELK diagrams, the microflow builder's entityPersistable map, and `alter entities in Probe add attribute … where persistent`, which added the attribute to the non-persistent Probe.Child too. The virtual System module had it too: System.HttpRequest, HttpResponse and SoapFault read persistent although HttpMessage and Error are not.", "cause": "A specialization's MaybeGeneralization is a DomainModels$Generalization, which has no Persistable property — the flag lives only on the root's NoGeneralization. entityFromGen initialised Persistable to true and only the NoGeneralization arm overwrote it, so a specialization always read the default; the System meta table likewise carried a meaningless `Persistable: true` on its specializations.", "file": "`mdl/backend/modelsdk/domainmodel.go` (`resolveInheritedPersistability`, called by ListDomainModels / GetDomainModel / GetDomainModelByID over every stored domain model plus the System entities); `domainmodel_carry.go` (`entityUnchanged` takes the statement's value for a specialization)", "insight": "A property Mendix stores on only one end of a chain is a READ of the chain, not a field of the element — entityFromGen sees one entity and cannot answer it, so the resolution belongs in the domain-model reads, which already decode every module. Resolve it there and every consumer (describe, the bulk `where persistent` filter, catalog, diagrams) is fixed at once; patching cmd_entities_describe.go alone would have left four. The trap on the way: once reads return the resolved value, any 'is this unchanged?' comparison against entityFromGen's raw default calls every specialization of a non-persistent entity changed and rebuilds it on each UpdateDomainModel — treat the inherited value like the 11+ view OQL, as not the element's content. The CLI round trip did not show that churn (write elision caught it), so it needs a unit test on entityUnchanged with a root-entity control.", "refs": ["ako/mxcli#1510", "mendixlabs/mxcli#1600"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-16", "symptom": "mendixlabs/mxcli#1510: MDL089 on a doc comment above a create that stores no documentation told the user to \"Move the doc comment directly above `create json structure …`, after the `create or modify published rest service …`\" — moving text written for one element onto a different one.", "cause": "ValidateDetachedDocComments built the move suggestion from DetachedDocComment.Next for every statement. That is right for a drop/grant standing between a comment and its create (#877), but a create IS the element the comment describes; the next storing statement is a different element.", "file": "mdl/executor/validate_detached_doc_comments.go", "fix": "When the statement head is a create, the warning says MDL cannot store documentation for that element and suggests a `--` comment; the next-statement suggestion stays for drop/grant/revoke/set/alter.", "test": "mdl/executor TestValidateProgram_DetachedDocCommentOnCreate_Issue1510 (create module role followed by a create entity); control TestValidateProgram_DetachedDocComment keeps the drop suggestion. Revert check: with the create branch disabled the test reports the move-to-next-create suggestion.", "insight": "A suggestion derived from position (\"the next statement that can take it\") is only right when the position is the mistake. Ask what the comment was written FOR before telling the user where to put it.", "refs": ["mdl/executor/validate_detached_doc_comments_test.go"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-16", "symptom": "mendixlabs/mxcli#1510: lint QUAL002 reported import/export mappings, published REST services and data transformers as undocumented (45 findings on one project), and nothing in MDL could close them: a `/** … */` above `create or modify published rest service` was dropped with MDL089. Every published REST service was reported even when Studio Pro HAD documented it, and `create or modify` of a Studio Pro-documented mapping, published REST service or data transformer wrote an empty Documentation over the stored text.", "cause": "The four create statements' AST had no Documentation field, so storesDocumentation() reported the comment as detached and the visitor never read it. The executors never set the model's Documentation (the mapping writers wrote whatever the model held, i.e. \"\"; the data transformer writer wrote a literal \"\"; the published REST writer only carried the stored value via keepStoredTopLevel). model.PublishedRestService and model.DataTransformer had no Documentation, and the catalog builder wrote \"\" for published_rest_services.Documentation (\"not stored on published REST\").", "file": "mdl/ast/ast_import_export_mapping.go, mdl/ast/ast_rest.go, mdl/ast/ast_datatransformer.go, mdl/visitor/visitor_import_export_mapping.go, mdl/visitor/visitor_rest.go, mdl/visitor/visitor_datatransformer.go, mdl/executor/cmd_import_mappings.go, mdl/executor/cmd_export_mappings.go, mdl/executor/cmd_published_rest.go, mdl/executor/cmd_datatransformer.go, mdl/executor/documentation_carry.go, mdl/backend/modelsdk/published_rest_write.go, mdl/backend/modelsdk/integration_read.go, mdl/backend/modelsdk/data_transformer_write.go, mdl/catalog/builder_rest.go, model/types.go", "fix": "Documentation + DocumentationSet on the four statements, read with findDocComment; the executors set it and carry the stored value when no comment is written (carriedDocumentation, #1018); model + modelsdk read and write the top-level `Documentation` key for published REST services and data transformers (published REST drops it from the keep-stored list); describe prints it with writeDocumentDocComment (`--` lines when the text holds `*/`); the catalog stores the service's documentation. Java action parameter descriptions were already writable (#1588).", "test": "mdl/visitor TestIntegrationDocumentsReadDocComment_Issue1510; mdl/executor TestIntegrationDocumentation_Issue1510 (PedApp copy: stored key, describe round trip, carry, `/** */` clears) and TestIntegrationDocumentation_StudioProMappingKeepsIt_Issue1510; mdl/catalog TestPublishedRestServiceDocumentationReachesCatalog_Issue1510; the integration TestDocumentation_SurvivesRewrite gains the four doctypes. Revert check: without the fix every new test fails with the reported symptom; stubbing only the carry fails the rewrite and Studio Pro cases.", "insight": "Verify the BSON key against Mendix's own reader, not only modelsdk/gen: `mx dump-mpr --module-names=X` prints the model as Mendix deserialises it, so the doc comment appearing as the unit's `documentation` there (11.6.6 and 11.15) proves the key is the one Studio Pro reads. A QUAL002 finding nobody can close has two suspects, the writer and the catalog reader, and here both were broken: the catalog's hard-coded \"\" made the rule fire on Studio Pro-documented services too.", "refs": ["mdl-examples/bug-tests/1510-documentation-for-mappings-rest-javaparams.mdl", "mdl/executor/integration_documentation_issue1510_test.go", "mdl/visitor/visitor_integration_documentation_test.go", "mdl/catalog/builder_rest_documentation_test.go"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/executor", "date": "2026-10-16", "symptom": "`snippetcall sc (snippet: M.S, class: 'x')` / `alter page M.P { set (Class: 'x') on sc }` passed check, exec and mx check (0 errors) and describe showed the class, but nothing in the running app carried it (mendixlabs/mxcli#1511)", "cause": "Not an mxcli defect: a Forms$SnippetCallWidget renders no DOM element - the snippet's widgets are inlined into the parent - so its Appearance (Class, Style, DynamicClasses, DesignProperties) has nothing to land on. Measured on 11.15.0 with run --local (hsqldb) + playwright check: .probe-x / .probe-dyn / the red border / pull-right / hide-tablet = 0 elements; the snippet's own container was a direct child of the enclosing container; a container on the same page with the same four settings carried all of them (control)", "file": "`mdl/executor/validate_snippetcall_appearance.go` (MDL-WIDGET48: `validateSnippetCallAppearance` in the widget-tree walk for CREATE / ALTER INSERT / REPLACE; `validateStoredSnippetCallAppearance` in the reference pass for ALTER PAGE SET and ALTER STYLING, typed via `widgetStorageTyper`), `mdl/linter/rules/snippet_call_appearance.go` (MPR013: catalog Class/Style/DynamicClasses + design properties read from the raw unit)", "insight": "**Valid BSON, a clean mx check and a correct describe prove nothing about whether an appearance setting renders** - only the DOM does. The positive control (same settings on a container on the same page) is what makes a 0-count meaningful: without it a stale build or a wrong selector reads the same. ALTER ... SET names a STORED widget, so whether it is a snippet call is only answerable against the document; `widgetStorageTyper` (pagemutator) already gives the $Type, so the check runs in the reference pass and appends a warning (never blocks). Clearing a class on a snippet call is the fix and must stay silent.", "refs": ["mendixlabs/mxcli#1511", "ako/mxcli#1393"], "rules": ["MDL-WIDGET48", "MPR013"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-10-20","symptom":"`check -p --references` reported CE5400 for an `export level api` microflow exposing a Hidden entity of a Protected (add-on) module and told the user to fix it in Studio Pro: `create persistent entity Shop.Order (…) export level api` was \"extraneous input 'export' expecting the start of a statement\", and attributes, associations and enumerations had no clause either (mendixlabs/mxcli#1498, kris-bom's point 2). check also missed CE5400 for a Hidden ENUMERATION parameter, which mxbuild reports the same way.","cause":"Only microflows, nanoflows and workflows had an EXPORT LEVEL clause. entityToGen/attributeToGen/assocToGen/crossAssocToGen/enumToGen wrote the \"Hidden\" constant and the #801 carry wrote the stored level back over the rebuild unconditionally, so even a semantic model holding API could not reach storage. validateProtectedModuleRefs judged entities only, from stored levels and a 'script-created = Hidden' bool.","fix":"`export level api|hidden` (the microflow clause) on create entity / view entity / each attribute / create association / create enumeration, `set export level` on alter entity / association / enumeration and on modify attribute; absent keeps the stored level. Converters write orDefault(level, \"Hidden\"); the entity, attribute, association and cross-association carries and keepStoredExportLevelUnlessSet stand down for an authored level; reads fill Attribute/Association/CrossModuleAssociation/Enumeration.ExportLevel; describe prints `export level api`, omitting Hidden. The validator takes a level stated anywhere in the script over the stored one and checks enumerations for CE5400; its hints name the alter statement. Gated at 9.3.0 (domain_model.export_levels).","file":"mdl/backend/modelsdk/domainmodel_carry.go","insight":"A carry added to stop a rewrite resetting a property (#801: ExportLevel back to Hidden) silently becomes the reason the property can never be authored: once there is a spelling, every carry of it must stand down for an authored value, and each one is a separate site (entity, attribute in two rebuild paths, association, cross-association patch, enumeration unit). A test that sets only Hidden over a stored API cannot tell an honoured clause from the carry, and only API over a stored Hidden cannot tell it from the constant — run both. Measure attributes and associations too before scoping a 'level' feature to entities: on 11.14.0 another module changing a Hidden attribute or retrieving over a Hidden association is CE1406 on its own, and CE1406 masks CE5400 in one mx check, so measure each rule in a copy without the other. check still does not predict the attribute/association CE1406.","refs":["mendixlabs/mxcli#1498","ako/mxcli#1351","ako/mxcli#801","ako/mxcli#816"],"ce":["CE5400","CE1406"]}
Loading
Loading