Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
17 commits
Select commit Hold shift + click to select a range
e4894b6
Add proposal: Mendix whiteboard
claude Oct 14, 2026
c3d2b01
Index the Mendix whiteboard proposal in the proposals README
claude Oct 14, 2026
e94a6df
fix(alter page): resolve widgets inside Accordion groups (#891)
claude Oct 15, 2026
09901ff
build: give sync-mods the cp fallback sync-skills already has
claude Oct 15, 2026
8d4aa86
test: regression case for describe dropping a combobox's association …
claude Oct 15, 2026
4b0242e
test: write #1291's bug-test DesignProperties in the canonical ( ) form
claude Oct 15, 2026
286bd43
fix(alter page): SET Label no longer reports success while storing no…
claude Oct 15, 2026
a88e9f8
fix: ALTER PAGE SET writes a textbox's Placeholder, Password and Vali…
claude Oct 15, 2026
592d29b
test(bug-tests): write the #292 regression script in canonical MDL
claude Oct 15, 2026
6d91f85
fix(deps): upgrade mongo-driver for the October 2026 BSON advisories
claude Oct 15, 2026
5e9c208
Merge pull request #1371 from ako/claude/intelligent-allen-nexywd
ako Oct 15, 2026
f67a96d
fix(check): refuse object-list item properties that would be dropped
claude Oct 15, 2026
0f59ff1
Merge pull request #1372 from ako/claude/relaxed-goldberg-q2vra6
ako Oct 15, 2026
09228b3
Merge pull request #1368 from ako/claude/mxcli-issue-1274-5uuuug
ako Oct 15, 2026
3b45000
Merge pull request #1366 from ako/claude/focused-mayer-to7loc
ako Oct 15, 2026
1badfb0
Merge pull request #1369 from ako/claude/mxcli-issue-414-b5tlrx
ako Oct 15, 2026
8cda154
Merge pull request #1370 from ako/claude/mxcli-issue-292-imud21
ako Oct 15, 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","date":"2026-10-15","symptom":"`alter page … set (Caption: …) on Qty` against a DataGrid 2 inside an **Accordion group** reports `widget \"Qty\" not found … available columns: Name, Qty`, and the qualified `on g1.Qty` reports `widget \"g1\" not found` — the grid and everything else in the group are unaddressable while the error advertises its columns","cause":"`findInWidgetChildren` descended into a pluggable widget's own `Object.Properties[].Value.Widgets` and into the `columns` object list (#834), but not into any OTHER object list — Accordion groups and Pop-up menu items keep their widgets at `Value.Objects[].Properties[].Value.Widgets`. The not-found message comes from `collectColumnNamesBson`, a generic walk of the whole tree, so it saw what the resolver could not. `collectWidgetScopeInChildren` had the same gap; `findNearestDSInChildren` had already been given the descent for #935","file":"`mdl/backend/pagemutator/mutator.go` (`objectListItemValues`, used by `findInWidgetChildren` and `collectWidgetScopeInChildren`)","insight":"Four walkers traverse the same page tree (`findInWidgetChildren`, `collectWidgetScopeInChildren`, `findNearestDSInChildren`, the generic `collectColumnNamesBson`) and each was patched per container, so they disagree: when an error message lists a name the resolver just refused, diff the walker that BUILT THE MESSAGE against the one that resolved — the message is a free oracle for what the resolver should reach. Key the descent on the BSON shape (`Objects[].Properties[].Value.Widgets`), not on a property key like `groups`, so Pop-up menu items are covered too; skip `columns` there so a column's derived name still wins over a same-named widget in its customContent cell. Unit fixture trap: a column type with no `ValueType.Type` makes the caption setter fall to `PrimitiveValue` and `DSet`-append onto a copied `bson.D`, so the write may or may not be visible depending on slice capacity — declare `header` as `TextTemplate`, as the shipped widget does. Control: the unfixed binary refuses with the reporter's exact message; fixed, `mx check` (11.12.1) 0 errors. Repro `mdl-examples/bug-tests/891-alter-page-grid-inside-accordion-group.mdl`. Issue #891 (ako/mxcli#1274)","refs":["#891","ako/mxcli#1274","#834","#935"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl-backend", "date": "2026-10-15", "symptom": "`alter page … { set Label = 'X' on <widget> }` prints \"Altered page\" and DESCRIBE still shows the old (or no) label — on an input widget that shows no label, and on a button", "cause": "setWidgetLabelMut fell through to `return nil` when the widget had neither a LabelTemplate document nor a legacy Label/Caption. A label-less input stores `LabelTemplate: null` (codec NullFields), so DGetDoc returns nil and nothing is written; a button has no label slot at all and got the same silent nil", "file": "`mdl/backend/pagemutator/mutator.go` (`setWidgetLabelMut`)", "insight": "The earlier half-fix (#292 Title + LabelTemplate doc) only tested a widget that already HAD a label — the shape that worked. Test the null slot and the no-slot widget, not just the populated one: every `DGetDoc(...) != nil` guard that ends in `return nil` is a silent no-op for the null case. Null LabelTemplate on a built-in input gets the same ClientTemplate create page writes (bson dump identical); on a CustomWidget it is refused, because every pluggable widget writes `LabelTemplate: null` whether or not its definition declares a Label system property. The refusal also surfaces in `check --references` via the setter probe", "refs": ["mendixlabs/mxcli#292", "ako/mxcli#1235"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "mdl/backend", "date": "2026-10-15", "symptom": "`alter page … set Placeholder = '…' on <textbox>` refused with `property \"Placeholder\" is not a property of this built-in widget`, though CREATE writes `Placeholder:` and DESCRIBE prints it; `Password`, `Validation` and `ValidationMessage` on a textbox refused the same way (mendixlabs/mxcli#414)", "cause": "setRawWidgetPropertyMut had no placeholder/password/validation/validationmessage case, so the keys fell through to the pluggable setter, which fails at noPluggableObjectError on any built-in widget", "file": "`mdl/backend/pagemutator/mutator.go` (setInputWidgetPropertyMut)", "insight": "The fourth instance of #1464's recipe (Image, Tooltip, RenderMode before it): diff buildTextBoxV3's GetStringProp/lookupPropCI keys against the SET switch and every CREATE-only key falls out at once — the issue named one (Placeholder), the diff found three more. Guard on the stored key (PlaceholderTemplate, a bool IsPasswordBox, a Forms$WidgetValidation), not the property name, so a pluggable widget's own `placeholder`/`validation` keeps the pluggable route and a checkbox keeps the built-in refusal. Placeholder is a Forms$ClientTemplate like LabelTemplate, so setTranslatableText covers it; the triage note's `set Label` no-op was already fixed by the LabelTemplate branch", "refs": ["mendixlabs/mxcli#414", "mendixlabs/mxcli#1464", "mendixlabs/mxcli#292"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl/executor","date":"2026-10-15","symptom":"`describe page` of an association combo box with an On change microflow printed Label/DataSource/OnChange but \"No `Attribute:` and no `CaptionAttribute:`\" (nightly-20260927-95091765, Mendix 11.12.1); re-executing the description writes an unbound combo box, and mx check then reports CE0642 \"Property 'Entity' is required.\" and \"Property 'Caption' is required.\"","cause":"Same as the 2026-10-02 finding: `w.OnChange != \"\"` in the generic pluggable branch's guard captured the combo box ahead of its own branch. Already fixed on main by the time the mirror was triaged, but the fix arrived inside a merge commit's conflict resolution (64a38bf6), so `git log --no-merges -S` finds nothing and the issue looked live","file":"`mdl/executor/cmd_pages_describe_output.go` (`outputWidgetMDLV3`, generic pluggable branch guard); test `cmd_pages_describe_combobox_onchange_test.go`","insight":"**When a report does not reproduce on main, build the reporter's own commit before theorising** (`git worktree add <dir> <nightly sha>` + `make build`, about two minutes). Here the reporter's 'Studio Pro-authored' framing led toward storage differences (EntityRef shape, PropertyTypes nesting, widget version), and every one checked out identical; the nightly binary reproduced it in one run on mxcli-authored BSON, and authoring was irrelevant. The tell was in the output itself: DataSource and OnChange survived while both mode-gated fields vanished together, which points at the emitter branch, not the reader. A fix made in a merge resolution is invisible to `--no-merges` history search, so search with merges included (`git log -S` without `--no-merges`) before concluding there is no fix. While verifying, a separate defect turned up: `OnChange: call microflow M.F(P = $dataView1)` on a pluggable widget checks clean and fails mx check CE0117, while `$currentObject` is clean. The regression script uses `$currentObject` so it does not carry that defect","refs":["ako/mxcli#1291","mendixlabs/mxcli#1236"],"ce":["CE0642","CE0117"],"test":"mdl/executor/cmd_pages_describe_combobox_onchange_test.go TestDescribeComboboxWithOnChangeKeepsItsBinding; mdl-examples/bug-tests/1291-combobox-association-onchange-describe.mdl"}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area":"mdl-executor","date":"2026-10-15","symptom":"`group g1 (Caption: 'Group one')` inside an Accordion passes `mxcli check`, `exec` reports \"Created page\", and `describe` shows the group with the package default `headerText: 'Header'` — the caption is gone. Same silence for `designproperties:` on a DataGrid 2 `column` and `attributeValue:` on an HTMLElement `attribute`","cause":"Object-list items were exempt from both unknown-property checks (`validateStaticWidgetUnknownProps`, `validatePluggableWidgetProperties`) with a comment saying the object-list engine validates them, but `buildObjectListItem` only walks the item SCHEMA and looks each key up in the MDL bag — a key matching no schema property or alias is never visited and never reported","file":"`mdl/executor/validate_widgets.go` (`validateObjectListItemUnknownProps`, `extensionsOf`)","insight":"Derive the item vocabulary from the mapping — schema keys, `MdlAliases`, and `<name>Params` for each texttemplate under either spelling, plus a chart series' friendly `DataSource:` — and do NOT reuse the top-level `isBuiltinPropName` allowance: `Caption`/`Class` being accepted universally is the hole. The Accordion definition is generated from the project's .mpk, so a test with `LoadWidgetRegistry(\"\")` has no mapping and passes vacuously; copy the .mpk from `testdata/pedapp/widgets` into a temp project. Measure false positives by sweeping every repo .mdl with `check -p` (base vs new binary) against a project holding the stock packages: all 6 new reports were real drops (verified by exec + bson dump), 3 of them in doctype/bug-test examples that taught the drop. Edit distance answers a truncated key badly (`attributeValue` -> `attributeName`); prefer candidates that extend the key. Issue #891 (ako/mxcli#1274)","refs":["#891","ako/mxcli#1274"],"rules":["MDL-WIDGET01"]}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"area": "go.mod", "date": "2026-10-15", "symptom": "A customer's release pipeline (Sonatype Lifecycle, \"Security-High\" policy, CVSS >= 7 blocks) refused the mxcli .exe, reporting go.mongodb.org/mongo-driver/v2 v2.6.0 with CVE-2026-107324 (8.2), CVE-2026-107325 (8.2) and CVE-2026-81521 (7.1), plus go.mongodb.org/mongo-driver v1.17.9 and github.com/klauspost/compress v1.17.6", "cause": "go.mod pinned mongo-driver/v2 v2.6.0 and mongo-driver v1.17.9, both predating the October 2026 BSON advisories. mxcli imports only the BSON packages (v2/bson in 271 files, v2/x/bsonx/bsoncore in 9, v1 bson+bson/primitive), never the mongo client, so CVE-2026-81521 (Client.BulkWrite namespace confusion) is unreachable — but CVE-2026-107324 (bson.Raw.Validate panic on a binary element declaring math.MaxInt32) and CVE-2026-107325 (bson.RawArray.Validate panic on a zero-length array) are in code mxcli calls on bytes read from a .mpr: modelsdk/canon/attributeref.go:92, modelsdk/mprread/generic.go:121, modelsdk/mpr/reader_raw.go:242, cmd/mxcli/cmd_fix_hashes.go:167", "file": "`go.mod` / `go.sum` — mongo-driver/v2 v2.6.0 -> v2.9.2, mongo-driver v1.17.9 -> v1.17.10", "insight": "Do NOT reach for a policy waiver on a scanner report before checking two things, because both answers here contradicted the obvious reading. (1) govulncheck says \"No vulnerabilities found\" on the affected tree — these CVEs are absent from the Go vuln DB (an OSV query for mongo-driver/v2@2.6.0 returns a bare `{}`), so a clean govulncheck is a data-source gap, not evidence; the vendor's own release notes are the authority. (2) A flagged TRANSITIVE module with no go.sum entry was never compiled: klauspost/compress v1.17.6 is exactly the version declared in mongo-driver/v2@v2.6.0's go.mod and appears in no go.sum and in no `go version -m bin/mxcli` line, which proves the scanner reads the module requirement graph, not the linked binary. Upgrading the parent raised that declared requirement to v1.19.2 and cleared the finding without a waiver. Conversely, \"we only use BSON, not the client\" is NOT a blanket non-exploitability argument — two of the three CVEs are in bson.Raw/RawArray.Validate, which mxcli calls on untrusted .mpr bytes (a malicious .mpr panics the CLI; DoS only, no code execution). Reachability per CVE, checked by grepping for the named symbol, beats a per-module verdict. v2.9.2 is the floor for all three: 81521 was fixed in v2.8.2, regressed out of v2.9.0/v2.9.1, and restored in v2.9.2. Verified: `go build ./...` clean, 104 test packages pass, `go version -m bin/mxcli` shows v2.9.2 / v1.17.10", "refs": ["CVE-2026-107324", "CVE-2026-107325", "CVE-2026-81521"]}
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

### 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.

### Added

- **`filemanager` — the classic file manager (`Forms$FileManager`) in MDL** (mendixlabs/mxcli#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`.
Expand Down
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,10 @@ sync-skill-packs:
sync-mods:
@mkdir -p cmd/mxcli/mods
@rsync -a --delete --exclude='.DS_Store' --exclude='tests/' --exclude='*.test.ts' --exclude='*.test.tsx' \
--exclude='.claude-plugin/types/' --exclude='tsconfig.json' mods/ cmd/mxcli/mods/
--exclude='.claude-plugin/types/' --exclude='tsconfig.json' mods/ cmd/mxcli/mods/ 2>/dev/null \
|| { rm -rf cmd/mxcli/mods && mkdir -p cmd/mxcli/mods && cp -R mods/. cmd/mxcli/mods/ \
&& find cmd/mxcli/mods \( -type d -name tests -o -path '*/.claude-plugin/types' \) -prune -exec rm -rf {} + \
&& find cmd/mxcli/mods \( -name '*.test.ts' -o -name '*.test.tsx' -o -name tsconfig.json -o -name .DS_Store \) -delete; }

# Sync commands from .claude/commands/mendix to cmd/mxcli/commands for embedding
sync-commands:
Expand Down
4 changes: 4 additions & 0 deletions docs-site/src/language/alter-page.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ ALTER PAGE Module.EditPage {
|----------|-------------|---------|
| `Caption` | Button/link caption | `SET (Caption: 'Submit') ON btnSave` |
| `Label` | Input field label | `SET (Label: 'Full Name') ON txtName` |
| `Placeholder` | Input hint text (text box, text area, date picker) | `SET (Placeholder: 'Enter your name') ON txtName` |
| `Password` | Mask a text box's input | `SET (Password: true) ON txtPin` |
| `Validation` | A text box's validation expression | `SET (Validation: '$value != empty') ON txtName` |
| `ValidationMessage` | Message shown when the validation fails | `SET (ValidationMessage: 'Name is required') ON txtName` |
| `ButtonStyle` | Button visual style | `SET (ButtonStyle: Danger) ON btnDelete` |
| `Class` | CSS class names | `SET (Class: 'card p-3') ON cMain` |
| `Style` | Inline CSS | `SET (Style: 'margin: 8px;') ON cBox` |
Expand Down
15 changes: 15 additions & 0 deletions docs-wiki/bug-patterns/silent-property-drop.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,21 @@ outcome into a three-way answer — an unrecognised key gets a "did you mean"
warning, a recognised-but-unmapped key gets "this will be dropped, set it in
Studio Pro", and a mapped key stays quiet.

**An exemption for "validated elsewhere" needs the elsewhere to exist.**
Object-list items — an Accordion `group`, a DataGrid `column`, a chart
`series` — were skipped by both unknown-property checks on the grounds that
"the object-list engine validates them". It did not: the item builder walks the
item's *schema* and looks each key up in the MDL bag, so a key matching no
schema property is simply never visited. `group g1 (Caption: …)`,
`designproperties:` on a column and `attributeValue:` on an HTMLElement
attribute all checked clean and vanished. The item's vocabulary is fully
derivable — its schema keys, their aliases, and each text template's
`<name>Params` — and the top-level rule's universal builtin allowance must
**not** carry over, since `Caption` and `Class` being accepted everywhere is
exactly what let them through. Sweep the example corpus with `check -p` against
a project that has the packages before and after: every new report there was a
real drop already in the examples.

**Where it cannot, enumerate generously and guard the list.** Built-in widgets
have no `.mpk` to subtract from, so their vocabulary is a hand-maintained union —
grammar keyword properties, every key the builders consume, and every property
Expand Down
Loading
Loading