Skip to content

Document Windows profile rename on edit - #52072

Merged
rachaelshaw merged 3 commits into
docs-v4.92.0from
jbelbo/51104-docs-windows-profile-name
Aug 28, 2026
Merged

Document Windows profile rename on edit#52072
rachaelshaw merged 3 commits into
docs-v4.92.0from
jbelbo/51104-docs-windows-profile-name

Conversation

@jbelbo

@jbelbo jbelbo commented Aug 27, 2026

Copy link
Copy Markdown
Member

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 .mobileconfig via PayloadDisplayName, which already worked and was simply never written down, and the 409 on a name collision.

No behaviour change for Android or Apple DDM.

@jbelbo jbelbo added the ~api-or-yaml-design Used for pull requests (PRs) with proposed API and YAML changes label Aug 27, 2026
@jbelbo jbelbo mentioned this pull request Aug 27, 2026
4 tasks
@jbelbo
jbelbo force-pushed the jbelbo/51104-docs-windows-profile-name branch from 8a4d757 to 860c776 Compare August 28, 2026 15:59
@jbelbo
jbelbo marked this pull request as ready for review August 28, 2026 17:48
@jbelbo
jbelbo requested a review from rachaelshaw as a code owner August 28, 2026 17:48
@rachaelshaw
rachaelshaw merged commit 1a69c00 into docs-v4.92.0 Aug 28, 2026
5 of 6 checks passed
@rachaelshaw
rachaelshaw deleted the jbelbo/51104-docs-windows-profile-name branch August 28, 2026 21:20
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 -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

~api-or-yaml-design Used for pull requests (PRs) with proposed API and YAML changes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants