Skip to content

chore: sync upstream fleetdm/fleet (v4.90.1) into flamingo-stack/fleetmdm fork - #116

Open
oleg-flamingocx wants to merge 1633 commits into
mainfrom
sync/upstream-main-v4.90.1
Open

chore: sync upstream fleetdm/fleet (v4.90.1) into flamingo-stack/fleetmdm fork#116
oleg-flamingocx wants to merge 1633 commits into
mainfrom
sync/upstream-main-v4.90.1

Conversation

@oleg-flamingocx

Copy link
Copy Markdown

No description provided.

fleet-release and others added 30 commits August 8, 2026 21:40
Automated ingestion of latest Fleet-maintained app data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Updates**
- Refreshed package metadata and download verification details for the
latest releases of Firefox Nightly, Franz, Gitify, Hey Desktop, Omnissa
Horizon Client, Python, Readest, Reqable, Shapr3D, Wealthfolio, and
YACReader.
  - Updated YACReader for both macOS and Windows.
- Improved Omnissa Horizon Client cleanup to remove an additional
component during uninstallation.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
Automated ingestion of latest Fleet-maintained app data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Updates**
- Updated BetterMouse, Chatbox, DevKnife, Firefox Nightly, Krisp,
Marked, MarkEdit, OK JSON, Python 3.14, Reqable, and Stats to newer
releases.
- Refreshed download links, version detection, installer packages, and
verification checksums.
  - Updated Krisp’s macOS package for the latest Apple silicon release.
- Changed OK JSON installation packages from ZIP to DMG on macOS and
Homebrew.
  - Preserved supported installation and uninstallation workflows.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
Co-authored-by: Allen Houchins <allenhouchins@mac.com>
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves fleetdm#31471 

I opted for removal for two reasons:
1. I've never seen this notification used before locally
2. The workaround to support these notifications are pretty bad, either
rely on platform detection and call system level notification centers,
or make every developer patch the underlying library.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

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

## Testing

- [x] QA'd all new/changed functionality manually

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
  * Removed unnecessary build-time notification behavior.
* Streamlined the development build configuration to improve reliability
and reduce setup overhead.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves fleetdm#50124

<img width="1465" height="149" alt="image"
src="https://github.com/user-attachments/assets/21e611a8-2c6d-464a-a986-ffabc9893725"
/>


# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [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.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops
- [x] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Prevented the “Turn on MDM” banner from appearing before a host’s
device details have been fetched.
* The banner continues to appear for eligible unenrolled macOS hosts
once current device details are available.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
**Related issue:** Resolves fleetdm#50764

An activation carries a predicate whose syntax is Apple's, so Fleet
can't validate it. On macOS 26.5 an invalid one — the issue's example is
`@invalid == 'AppleTV'` — wedges the host's MDM subsystem: declarative
commands stop completing, other commands are picked up and never finish,
and removing the enrollment profile on the device fails too. The host
can't be recovered remotely. Apple is tracking it as FB24193230.

Until that's fixed, uploading an activation requires
`FLEET_MDM_ENABLE_CUSTOM_ACTIVATIONS` (`mdm.enable_custom_activations`),
which is off by default. It sits alongside the existing
`mdm.enable_custom_*` settings.

- The check lives in the validation that the create, edit, and GitOps
batch paths already share, so there's one gate rather than three that
could drift apart.
- Removing a stored activation deliberately doesn't reach that
validation, so an operator can still undo one with the setting off. That
matters here, since a host with a bad predicate can't be fixed from the
device.
- Serving is untouched — an activation already stored still goes to
devices. The issue asks to block uploads only.

Existing tests default to the setting being on via a variadic option on
the shared setup, so none of the callers changed. The new test turns it
off and asserts the upload is refused while the same declaration without
an activation still succeeds.

No changes file: the feature is unreleased, so there is nothing
user-visible to note.

Remaining from the issue, to follow separately: the parent story update
on fleetdm#48222, and a docs PR.

# Checklist for submitter

- [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
- [ ] QA'd all new/changed functionality manually


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added an optional server setting to enable custom Apple MDM
activations.
  * Custom activation uploads are rejected when the setting is disabled.
* Removing an existing activation remains supported regardless of the
setting.
* **Tests**
* Added coverage for disabled custom activation uploads and enabled
integration scenarios.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Automated ingestion of latest Fleet-maintained app data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added support for the latest releases of numerous macOS and Windows
applications, including Docker Desktop, Firefox Nightly, Readest,
Reqable, Rize, WhatsApp, Zoom Rooms, and others.
* Refreshed download information and integrity checks to ensure
installers use current release packages.

* **Bug Fixes**
* Improved OK JSON removal by also clearing its associated application
data during uninstall.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->

Fixes the "Slack root notification" step in the `TUF expiration check:
updates.fleetdm.com` workflow, which failed with `Error: Need to provide
valid JSON payload` in [this
run](https://github.com/fleetdm/fleet/actions/runs/31379218985). The
payload's top-level `"text"` field was an unterminated string, so the
slackapi action rejected it — meaning the warning that `root.json` is
within 30 days of expiring never reached Slack. Restored the line to
match the other three notification steps in the same workflow.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [ ] 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] QA'd all new/changed functionality manually (verified all four
Slack payloads in the workflow parse as valid JSON after expression
substitution; this PR itself triggers the workflow since it touches the
file)


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Improvements**
* Slack root notifications now include a direct link to the related pull
request or workflow after the job status.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Added YouTube video to article

---------

Co-authored-by: Noah Talerman <47070608+noahtalerman@users.noreply.github.com>
Discussed [on
Slack](https://fleetdm.slack.com/archives/C091KKQ8U73/p1781714056870039?thread_ts=1781714014.565039&cid=C091KKQ8U73).

@rfairburn Can you give this a quick look? Mainly the line about using
`query` and setting `device_mapping=true`.
…tdm#50885)

**Related issue:** Resolves fleetdm#50875

Docker Desktop on macOS never reported an installed version or
"Installed" status, and offered "Install" on hosts that already had it.

## Root cause

The FMA's `unique_identifier` was `com.electron.dockerdesktop`, which
belongs to the embedded Electron bundle. The installed app reports a
different identifier:

| Path | CFBundleIdentifier |
|---|---|
| `/Applications/Docker.app` | `com.docker.docker` |
| `/Applications/Docker.app/Contents/MacOS/Docker Desktop.app` |
`com.electron.dockerdesktop` |

The identifier was changed from `com.docker.docker` →
`com.electron.dockerdesktop` in fleetdm#37670 (Jan 5) as "the new bundle
identifier … reflecting the current packaging". The top-level bundle
never changed.

That was latent until fleetdm#47831 (fleetdm#44199, Jul 9) added an embedded-bundle
filter to the macOS software inventory query in
`server/service/osquery_utils/queries.go`:

```sql
FROM apps
WHERE path NOT LIKE '%.app/Contents/%'
```

`/Applications/Docker.app/Contents/MacOS/Docker Desktop.app` matches
that pattern, so the only row carrying the embedded identifier is
filtered out and inventory keeps just `/Applications/Docker.app` →
`com.docker.docker`. Since FMA↔inventory matching is by bundle
identifier (`addSoftwareTitleToMatchingSoftware`), the title the FMA
owns had zero installed versions.

**Patch policies kept passing**, because they run the FMA's
`exists`/`patched` SQL directly against the host's *unfiltered* `apps`
table. That's also why fleetdm#50041 needed a `.back` path exclusion, and why
patch status and the software UI have disagreed since July.

## What changed

**Catalog** — `unique_identifier` is now `com.docker.docker`, with
`docker-desktop/darwin.json` regenerated. `outputs/apps.json` needed a
hand-edit because `updateAppsListFile` (`cmd/maintained-apps/main.go`)
only appends new apps and never updates an existing entry's identifier —
filed separately.

The remaining `com.electron.dockerdesktop` references are intentional
and untouched: the install script's quit/relaunch targets (the Electron
bundle is what responds to AppleScript) and the cask's zap paths. The
`.back` exclusion in the patched query also stays —
`/Applications/Docker.app.back` is a *top-level* bundle reporting
`com.docker.docker` at a path the nested-bundle filter does not match,
so a stale `.back` would otherwise show a false "Update available".

**Migration** (`20260810152924_FixDockerDesktopBundleIdentifier`) —
`fleet_maintained_apps` self-heals on catalog sync
(`UpsertMaintainedApp` updates `unique_identifier` on duplicate slug)
and `ReconcileMaintainedAppSoftwareNames` renames the existing "Docker"
title, but an already-added installer's `software_installers.title_id`
binding does not:

- **No `com.docker.docker` title yet** → relabel the stale title in
place, so everything already pointing at it stays correct.
- **Title already exists** (the normal case — any host with Docker
creates it) → merge the stale title into it: installer, install history,
queued installs, patch policy, `software.title_id`, and per-team
settings (icons, display names, pins, update schedules), then drop the
stale title.

## Notes for reviewers

- **Teams that already have an installer on the target title are
skipped** rather than ending up with two installers on one title.
`dedup_token` is the *version* for FMAs and the *storage_id* otherwise,
so `idx_software_installers_dedup` would not have caught that collision.
Those teams keep the pre-migration state instead of having data silently
reshaped.
- **The stale title is only deleted once nothing depends on it.**
`fk_software_installers_title` is `ON DELETE SET NULL`, so deleting it
while an installer still pointed at it would orphan that installer. Note
also that `fk_patch_software_title_id` is `ON DELETE CASCADE` —
re-pointing the patch policy is what keeps it from being deleted
outright.
- **Dangling-reference check:** the only title-referencing columns
without an FK to `software_titles` are `software.title_id` (re-pointed),
`software_titles_host_counts` (deleted; the cron recomputes), and
`kernel_host_counts` / `in_house_app_install_tokens`, neither of which
can hold a macOS app title.
- **Naming lags briefly.** The existing title is named "Docker" (from
osquery); `ReconcileMaintainedAppSoftwareNames` renames it to "Docker
Desktop" on the next catalog sync, so there is a window after upgrade
where the name is still "Docker". I left that to the sync rather than
duplicating the rename logic in the migration.
- **This fixes one app, not the class.** Any other macOS FMA keyed on a
nested bundle fails the same silent way, and a green patch policy will
not reveal it. An audit is filed separately.

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`.
- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements).
Table/column names in the migration's generated SQL come from hardcoded
struct literals, never from data; all values are placeholders.

## Testing

- [x] Added/updated automated tests

Five migration tests cover: relabel-in-place,
merge-into-inventory-title, duplicate per-team settings dropped, teams
with an existing installer skipped (and the stale title consequently
retained), and no-op when the FMA was never added. The merge test also
asserts `updated_at` is not restamped. Updated the homebrew ingester
test expectations for the new identifier.

Verified: full `server/datastore/mysql/migrations/tables` suite passes
(201s), `ee/maintained-apps/...`, `cmd/maintained-apps/...`, and the FMA
datastore tests pass, `make lint-go-incremental` clean.

Root cause was confirmed against real bundles rather than inferred —
`PlistBuddy` on both Docker bundles for the identifiers above, and
`lsregister -dump` to confirm LaunchServices registers the nested
bundles (which is why the raw `apps` table sees them and patch policies
pass).

- [ ] QA'd all new/changed functionality manually

Needs QA on a real instance: add the Docker Desktop FMA, confirm the
installed version and "Installed" status appear on a host that already
has it, and confirm an upgrade over an instance that already had the FMA
added re-points the existing installer.

For unreleased bug fixes in a release candidate, one of:

- [x] Confirmed that the fix is not expected to adversely impact load
test results

The migration touches only rows tied to a single software title, and is
a no-op on instances that never added the Docker Desktop FMA.

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.

Five of the written tables have `updated_at` as `ON UPDATE
CURRENT_TIMESTAMP`: `software_installers`, `host_software_installs`,
`software_install_upcoming_activities`, `policies`, and
`software_title_team_pins`. Since this re-points a foreign key rather
than modifying the records, each statement assigns `updated_at =
updated_at` so MySQL leaves them alone, with a test asserting it.
(Bumping them would have been cosmetic — none of these columns drives
ordering, scheduling, or invalidation; policy membership uses
`policy_membership.updated_at` and `hosts.policy_updated_at`, and the
activity feed orders by the activities table — but preserving them is
more faithful to what the migration actually does.)

- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`). No columns added or altered;
this is a data-only migration.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved macOS Docker Desktop detection so installed versions and
“Installed” status are reported accurately.
* Ensured existing Docker Desktop installations and upgrade history
remain correctly associated after detection updates.
* Improved handling of stale application bundles during patch
evaluation.
* **Maintenance**
* Updated detection data and migration coverage to support the corrected
Docker Desktop identification.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
…fleetdm#50866)

<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves fleetdm#49889 

It now jumps directly to the My Device page if the migration flow sees
the device being unmanaged locally, even if Fleet carries stale data.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [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.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops
- [x] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

## fleetd/orbit/Fleet Desktop

- [x] Verified compatibility with the latest released version of Fleet
(see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md))
- [x] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes
- [x] Verified that fleetd runs on macOS, Linux and Windows
- [x] Verified auto-update works from the released version of component
to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Improved macOS MDM migration handling by checking the device’s local
enrollment status before sending migration webhook notifications.
* Webhook notifications are now skipped when the device is not locally
enrolled, preventing unnecessary migration events.
  * Improved detection of separate DEP and MDM enrollment states.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Automated ingestion of latest Fleet-maintained app data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Updates**
* Updated macOS installer details and checksums for Cisco Jabber,
Downie, Firefox Nightly, GoLand, Grammarly Desktop, IntelliJ IDEA,
Maccy, Marked, Microsoft Edge, NordPass, Ollama, SABnzbd, and Surge.
  * Updated Portfolio Performance for Windows to version 0.86.1.
* Added support for the latest available app releases, improving version
detection and installation reliability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
…of a GUI (fleetdm#50363)

<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves fleetdm#50312

Adds a guide for building and validating configuration profiles with an
AI agent instead of a GUI profile editor.

The framing: a GUI's payload picker constrains you to settings that
exist with values the platform accepts, and that constraint is the real
value of a profile editor. Everything else about it is transcription.
Every one of those pickers is a GUI over a published schema, so the
guide replaces the transcription with an agent, keeps the constraint by
pointing the agent at the same schema, and the unit of work becomes
intent rather than XML.

## Structure

The guide is symmetric across Apple, Windows, and Android at every step
that has platform-specific content:

| Step | Apple | Windows | Android |
|---|---|---|---|
| 1. Put the schema where the agent can read it | contour, schema
embedded in the binary | Microsoft's per-CSP DDF pages | Google's Policy
discovery document |
| 4. Traps | 3 contour behaviors | 5 DDF-derived behaviors | 2 verified
gaps in local validation |
| 5. CI gate | `contour ... --strict` on `ubuntu-latest` | `fleetctl
gitops --dry-run` plus a DDF node lookup | `fleetctl gitops --dry-run` |

Steps 2, 3, and 6 are platform-neutral. No platform is described by
comparison to another, and no platform is described as thinner or weaker
than another, because on inspection none of them is.

# Checklist for submitter

- [x] Documentation-only change. No code, tests, migrations,
configuration settings, or fleetd changes.

---------

Co-authored-by: Allen Houchins <32207388+allenhouchins@users.noreply.github.com>
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves fleetdm#50540
<img width="822" height="275" alt="Screenshot 2026-08-06 at 8 36 17 PM"
src="https://github.com/user-attachments/assets/fa1f6746-80d6-448d-a5f0-e3459b64d7d8"
/>
<img width="443" height="171" alt="Screenshot 2026-08-06 at 8 49 38 PM"
src="https://github.com/user-attachments/assets/315468f3-258a-4e33-b05c-58bf2923282a"
/>

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

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

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

## Summary

The "Install details" modal showed this copy for a failed install on
Android hosts:

> The MDM command (request) to install **Slack** on **LeAnn Gove's
Samsung SM-S906U1** failed. Please re-attempt this installation.

"Re-attempt this installation" is misleading. Only the end user can
retry via the Google Play Store in their work profile.

This PR splits the copy into two variants for Android:
- **Admin-facing** (Host details / activity feed): "Fleet failed to
install **App** on **Host** (timestamp). The end user can retry via the
Google Play Store in their work profile."
- **My Device page** (end user, who already has a Retry button): "Fleet
failed to install **App** (timestamp). Retry via the Google Play Store
in your work profile, or select **Retry** below."

The Apple copy is unchanged.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

## Bug Fixes

- Clarified installation failure messages across Apple, Android, and
unsupported platforms.
- Added guidance for retrying failed Android installations through the
Google Play Store in the work profile.
- Improved first-person messaging for Android devices using the My
Device experience.
- Added clearer fallback messages when installation verification times
out or the platform is unsupported.
- Updated installation status messaging for Android verification and
failure scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves fleetdm#50804 

Verified with a 26.5 iPhone, before this fix it didn't prompt, with this
fix it did prompt on ADE enrollment.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [ ] 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. Unreleased

- [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.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops
- [x] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

For unreleased bug fixes in a release candidate, one of:

- [x] Confirmed that the fix is not expected to adversely impact load
test results
- [ ] Alerted the release DRI if additional load testing is needed


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
  * Improved operating system update handling during device enrollment.
* Devices configured to require the latest available OS version now
correctly receive updates, including iPadOS devices running an older
version.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Resolves fleetdm#50703

Stat() returned Perm{Known: false} unconditionally on Windows, so the
world_writable risk flag on agent_instruction rows could never fire no
matter what the file's real ACL was.

Split the permission read per platform: perm_unix.go keeps the mode-bit
logic, perm_windows.go reads the DACL via GetSecurityInfo, and
perm_acl.go holds the platform-neutral ACE decision rules so they are
unit-testable anywhere. Known: false now means "could not determine"
rather than "Windows".

Everyone (S-1-1-0) and Authenticated Users (S-1-5-11) count as world;
BUILTIN\Users is excluded because standard locations grant it create
rights by default.

Also adds ./orbit/pkg/table/ai_tools/... to the Windows CI package list,
which otherwise never exercises this code.
Added a policy query for macOS version checks and updated notes on
version column handling.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Documentation**
* Added queries for checking operating system architecture and version.
* Added a policy check for outdated macOS versions with Screen Sharing
or Remote Management enabled.
  * Clarified semantic-version ordering for operating system versions.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
…0840)

**Related issue:** Resolves fleetdm#50105 

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

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Normalized Windows-style line endings in uploaded shell and Python
packages before storage and installation.
* Prevented Linux installation failures caused by carriage return
characters.
* Preserved Windows-style line endings for PowerShell packages to
maintain compatibility.
* **Tests**
* Added coverage confirming shell and Python packages use Unix-style
line endings while PowerShell packages retain their original format.
* **Documentation**
* Added a changelog entry describing the line-ending normalization
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Changes:
- updated the send-data-to-vanta script to log an error and stop running
for a Vanta connection if the response from a Fleet instance's
`/api/v1/fleet/users` endpoint does not contain an array of users.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
  * Added validation for Fleet user data before synchronization.
* Invalid or missing user data now records an error and stops processing
safely.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
…fleetdm#50879)

**Related issue:** Resolves fleetdm#50764

Renames the setting added in fleetdm#50863 from `mdm.enable_custom_activations`
to `mdm.allow_custom_activations`, so it reads as the safety override it
is — alongside `mdm.allow_all_declarations` — rather than as a feature
toggle like the `mdm.enable_custom_*` settings.

The environment variable is now `FLEET_MDM_ALLOW_CUSTOM_ACTIVATIONS`,
and the error text shown on a blocked upload was updated to match.
Nothing has shipped with the old name, so no compatibility handling is
needed.

# Checklist for submitter

- [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

- [ ] QA'd all new/changed functionality manually


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Configuration**
* Renamed the MDM custom activation setting to
`allow_custom_activations`.
  * Preserved the existing default value and behavior.

* **Bug Fixes**
* Updated activation validation and error messaging to use the renamed
setting consistently.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves fleetdm#50878 

Resets label_updated_at to the "never" sentinel (2000-01-01 UTC) so that
the exclude-any dynamic-label guard treats the cleared memberships as
not-yet-reported instead of trusting them until the next label report.

Prior to this fix, hosts could see profiles get installed on enrollment,
then relatively quickly removed once labels actually got calculated, as
opposed to having them withheld until the exclude label query could be
ran.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [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.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops
- [x] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [x] Added/updated automated tests
- [x] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [x] QA'd all new/changed functionality manually


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Fixed an issue where profiles with exclude-any labels could be
installed before label results were available after DEP re-enrollment.
* Label status now resets correctly during re-enrollment while
preserving unaffected hosts’ label information.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Related issue: fleetdm#47589

Orbit reads the end user's LUKS passphrase from the zenity/kdialog
dialog's stdout, but launched it with `sudo -i`. The login shell sources
/etc/profile, /etc/profile.d/* and ~/.profile first, and anything they
print lands on the same stdout, so the captured passphrase gets that
output prefixed to it. cryptsetup rejects the result and exits 2, which
surfaces as "Passphrase incorrect. Please try again." for a valid
passphrase -- silently, since the validation loop only logs at debug
level.
Automated ingestion of latest Fleet-maintained app data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Updates**
- Refreshed supported application packages across macOS and Windows,
including Adobe Acrobat Reader, Android Studio, Docker, Firefox,
Microsoft Edge, Notion, Postman, Slack, Teleport, and many others.
- Updated installer downloads, version detection, and integrity checks
to deliver the latest releases.

- **Bug Fixes**
  - Improved Autopsy upgrade removal and Slack installation behavior.

- **Configuration**
- Marked Adobe Acrobat Pro, Cisco Jabber, Keeper Password Manager, and
NVIDIA GeForce NOW as frozen.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
Co-authored-by: Allen Houchins <allenhouchins@mac.com>
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves  failing CI

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [ ] 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.

- [ ] 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.
- [ ] Timeouts are implemented and retries are limited to avoid infinite
loops
- [ ] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [ ] Added/updated automated tests
- [ ] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [ ] QA'd all new/changed functionality manually

For unreleased bug fixes in a release candidate, one of:

- [ ] Confirmed that the fix is not expected to adversely impact load
test results
- [ ] Alerted the release DRI if additional load testing is needed

## Database migrations

- [ ] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [ ] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [ ] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).

## New Fleet configuration settings

- [ ] Setting(s) is/are explicitly excluded from GitOps

If you didn't check the box above, follow this checklist for
GitOps-enabled settings:

- [ ] Verified that the setting is exported via `fleetctl
generate-gitops`
- [ ] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [ ] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)
- [ ] Verified that any relevant UI is disabled when GitOps mode is
enabled

## fleetd/orbit/Fleet Desktop

- [ ] Verified compatibility with the latest released version of Fleet
(see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md))
- [ ] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes
- [ ] Verified that fleetd runs on macOS, Linux and Windows
- [ ] Verified auto-update works from the released version of component
to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
  * Clarified how operating system versions are ordered and compared.
* Added a macOS policy query example combining version and sharing
settings.
  * Improved formatting for existing SQL examples.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
…er endpoint (fleetdm#50945)

The GitOps role is denied on `/hosts` and `/hosts/{id}`, but `GET
/hosts/identifier/{identifier}` authorized its host check with
`selective_read`, so a GitOps token could read full host details for any
host whose identifier it knew. It now runs the same `ActionRead` check
as `/hosts/{id}`, returning only the host's `id` rather than an error so
the deprecated Puppet module's profile pre-assignment keeps working.

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

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Bug Fixes**
- GitOps users can now resolve host identifiers and receive the host ID
without access to additional host details.
- Users with full host-read permissions continue to receive complete
host information.
- Unauthorized access remains denied, including GitOps access outside
the permitted team scope.
  - Preserved identifier-only responses for legacy integrations.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** fleetdm#46471 
The issue has been fixed since 4.87.0, this is just to unify a few cases
where extension is parsed from filename.

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [ ] 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.

- [ ] 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.
- [ ] Timeouts are implemented and retries are limited to avoid infinite
loops
- [ ] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [x] Added/updated automated tests
- [ ] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [x] QA'd all new/changed functionality manually

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [ ] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- This will cause a timestamp update for affected rows, which I think is
reasonable because they were actually modified.
- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
* Installer filenames now preserve their original casing while
extensions are consistently stored and processed in lowercase.
* Improved compatibility with uppercase and mixed-case installer
extensions, including script packages.
  * Existing installer records are normalized during database upgrades.

* **Tests**
* Added coverage for mixed-case filenames, extension handling, platform
routing, downloads, and database migration behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
getvictor and others added 29 commits August 18, 2026 13:51
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves fleetdm#48850

This is part 2 of parent fleetdm#43481

# Checklist for submitter


## Testing

- [x] Added/updated automated tests
- [x] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [x] QA'd all new/changed functionality manually

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **New Features**
* Added automatic Microsoft Windows Autopilot synchronization every five
minutes.
  * New devices are matched to existing hosts or added as pending hosts.
* Device removals, updates, group tags, hardware details, and enrollment
status are handled automatically.
* Improved Windows enrollment linking with Zero Touch Provisioning
identifiers.
  * Preserved Autopilot enrollment details during re-enrollment.

* **Bug Fixes**
* Improved handling of duplicate devices, invalid credentials,
pagination failures, and tenant-specific sync errors.
* Prevented active Autopilot hosts from being incorrectly expired or
removed.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves #

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [ ] 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.

- [ ] 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.
- [ ] Timeouts are implemented and retries are limited to avoid infinite
loops
- [ ] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [ ] Added/updated automated tests
- [ ] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [ ] QA'd all new/changed functionality manually

For unreleased bug fixes in a release candidate, one of:

- [ ] Confirmed that the fix is not expected to adversely impact load
test results
- [ ] Alerted the release DRI if additional load testing is needed

## Database migrations

- [ ] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [ ] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [ ] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).

## New Fleet configuration settings

- [ ] Setting(s) is/are explicitly excluded from GitOps

If you didn't check the box above, follow this checklist for
GitOps-enabled settings:

- [ ] Verified that the setting is exported via `fleetctl
generate-gitops`
- [ ] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [ ] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)
- [ ] Verified that any relevant UI is disabled when GitOps mode is
enabled

## fleetd/orbit/Fleet Desktop

- [ ] Verified compatibility with the latest released version of Fleet
(see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md))
- [ ] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes
- [ ] Verified that fleetd runs on macOS, Linux and Windows
- [ ] Verified auto-update works from the released version of component
to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))
Removed author information and promotional content from the article.

<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves #

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [ ] 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.

- [ ] 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.
- [ ] Timeouts are implemented and retries are limited to avoid infinite
loops
- [ ] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

- [ ] Added/updated automated tests
- [ ] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [ ] QA'd all new/changed functionality manually

For unreleased bug fixes in a release candidate, one of:

- [ ] Confirmed that the fix is not expected to adversely impact load
test results
- [ ] Alerted the release DRI if additional load testing is needed

## Database migrations

- [ ] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [ ] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [ ] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).

## New Fleet configuration settings

- [ ] Setting(s) is/are explicitly excluded from GitOps

If you didn't check the box above, follow this checklist for
GitOps-enabled settings:

- [ ] Verified that the setting is exported via `fleetctl
generate-gitops`
- [ ] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [ ] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)
- [ ] Verified that any relevant UI is disabled when GitOps mode is
enabled

## fleetd/orbit/Fleet Desktop

- [ ] Verified compatibility with the latest released version of Fleet
(see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md))
- [ ] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes
- [ ] Verified that fleetd runs on macOS, Linux and Windows
- [ ] Verified auto-update works from the released version of component
to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))
Automated ingestion of latest Fleet-maintained app data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Updates**
* Updated available versions for 27 maintained applications across macOS
and Windows, including Anytype, Arduino IDE, Beekeeper Studio, ChatGPT,
Claude, Godot, JetBrains Toolbox, VirtualBox, Visual Studio, Zed,
Zotero, and others.
* Refreshed download details, version detection, and verification data
to support installation of the latest releases.
* **Bug Fixes**
* Improved Opera for macOS removal by closing the application before
deleting related files.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
…#51142)

<!-- Add the related story/sub-task/bug number, like Resolves fleetdm#123, or
remove if NA -->
**Related issue:** Resolves fleetdm#40637

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Added a redirect so the legacy policy automation configuration profile
link now opens the corresponding guide.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
On some template files the result for the "All hosts" label is defined
with ID=6 (`fleet_label_query_6`). My local deployment has label ID `11`
for the "All hosts" label, so when running live queries against "All
hosts" they were not scheduled on the osquery-perf hosts.

- [X] QA'd all new/changed functionality manually

---

PS: Bug found while developing the WebSocket implementation on fleetd.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Bug Fixes**
  * Improved label query handling for the built-in “All hosts” label.
* Membership checks now succeed consistently without relying on
deployment-specific identifiers.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
- Example YAML was incorrect.
- Clarified what conflict means, it wasn't explicit.
Automated ingestion of latest Fleet-maintained app data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Updates**
- Updated maintained app packages to newer releases across Windows and
macOS, including Amazon Corretto, Claude, Connect Fonts, Dropbox,
Firefox, Google Chrome, Granola, Kiro, Microsoft 365 apps, Thunderbird,
Unity Hub, Warp, and WhatRoute.
- Refreshed version detection, installer links, and package checksums
where applicable.
- Updated select installation and removal workflows to safely close
applications and clean up related services or user data.
- Microsoft 365 installers now reference the latest corresponding
package builds.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
**Related issue:** Resolves fleetdm#49268

Releasing a device from Apple Business never sends the `deleted` op_type
that would clear its `host_dep_assignments` row, so the row outlives the
assignment. Deleting the host then wrote a "host deleted" activity and
immediately recreated the host as pending, and the only repair was
setting `deleted_at` by hand.

Fleet now asks Apple whether the device is still assigned before
deleting an ADE host:

- **Not assigned** — mark the assignment deleted first, the same thing
the DEP syncer does on a `deleted` op_type, so the lifecycle declines to
restore the host. An assignment left without an ABM token is treated the
same way: there is no organization left to ask, and nothing that could
restore through it.
- **Still assigned** — unchanged, the host is deleted and recreated as
pending.
- **Apple unreachable** — the delete is refused (502) rather than
reported as a success that reverses itself.

Hosts without a live ADE assignment, free tier, and deployments without
Apple Business are unaffected and make no Apple call.

Bulk deletes ask Apple once per 200 serials per ABM token, grouped by
token since each authenticates as a different organization. Hosts Apple
could not be asked about are left in place and named in the error; the
rest of the batch is still deleted.

## Notes for the reviewer

- **Bulk delete returns 202 after 30s** and finishes in a detached
goroutine, so the skipped-hosts error may never reach the caller on
large batches. Reporting partial results reliably would need a
job/status surface, which felt out of scope here.
- **`MarkHostDEPAssignmentsDeleted` is used rather than
`DeleteHostDEPAssignments`**, against the latter's doc comment.
`DeleteHostDEPAssignments` is keyed by ABM token (so it cannot express
an assignment that lost its token) and also deletes pending host rows
matching the serial — a side effect this path does not want. The doc
comment has been updated to explain when each applies.
- **The assignment is marked deleted before the host delete, outside a
transaction.** This is deliberate: the record is marked because Apple
said the device is not ours, which holds whether or not the delete then
succeeds. A failed delete leaves the record more accurate than it was,
and the retry succeeds because no live assignment remains.
- **The DEP test mock now answers Get Device Details.** Host deletion
consults it in production; the suite's fake server did not serve it, so
every ADE host delete was refused.

# 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] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)

- [ ] QA'd all new/changed functionality manually


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Bug Fixes**
* Host deletion now verifies Apple Business Manager assignments before
proceeding.
* Hosts with unverified assignments are protected from deletion, while
eligible hosts continue to be deleted during bulk operations.
* Apple connectivity or verification failures now return an error
instead of reporting a successful deletion.
* Disowned Apple assignments are cleared to prevent stale records from
restoring deleted hosts.
* Apple assignment checks now support multiple hosts efficiently during
bulk deletion.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Automated ingestion of latest Fleet-maintained app data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Updates**
* Updated Amazon Corretto 8, 17, 21, 25, and 26 packages for Windows to
their latest patched releases.
  * Updated AWS VPN Client for macOS to version 6.0.2.
  * Updated Azul Zulu JDK and JRE 25 for Windows to version 25.36.205.
  * Updated Firefox Nightly for Windows to version 156.2608.1809.0.
* Refreshed download links, version checks, checksums, and applicable
uninstall references.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
Automated ingestion of latest Fleet-maintained app data.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Updates**
  * Updated the macOS Teleport Connect package to version 18.10.6.
  * Updated the macOS Teleport Suite package to version 18.10.6.
* Refreshed installer links, checksums, and version requirements for the
updated packages.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
Merges 1618 upstream commits (fleetdm/fleet b139336) into the OpenFrame
fork, per openframe/docs/upstream-sync-conflict-resolution.md.

Conflicts resolved: 130 paths.

  92 modify/delete — fork-deleted, upstream-modified. Kept deleted: 59 under
     .github/ (fork ships its own lean pipeline) and 33 under docs/ (fork
     commit 1b972ff replaced upstream's docs with openframe/docs).
  17 file location — fork-added sidecar .md notes inside directories upstream
     renamed (tools/fleet-mcp → cmd/fleet-mcp, and the SoftwareSummaryCard
     TitleVersionsTable move). Followed upstream's rename.
  21 content — resolved keep-both per the cardinal rule; details below.

Content conflicts:

  .gitignore, cmd/fleet/serve.go, server/fleet/datastore.go,
  server/mock/datastore_mock.go, cmd/osquery-perf/agent.go
    Independent additions on both sides; kept both.

  charts/fleet/{Chart.yaml,values.yaml}
    Took upstream's version/appVersion (v7.0.16 / v4.90.1) — the chart version
    is upstream's lineage that the fork carries, not fork-owned numbering.
    All 115 chart OPENFRAME markers preserved.

  go.mod / go.sum
    Union, then `go mod tidy`. go.mod now differs from upstream by exactly the
    fork's one dep (github.com/robfig/cron/v3).

  server/config/config.go
    Upstream added AllowPrivateNetworkIntegrations, BypassNetworkBlocking and
    redis.LiveQuerySmallTargetThreshold; re-applied the fork's QueryResultsTTL /
    QueryResultsCleanupInterval fields and the redis KeyPrefix read.

  server/datastore/mysql/policies.go
    Upstream changed 5 signatures (automationType string →
    fleet.PolicyAutomationType, new platform arg) and added
    platformFilterClause. Took each new signature and re-applied the fork's
    multitenancy fence on top. ListGlobalPolicies now passes the pinned team
    *and* upstream's platform filter.

  client/orbit_client.go, orbit/cmd/orbit/orbit.go
    Upstream added bypassEndUserAuth (param + CLI flag + capability delete).
    Placed it before the fork's two trailing NewOrbitClient params
    (openFrameMode, authManager) at both call sites.

  6 migrations
    Upstream re-timestamped 5 migrations the fork had already made idempotent
    (e.g. 20260611202649 → 20260702013055). Took upstream's new file and
    function names, re-applied the fork's idempotency markers and guards.
    NOTE: because the timestamps changed, goose will re-run these on existing
    fork deployments — safe only because they are idempotent.
    AddUniqueHashToSoftware: kept the fork's guard, took upstream's comment
    (it references fleet.Software.ComputeRawChecksum;
    mysql.softwareChecksumComputedColumn no longer exists).

  server/service/osquery_utils/queries.go (+ tests)
    Upstream switched certificates_windows to osquery's subject2/issuer2
    columns and added a Discovery gate; the fork hex-encodes the DN columns so
    raw X.509 punctuation never reaches the edge WAF. Resolved so the query
    hex-encodes upstream's new columns (subject2_hex/issuer2_hex) and the
    decode is platform-aware (decodeCertificateDNColumns now takes the column
    set). Kept upstream's Discovery gate. Fork tests updated: per-platform DN
    formats (Windows parses comma-separated attribute pairs, not slash-
    separated), the new observedScopes mock param, and the SQL guard test now
    keys off the production column lists.

Verified: all 14 OPENFRAME slugs retain their exact pre-merge marker counts
(mysql-multitenancy 205, host-assignments 61, helm 53, agent-openframe-mode 47,
redis-key-prefix 42, hardening 28, vuln-persistence 18, query-results-ttl 16,
waf-inventory-shape 13, agent-json-content-type 8, cloudsql-v2 6,
redis-seed-nodes 5, migration-race 3, osquery-host-id 2). Redis pool prefix
wiring, the policy_hosts/query_hosts host filters, orbit's openframe flags and
the openframe-mode gate around the device-token rotation all re-verified.
… in openframe mode

Upstream v4.90 added a pack-config cache keyed by (teamID, queryReportsDisabled)
in getPackConfig, on the premise that every host in a team receives the same
scheduled queries unless some query uses label targeting — in which case it
falls back to a per-host DB read.

That premise does not hold in openframe mode: ListScheduledQueriesForAgents
also filters by the query_hosts table, so the pack config is host-specific even
with zero label-scoped queries. The team-level cache would therefore serve the
first host's scheduled queries to every other host in the team.

This produced no merge conflict — the fork never touched that line, and the
feature is new upstream code. It is the "query-planner change bypasses the host
filter" row of the semantic-conflict watchlist.

Gate canUseCache on !fleet.IsOpenframeMode(), which covers both the cache read
and the cache write (both are guarded by the same flag).

The test fails without the gate: host 2 is served host 1's queries.
Mandatory post-merge step 1 from the upstream-sync runbook. The v4.90.1 sync
imports 45 brand-new upstream migrations; a new file is never a merge conflict,
so none of them arrived idempotent. OpenFrame tenants are provisioned against
databases that may be partially migrated (restored snapshots, re-run Helm
migration jobs), so a re-applied migration must be a no-op rather than a hard
failure.

Transformations applied, following openframe/docs/migrations.md:

  13 files  CREATE TABLE -> CREATE TABLE IF NOT EXISTS,
            DROP TABLE -> DROP TABLE IF EXISTS,
            INSERT INTO -> INSERT IGNORE INTO

  14 files  Go existence guards for what SQL cannot express idempotently:
            columnExists / indexExistsTx around ALTER ... ADD COLUMN,
            ADD INDEX / ADD KEY, ADD CONSTRAINT and CREATE INDEX.

            For a compound atomic ALTER (e.g. AddAndroidProfileVariableTracking,
            AddCertAndAndroidAppVariableTracking, PolicyAutomationResendConfig-
            Profile) a single sentinel-column guard gates the whole statement.

            Four migrations swap one index for another
            (AddWindowsMDMConfigProfilesPriorContent,
            MultipleCustomPackagesPerTitle, AddWindowsEnrollmentDefaultFleet,
            plus the DDM activation column add). MySQL DDL is not
            transactional, so the DROP INDEX and ADD INDEX were split into
            separately-guarded statements — a run interrupted between them can
            now complete instead of failing on the second attempt.

  27 files  Already idempotent; reviewed and marked. These are pure UPDATE /
            DELETE backfills, MODIFY/CHANGE COLUMN to an identical definition,
            count-then-act incremental steps, or DDL upstream already wrote as
            IF NOT EXISTS / INSERT IGNORE / columnExists-guarded.

Every one of the 45 now carries the `// Idempotent migration.` marker.

Also adds a static guard test (no MySQL, no Docker) that scans the whole
migration corpus for the three textual rules the convention rewrites, so the
next sync fails here rather than at `fleet prepare db` against a tenant. The
test comment records why an ADD COLUMN guard cannot be checked by regex and
stays a review item.

The test documents 21 pre-existing gaps from the fork's original bulk pass in
knownNonIdempotentMigrations; the list is asserted to be exact, so entries
cannot rot. None are from this sync. Burning them down is separate work.
… sites

The merge changed two signatures that test code calls directly, and `go build`
on non-test packages does not catch it — only `go vet` / `go test` do.

client/orbit_client_test.go (upstream's own test) now passes the fork's two
trailing NewOrbitClient params. client/orbit_client_openframe_test.go passes
upstream's new bypassEndUserAuth=false ahead of them, at both call sites.

server/datastore/mysql/policies_queries_openframe_test.go adopts upstream's new
platform argument on ListGlobalPolicies, ListTeamPolicies,
ListMergedTeamPolicies, CountMergedTeamPolicies and CountPolicies. Empty string
means "no platform filter", preserving what each assertion was checking.

These are signature plumbing only — no assertion changed, so the fork's
multitenancy fences stay under test.
The marker-coverage check skips the fleet-mcp tree: it is upstream code whose
prose legitimately contains fork-looking tokens ("get_policy_hosts", "list of
hosts"). Upstream renamed the directory in v4.90, and the merge followed the
rename, so the hardcoded /tools/fleet-mcp/ skip stopped matching and the check
started reporting three upstream files as unmarked fork code.
…ry slug

Three pre-existing defects in the gate the runbook calls mandatory. All three
predate this sync; they surfaced because this is the first sync to actually run
the gate end to end.

1. The build step could never pass on a source checkout. It builds with
   -tags full, but server/bindata/generated.go is produced by the webpack build
   (make generate) and placeholder.go is //go:build !full — so under the full
   tag the package has zero Go files and the build fails with "build constraints
   exclude all Go files", regardless of the merge. Since this is step 1, the
   overall result was always FAIL, which trains reviewers to ignore it. Now the
   full tag is used only when the generated file is present, and the fallback is
   announced.

2. The marker-presence detector — whose entire job is catching fork code
   dropped by a merge — checked 8 of the 14 slugs in the tree. It was blind to
   mysql-multitenancy (205 markers across 41 files, the largest fork feature by
   a wide margin), helm, hardening, vuln-persistence, waf-inventory-shape and
   cloudsql-v2. All 14 are now checked, with a note to keep the list complete.

3. The marker-coverage check flagged continuation lines of multi-line
   OPENFRAME() rationale notes, because only the line containing the marker
   counted as covered. That is what made hosts.go's "deliberately NOT
   team-fenced" note on HostByUUID a standing failure. Contiguous comment lines
   following a marker comment now count as part of that note.

Also widens the vet step to server/service and client. Signature drift from an
upstream sync usually lands in test code, which `go build` on non-test packages
does not compile — this sync had exactly that in three files.

Result: the fast tier now passes cleanly. The MySQL tier still needs Docker.
…found

The runbook is the entry point for this work, and following it end to end
surfaced errors in it. Corrections, all verified against the tree:

Facts that were wrong:
  - Baseline said ~v4.81.2; now ~v4.90.1 (upstream b139336).
  - The slug list had 7 of the 14 slugs actually in the tree, omitting
    mysql-multitenancy — 205 markers over ~41 files, the largest fork feature.
    Adds the grep that regenerates the list authoritatively.
  - The hotspot table pointed at server/service/orbit_client.go, which does not
    exist; the file is client/orbit_client.go.
  - It placed the query-results-ttl cron registration and the Redis KeyPrefix
    pool wiring in cmd/fleet/serve.go. They live in cmd/fleet/cron_registration.go
    and cmd/fleet/redis.go. serve.go holds the multitenancy boot check instead.
  - The migration-detection command used `upstream/main...HEAD`, which lists
    fork-added files — the opposite of what it is looking for. Corrected to
    `HEAD...upstream/main`, with a note about the direction.

Coverage that was missing:
  - Hotspot rows for the mysql-multitenancy fences (the largest fork surface,
    previously unlisted) and for waf-inventory-shape in osquery_utils/queries.go.
  - Watchlist row: upstream putting a team-keyed cache in front of host-scoped
    data. This sync hit it — see the pack-config cache fix on this branch.
  - Watchlist row: upstream re-timestamping an already-applied migration, which
    makes goose re-run it on every tenant. Five of those here.
  - Watchlist row: an upstream signature change that only breaks test code, so a
    clean `go build` hides it. Three files here.

Post-merge steps now note that the fast verify tier is expected to be all green
(it previously could not be), that per-slug marker counts are the stronger
check, and that a no-op `make generate-mock` diff confirms the interface
resolution.
The manifest claimed "No top-level directory was deleted ... Deletions are
confined to `.github/`", with ~84 deleted files. Fork commit 1b972ff removed
upstream's entire docs tree (628 files); the fork keeps 39 docs/ files against
upstream's 639. Real total is closer to ~690.

This is not cosmetic at sync time: those deletions are 33 of the 92
modify/delete conflicts in the v4.90.1 merge, and a reader trusting the manifest
would not expect them or know they all resolve as "stay deleted".

Also moves the "as of" baseline off fork commit cb06c5d (stale by many fork
commits) onto the v4.90.1 sync, and marks the counts as approximate so they are
recomputed rather than trusted.
Chart.yaml moved to version v7.0.16 / appVersion v4.90.1 in the merge. Both
numbers are upstream's lineage that the fork carries along rather than fork-owned
numbering, so the conflict was resolved by taking upstream.
…ught

Adds three things this doc was missing.

The static guard: TestOpenframeMigrationsAreIdempotent scans the whole migration
corpus for the three textual rules with no MySQL or Docker, so a forgotten sweep
fails in the fast bundle instead of at `fleet prepare db` against a tenant. Its
two limits are stated plainly — it cannot judge an ADD COLUMN guard, and its
allowlist of 21 pre-existing gaps is asserted exact so it cannot rot.

The v4.90.1 numbers: 45 new migrations, none idempotent (13 textual rewrites, 14
Go guards, 28 already safe).

Two behaviors that were not written down:

  - Upstream re-timestamps migrations. Five already-applied ones were renamed,
    and goose keys on the version number, so they re-run on every tenant.
    Idempotency is the only thing making that safe. Verified by replaying all 50
    new migrations over their own applied schema.

  - A full replay from version 0 fails, and always did — at a 2017 migration
    that alters nano_view_queue, which is a VIEW in the modern schema. The
    invariant covers a migration re-attempted against a schema that already has
    its objects, not replaying the whole history. Recorded so "all migrations are
    idempotent" is not read more broadly than it holds.
…vel caches

Documents the class of bug the v4.90.1 sync hit, next to the feature that causes
it. Because the policy/query filters are per host, any upstream cache keyed by
team in front of them will serve one host's data to another. Upstream's stated
assumption is that a team's hosts all get the same scheduled queries unless label
targeting is used, and query_hosts breaks that without touching the code that
says it — so there is no merge conflict to notice.

Names the concrete instance (svc.packConfigCache in getPackConfig, now gated on
!IsOpenframeMode and pinned by pack_config_cache_openframe_test.go) and asks for
the same check on future syncs.

Also notes that the policy filter now sits in policyQueriesForHostInScope, the
shared helper, so upstream's new restrict-to-policy-IDs caller inherits it.
v4.90 moved certificates_windows onto osquery's subject2/issuer2 columns, which
preserve the DN attribute keys and are gated by upstream on a Discovery query.
The hex-encoding had to follow the columns the ingest actually reads, so the
Windows aliases are now subject2_hex/issuer2_hex and decodeCertificateDNColumns
takes the column set rather than assuming one.

Documents the per-platform column table, notes that the decode also absorbs the
\xHH unescaping upstream does inline, and adds the sync check: if upstream changes
which columns the ingest reads, the hex() wrapping must follow or the WAF
regression comes back silently. Also records that the two platforms' DN formats
are not interchangeable, which is what made the fork's own test fail until its
Windows case used a comma-separated DN.
v4.90 added TestEmbeddedCleanupScriptMatchesDocs, which asserts that the script
embedded at server/service/embedded_scripts/delete-duplicate-scep-certificates.sh
stays byte-identical to the published copy under
docs/solutions/macos/scripts/. The fork deleted upstream's whole docs tree
(1b972ff), so the test cannot find its reference file and fails on a missing
path.

This is the docs-deletion equivalent of the semantic-conflict watchlist: a new
upstream test reaches for a path the fork removed, and there is no merge conflict
to notice it.

Restores just that one file, unmodified from upstream, rather than skipping the
test — the guard is worth keeping. Runtime is unaffected either way; only the test
reads the docs copy, while the server uses the embedded one. Both were already
byte-identical, so the restored file makes the assertion pass as intended rather
than papering over drift.
…xtra column

The fork exposes osquery_host_id (OPENFRAME(osquery-host-id) changes the json/csv
tag upstream sets to "-"), so the hosts/report CSV carries one column more than
upstream's tests expect. Two assertions break on that:

  - the exact column count. Pre-merge upstream expected 57 while the fork emitted
    58; upstream added a column in v4.90 and now expects 58 against the fork's 59.
    The off-by-one is pre-existing and unrelated to this merge — the merge only
    changed the number it is off by. Updated to 59 with a marker naming the cause,
    so the next reader does not have to rediscover it.

  - the per-value assertions, which indexed columns by hardcoded position.
    osquery_host_id is emitted right after id, shifting every later index by one.
    Rather than re-number them (upstream had already re-numbered once for
    hardware_marketing_name, and the fork would have to redo it after every such
    change), these now resolve indices from the header row by name. That makes
    them immune to either side adding a column and removes a recurring conflict
    surface.

TestHostsReportDownload and TestHostsReportWithPolicyResults now pass.
…t row

Fourth break class this sync produced with no merge conflict. The fork deleted
upstream's docs tree and most of .github/; a new upstream test that reads one of
those paths compiles cleanly and fails only at run time on a missing file.
v4.90's TestEmbeddedCleanupScriptMatchesDocs is the instance.

Records the remedy that keeps the guard intact — restore the single referenced
file from upstream rather than skip the test — and what to grep for.
@oleg-flamingocx oleg-flamingocx self-assigned this Aug 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.