Document Windows profile rename on edit - #52072
Merged
rachaelshaw merged 3 commits intoAug 28, 2026
Merged
Conversation
4 tasks
jbelbo
force-pushed
the
jbelbo/51104-docs-windows-profile-name
branch
from
August 28, 2026 15:59
8a4d757 to
860c776
Compare
jbelbo
marked this pull request as ready for review
August 28, 2026 17:48
rachaelshaw
approved these changes
Aug 28, 2026
jbelbo
added a commit
that referenced
this pull request
Aug 31, 2026
**Related issue:** Resolves #51104 Reference doc PR: #52072 ## What was done Editing a Windows configuration profile and uploading a replacement file with a different name replaced the contents but kept the original name, so the profile list, the downloaded file and the activity all kept showing the old one. The edit endpoint already receives the uploaded file but dropped its file name before reaching the service, which then forced the stored name. It now passes the file name through and the profile is renamed in place: same `profile_uuid`, same targets, same per-host delivery state. Host pages resolve the profile name from the live profile row rather than the denormalized `host_mdm_windows_profiles.profile_name` copy, so a rename writes no per-host rows at all. The delete paths snapshot the live name on the way out, since those rows outlive the profile and the copy is what reads fall back to once it's gone. Scoped to Windows. Android and Apple DDM behave the same way and are unchanged. Apple `.mobileconfig` is unaffected, its name comes from `PayloadDisplayName` in the file and already updated. Also adds a 255-character check on the profile name, which previously surfaced MySQL's raw `Data too long for column 'name'` to the caller. ## Steps to reproduce 1. **Controls > OS settings > Configuration profiles**, upload `disable-onedrive.xml`. 2. Hover the row, select the edit pencil, then the pencil in the modal, and upload `enable-firewall.xml`. The profile is still called `disable-onedrive`, Download returns `<date>_disable-onedrive.xml` containing the firewall settings, and the activity reads `disable-onedrive`. Only "Updated" changes. ## How I tested Scenarios run end to end against a local server on the `main` binary and then this branch: | | pre-fix | post-fix | |---|---|---| | Edit `disable-onedrive.xml` with `enable-firewall.xml` | name, download and activity stay `disable-onedrive` | all three read `enable-firewall`, UUID unchanged | | 300-char file name on create | `422`, `Error 1406 (22001): Data too long for column 'name'` | `400`, `maximum configuration profile name length is 255 characters` | | 300-char file name on edit | `200`, silently ignored | `400`, same message, profile untouched | | Rename onto a name already in use | `200` (rename was impossible) | `409`, profile untouched | | Labels-only edit | name preserved | name preserved | Host display, watching both the page and the stored copy: ``` start: page=disable-onedrive stored=disable-onedrive after rename: page=enable-firewall stored=disable-onedrive (no per-host write) after case rename: page=ENABLE-FIREWALL stored=disable-onedrive after delete: page=ENABLE-FIREWALL stored=ENABLE-FIREWALL (snapshotted) ``` ``` TestMDMWindows / TestTeams / TestMDMShared (datastore) ... PASS TestUpdateMDMWindowsConfigProfile (service) ............. PASS TestIntegrationsMDM/TestUpdateConfigProfile ............. PASS make lint-go-incremental ................................ 0 issues ``` ## Checklist for submitter - [x] Changes file added for user-visible changes in `changes/`, `orbit/changes/` or `ee/fleetd-chrome/changes`. See [Changes files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files) for more information. - [x] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements), JS inline code is prevented especially for url redirects, and untrusted data interpolated into shell scripts/commands is validated against shell metacharacters. ### Testing - [x] Added/updated automated tests - [x] QA'd all new/changed functionality manually ## Notes for reviewers - Resolving the name on read is what closes the reconcile-cron race @getvictor raised: there is no denormalized copy to go stale while the profile exists, so nothing for the cron to overwrite. It also removes the per-host write, so there's no 100K-host operation to load test. - The delete snapshot compares with `CAST(mwcp.name AS BINARY)`. The column is `utf8mb4_unicode_ci`, so a plain `!=` treats `foo` and `Foo` as equal and would skip a case-only rename. - The cross-platform name check is a `NOT EXISTS` inside the `UPDATE` rather than a preceding `SELECT`, so check and write are atomic. Same shape `NewMDMWindowsConfigProfile` uses on insert. - `UpdateMDMWindowsConfigProfile` uses `withRetryTxx`: that cross-table guard deadlocks with the create paths under concurrent claims of the same name (`ERROR 1213` on 20 of 80 transactions locally). - GitOps still matches Windows profiles by name, so a profile renamed in the UI and later reconciled from a YAML file using the old name is delete-then-insert, as before. GitOps mode disables the edit button. <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Editing a Windows configuration profile with a differently named file now renames the profile while preserving its identity. * Profile names are retained correctly when profiles or teams are deleted. * **Bug Fixes** * Duplicate or reserved profile names are rejected without changing the existing profile. * File names longer than 255 characters now show a clear validation message instead of a database error. * Profile names remain accurate in profile lists, downloads, and activity history. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
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.
Reference doc change for #51104
Implementation PR: #52055
Editing a Windows configuration profile and uploading a replacement file with a different name now renames the profile. Previously the contents were replaced but the name was kept.
Documenting that exposed a contradiction in the existing "Uploading a new profile file" section. It opened with "The new profile must match the identity of the existing profile" as a blanket rule, then listed only DDM and
.mobileconfig. That's wrong for Windows and Android, which have no identifier inside the file and accept any valid replacement, and for Windows it now conflicts with the rename behaviour, since name is the only identity a Windows profile has.So this rewrites the section as one list covering all four profile types, saying for each what the new file must match and what the profile is called afterwards. It also documents renaming for
.mobileconfigviaPayloadDisplayName, which already worked and was simply never written down, and the409on a name collision.No behaviour change for Android or Apple DDM.