Commit Graph
4332 Commits
Author SHA1 Message Date
Nico a335b3e6d4 Fix VPP API retry recursion causing server OOM (#46659)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #46656

`server/mdm/apple/vpp.do` retried transient Apple errors by **calling
itself recursively**, with the rate-limit branch nesting `retry.Do`
inside `retry.Do`.

This change replaces the recursion with a single retry loop (respecting
the prior 1 initial attempt + 3 retries), closes each response before
retrying, honors Apple's `Retry-After` capped at 30s so that a
multi-minute value can't block a synchronous request, and threads
`context` through the VPP calls so the backoff is cancellable. The retry
timings are otherwise unchanged from before.

Following @sgress454 suggestion, I considered routing this through the
shared `retry.Do` helper (a single attempt wrapped in `retry.Do` + an
error filter) but figured out that:
- retry.Do` owns its own wait schedule and its error filter returns an
outcome enum rather than a duration, so it can't honor Apple's
per-response `Retry-After` value.
- also, I'd have to change the `retry` package to receive an extra `ctx`
param so that the backoff is context-aware (which IMHO is more blast
radius than this incident fix should carry).

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops

## Testing

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

**What was verified.** The new automated test cannot run against `main`
(the fix changes the VPP function signatures and adds the retry knobs),
so to confirm the actual failure mode I checked out `main` and ran a
small repro that drives the VPP client against an Apple endpoint that
always returns the rate-limit error. On `main`, the call **never
returns** — `do()` recurses without bound — and the repro times out:

```
--- FAIL: TestReproUnboundedRecursionOnMain (10.00s)
    zz_repro_main_test.go:30: AssociateAssets did NOT return within 10s — unbounded retry recursion in do() on main
FAIL
FAIL	github.com/fleetdm/fleet/v4/server/mdm/apple/vpp	10.642s
```

On this branch the same scenario returns a bounded error promptly. That
behavior is covered by the new `TestDoRetryIsBoundedAndNonRecursive`
(bounded rate-limit retries, `Retry-After` honored-but-capped, and
context cancellation), and the full `server/mdm/apple/vpp` package
passes.
**I did not perform an end-to-end QA against a live Apple endpoint**.


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

* **Bug Fixes**
* Fixed a server out-of-memory crash that occurred when Apple VPP API
repeatedly returned transient errors during VPP operations, including
app installs, user registration, and license seat releases.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-02 16:18:02 -03:00
Carlo cbf2be25ed Fix host software label scope after FMA replacement (#46649)
Resolves #43863
2026-06-02 15:09:21 -04:00
Magnus Jensen a4d1cfab1f CSUD: Add validation for OS Update profiles and OS updates being configured (#46545)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #45282

# 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

* **New Features**
* Deploy custom OS update configuration profiles for Apple
(macOS/iOS/iPadOS) and Windows; tracks and enforces one custom OS‑update
profile per scope.

* **Improvements**
* Prevent changing OS update settings when a custom profile exists;
returns guidance to remove the custom profile first.
* Batch upload now detects OS‑update payloads and enforces license
requirements.
  * UI error handling surfaces API-specific messages.
* FileVault control separated from OS updates and gated behind a
configurable flag/license.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-02 17:28:58 +02:00
Victor LyuboslavskyandKonstantin Sykulev ea5b15699e windows_mdm: link enrollment row via DevDetail at first management session (#46268)
Closes the race after Windows BYOD MDM enrollment (Settings > Access
work or school > Connect) where mdm_windows_enrollments.host_uuid stayed
empty for ~10s while osquery's distributed-read cycle ran
directIngestMDMDeviceID Windows. During that gap any server-side lookup
keyed on host UUID via MDMWindowsGetEnrolledDeviceWithHostUUID returned
NotFound.

processIncomingMDMCmds now inspects unlinked enrollments on every
management session: it parses any incoming Results for
./DevDetail/Ext/Microsoft/SMBIOSSerialNumber, looks up the Windows host
by hardware_serial, and updates host_uuid. If still unlinked after
processing the incoming message, it appends a Get for that LocURI to the
response so the device replies on the next round-trip. The Get is
idempotent and reinjected each session until linkage succeeds.

The post-link UPN/SCIM/DEP bookkeeping previously inlined in
directIngestMDMDeviceIDWindows is extracted into a shared helper
(osquery_utils.LinkWindowsHostMDMEnrollment) so both the new SyncML path
and the osquery direct-ingest backstop run it exactly once per linkage.

New datastore method WindowsHostLiteByHardwareSerial does a Windows-only
serial lookup and returns NotFound when two Windows hosts share a
serial, so we never mis-link on virtualization-shared SMBIOS values.

For Autopilot and Entra-during-OOBE the host record does not exist until
fleetd installs later in ESP, so the osquery backstop and the name-based
fallback in setup_experience.go remain in place for those flows.

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

# 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] Timeouts are implemented and retries are limited to avoid infinite
loops

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

* **New Features**
* Immediately link Windows BYOD MDM enrollments to host records during
the first management session when a device serial is present, and prompt
the device to resend serial info if missing.
* Detect and ignore placeholder/ambiguous hardware serials to avoid
incorrect host linking.
  * Reduce noisy warnings for internal-sync command IDs.

* **Bug Fixes**
* Resolve a race causing Windows MDM enrollments to remain unlinked for
several seconds.

* **Tests**
* Added coverage for serial-based linkage, retry behavior, placeholder
detection, and internal-command ID handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Konstantin Sykulev <konst@sykulev.com>
2026-06-02 09:41:07 -05:00
Victor Lyuboslavsky 0858580ff5 Refactored ListHostSoftware and ModifyAppConfig for nilaway (#46555)
Refactored `ListHostSoftware` and `ModifyAppConfig` into smaller helpers
so nilaway can analyze them for nil-pointer dereferences

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

Refactoring. No functional changes.

# 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

* **Refactor**
* Improved host software listing by consolidating assembly, merging,
deduplication, and out-of-scope filtering into dedicated helpers for
more reliable and maintainable results.
* Streamlined app configuration updates by extracting conditional-access
(Okta) validation into a focused helper, improving validation
consistency and error reporting.

* **Chores**
* Updated static analysis configuration: bumped a pinned plugin version
and removed a suppression rule that hid certain internal lint messages.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-02 08:48:56 -05:00
Juan Fernandez 923d1a2e3d Fix FK constraint failure in RecordPolicyQueryExecutions when policy deleted mid-flight (#46587)
Fixes #40362

Use INSERT IGNORE in the sync path so that a policy deleted between
distributed query dispatch and result ingestion is silently skipped,
matching AsyncBatchInsertPolicyMembership which already handles this
race with the same approach.
2026-06-02 08:45:51 -04:00
5955a6f594 43116 fix Fedora wipe btrfs snapshots (#45704)
**Related issue:** Resolves #43116

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


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

* **Bug Fixes**
* Fedora/Linux wipe now removes Btrfs snapshots (including read-only)
before wiping so snapshots won’t persist.

* **UI**
* Linux-specific guidance and external links added to wipe dialogs and
wiped/failed-wipe activity items; wipe status tags suppressed for Linux
hosts.
* Activity entries include host platform to enable platform-specific
messaging.

* **Tests**
* Updated tests to cover Linux-specific wipe messaging, links, and
activity payloads.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Jordan Montgomery <elijah.jordan.montgomery@gmail.com>
Co-authored-by: Mike Thomas <78363703+mike-j-thomas@users.noreply.github.com>
Co-authored-by: Noah Talerman <47070608+noahtalerman@users.noreply.github.com>
2026-06-02 10:14:02 +01:00
Victor Lyuboslavsky 56fe9ed6e1 Fixed the mdm_unenrolled activity not appearing in host details page (#46573)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #46119 

New activities visible on host details page:
<img width="482" height="424" alt="image"
src="https://github.com/user-attachments/assets/8b8b33b2-c135-4061-b258-473fcc109d89"
/>

# 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

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

* **Bug Fixes**
* MDM unenrollment events now appear on the host activity timeline in
host details.

* **New Features**
* Host activity entries for MDM unenroll show platform- and actor-aware
messaging and appropriate action/icon visibility.

* **Tests**
* Added tests to verify rendering and messaging for various platforms
and actor presence.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-01 18:01:15 -05:00
Victor Lyuboslavsky 1072c852e8 Added support for validating Microsoft Entra v2 access tokens (#46416)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #46388 

Video demo: https://www.youtube.com/watch?v=t3yuGh0kwP8
Docs PR: https://github.com/fleetdm/fleet/pull/46483

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

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

## New Fleet configuration settings

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

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
- [x] 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)
- [x] 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)
- [x] Verified that any relevant UI is disabled when GitOps mode is
enabled

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

* **New Features**
* UI to add/remove Entra application (client) IDs for Windows automatic
enrollment; add/delete modals and list management.

* **Enhancements**
  * Activity feed entries for added/removed Entra client IDs.
* Entra client ID allowlist surfaced in GitOps and persisted config;
client IDs normalized (trim/lowercase) and de-duplicated.

* **Documentation**
* Note: from July 1, 2026 new on‑prem Windows MDM apps receive Entra v2
tokens with aud = client ID; v1 tokens remain supported.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-01 17:58:51 -05:00
Sharon Katz 7fb464abc4 Clean up policy query to use parameter binding for platform filter (#46604)
## Summary
- Refactored the conditional access policy query to use `CONCAT('%', ?,
'%')` with a bound parameter instead of string concatenation for the
platform `LIKE` clause, consistent with how other queries in this file
handle string filters.

## Test plan
- [ ] Verify conditional access policy lookup still returns correct
results for macOS/Windows hosts.
- [ ] Confirm no regression in policy filtering behavior.

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

## Summary by CodeRabbit

* **Chores**
* Improved platform filtering in conditional access policy queries to
enhance query reliability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-01 18:15:02 -04:00
Konstantin Sykulev 19f14c1c8c Corrected configuration profiles endpoint handler (#46580)
**Related issue:** Resolves #46283

# 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



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

* **Bug Fixes**
* Fixed an error in the "Get host's OS settings" API so it no longer
fails when only Android MDM is enabled.
* Configuration profiles endpoint now correctly responds when Android or
Windows MDM is the active platform, in addition to Apple MDM.

* **Tests**
* Added tests covering configuration profiles behavior across Apple,
Windows, and Android MDM configurations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-01 15:23:20 -05:00
Steven Palmesano b993da7967 Use new MDM status on hosts page and show tooltip; show "Not supported" for Linux (#46377)
**Related issue:** Resolves #46066

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.


## 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**
* Corrected MDM status label in the hosts table so enrollment states
display accurately.
* Fixed platform handling so "Not supported" appears appropriately for
Chrome and Linux hosts.

* **New Features**
* Added a hover tooltip on the MDM status in the hosts table to show
additional context.

* **Style**
* Improved tooltip text wrapping to keep status names on a single line.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-01 13:16:56 -05:00
Konstantin Sykulev f619655a61 Certificate template duplicate name error (#46414)
**Related issue:** Resolves #44821

# 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**
* Fixed inline validation to show duplicate certificate name errors even
when the conflicting certificate is on a different page.
* Improved server-side error handling during certificate creation to
better detect name conflicts and present clearer, focused feedback on
the Name field.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46414?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-01 10:01:47 -05:00
Lucas Manuel Rodriguez 9032883b47 Fix fleetctl get fleets to use source of truth (DB) for software (#46480)
Resolves #44970 (1/2).

---

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
- [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**
* `fleetctl get fleets` / `get teams` now display software and setup
experience from authoritative software endpoints.
* Preserve literal setup_experience fields (avoid erroneous macos_setup
renames) when applying and when transmitting JSON for software entries.
* **Tests**
* Added regression tests and test helpers to ensure
software/setup_experience are sourced correctly and to prevent nil
panics in related tests.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-06-01 11:41:34 -03:00
Juan Fernandez 66667c3248 Fix S3 carve cleanup never running and panic on empty carves (#43045) (#46462)
Resolves #43045 

Fixed a bug where the carve cleanup cron job called the MySQL
implementation instead of the S3-aware implementation on S3-configured
deployments, meaning expired carves were never marked as expired in S3.
Also fixed a panic in S3 carve cleanup that occurred when there were no
non-expired carves.
2026-06-01 10:11:49 -04:00
Victor LyuboslavskyandLucas Manuel Rodriguez 8a28b83b00 Redis host cache optimizations (#46458)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #46338 

Changes load tested (osquery load test).
<img width="1532" height="282" alt="image"
src="https://github.com/user-attachments/assets/9eb38629-918e-4e05-bc0b-e2ae22e8b148"
/>
<img width="1414" height="937" alt="image"
src="https://github.com/user-attachments/assets/1b90afd3-087c-452e-939f-b495df3e59c8"
/>


# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/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

* **Performance Improvements**
* Extended host cache retention period from 60 seconds to 180 seconds to
improve overall cache efficiency and hit rates.
* Optimized host cache invalidation strategy to eliminate unnecessary
reverse-index lookups, significantly reducing database reader load and
Redis CPU consumption.

* **Tests**
* Added test coverage for host update cache invalidation edge cases to
ensure proper behavior.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46458?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

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

---------

Co-authored-by: Lucas Manuel Rodriguez <lucas@fleetdm.com>
2026-06-01 08:12:50 -05:00
Luke Heath 774e1e7352 Cherry-pick #45742: Adding changes for Fleet v4.86.0 (#46506) 2026-06-01 08:09:33 -05:00
Konstantin Sykulev 9e10c3cc22 Surface real error message on android enterprise connect (#46466)
**Related issue:** Resolves #45107

# 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

* **New Features**
* Android Enterprise connection error messages now surface actual
failure reasons to users instead of generic fallback text, enabling more
accurate troubleshooting.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46466?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-29 14:44:42 -05:00
Steven Palmesano 121a6df417 Enable "Show example payload" buttons in GitOps mode (#46355)
We allow this already with "Preview payload" under Settings >
Integrations > MDM > End user migration workflow.

**Related issue:** Resolves #44719

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.


## Testing

- [x] QA'd all new/changed functionality manually
2026-05-29 05:27:46 -05:00
Magnus JensenandClaude b42a154cf6 Optimize Apple profile reconciler approach by moving logic to code (#45573)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Closes #46153 

This PR is big, but I found it worth it to include in the same PR to
keep the mental change context in one place.

This PR moves away from our previous version of a big SQL computing the
desired state and label membership with big union branches. It does so
by switching the model up completely, first:
- We batch read hosts (current hardcoded is 5k), and we always iterate
5k hosts and then decide if they have changes, so that means a tick
(30s) could read 5k hosts that DOES NOT require changes, but that is
computed in code after, rather than relying on a big SQL to do it
(twice).
- We then for those hosts, bulk fetch label memberships, their related
team profiles and current rows. This performs much better as we can
lookup everything we need by primary key or super fast indexed columns,
simple fetch all these calls.
- Then once gathered the information we move to the code to determine if
the operation is install, remove, NO-OP (Desired state calculation),
then we check the label membership to further determine it's final
action.
- We then move to what we did before, which is queue the correct command
etc.

It comes with some slight caveats, which is we now load a lot more data
into memory (but before we could spike worse), so when loadtesting we
watched CPU/Memory utilization, which never seemed to spike as the
datasets are kept as small as possible.

_Cleanup will come in a follow-up PR where we remove all the old code._

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

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

* **Performance**
* Optimized Apple profile and DDM (Declarations) reconciliation engine
with batched processing for significantly improved performance in
environments with large numbers of Apple-enrolled hosts.
* Implemented cursor-based pagination for more efficient reconciliation
across large fleets.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45573?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-05-29 09:46:17 +02:00
Magnus Jensen 0431f52b9e support standard and none end user account types (#46179)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #45286 

# 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


Create local admin account = true
Primary account type = none
End user auth required = true
= No primary account setup screen shown - jumps straight to
username/password login which I can login to with the password shown in
the UI.
Running `dscacheutil -q user | grep -A 3 -B 2 -e uid:\ 5'[0-9][0-9]’`
only returns `_fleetadmin`

**Note: EACAS is not available on this mac (or this user?)** - however
it’s still possible to Wipe via MDM commands.

Create local admin account = true
Primary account type = standard
End user auth required = true
= Primary account setup screen shown (also works with IDP info being
locked and populated).
Running `dscacheutil -q user | grep -A 3 -B 2 -e uid:\ 5'[0-9][0-9]’`
returns `_fleetadmin` and my end user (IDP info locked in this case)
Opening Settings -> Users & Groups -> Shows my primary account as
“Standard”

**Note: Benefit of the user can’t do EACAS** (Prompted: “Admin user
required”)
__fleetadmin also can’t do EACAS_

Create local admin account = false
Primary Account type = N/A (but admin)
End user auth required = true
= Shown primary account setup screen with IDP info populated and locked
Running `dscacheutil -q user | grep -A 3 -B 2 -e uid:\ 5'[0-9][0-9]’`
only returns my primary user
Opening Settings -> Users & groups -> shows my primary account as
“Admin"


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

* **New Features**
* macOS setup now supports end-user account types: `admin`, `standard`,
or `none`.
* Setup flows and device commands respect the selected primary account
type (e.g., create regular user or skip creation).

* **Validation**
* Configuration now enforces that a local admin account exists/enabled
when required by the chosen end-user account type.

* **Tests**
* Added coverage for `standard` and `none` validation and command
behavior.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46179?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-29 09:33:02 +02:00
Konstantin Sykulev 87bb4090a8 Android profile content checksums (#46276)
**Related issue:** Resolves #43456

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

## 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.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [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

* **New Features**
* Android MDM profiles now include content checksums; devices are
re-synced only when profile content changes, reducing unnecessary
deliveries.

* **Migrations**
* Database schema updated to add and backfill checksum fields for
Android configuration and host profiles.

* **Tests**
* Added and updated tests to validate checksum generation, backfill, and
behavior in profile delivery scenarios.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46276?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-28 16:50:33 -05:00
Sharon Katz 1ab42218a8 Fix GET /software/versions 422 too many placeholders without per_page (#45737)
Closes #43030

## Summary

- Batches title IDs in `getDisplayNamesByTeamAndTitleIds` (chunks of
32,000) to avoid exceeding MySQL's 65,535 prepared statement placeholder
limit
- Uses the existing `BatchProcessSimple` utility, matching the pattern
already used in `software_titles.go`

## Root cause

When `GET /api/v1/fleet/software/versions` is called without a
`per_page` parameter, `DefaultPerPage` (1,000,000) is used.
`ListSoftware` collects all `titleIDs` from the paginated results and
passes them to `getDisplayNamesByTeamAndTitleIds`, which builds an `IN
(?)` clause that exceeds MySQL's 65,535 placeholder limit.

## Manual testing

1. Started a local Fleet server with MySQL via `docker compose up` and
`fleet serve --dev`
2. Seeded the database with 70,000 software titles, software entries,
and software_host_counts records
3. **Before the fix**: `GET /api/latest/fleet/software/versions` (no
`per_page`) returned HTTP 422 with `"Prepared statement contains too
many placeholders"`
4. **After the fix**: the same request returns HTTP 200 with all 70,000
results
5. `GET /api/latest/fleet/software/versions?per_page=20` continued to
work correctly in both cases

## Test plan

- [x] Manual reproduction and verification (see above)
- [x] `make lint-go-incremental` passes
- [x] `go build ./server/datastore/mysql/...` compiles cleanly
- [ ] CI passes

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

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed `GET /api/v1/fleet/software/versions` endpoint to prevent errors
when returning results from large software inventories.

* **Tests**
  * Added test coverage for high-volume display name queries.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45737?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-28 17:11:04 -04:00
Jordan Montgomery c70f6796a0 Add cert rollover tool, update Filevault key decryption for rollover process (#46226)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #46226

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

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

* **New Features**
* Add CA certificate rollover CLI to renew MDM CA certs with an
extend-years option while preserving the private key and certificate
properties.
* **Improvements**
* Decryption logic updated to accept previously-rolled CA certificates
so escrowed disk-encryption keys can be decrypted after rollover.
* **Tests**
  * Expanded tests and mocks to cover rollover and decryption scenarios.
* **Chores**
* Updated ignore rules and added a changelog entry for the rollover
process.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46226?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-28 16:31:18 -04:00
Dante Catalfamo 2c47cee122 Fix FileVault key escrow on ADE-enrolled Macs (#45928)
After ADE enrollment with enable_disk_encryption: true, hosts reported
as unencrypted with the disk-encryption policy failing and no recovery
key escrowed until the user logged out/in or restarted.

## Root cause
Fleet's shared macOS disk-encryption probe was:

```
SELECT 1 FROM disk_encryption
WHERE user_uuid IS NOT "" AND filevault_status = 'on' LIMIT 1
```

On the osquery disk_encryption table, filevault_status and user_uuid
are populated from independent sources: filevault_status from
`fdesetup status`, user_uuid from `diskutil apfs listCryptoUsers`
(the UUID of a user with SecureToken authority to unlock the volume).

In the post-ADE window, even with ForceEnableInSetupAssistant=true,
SecureToken propagation can lag — filevault_status='on' but
user_uuid='' for a brief period that resolves on a session event.
When the predicate failed, the query returned 0 rows and three
downstream behaviors broke in lockstep:

  - host_disks.encrypted flipped to false ("unencrypted")
  - the built-in "Full disk encryption enabled (macOS)" policy failed
  - mdm_disk_encryption_key_file_*_darwin returned encrypted=0,
    gating the PRK ingest and leaving the recovery key un-escrowed

The predicate originated in groob's standard query library entry
from 2021 as a strict compliance check ("is the host actually
protected, with a user able to unlock it?"). When the disk-encryption
status feature shipped in Nov 2022 (PR #8526, issue #3906), the
same string was reused verbatim and later extracted into
usesMacOSDiskEncryptionQuery — never revisited for whether the
SecureToken gate made sense outside the compliance-policy context.

**Related issue:** Resolves #45369
2026-05-28 16:18:12 -04:00
Sharon Katz d498c1e312 Hide "Rotate password" button for Observer role in Recovery Lock modal (#45649)
Closes #42249
Supersedes #42247 (stale draft with merge conflicts)

## Summary

- Hides the "Rotate password" button entirely in the Recovery Lock
password modal when the user has the Observer role (`canRotatePassword`
is false), instead of showing a disabled span with a tooltip
- Removes unused `TooltipWrapper` import and orphaned SCSS styles for
the disabled state
- Consistent with the existing pattern in `ManagedAccountModal` which
already hides the button for observers

## Changes

- `RecoveryLockPasswordModal.tsx`: Return `null` when
`!canRotatePassword` instead of rendering disabled tooltip
- `_styles.scss`: Remove `__rotate-button--disabled` styles
- Added `RecoveryLockPasswordModal.tests.tsx` with two tests covering
button visibility based on role

## How I tested

- Added unit tests (following the `ManagedAccountModal.tests.tsx`
pattern) that verify:
- The "Rotate password" button is **not rendered** when
`canRotatePassword={false}` (Observer role)
- The "Rotate password" button **is rendered** when
`canRotatePassword={true}` (Admin/Maintainer role)
- Both tests pass locally
- ESLint passed clean on all changed files
- Webpack build succeeded; verified the built bundle no longer contains
the old tooltip text or disabled-button CSS class

## Test plan

- [ ] Log in as an Observer, navigate to a macOS host with Recovery
Lock, open the Recovery Lock password modal, and confirm the "Rotate
password" button is not visible
- [ ] Log in as an Admin/Maintainer and confirm the "Rotate password"
button still appears and works

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

* **Bug Fixes**
* The "Rotate password" control in the Recovery Lock Password modal is
now hidden when password rotation is unavailable (e.g., for Observer
role) instead of being shown as a disabled control.

* **Tests**
* Added tests verifying the rotate-button visibility behavior based on
rotation availability/permissions.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45649?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-28 15:45:16 -04:00
Lucas Manuel Rodriguez a1d91464ea Fix issue with permissions in host activity list for fleet-users (#46362)
**Related issue:** Resolves #46009.

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/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**
* Resolved an authorization issue preventing users from viewing past
host activities on hosts that contained user-initiated operations such
as lock, wipe, run script, or install software.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46362?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-28 14:57:27 -03:00
RachelElysia 7c3355295a Fleet UI: "Fleet spotlight" (Command palette menu) (#43756) 2026-05-28 09:25:54 -04:00
Dante Catalfamo dc56776a30 Don't process empty vuln data and remove existing records (#46075)
**Related issue:** Resolves #45602
2026-05-27 17:08:47 -04:00
Jonathan Katz f79508580b Make software installer edits not cancel setup experience installs (#46236)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42744

# 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
- [ ] 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
    - Tested setup experience on a macOS virtual machine, see below.

This is what happens after the change:
- Editing pkg while setup experience is running, whether the package is
pending or currently running, doesn't cancel anything. Installs were
successful.
- Editing pkg while queueing a normal install caused it to cancel with
no record.
- Deleting while an installer is running causes the row to disappear
immediately in the setup experience UI, HSI row removed.

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

* **Bug Fixes**
* Editing a software installer no longer cancels in-progress
setup-experience installs; running setup-experience flows are preserved
when installer scripts are updated.
* Deleting an installer still removes its associated pending
setup-experience entries and related pending host-install records.
* GitOps batch updates: editing installers in a batch preserves running
setup experiences; omitting an installer from a batch deletes only that
installer’s pending entries.

* **Tests**
* Added/updated integration tests validating edit/delete behavior during
setup experience.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46236?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-27 13:52:58 -04:00
Sharon Katz 6a481477e8 POST /api/latest/fleet/targets returns more info than needed (#46082)
## Summary

Fixes a security issue where `POST /api/latest/fleet/targets` returned
sensitive fleet configuration to users with insufficient privileges.
Other team-facing endpoints apply proper access controls; the target
search path did not.

- Replaces the `teamSearchResult` struct with a slim version containing
only the non-sensitive fields documented in the API response (`id`,
`created_at`, `name`, `description`, `user_count`, `host_count`,
`display_text`, `count`).
- Removes the `MarshalJSON`/`UnmarshalJSON` methods (~70 lines) that
serialized fields the target picker never uses.
- Verified that no frontend component, fleetctl client, or integration
test reads sensitive fields from the target search response.
- Validated the response shape matches the documented API contract in
`docs/REST API/rest-api.md`.

Closes fleetdm/confidential#16054
Related advisory: GHSA-88p2-jj8w-j8qg

## How we reproduced

1. Started local dev server (`fleet serve --dev --dev_license`)
2. Created a global observer user and a saved query with
`observer_can_run = true`
3. Logged in as the observer

**Before fix** -- same observer session, same team:

```
GET /api/latest/fleet/fleets/2/secrets
  -> secret: "********"  (correctly masked)

POST /api/latest/fleet/targets  {"query":"","query_id":7,"selected":{"hosts":[],"labels":[],"teams":[]}}
  -> sensitive configuration leaked for all teams
```

**After fix** -- rebuilt binary, restarted server, same observer:

```
GET /api/latest/fleet/fleets/2/secrets
  -> secret: "********"  (unchanged)

POST /api/latest/fleet/targets  (same request)
  -> only non-sensitive fields returned (id, name, display_text, count, etc.)
```

Also verified admin target search still returns team metadata correctly.

## Test plan

- [x] Manual reproduction on local dev server
- [x] Manual verification after fix
- [x] Admin target search still returns team metadata (id, name,
host_count, display_text)
- [x] Verified no consumers (frontend, fleetctl, tests) read sensitive
fields from target search
- [x] Validated response matches documented API contract in `docs/REST
API/rest-api.md`
- [x] Unit test verifies response contains only documented non-sensitive
fields
- [x] `go test ./server/service/ -run TestSearchTargets` passes
- [ ] CI passes
2026-05-27 11:33:05 -04:00
Robert FairburnandMagnus Jensen 0c41e29336 Cleanup script for failed starts after renumbered migrations (#46177)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #

# 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


## Database migrations

- [X] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.

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

* **New Features**
* Added a migration cleanup tool to recover from failed starts after
migration renumbering.
* Supports dry-run mode to preview the SQL changes and apply mode to
execute fixes.
* Includes secure database connection options and safe, transactional
execution with reporting for detected issues.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46177?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: Magnus Jensen <magnus@fleetdm.com>
2026-05-27 11:04:45 +02:00
Victor Lyuboslavsky 33889ec177 Fixed stale pending MDM profiles reappearing (#46111) 2026-05-26 19:34:44 -05:00
Lucas Manuel Rodriguez 5b2427d187 Add backend changes for continuous automations on policies (#45999)
Resolves #45149 and #45150.

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.

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

## 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.
- [X] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
- [X] 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)
- [x] 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)

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

* **New Features**
* Added team policy setting continuous_automations_enabled (default:
false) to re-run software/script automations on every failing
evaluation; exposed in APIs and GitOps YAML. Disallowed for "All fleets"
and requires a premium license.

* **Tests**
* Added integration tests for CRUD, GitOps, and re-queuing behavior
validating continuous automations.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45999?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 21:11:18 -03:00
Konstantin Sykulev 6ae04f95b8 Better android host names (#46135)
**Related issue:** Resolves #41053

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

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

* **New Features**
* Android hosts associated with an IdP now display as "{IdP first
name}'s {device model}" when IdP fullname is available.
* Enrollment now links hosts to an MDM IdP account when enrollment
payload includes IdP info.

* **Bug Fixes / Behavior**
* Unenrollment records and host naming use device brand+model for
hardware identification and sensible fallbacks when IdP data is missing.
* Re-enrollment updates IdP association without creating duplicate
hosts.

* **Tests**
* Added tests covering display-name and hardware-model behavior with and
without IdP data.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46135?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 15:19:14 -05:00
Lucas Manuel Rodriguez 590bf185c2 Fix missing tags for OPA policy (#46203)
Resolves #46009.

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/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**
* Fixed permissions for host activity items by aligning serialized field
names used by authorization rules, ensuring fleet-scoped users receive
correct access rights when listing and reading host activities.

* **Tests**
* Added authorization tests validating host activity access control
across user roles and team scopes, including denial cases for
unauthorized and GitOps-scoped users, and verifying policy evaluation
depends on correct serialized field naming.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46203?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 15:15:38 -03:00
Victor Lyuboslavsky e790260b85 Android commands backend (#46031)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #41683 

Support for Android lock, wipe, and clear passcode commands. Behavior is
slightly different between BYOD and CODO. The fleetdm.com proxy isn't
wired up, so they only work with direct Google connection.

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

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

* **New Features**
* Clear-passcode CLI plus Android Lock and Wipe commands (Wipe
restricted to company-owned devices).
* BYO unenroll now removes only the work profile, preserving personal
data.
* Commands issued with a 10-year duration; UI/CLI show Android-specific
messaging and command IDs.

* **Improvements**
* Host MDM pages reflect command lifecycle transitions (pending →
acknowledged or error with code/message) via Pub/Sub updates.

* **Documentation**
* Updated docs for Android MDM commands, ownership rules, and command
duration.

* **Tests**
  * New unit and integration tests for Android MDM flows.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46031?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 12:16:03 -05:00
Jonathan Katz 484adf3494 Fix GitOps policy install software parse function setting the wrong FMA slug field. (#46167)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #46164

The policy does parse correctly into a GitOpsPolicySpec struct, but
because there were two fields called `fleet_maintained_app_slug` it
wasn't obvious that this would happen.

# 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
- [ ] 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 patch policies with different software
application slugs were incorrectly using the slug from the install
automation setting instead of the patch policy's own configured slug,
causing incorrect policy queries and validation.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46167?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-26 10:13:10 -04:00
Jonathan Katz 5d59b0e627 Skip VPP label validation in dry runs (#46106)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #45844
Skips label validation against the database in dry runs, because if new
ones are being applied in the same run then they wouldnt be in the db
ahead of time.

# 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
- [ ] 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
- Added a new label and vpp reference to it, both dry run and real run
worked.

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

## Summary by CodeRabbit

## Release Notes

**Bug Fixes**
* GitOps dry runs no longer fail when a VPP app references a label that
is introduced within the same run.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46106?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-25 12:04:06 -04:00
Victor Lyuboslavsky 4146978777 Windows MDM validation fixes (#46029)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42219 
Resolves #42224

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

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

* **Bug Fixes**
* Enhanced Windows MDM profile validation: uploads that are non-XML,
empty, or lack required SyncML top-level elements are rejected; LocURI
values that are empty, start with `/`, contain `..` path traversal, or
are otherwise malformed are now rejected (whitespace-trimmed),
preventing later device deployment failures.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46029?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-24 08:02:01 -05:00
Victor Lyuboslavsky fc10afe147 Fixed the "host is offline" banner on the My device page incorrectly appearing (#46091) 2026-05-22 18:37:57 -05:00
Jonathan Katz 5d9b102a1b 45190 patch policy wrong installer (#46087)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #
Adds a missing `is_active=1` check to get the actual active installer
for the software automation's installer.

# 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
- [ ] 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
- I tested by pinning the version of the app to the older one, then
unpinning and back and checked that the policy is associated to the
correct installer with the query below.
- I did not manually test updating to a new FMA version. It's possible
to do that easily by creating a new branch with a newer version and
referring FLEET_DEV_MAINTAINED_APPS_BASE_URL to it.
 
 ```
 SELECT 
  si.id, 
  si.team_id, 
  si.title_id, 
  si.filename, 
  si.version, 
  si.storage_id, 
  si.uploaded_at, 
  si.updated_at, 
  si.url, 
  si.fleet_maintained_app_id, 
  si.install_during_setup, 
  si.is_active, 
  si.patch_query, 
  si.http_etag,
  p.patch_software_title_id,
  p.software_installer_id,
  p.query
FROM software_installers  si
LEFT JOIN policies p on si.id = p.software_installer_id
WHERE filename LIKE "%<app name>%" AND platform = "darwin" AND
global_or_team_id = <team id>;
 ```

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

## Summary by CodeRabbit

* **Bug Fixes**
* Patch policies using software install automations now correctly
prioritize active installers, ensuring deployment uses the latest
appropriate version rather than inactive or outdated alternatives.

* **Tests**
* Added test scenarios to validate policy installer version selection
and active status during automation evaluation.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46087?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-22 15:11:23 -04:00
Victor Lyuboslavsky 3f6f138530 Fix duplicate Android host on orbit-enroll when Apple MDM is off (#46008)
The Fleet Android Agent's orbit-enroll did not match the existing
AMAPI-created host record on Fleet instances with Apple MDM disabled,
creating a duplicate hosts row alongside the AMAPI-enrolled one. The
Android-specific UUID match clause in matchHostDuringEnrollment was
gated by isMDMEnabled, which only reflects Apple MDM status. Gate the
clause on platform="android" instead. The Fleet Android Agent always
sends this since PR #43809, and the SELECT itself filters
platform=android, so the clause is Android-safe by construction and no
longer depends on the Apple-MDM flag. The serial-match clause keeps its
existing isMDMEnabled gate.

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

# 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] Updated 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

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

* **Bug Fixes**
* Prevents duplicate host records when enrolling Android devices on
instances with Apple MDM disabled.
* Improves enrollment host-matching so devices are identified by their
platform, reducing misattributed or duplicate hosts during enrollment.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/46008?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-21 16:44:44 -05:00
Lucas Manuel RodriguezandCopilot Autofix powered by AI 377c5ad127 Fix iOS and iPadOS logos in dark theme (#45838)
Resolves: https://github.com/fleetdm/fleet/issues/45839.

Dogfood:
<img width="778" height="314" alt="Screenshot 2026-05-19 at 5 44 52 PM"
src="https://github.com/user-attachments/assets/4a6433bf-612d-42bb-b3ea-961c19f54e90"
/>

With changes in this PR:
<img width="1811" height="373" alt="Screenshot 2026-05-20 at 9 22 58 AM"
src="https://github.com/user-attachments/assets/ebf0f432-6592-40a2-bacb-72f6e63f7827"
/>
<img width="1811" height="373" alt="Screenshot 2026-05-20 at 9 22 44 AM"
src="https://github.com/user-attachments/assets/f8bac481-4263-4d95-932d-f8599ed87055"
/>

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.

## 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**
* Fixed iOS and iPadOS icons so they render correctly in dark theme
across the operating-system list.
* Improved icon visibility and contrast in dark mode to ensure
consistent appearance with other platform icons.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45838?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
2026-05-21 17:30:37 -03:00
Lucas Manuel Rodriguezandcoderabbitai[bot] aeac57bd04 Fix to populate host_emails during Linux/Windows SSO enrollment (#45951)
Resolves #45066.

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/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**
* Fixed user email/device mapping for Windows and Linux hosts enrolling
via end-user authentication (browser-based and EUA-token flows). Host
listings and device mapping now reliably show the IdP email after
enrollment, improving device identification and inventory accuracy.

* **Tests**
* Expanded integration tests to validate end-to-end enrollment and
device mapping across platforms.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45951?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-05-21 16:38:44 -03:00
Lucas Manuel Rodriguezandcoderabbitai[bot] 4e3f8c0b69 Allow technicians to transfer hosts (#45956)
Resolves #41783.

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

* **New Features**
* Technicians can transfer hosts between fleets (Fleet Premium). Global
technicians can transfer via the Fleet UI and REST API; fleet-scoped
technicians can transfer between fleets they manage via the REST API.
* Bulk transfer selection added on the hosts list for eligible global
technicians, enabling multi-host transfers while preserving other bulk
behaviors.

* **Tests**
* Added and updated tests covering Transfer visibility and authorization
for global and fleet-scoped technician roles.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45956?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

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

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-05-21 15:46:09 -03:00
Sharon Katz 8bb59b71cb Fix List certificate templates API docs: parameter name is fleet_id, not fleet (#45969) (#45978)
Closes #45969

## Summary

The `List certificate templates` API endpoint returned `null` for
certificates because the **API docs documented the wrong query parameter
name**. The docs said `fleet` but the code accepts `fleet_id` (or the
deprecated `team_id`). Customers following the docs used `?fleet=11`,
which was silently ignored, causing the endpoint to default to team 0
(unassigned) -- which typically has no certificates.

- **Docs fix**: Changed the parameter name from `fleet` (string) to
`fleet_id` (integer) in the REST API docs, matching how all other list
endpoints document this parameter.
- **API quality fix**: Initialize the `templates` slice in
`GetCertificateTemplatesByTeamID` so that when no templates exist, the
JSON response returns `"certificates": []` instead of `"certificates":
null`.

## Root cause

In `docs/REST API/rest-api.md`, the "List certificate templates"
endpoint documented the query parameter as `fleet` (string), but the
request struct accepts `fleet_id` or `team_id`:

```go
type listCertificateTemplatesRequest struct {
    TeamID uint `query:"team_id,optional" renameto:"fleet_id"`
}
```

When the customer used `?fleet=11` (as documented), the parameter was
unrecognized and silently ignored. The endpoint defaulted to `team_id=0`
(unassigned), which had no certificates. The nil Go slice then
serialized to JSON `null`.

Credit to Andrey Kizimenko for identifying the docs mismatch.

## Changes

- `docs/REST API/rest-api.md` -- Fix parameter name from `fleet`
(string) to `fleet_id` (integer)
- `server/datastore/mysql/certificate_templates.go:174` -- Initialize
slice to avoid `null` in JSON
- `server/datastore/mysql/certificate_templates_test.go:489` -- Add
`require.NotNil` regression test

## Testing

All tests run locally against a real MySQL (Docker) and Redis instance:

| Test suite | Command | Result |
|---|---|---|
| Datastore integration (all certificate tests) | `MYSQL_TEST=1 go test
-run TestCertificates ./server/datastore/mysql/...` | 11 suites, 33
subtests, all PASS |
| Service unit tests | `go test -run
"TestCreateCertificateTemplate\|TestApplyCertificateTemplateSpecs\|..."`
| 4 suites, all PASS |
| Enterprise integration (full HTTP) | `MYSQL_TEST=1 REDIS_TEST=1 go
test -run "TestIntegrationsEnterprise/TestCertificatesSpecs"` | PASS |
| Enterprise integration (team delete) | `MYSQL_TEST=1 REDIS_TEST=1 go
test -run
"TestIntegrationsEnterprise/TestDeleteTeamCertificateTemplates"` | PASS
|
| Static analysis | `go build`, `go vet` | Clean |

Andrey's reproduction confirmed via screenshots:
- `?fleet_id=11` returns certificates correctly
- `?fleet=11` (the documented param) returns `null` -- the bug
- No param returns results when "unassigned" team has certificates

## QA steps

1. Follow the API docs to list certificate templates using
`?fleet_id=<id>`
2. Verify the response contains `"certificates": [...]` with the correct
data
3. Call without `fleet_id` and verify `"certificates": []` (not `null`)
for a team with no templates

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

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed the "List certificate templates" API documentation with the
correct query parameter name, enabling proper filtering of results.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45978?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-21 11:09:19 -04:00
Victor Lyuboslavsky 24da012f18 Fixed Android Enterprise page not refreshing (#45914)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #45862 

Speculative fixes since I wasn't able to repro issue locally.
Refresh AppContext and the React Query ["config"] cache directly after
the SSE/DELETE response so AndroidMdmCard and AndroidMdmPage flip
without a manual page reload, with a bounded retry to defeat the 1s
cached_mysql.AppConfig TTL. Also harden startSSE to detect the success
signal across chunk boundaries and reject (rather than hang) when the
stream ends without it.

# 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] Timeouts are implemented and retries are limited to avoid infinite
loops

## Testing

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

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

* **Bug Fixes**
* Fixed Android Enterprise page not refreshing after connecting or
disconnecting Android MDM. The Enterprise ID and card state now update
automatically without requiring a manual page reload.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45914?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-20 17:13:42 -05:00
Juan Fernandez 29f41af47d Fix NDES dynamic SCEP regression caused by ntlmssp anonymous probe (#45784)
Fixes #45763 

The recent bump of github.com/Azure/go-ntlmssp to v0.1.1 changed the
Negotiator to send an unauthenticated probe before NTLM. NTLM is
connection-bound on IIS, and the extra round-trip breaks the handshake
on NDES setups behind reverse proxies, Okta Access, or a WAF.
2026-05-20 11:16:15 -04:00
Lucas Manuel Rodriguez b4e907801f Add Android to the OS list (#45834)
Resolves #45711

- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.

## Testing

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

<img width="1216" height="527" alt="Screenshot 2026-05-19 at 5 30 48 PM"
src="https://github.com/user-attachments/assets/05a0a93f-3b5b-4ba9-80c5-b0a91b9de1f3"
/>
<img width="1216" height="527" alt="Screenshot 2026-05-19 at 5 30 37 PM"
src="https://github.com/user-attachments/assets/3e23e88e-6a95-46f6-a68f-12fb98f1aefe"
/>
<img width="1216" height="527" alt="Screenshot 2026-05-19 at 5 29 45 PM"
src="https://github.com/user-attachments/assets/417ca981-0781-4df5-811b-dafaabbd61a9"
/>
<img width="1216" height="527" alt="Screenshot 2026-05-19 at 5 29 30 PM"
src="https://github.com/user-attachments/assets/cf13985d-5cb3-414a-9135-5cf4c5ee0dd1"
/>
<img width="1216" height="527" alt="Screenshot 2026-05-19 at 5 31 33 PM"
src="https://github.com/user-attachments/assets/8500e7b2-cc7b-425d-b6b7-bbbf128faac4"
/>


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

* **Bug Fixes**
* Fixed host listing so filtering by Android OS name and version returns
matching hosts.

* **New Features**
* Android hosts are now included in the operating systems aggregation
and UI, with a dedicated Android icon.
* Android OS version information is captured during device enrollment
and on status reports.

<!-- review_stack_entry_start -->

[![Review Change
Stack](https://storage.googleapis.com/coderabbit_public_assets/review-stack-in-coderabbit-ui.svg)](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45834?utm_source=github_walkthrough&utm_medium=github&utm_campaign=change_stack)

<!-- review_stack_entry_end -->
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-05-20 10:43:10 -03:00