5285 Commits
Author SHA1 Message Date
Rahul RaghunathanandRachelElysia f292c7def4 Add sortable 'Added to Fleet' column to hosts table (#50098)
**Related issue:** Resolves #50083

# Screenshot demonstrating the fix

- Hosts page:
<img width="1473" height="335" alt="image"
src="https://github.com/user-attachments/assets/2f88ad6e-a514-4304-ac80-f56678e6be47"
/>

- Edit columns modal:
<img width="798" height="707" alt="image"
src="https://github.com/user-attachments/assets/0a79e8f3-1b21-4f84-bd04-726f44b9a0fa"
/>

## Note on sort direction

The new "Added to Fleet" column renders as a "days ago" duration (same
formatter as Last seen / Last fetched / Last restarted). To keep
behavior consistent across all four time-ago columns on the hosts table,
this PR applies the sort-direction inversion originally introduced for
`last_restarted_at` in #14878 (fix for #13160) to all of them:

- `seen_time` (Last seen)
- `detail_updated_at` (Last fetched)
- `last_restarted_at` (Last restarted) — unchanged behavior
- `last_enrolled_at` (Added to Fleet) — new

Arrow-down on any of these columns now sorts by the visible duration
(biggest "days ago" first / oldest date first), rather than by the raw
underlying timestamp. This is a user-facing behavior change on Last seen
and Last fetched — please re-QA sort order on those two columns
alongside the new one.

# 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

<!-- Attach: Edit columns modal showing the new "Added to Fleet" column
option, and the Hosts page with the column enabled -->

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

* **New Features**
  * Added an **Added to Fleet** column to the hosts table.
* Displays when each host last enrolled with Fleet, with an explanatory
tooltip.
* The column is hidden by default and can be enabled through table
settings.
  * Supports ascending and descending sorting.

* **Bug Fixes**
* Corrected descending sorting for **Last seen** and **Last fetched** to
reflect the displayed host age.

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

---------

Co-authored-by: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
2026-08-07 13:38:41 -04:00
George Karr d96ceb2c51 Add patch when closed policies (#50726)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #39962

# 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
- [ ] 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.
  - N/A
- [x] 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:

- [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**
* Added “Patch when closed” deployment policies to update software only
when the application is not running.
* Added deployment controls for force install, patching, and manual,
forced, or closed-app patch options.
* Fleet-maintained apps now automatically detect whether the application
is open.
* GitOps configurations support patch-when-closed settings with
validation.

* **UI Improvements**
* Added clear activity and installation messages when updates are
skipped because an app is open.
  * Replaced the Patch action with a unified Deploy workflow.

* **Bug Fixes**
* Prevented skipped updates from being incorrectly retried as failed
installations.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-07 12:37:20 -05:00
RachelElysia ddbc65a4f6 Self-service: "Install all" respects the search query (#50751)
## Issue

Resolves #50528.

## Description

On the My device > Self-service page, with a category selected and a
search query typed, the "Install all" button previously ignored the
search: it counted (and queued) every uninstalled item in the category,
including software the search had filtered out.

This PR scopes the button — count *and* install target — to the visible
subset:

- **Backend:** `POST /device/{token}/software/install_all` now accepts a
`query` param. It's threaded through
`SelfServiceInstallAllSoftwareTitles` → `GetSoftwareTitlesForInstallAll`
→ `opts.ListOptions.MatchQuery` on `ListHostSoftware`, reusing the same
LIKE-on-`software_titles.name` semantics as the self-service list
endpoint.
- **Frontend:** new `filterSoftwareByQuery` helper layers on top of the
category filter to drive `uninstalledCount` / `hasInProgress` and the
value sent to install_all. Empty queries are stripped so the API isn't
called with `?query=`.

`display_name` matching is deliberately out of scope — the search filter
across BE list, desktop table, and mobile filter is all raw-`name`-only
today, so broadening install_all alone would re-introduce a similar
mismatch. Filed as a follow-up: #50750.

## Screen recording

In recording:
- (FE fix) showing that the UI is filtering out install all count to be
only what's on the screen
- (BE fix) showing that the call to the API only queues up the install
all for the installers shown on the screen when clicked



https://github.com/user-attachments/assets/aaae3d29-dccf-484d-910f-67ca335bf0e8



## Testing

- FE unit tests: `filterSoftwareByQuery` helper, `SelfServiceCard`
count-with-query + POST-with-query, `InstallAllInCategoryButton` prop
forwarding.
- BE unit test: EE service forwards the match query to the datastore.
- BE datastore test: query, category+query, empty-match cases.
- BE integration test: new "scopes to the query parameter when provided"
subtest in `TestInstallAllSelfServiceSoftware`.

- [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**
  * “Install all” now respects the active self-service search query.
* Counts, progress indicators, and installation requests now reflect
only software matching the current search and category filters.
* Empty or whitespace-only searches continue to include all software in
the selected category.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-07 13:31:31 -04:00
Andrew MellorandJordan Montgomery eb4acf4d1e 47717 auld UI latest os version (#50571)
**Related issue:** Resolves #47717

# Checklist for submitter

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

- [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. _Front end only_

## 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**
* Added Apple OS update targeting options for no enforcement, a custom
minimum version, or the latest available version.
* Added configurable whole-day deadlines for macOS, iOS, and iPadOS
updates.
* Added platform-specific target controls, validation, and automatic
new-host updates for latest-version targeting.
* Displayed minimum versions, pending status, and update deadlines in
host details and activity feeds.
  * Clarified Windows deadlines as days after release.

* **Style**
  * Improved layout and spacing for Apple and Windows update forms.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Jordan Montgomery <elijah.jordan.montgomery@gmail.com>
2026-08-07 18:25:37 +01:00
c510e5b6e2 Add tooltip explaining no Refetch button for Android hosts on Host details page (#50666)
Follow up PR for the following quick win based on feedback here:
- https://github.com/fleetdm/fleet/issues/50001
<img width="899" height="217" alt="Screenshot 2026-08-06 at 10 32 24 AM"
src="https://github.com/user-attachments/assets/462df6ae-ec09-433d-831b-9a0e3c242081"
/>

- [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 host details now display a disabled **Refetch** button with an
explanatory tooltip.
* The tooltip explains automatic synchronization and links to manual
Android synchronization instructions in a new tab.
* The **Last fetched** information is displayed directly without an
additional tooltip.

* **Documentation**
* Updated Android host documentation to reflect the disabled Refetch
control and manual synchronization guidance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: LeAnn Gove <leann@fleetdm.com>
Co-authored-by: LeAnn <97471894+Leanngove@users.noreply.github.com>
2026-08-07 10:18:24 -07:00
Allen Houchins 051d12718c Add JetBrains ReSharper as a Windows Fleet-maintained app (#50659)
**Related issue:** Resolves #50567

Adds JetBrains ReSharper as a Windows Fleet-maintained app (winget
`JetBrains.ReSharper`, version `2026.2.0.2`).

ReSharper is a Visual Studio extension rather than a standalone app, so
it does not follow the pattern of the other JetBrains FMAs (Rider,
PhpStorm, DataGrip, etc.), which are plain NSIS installers that take
`/S`. Reviewers should read the risks below before approving — a couple
of things can only be confirmed from a validator run.

## What's here

- `ee/maintained-apps/inputs/winget/resharper.json`
- `ee/maintained-apps/inputs/winget/scripts/resharper_install.ps1` /
`resharper_uninstall.ps1`
- Generated `ee/maintained-apps/outputs/resharper/windows.json` +
`apps.json` entry
- Icon (`Resharper.tsx`, website PNG, alphabetical `index.ts` entries),
generated from JetBrains' own brand asset

## Decisions that differ from the other JetBrains FMAs

**`use_display_version_for_patch` is omitted.** Every other JetBrains
winget input sets it, but the ReSharper manifest has no
`AppsAndFeaturesEntries`, so the ingester hard-errors with
`use_display_version_for_patch is set but no DisplayVersion found in
winget manifest`. The patch policy therefore compares against winget's
`2026.2.0.2`.

**Custom `exists_query` instead of `fuzzy_match_name`.** The prefix is
loose enough to match a possible per-VS-instance suffix, and excludes
the separate ReSharper C++ and ReSharper SDK products:

```sql
SELECT 1 FROM programs WHERE name LIKE 'JetBrains ReSharper%' AND name NOT LIKE 'JetBrains ReSharper C++%' AND name NOT LIKE 'JetBrains ReSharper SDK%' AND publisher = 'JetBrains s.r.o.';
```

**Install script detects Visual Studio.** It builds `/VsVersion` from
the instances `vswhere` reports and runs the installer with
`/Silent=True /PerMachine=True /SkipEtwService=True`:

- `/PerMachine=True` — the installer otherwise targets `%LocalAppData%`,
which under Fleet's SYSTEM context would land in the SYSTEM profile
instead of the developer's. The path is not configurable
([RSRP-428991](https://youtrack.jetbrains.com/issue/RSRP-428991)).
- `/SkipEtwService=True` — JetBrains documents that `EtwHostService.msi`
always raises a UAC prompt, so a fully silent install of every component
is not possible
([SUPPORT-A-3189](https://youtrack.jetbrains.com/articles/SUPPORT-A-3189)).
- It then waits for the uninstall registry entry (what osquery reads),
because the web bootstrapper can outlive its own exit code, and logs the
resulting ARP entries.

**Uninstall removes every matching entry**, since ReSharper registers
one per Visual Studio instance, using the defensive `UninstallString`
parser and appending `/Silent=True` rather than the NSIS `/S`.

Switches come from [JetBrains' silent install/uninstall
article](https://resharper-support.jetbrains.com/hc/en-us/articles/207241485-How-to-use-silent-install-and-silent-uninstall-of-ReSharper-via-Command-Line),
not guesswork.

## `unique_identifier` is provisional

`program_publisher` is verified — `JetBrains s.r.o.` is hard-coded next
to the ARP value names (`DisplayName`, `DisplayVersion`,
`UninstallString`, `Publisher`) in `JetBrains.Platform.Installer.exe`,
extracted from the installer.

The **DisplayName is not verifiable offline.** The winget URL is a
two-stage web bootstrapper: the 69 MB `.web.exe` contains
`JetBrains.Platform.Installer.Bootstrap.exe`, which downloads the
JetBrains dotUltimate installer, which downloads the product packages.
The ARP entry is written by that downloaded stage under
`Software\Microsoft\Windows\CurrentVersion\Uninstall\{GUID}`, with
`DisplayName` taken from a per-VS-host `PresentableName`. So `JetBrains
ReSharper` is a best-supported guess.

It can be confirmed from a validator run:
`cmd/maintained-apps/validate/windows.go` searches `programs` with a
loose `LOWER(name) LIKE '%…%'` on both the catalog name and
`unique_identifier`, and logs `Found app: '<DisplayName>' … Version:
<ver>` after running `MutateSoftwareOnIngestion`. That reveals both the
true DisplayName and the post-mutation version. The install script
prints the same information. **Expect a follow-up commit correcting
`unique_identifier` (and possibly the exists query) once that log
lands.**

## Risks

1. **Payload is not pinned.** The SHA covers only the 69 MB
bootstrapper; roughly 1.7 GB is fetched from `download.jetbrains.com` at
install time. JetBrains publishes only a `windowsWeb` download for
ReSharper, so there is no offline installer to point at. Install
duration may exceed script timeouts.
2. **Requires Visual Studio.** With no VS present the installer has
nothing to install, so the script exits 1 with a clear message.
`windows-latest` runners ship Visual Studio 2022 Enterprise, so
validation should be able to install.
3. **`/PerMachine=True` conflicts with pre-existing per-user installs.**
JetBrains states machine-wide mode "is not compatible with existing
installations in user profiles"; one must be removed first.
4. **`/SkipEtwService=True` omits the ETW host service**, so
dotTrace/dotMemory profiling integration is incomplete. This is the
documented tradeoff for an unattended install.
5. **Version reconciliation unconfirmed.** If the DisplayName ends in a
marketing version, the JetBrains name-based version mutation fires and
the validator's prefix check passes; a VS-suffixed name would instead
fall back to the registry `DisplayVersion`.

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

## Testing

- [x] `go test ./ee/maintained-apps/...` passes; both output JSON files
parse; generated SHA matches the winget manifest.
- [ ] QA'd all new/changed functionality manually — **not done.**
Install/uninstall need a Windows host with Visual Studio; relying on the
FMA Windows validator, which is also how `unique_identifier` gets
confirmed.


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

* **New Features**
  * Added ReSharper to the maintained Windows applications catalog.
* Added support for silent machine-wide installation and uninstallation.
* Added Visual Studio compatibility checks and installation failure
reporting.
  * Added a ReSharper icon for display in the software catalog.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-07 12:16:17 -05:00
kitzyandAllen Houchins 5db78a63e3 Add Visual Studio 2022 (Community/Professional/Enterprise) as Windows FMAs (#50717)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #50653

Adds **Visual Studio 2022 Community, Professional, and Enterprise** as
Windows Fleet-maintained apps. customer-universitas needs all three
editions.

## What's here

- Three input files, one per edition, each pointing at its own winget
package
(`Microsoft.VisualStudio.2022.{Community,Professional,Enterprise}`, all
at `17.14.37`).
- A shared install script (`visual_studio_2022_install.ps1`) — the
downloaded file is a ~4 MB bootstrapper, not the IDE. The real multi-GB
payload downloads from Microsoft *during* the install script, so install
time depends on the host's network speed and counts against Fleet's
1-hour software-install timeout. `--wait` is required or the
bootstrapper forks the real install to a background process and returns
almost immediately.
- Three uninstall scripts (one per edition) that resolve the install
path via `vswhere.exe -products
Microsoft.VisualStudio.Product.<Edition>` and call `vs_installer.exe
uninstall --installPath <path> --quiet --norestart --wait`, since VS has
no normal `UninstallString`.
- Both scripts map winget's documented `3010`/`1641` (reboot
pending/initiated) to a successful exit, and fail clearly on
`1001`/`1618` (another VS Installer operation already running).
- Default install ships the bare IDE shell (no `--add` workloads) —
matches plain `winget install` behavior, per the issue's own conclusion
that this needs no special-casing.
- Icons: no scriptable source (no Windows host to extract the real
per-edition `.exe` icon, and Microsoft's own download pages don't expose
one) turned up distinct Community/Professional/Enterprise badge art, so
all three currently use the same public Visual Studio mark ([Wikimedia
Commons](https://commons.wikimedia.org/wiki/File:Visual_Studio_Icon_2022.svg),
marked public domain). **Flagging for #g-software Product Designer** to
swap in the real per-edition badges if we have them.

## What I could not verify (no Windows host in this environment)

- `unique_identifier`/publisher (`Visual Studio
Community/Professional/Enterprise 2022`, publisher `Microsoft
Corporation`) are taken from the winget locale manifest, not confirmed
against a live registry entry.
- The version-string quirk the issue calls out: winget's
`AppsAndFeaturesEntries.DisplayVersion` is `"17.14.37 (July 2026)"`, not
a clean version. I deliberately did **not** set
`use_display_version_for_patch` — feeding that non-numeric string in as
the patch target would break `version_compare` ordering across future
version bumps (see the comment in `ingester.go`). Instead the patch
policy compares against the plain winget `PackageVersion` (`17.14.37`),
same as most winget FMAs. This should hold up if `version_compare` reads
leading numeric-dot segments and ignores the trailing text, but I can't
confirm that against real `programs.version` output without a host.
- Whether `vs_installer.exe` actually honors `--wait` for `uninstall`
the way the bootstrapper does for `install` — Microsoft's own docs say
`--wait` "can only be passed into the bootstrapper; the installer
(setup.exe) doesn't support it," which is in tension with the exact
command this issue asked for and what I've seen used in the wild. Worth
watching in validation logs.
- End-to-end install timing on a normal (non-datacenter) connection,
within the 1-hour timeout.

# Checklist for submitter

- [ ] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
<!-- Not added — no precedent for a changes file on FMA-addition PRs
(e.g. #50553, TeamViewer Host). -->

- [ ] 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] `apps.json` is valid JSON with descriptions filled in for all
three editions
- [x] Generator output reviewed: exists/patched queries, SHA256 (matches
the live winget manifest), installer URLs
- [x] `go build`/`go test ./ee/maintained-apps/...` pass; no shared
ingester/validator code changed
- [ ] FMA validator: install → detect → uninstall on a Windows host —
**pending, needs a Windows host**
- [ ] QA'd all new/changed functionality manually — **pending, same
reason**

## FMA-specific (from issue #50653's acceptance criteria)

- [x] Edition scope decided and recorded on the issue (all three:
Community, Professional, Enterprise)
- [x] Input added under `ee/maintained-apps/inputs/winget/`
- [x] Custom install script handles `3010`/`1641` as success and fails
clearly on `1618`/`1001`
- [x] Custom uninstall script resolves the install path via `vswhere`
and calls `vs_installer.exe uninstall`
- [ ] Identity fields verified against a real installed host — **not
yet, see above**
- [ ] Patch policy verified against actual `programs.version` — **not
yet, see above**
- [ ] Install verified end to end within the 1-hour timeout on a
normal-speed connection — **not yet**
- [ ] Passes the FMA validator: install → detect → uninstall — **not
yet**
- [x] Icon exists (shared placeholder mark across all three editions —
flagged for PD)

No shared/ingester/validator code changed.


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

- **New Features**
- Added Visual Studio 2022 Community, Professional, and Enterprise
editions to the software catalog.
- Added support for installing and uninstalling each edition with quiet
execution, installation detection, error handling, and reboot handling.
  - Added version 17.14.37 metadata and update detection.
- Added Visual Studio branding and edition-specific icons throughout the
software interface.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Allen Houchins <allenhouchins@mac.com>
2026-08-07 10:59:27 -05:00
Jonathan Katz 6ef4ba3910 Merge remote-tracking branch 'origin/main' into feat/39962-patch-when-closed 2026-08-07 10:12:53 -04:00
Nico 5a1365dc41 40493 webhooks for host activities (#50595)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #40493

Changes already reviewed in the PRs merged to this feature branch.
Only additive change was
https://github.com/fleetdm/fleet/pull/50595/commits/c0934e1fee46a734f9499a4c782563d4fcc345c4
to address CodeRabbit's comments.

# 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



https://github.com/user-attachments/assets/ea7f5157-a67a-4d83-842d-62197bd1546d



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

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

## Summary by CodeRabbit

* **New Features**
* Added host activity automations with configurable webhook
destinations.
* Manage automations from the Hosts page with validation, permissions,
and enable/disable controls.
  * Added GitOps support for team and unassigned-host webhook settings.
* Activity webhooks now include fleet-scoped host IDs where applicable.
  * Added profile UUIDs to MDM profile resend activity details.

* **Bug Fixes**
* Improved Windows MDM enrollment activity details by including the
linked host ID when available.
  * Preserved existing webhook settings when omitted during updates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-07 09:49:24 -03:00
NicoandLucas Manuel Rodriguez 358b8c43a5 iOS/iPadOS: More host vitals (#50496)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #39281 

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.

## Testing

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



https://github.com/user-attachments/assets/8ef7c66d-f8a6-46d5-ba17-66c1df8171b6



https://github.com/user-attachments/assets/6f67b49b-daf1-4acd-ad0f-55a7d1225a44



## 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**
  * Added 29 iOS/iPadOS device vitals to host details and API responses.
* Added a “View all” modal for browsing complete device vitals,
including subscriptions and accessibility details.
* Added support for cellular technology, organization information,
attestation data, and device settings.
* **Privacy**
  * Personal/BYOD enrollments exclude expanded device-vitals fields.
* Sensitive vitals are removed from device URL-authenticated responses.
* **Bug Fixes**
* Stale vitals are cleared when enrollment ownership changes or hosts
are deleted.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Lucas Manuel Rodriguez <lucas@fleetdm.com>
2026-08-07 09:49:14 -03:00
Magnus Jensen 51d9f493ef show user-scope icon for ios and ipados (#50715) 2026-08-07 10:00:23 +02:00
Juan Fernandez e29210e6f6 Software inventory & vulnerabilities: Add Adobe plugins
Resolves #45414 

- Added Adobe plugins to software inventory: Fleet now detects Adobe Creative Cloud plugins (CEP and UXP extensions) on macOS and Windows hosts and lists them on the Software page and host details with the software type "Plugin (Adobe)", including version and host count.
- Adobe plugins are excluded from vulnerability scanning, so no vulnerabilities are reported for them. No vulnerability data source maps an Adobe CEP or UXP extension to a CVE; Adobe files CVEs against the host application (Photoshop, Acrobat, and so on), which Fleet already scans.
2026-08-06 17:01:07 -04:00
Jonathan Katz 1f86654e8f Patch when closed: default continuous automation off for Force patch (#50691)
- Sets continuous automations to off by default in the Deploy modal and
Edit policy page

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

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

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**
- Continuous automation settings now behave consistently when creating
or editing Force patch policies.
- Manual patching disables continuous automation, while closed patching
enables it.
  - Other patch selections preserve the current automation setting.
- Saving existing policies now correctly retains the configured
automation state.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 14:26:23 -04:00
RachelElysia 790b240bee Fleet UI: Fix stretched software table headers on empty refetch (#50613) 2026-08-06 10:18:21 -07:00
Siddharth KhengareandRachelElysia 7eb8838815 Use EmptyState for configuration profiles empty state #49461 (#49772)
---------

Co-authored-by: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
2026-08-06 09:04:51 -07:00
Victor Lyuboslavsky 49bf85c54d Windows managed local account: design feedback on the Users tab and error tooltip (#50675)
Fixes from @melpike's feedback.

Keep the Windows tab visible when Windows MDM is off rather than hiding
it, and disable Create hidden admin with a tooltip pointing at Windows
MDM, matching how the macOS tab already behaves.
- Extracted `TurnOnMdmTooltipWrapper` to reduce code duplication

Reword the password-policy error fleetd reports so it reads as
sentences. The whole string is generated by Fleet, not by Windows, and
it is now shown to admins verbatim in the Show managed account tooltip.

Left-align that tooltip.

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

# Checklist for submitter

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

## Summary by CodeRabbit

* **New Features**
* Windows account setup remains visible when Windows MDM is unavailable.
  * Added guidance for enabling Apple or Windows MDM when required.
* Managed-account error tooltips now show detailed failure information
when available.

* **Bug Fixes**
  * Prevented unavailable managed-account options from being selected.
  * Improved Windows account error messages and password-policy wording.
  * Improved visual feedback for disabled actions in dropdown menus.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 10:19:55 -05:00
Nico efa8775ea7 Fix policy automations table dropping rows for multi-host automation runs (#50684)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #50683

The policy details page's Automation runs table showed the correct run
count but rendered only one row when a single automation run covered
multiple hosts (e.g. a failing-policies webhook batch): rows are
(activity, host) pairs, so batch rows share an activity id, and the
table's default row.id keying collapsed the duplicates.

# 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

#### Before

<img width="810" height="274" alt="Screenshot 2026-08-06 at 11 36 27 AM"
src="https://github.com/user-attachments/assets/c55a54c0-5d9b-4945-b712-c2449f3a4a8c"
/>


#### After

<img width="1467" height="510" alt="Screenshot 2026-08-06 at 11 23
41 AM"
src="https://github.com/user-attachments/assets/d0e560a3-0270-49aa-989d-0812fd156813"
/>



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

## Summary by CodeRabbit

* **Bug Fixes**
* Fixed policy automation activity tables so activities with the same ID
are displayed as separate rows for each host.
  * Corrected total run counts shown for host-specific activity rows.


<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 12:14:42 -03:00
Victor Lyuboslavsky 658ebbf509 Frontend: Windows managed local account (#50241)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #48722 

Demo: https://www.youtube.com/watch?v=zm5WmJY-o4Y

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

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

* **New Features**
* Added Windows support for creating and managing local administrator
accounts.
* Added a Windows-specific option in user setup when Windows MDM is
configured.
* Added managed-account actions and status visibility for Windows hosts.
* Added guidance noting that this feature requires `fleetd` 1.60.0 or
later.

* **Improvements**
* Updated local account descriptions, help text, and authentication
guidance.
  * Improved managed-account status and password-rotation messaging.
* Added clearer feedback when account creation or password escrow is
pending.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 07:05:13 -05:00
George Karr 985ebe3c38 Make dashboard 'Hosts enrolled' platform links keyboard accessible (#48214) (#49839) 2026-08-05 16:01:21 -05:00
George Karr 40d58607bb Fix script/query editor selecting text when scrolling after a single click (#48490) (#49744) 2026-08-05 16:00:56 -05:00
Jonathan Katz a0805e49d8 Add software installer file size check before upload (#50475)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42735 
- Exposes max_software_package_size in the `GET /api/v1/fleet/config`
endpoint
- Add frontend logic to use it to deny files that are too big before
they get uploaded

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

- [ ] 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
  - Tested on Chrome, Safari, and Firefox on macOS


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

* **New Features**
* Added a configurable maximum software package size to application
settings.
* Software uploads exceeding the limit are rejected with a clear,
size-specific error message.
  * Packages at or below the configured limit are accepted.
  * Added user-friendly file-size formatting across common units.
* Upload validation accounts for the complete request size, including
scripts and settings.

* **Tests**
* Added coverage for upload validation, boundary conditions, size
formatting, and configuration responses.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 15:57:20 -04:00
George Karrandtest 1dcad647f9 Fix dark-mode contrast of status-filter dropdown selected-value icon (#47581) (#49622)
**Related issue:** Resolves #47581

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

## What / why

In dark mode, the status-filter dropdown's selected-value icon on the
Hosts page rendered near-black and was barely visible at rest (only
appearing on hover/open).

The leading filter icon is rendered two different ways, and both were
broken in dark mode:

1. **SVG icon** (`iconName="filter-alt"` — PoliciesFilter,
HostsFilterBlock) renders `.dropdown__custom-value .dropdown__icon`. The
base `Dropdown` only applied a theme-aware `fill` on hover/open; at rest
it fell back to a near-black default. Added a rest-state rule (`fill:
$ui-fleet-black-75`) so the icon is theme-aware at rest. Light mode
resolves to the same color as before (no visual change); dark mode now
uses the light shade.

2. **Black PNG** (`icon-filter-v2-black-16x16@2x.png` via `::before` —
DiskEncryptionStatusFilter, BootstrapPackageStatusFilter) is a hardcoded
black glyph that never adapts to the theme. Added `filter: invert(1)`
scoped to `body.dark-mode` so it becomes a light glyph in dark mode
only.

Frontend/SCSS-only change.

## Testing

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

Verify in **dark mode** on the Hosts page:
- Controls → OS settings → Disk encryption → click a status (lands on
`/hosts/manage?...&os_settings_disk_encryption=enforcing`) — the
"Enforcing" filter icon is clearly visible at rest.
- Bootstrap package status filter and policy pass/fail filter icons are
also visible at rest.
- Light mode appearance is unchanged.


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

- **Bug Fixes**
  - Improved visibility of selected status-filter icons in dark mode.
- Updated disk encryption, bootstrap package, and policy status filters
on the Hosts page with clearer, theme-aware icons.
- Improved contrast and consistency for dropdown icons across dark-mode
views, preventing selected icons from appearing nearly black or
difficult to see.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: test <test@test.com>
2026-08-05 12:32:08 -05:00
Noah Talerman 781ba43596 Rename 'Certificate enrollment' to 'Certificate authorities' (#50535) 2026-08-05 10:25:09 -07:00
Allen Houchins bc3eee5f32 Re-add Dell Display and Peripheral Manager Windows FMA, validate on client-OS runner (#50313)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** NA (Windows FMA workstream; follow-up to #49127,
which dropped DDPM)

Re-adds **Dell Display and Peripheral Manager**
(`Dell.DisplayAndPeripheralManager` 2.2.2.8) as a Windows
Fleet-maintained app, and adds a `requires_client_os` routing override
so its CI validation always runs on the `windows-11-arm` runner.

## Why DDPM was dropped before, and why it's viable now

DDPM was dropped from the earlier re-add because its InstallShield setup
aborted with `0x80042000` under every documented silent switch, which
was diagnosed at the time as a .NET-prerequisite/headless-chaining
problem. A new debug run with Dell's own `/CreateDebugLog` switch shows
the real cause: the setup evaluates the OS at `OFUIBefore` and
terminates because the runner reports **Microsoft Windows Server 2025**.
DDPM is a Windows 10/11 client application and refuses to install on
Server SKUs — which is exactly what GitHub's x64 `windows-latest` image
is.

```
OSetUMode() 0 AP:2.2.2.8
OFUIBefore
Os Major10 Minor0
OS - 44444
// End Log File...
```

## `requires_client_os` CI routing

- New optional winget input field `requires_client_os: true` (documented
in `ee/maintained-apps/README.md` and on the Go input struct; ignored by
ingestion).
- `.github/scripts/partition-fma-apps.sh` routes any app with this flag
to `windows-11-arm` — the only GitHub-hosted client-OS Windows runner —
regardless of `installer_arch`. The x64 installer runs there under Prism
emulation; DDPM's gate is the OS SKU, not the architecture.
- Verified locally: partitioning the full 421-app Windows catalog
reroutes only `dell-display-and-peripheral-manager/windows`.

## App identity (verified against the real installer)

- Downloaded `DDPM-Setup_2.2.2.8.exe` from `dl.dell.com` (Chrome UA per
#49123); SHA256 matches the winget manifest.
- Embedded InstallShield `[Application]` block: `Name=Dell Display and
Peripheral Manager`, `Company=Dell Technologies`; ProductCode matches
the manifest GUID. The setup log reports `AP:2.2.2.8` as the registering
version.
- Installs with Dell's documented managed-deployment switches `/Silent
/HeadlessMode=true /TelemetryConsent=false /TurnOffCA` — the final
pre-drop iteration (6d0f2c00af), which also declines telemetry and
disables DDPM's self-updater on Fleet-managed hosts. Uninstalls via
`msiexec /x` on the ProductCode looked up in the registry by
DisplayName.

Input/uninstall script/icon are restored from the pre-drop state; the
install script is the final pre-drop iteration with its root-cause
comment corrected (Server-SKU OS gate, not headless-SYSTEM chaining).
Output regenerated (winget still at 2.2.2.8; script refs verified).

# Checklist for submitter

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

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

## Testing

- [x] QA'd all new/changed functionality manually (partition script
exercised locally over the full catalog and a mixed PR-style slug list;
ingester regenerated with no output drift; `go test
./ee/maintained-apps/ingesters/winget/` passes)
- [ ] `test-fma-windows-pr-only` validates DDPM on the `windows-11-arm`
runner in this PR's CI


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

* **New Features**
* Added Dell Display and Peripheral Manager to the Windows software
catalog, including installation, uninstallation, detection, metadata,
and an app icon.
* Added support for routing applications that require a Windows client
operating system to the appropriate Windows 11 ARM test environment.

* **Documentation**
* Documented Windows client operating system routing behavior and test
environment architecture details.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 12:21:55 -05:00
Magnus JensenandCopilot Autofix powered by AI 3cbdff01cd Update Release from AB modal copy and route back to list hosts on Pending (#50558)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #50350 and Resolves #50358 

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

- [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**
  * Added enrollment-status messaging when releasing a host.
* Pending-enrollment hosts now display a notice that they will also be
removed from Fleet.
  * Added a “Learn More” link to release-device documentation.

* **Bug Fixes**
* Improved navigation after releasing hosts with pending enrollment by
returning to the hosts list.
* Prevented unnecessary host details and activity refreshes when
pending-enrollment hosts are released.
<!-- 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-08-05 19:16:03 +02:00
RachelElysia 8d616e31cb Fleet UI: Flush Self-service search right without Install all button (#50534) 2026-08-05 09:15:15 -07:00
Jonathan Katz 298146f8c4 Patch when closed: Fix generate-gitops generating invalid file and frontend copy (#50542)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** 
Resolves #50522 
Resolves #50523 

# Checklist for submitter

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

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**
* Pre-install queries are no longer exported for apps configured to
patch when closed.
* Updated automation activity labels to clearly identify skipped
patches, including the software name when available.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 10:02:26 -04:00
Victor Lyuboslavsky a4af4d896c Add default fleet for new Windows MDM enrollments (#41787) (#49922)
Demo: https://www.youtube.com/watch?v=cWxZlu9WuwA
Guide updates: https://github.com/fleetdm/fleet/pull/49603/changes

IT admins can configure the fleet that hosts enrolling through
user-driven Windows MDM enrollment (Windows Autopilot, Entra join) are
automatically assigned to, via the Windows MDM settings page, the
mdm.windows_enrollment.default_fleet config setting, or GitOps.

- New windows_enrollment_config row stores the default team; the config
API surfaces it by fleet name and hydrates reads from the row so team
renames and deletions never serve a stale name. Deleting the fleet
clears the setting.
- New edited_windows_enrollment_default_fleet activity, emitted only
when the value changes.
- The OMA-DM session persists the device-reported SMBIOS serial on
still-unlinked enrollments, and orbit enrollment reverse-links by that
serial and assigns the default fleet before orbit's one-shot
setup-experience init, so the default fleet's software, scripts, and
profiles apply during the Autopilot ESP. The DevDetail and osquery link
paths keep the same assignment as fallbacks, and the EUA-token link path
now shares the same post-link bookkeeping.
- Hosts are only assigned when new to Fleet in this enrollment cycle:
existing hosts, including ones parked in Unassigned, keep their fleet on
re-enrollment, matching macOS ABM behavior.
- GitOps defers applying the setting until teams declared in the same
run are created, and fleetctl generate-gitops exports it.
- Windows MDM settings page redesign per Figma: programmatic enrollment
toggle, User driven enrollment section with the Entra-gated Default
fleet dropdown, and a Migration section.

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

# 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

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

## New Fleet configuration 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**
* Added support for assigning a default Fleet Premium fleet to new
Windows MDM enrollments, including Autopilot and Entra join.
* Default-fleet settings can be configured, cleared, and managed through
Windows MDM settings and GitOps.
* Assigned fleet software, scripts, and profiles can apply during
out-of-box setup.
  * Added activity-feed visibility for default-fleet changes.
  * Improved Windows enrollment matching using hardware serial numbers.

* **Documentation**
  * Documented default-fleet assignment for Windows enrollment.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 16:30:02 -05:00
LeAnn c49d3d8191 Hide Self-service preview tabs in Edit appearance for Android apps (#50533)
<img width="890" height="562" alt="Screenshot 2026-08-04 at 12 57 28 PM"
src="https://github.com/user-attachments/assets/cb3a0817-13a8-483e-a5ad-d6c430c81f32"
/>

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

# 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

Android apps are always self-service and installed from the Play Store
in the end user's work profile — there's no Fleet self-service web view
for them. The "Edit appearance" modal's Preview section still showed a
"Fleet" / "Self-service" tab pair with a browser-style self-service
preview for Android titles, which doesn't reflect what end users
actually see (#44791).

This PR removes the tab nav for Android software titles in
`EditIconModal` — the Preview section now renders just the Fleet card,
with no tabs and no Self-service preview.

## Test plan

- [x] `yarn test` for `EditIconModal.tests.tsx` (added a test asserting
no tabs/Self-service text render for an `android_apps` source, existing
test confirms tabs still render for non-Android)
- [x] Manually verified in a local dev instance: seeded an Android
software title, opened Actions > Edit appearance, confirmed Preview
renders the Fleet card directly with no tabs

(Recreated from #50530, which accidentally included unrelated commits
from a stale branch base.)

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

* **Bug Fixes**
* Removed the misleading Android Self-service preview from the Edit
appearance modal.
* Android app previews now show only the Fleet preview and Version view.
* Other software continues to display both Fleet and Self-service
preview options.
* **Tests**
* Added coverage to verify the correct preview tabs and version display
for Android apps.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 13:25:33 -07:00
Steven PalmesanoandRachelElysia 0c1e75ae8a Normalize tags (#48982)
---------

Co-authored-by: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
2026-08-04 12:23:34 -07:00
Carlo DiCelico aec941a6c9 fix test-preview 2026-08-04 13:53:56 -04:00
Carlo DiCelico 4bf182c143 address eng qa and reviewer feedback 2026-08-04 13:01:20 -04:00
NicoandCopilot Autofix powered by AI f12954b2af Link custom host vitals from the host name template description (#50491)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #49489

The host name template card's description only linked to built-in and
custom variables, even though `$FLEET_HOST_VITAL_<id>` references are
also supported there as of #49489. This was missed when that story
shipped, leaving admins without a pointer to the custom host vitals tab
from the one place they'd set up a template.

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

Already included in main as part of the feature branch merge.

<img width="767" height="117" alt="Screenshot 2026-08-04 at 11 22 07 AM"
src="https://github.com/user-attachments/assets/6358ed90-88e1-4f97-8f26-ab56d00bde0b"
/>


## Testing

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


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

## Summary by CodeRabbit

* **Documentation**
* Updated OS Settings documentation with separate links for built-in and
custom host vitals variables to improve accessibility and user
reference.

<!-- 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-08-04 12:12:31 -03:00
Juan Fernandez 60ad78f897 Add Omarchy as a supported Linux platform
Resolves #50069

Omarchy 4 ships its own /etc/os-release with ID=omarchy, where earlier
versions inherited ID=arch from Arch Linux. Since HostLinuxOSs and
HOST_LINUX_PLATFORMS gate nearly every Linux check, these hosts had
empty vitals and software inventory, were missed by linux-scoped
policies and labels, had no disk encryption or key escrow, and lost Run
script in the UI (the API was unaffected).

Add "omarchy" to HostLinuxOSs, HostNeitherDebNorRpmPackageOSs (pacman-
based), IsLUKSSupported, HOST_LINUX_PLATFORMS,
DISK_ENCRYPTION_SUPPORTED_LINUX_PLATFORMS, and the Vitals
disk-encryption tooltip. Regenerate understanding-host-vitals.md.

Aggregate Omarchy onto the "Arch Linux" / "rolling" OS inventory row,
where these hosts sat before quattro. Unlike CachyOS, Omarchy reports a
real release number rather than BUILD_ID=rolling, so the version is
pinned after parsing instead of rewriting the ingested build value.

Also add a fleetd test container, built on archlinux since Omarchy
publishes no image.
2026-08-04 10:32:44 -04:00
Allen Houchins b668734d5c Remove Fig FMA (cask removed from Homebrew upstream) (#50483)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** NA

Removes the **Fig** Fleet-maintained app. Its Homebrew cask no longer
exists.

Homebrew deleted the `fig` cask in
[`a36fac3b75`](https://github.com/Homebrew/homebrew-cask/commit/a36fac3b75f633a9c787c4c73fc46606939947a3)
on **2026-08-04**, the end of a long deprecation:

| Date | Upstream change |
|---|---|
| 2024-08-03 | `fig: deprecate` |
| 2025-08-02 | `fig: disable` |
| 2026-08-04 | `fig: remove cask` |

`https://formulae.brew.sh/api/cask/fig.json` now returns **404**, so the
nightly ingester panics and no maintained apps are generated at all:

```
{"time":"2026-08-04T02:38:58.15272663Z","level":"INFO","msg":"ingesting homebrew app","name":"fig"}
panic: ingesting homebrew app: app not found in brew API
```

Note that `"frozen": true` does **not** fix this — that flag only gates
the output write, and the ingester still fetches the cask first and
panics on the 404. Removing the input is the fix.

There is no successor cask to migrate to. Fig was acquired by AWS and
folded into Amazon Q Developer CLI, which is not distributed via
Homebrew (`amazon-q`, `amazon-q-developer-cli`, `q-cli`, and
`codewhisperer` all 404), and `fig.io` itself now returns 503.

### Changes

- Deleted `ee/maintained-apps/inputs/homebrew/fig.json`
- Deleted `ee/maintained-apps/outputs/fig/darwin.json`
- Removed the `fig/darwin` entry from
`ee/maintained-apps/outputs/apps.json`
- Deleted the `Fig` icon component and its `index.ts` import/map entry
- Deleted `website/assets/images/app-icon-fig-60x60@2x.png`

The output file is deleted rather than orphaned so the PR validator's
changed-app detector doesn't keep validating a removed app.

# Checklist for submitter

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

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

Verified `apps.json` still parses and the `fig/darwin` slug is gone
(1390 apps remain, `figma` untouched), `tsc --noEmit` is clean after
removing the `Fig` icon import, and no references to `fig`,
`com.mschrage.fig`, `fig/darwin`, or `repo.fig.io` remain anywhere in
the repo.

> [!NOTE]
> Existing hosts with Fig installed will no longer see it as a
Fleet-maintained app. The app is end-of-life upstream, so there is no
version for Fleet to track or patch to.
2026-08-04 07:19:45 -05:00
Allen Houchins b2b2081ad4 Remove Gadwin PrintScreen, PrintScreen Pro, and ScreenRecorder FMAs (expired TLS cert on download host) (#50470)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** NA

Removes the three Gadwin Fleet-maintained apps: **Gadwin PrintScreen**,
**Gadwin PrintScreen Pro**, and **Gadwin ScreenRecorder**.

All three download their installers from `www.gadwin.com`, whose Let's
Encrypt certificate **expired 2026-08-02** and has not been renewed:

```
subject=CN=gadwin.com
issuer=C=US, O=Let's Encrypt, CN=R13
notBefore=May  4 13:06:54 2026 GMT
notAfter=Aug  2 13:06:53 2026 GMT
```

Every FMA validation run now fails these three apps:

```
level=ERROR msg="Error downloading maintained app: downloading installer:
performing request for URL https://www.gadwin.com/download/PrintScreen650_Win64.msi:
tls: failed to verify certificate: x509: certificate has expired or is not yet valid"
app="Gadwin PrintScreen"
```

This is not just CI: Fleet fetches the installer from that same URL when
a user installs the app, so all three are currently uninstallable for
customers.

> [!NOTE]
> The certificate expired only one day before this PR was opened. If
Gadwin renews it, these apps become viable again and the alternative fix
is `"frozen": true` in each winget input (which skips validation) rather
than removal. Removing was chosen because a lapsed auto-renewing
certificate means no one is maintaining the download host, and a broken
installer URL is worse for users than an absent app. Happy to switch to
a freeze if reviewers prefer to wait it out.

### What's removed

Per app, all locations that applied:

| Location | PrintScreen | PrintScreen Pro | ScreenRecorder |
|---|---|---|---|
| `ee/maintained-apps/inputs/winget/<slug>.json` |  |  |  |
| `ee/maintained-apps/outputs/<slug>/windows.json` |  |  |  |
| `ee/maintained-apps/outputs/apps.json` entry |  |  |  |
| `frontend/.../icons/<Name>.tsx` |  |  | — (none existed) |
| import + mapping in `icons/index.ts` |  |  | — |
| `website/assets/images/app-icon-<slug>-60x60@2x.png` |  |  | — (none
existed) |

All three are Windows-only (no Homebrew input or `darwin.json`), so no
macOS counterpart is affected and no shared icons needed to be retained.
`apps.json` goes from 1393 to 1390 apps. The diff is deletion-only.

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

Verification performed:

- `apps.json` parses as valid JSON; no `gadwin` slugs remain.
- Repo-wide grep for `gadwin` returns no dangling references. (The one
remaining hit, `cmd/osquery-perf/software-library/software.sql`, is a
simulated host-inventory fixture, not an FMA definition — intentionally
left in place.)
- `npx tsc --noEmit` reports no errors related to the removed icon
components or the icon index.
- `npx prettier --check` passes on `icons/index.ts` and `apps.json`.
- `go build ./cmd/maintained-apps/... ./ee/maintained-apps/...` and `go
test ./ee/maintained-apps/...` pass.


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

## Summary by CodeRabbit

* **Chores**
* Removed Gadwin PrintScreen, Gadwin PrintScreen Pro, and Gadwin
ScreenRecorder from the maintained Windows application catalog.
* Removed their associated software listings, installation details, and
product icons from the application interface.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 21:37:09 -05:00
Allen Houchins 2431d580b0 Add QEMU as a Windows Fleet-maintained app (#50471)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #50126

Adds **QEMU** (`SoftwareFreedomConservancy.QEMU`) as a Windows
Fleet-maintained app, requested by a customer in #50126. Windows-only:
on macOS, Homebrew ships QEMU as a formula (CLI tools, no `.app`
bundle), so it isn't a viable macOS FMA.

## App identity (verified against the real installer)

- Downloaded `qemu-w64-setup-20260501.exe` from `qemu.weilnetz.de`;
SHA256 matches the winget manifest.
- QEMU's NSIS definition
([`qemu.nsi`](https://gitlab.com/qemu-project/qemu/-/blob/master/qemu.nsi))
writes the uninstall key `HKLM\...\Uninstall\QEMU` (64-bit view via
`SetRegView 64`) with `DisplayName "QEMU"` and `DisplayVersion` set to
the meson project version — which equals the winget `PackageVersion`, so
the patch policy reconciles cleanly.
- **No `Publisher` value is written to the registry**, so the default
generated exists query (`... AND publisher = 'QEMU Community'`) would
never match. The input overrides it with `exists_query: SELECT 1 FROM
programs WHERE name = 'QEMU';` — exact name match, so entries like "QEMU
guest agent" (virtio-win) are left alone.

## Install/uninstall scripts

- NSIS installer, machine scope, x64. Install: standard silent `/S`
(same pattern as AnyBurn).
- Uninstall: registry lookup by exact DisplayName across both registry
views, defensive UninstallString parsing, `/S _?=<installdir>` so the
uninstaller runs in place (instead of relaunching from `%TEMP%` and
returning immediately), verification that the ARP entry is actually
gone, then sweep of the leftover uninstaller/install dir,
`HKLM\SOFTWARE\QEMU`, and shortcuts.

## Version caveat

winget's newest version dir for this package is **11.0.50 — a QEMU
development snapshot** (QEMU uses `x.y.50` for post-release dev builds;
only x64, no arm64), added upstream alongside the 11.0.0 stable release.
The ingester picks the highest version, so this FMA currently ships the
snapshot build; it will move to the next stable (e.g. 11.0.1/11.1.0) as
soon as winget has it. The installer URL is date-pinned
(`.../2026/qemu-w64-setup-20260501.exe`), so there's no hash-drift risk.
If we'd rather not offer dev snapshots, that needs an ingester-level
version filter — flagging for maintainer input rather than building it
into this PR.

## Icon

Official 128×128 QEMU icon from the upstream source tree
(`ui/icons/qemu_128x128.png`), generated via
`tools/software/icons/generate-icons.sh`.

# Checklist for submitter

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

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

## Testing

- [x] Verified installer SHA256, registry identity
(DisplayName/DisplayVersion/no Publisher), and silent switches against
the real installer and upstream `qemu.nsi`/`meson.build`
- [ ] `test-fma-windows-pr-only` validates QEMU install/uninstall in
this PR's CI


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

## Summary by CodeRabbit

* **New Features**
  * Added QEMU to the Windows software catalog.
* Added support for silent QEMU installation and reliable
uninstallation.
  * Added QEMU version detection and upgrade validation.
  * Added a QEMU icon to the software interface.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 21:36:12 -05:00
RachelElysia e7a9456044 Fleet UI: Align toast icon with first line of message (#50449) 2026-08-03 14:52:30 -07:00
Carlo DiCelico e89dc4c433 fe reviewer pass 2026-08-03 17:08:23 -04:00
Carlo DiCelico a9c10da53f follow-on UI fixes 2026-08-03 17:01:35 -04:00
Jordan Montgomery 3ea4304126 Fix validation on account provisioning page to require secret (#50443)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #50248

Clears the secret field with a clear error, forcing the user to re-enter
it, on a URL change, and displays the actual server error strings rather
than a generic error(though the server errors are currently largely
unreachable via frontend since validation has been tightened up).

# Checklist for submitter

If some of the following don't apply, delete the relevant line.
Unreleased bug so no changes file
- [ ] 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

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

* **New Features**
  * Added HTTPS validation for account provisioning token URLs.
* Server-side validation errors now appear on the relevant form fields.
  * Update failures display helpful server-provided error messages.

* **Bug Fixes**
* Changing a token URL now clears masked secrets and requires the secret
to be entered again.
  * Prevented form submission when required secret re-entry is missing.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 14:47:47 -04:00
Carlo DiCelico a1246a031c Figma fidelity pass 2026-08-03 14:32:33 -04:00
RachelElysia 756295aabf Fleet UI: Button icon padding correction (#50195) 2026-08-03 11:10:52 -07:00
RachelElysia 75db0f1adf Fleet UI: Fix New user form dropdown layout shift (#50444) 2026-08-03 11:09:36 -07:00
Allen Houchins 89acb97395 Add NVDA as a Windows Fleet-maintained app (#50450)
**Related issue:** Resolves #50125

Adds NVDA as a Windows Fleet-maintained app, from winget `NVAccess.NVDA`
(2026.1.1, NSIS/nullsoft, x86 launcher).

## Identity — read out of the shipped installer, not the manifest

I downloaded the 60 MB installer, extracted the NSIS payload, and read
the identity fields from `_buildVersion.pyc` and the PE headers. The
winget manifest is misleading in two ways:

| Field | winget says | Actually is | Source |
|---|---|---|---|
| Architecture | `x86` | **x64** app behind a 32-bit NSIS launcher stub
| `nvda_noUIAccess.exe` / `nvda_slave.exe` PE headers |
| Registry DisplayName | PackageName `NVDA` | **`NVDA 2026.1.1`** |
`source/installer.py` `getUninstallerRegInfo()`: `DisplayName=f"{name}
{version}"` |
| Publisher | `NV Access` | `NV Access` (matches) | `_buildVersion.pyc`:
`publisher = "NV Access"` |

Two consequences:

- Because NVDA itself is a **64-bit** process, it registers under the
native registry view, **not** `Wow6432Node` (the launcher's 32-bit-ness
is irrelevant). Both scripts check both views anyway, for legacy 32-bit
copies.
- DisplayName carries the version, so this needs `fuzzy_match_name:
true` → `name LIKE 'NVDA %'`. Publisher matches the locale manifest, so
no `program_publisher` override.

`installer_arch` stays `x86` because that's what the manifest declares
and the ingester matches on it.

## Version reconciles without a validator exception

DisplayVersion is the 4-part `2026.1.1.55980` (`version_detailed`)
against winget's `2026.1.1`:

- **Validator:** passes via the existing
`strings.HasPrefix(result.Version, appVersion+".")` branch in
`cmd/maintained-apps/validate/windows.go`. No new skip added —
deliberately, since existence-only skips make patch policies always
report "patched".
- **Patch policy:** `version_compare('2026.1.1.55980', '2026.1.1')` is
`> 0`, so an installed copy reads as newer, not outdated. No perpetual
false "update available".

## The install script can't trust the exit code

`source/gui/installerGui.py` `doInstall()` pops `winUser.MessageBox` /
`gui.messageBox` on **every** install failure path with **no `if silent`
guard**, and then falls through and exits **0**. Under SYSTEM in session
0 that means:

1. a failure **hangs forever** — nobody can click Retry/Cancel; and
2. if it were dismissed, a failed install would report **success**.

So `nvda_install.ps1` uses a watchdog plus an Add/Remove Programs
registration poll as the real success signal — the same shape as the
existing `azure_data_studio_install.ps1`. Timeouts are 420 + 120 + 30 =
570s, under the caller's 10-minute cap.

On timeout it kills only the launcher's `%TEMP%` children
(`nvda_noUIAccess` / `nvda_uiAccess`), **deliberately not `nvda.exe`** —
an installed NVDA runs as `nvda.exe`, and force-killing it would cut off
a signed-in user's screen reader with no warning.

## Uninstall

Vendor-documented `/S` (NVDA user guide, "Uninstalling NVDA"), plus
`_?=` last so the NSIS uninstaller runs in place instead of relaunching
from `%TEMP%` and returning immediately. NVDA writes **no**
`QuietUninstallString`, and its `UninstallString` is an **unquoted path
containing spaces** (`C:\Program Files\NVDA\uninstall.exe`), so the
parser handles that form. The directory comes from NVDA's `InstallDir`
value (not `InstallLocation`). Absence of the ARP entry is the success
signal, since NVDA removes it via `nvda_slave.exe unregisterInstall`.

## Reviewer notes

- **`installer_scope` is `""`, not `"machine"`.** NVDA genuinely
installs machine-wide (`%ProgramFiles%\NVDA` + HKLM), but the winget
manifest declares no `Scope`, so the ingester derives `""` and
`"machine"` panics with "failed to find installer". The one-line
ingester fix for this is designed in #48248 but isn't in `main`; I chose
not to change shared installer-selection code for a single-app addition.
Happy to land that fix here instead if preferred.
- **Upgrade caveat:** if NVDA is running for a signed-in user,
`--install-silent` refuses to overwrite its own running files by design
(`installer.py` `install()`). The script fails with an actionable
message rather than force-killing the screen reader.
- Installer URL is version-pinned
(`download.nvaccess.org/releases/2026.1.1/...`), not a "latest"
redirect. SHA verified against my own download of the file.

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

## Testing

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

`go test ./ee/maintained-apps/...` passes; prettier and `tsc --noEmit`
are clean. I have no Windows host or `pwsh`, so **the install/uninstall
scripts are unexercised** until FMA validation CI runs them on a Windows
runner. No changes file — consistent with other FMA additions (#50415,
#50348, #50352).
2026-08-03 12:40:44 -05:00
kitzyandAllen Houchins 4036f9bfcb Add Microsoft ODBC Driver 18 for SQL Server as a Windows Fleet-maintained app (#50348)
**Related issue:** Resolves #50327

Adds Microsoft ODBC Driver 18 for SQL Server as a Windows
Fleet-maintained app, from winget `Microsoft.msodbcsql.18` (18.6.2.1,
MSI, machine scope, x64, en-US). Sibling of #50342 (driver 17); the two
install side by side and are separate products.

## Verification

Identity read from the MSI Property table:

```
ProductName    Microsoft ODBC Driver 18 for SQL Server
Manufacturer   Microsoft Corporation
ProductCode    {820A3DEC-9783-42AE-B12D-750FCCF07E10}
UpgradeCode    {ADA68B65-BFF8-4E6A-B082-CC6682D425B8}
ALLUSERS       1
```

- Installer SHA confirmed against a local download (`20314529…4b82`).
- The UpgradeCode differs from driver 17's (`{0123A210-…}`), which
confirms they are independent products rather than upgrades of one
another. The generated uninstall script picked up 18's, so uninstalling
one will not touch the other.
- Because `ProductName` already carries the major version, the exists
query is a simple equality — no `version LIKE '18.%'` pinning needed,
and no risk of 17 and 18 matching each other.

Like driver 17, the MSI refuses to install without
`IACCEPTMSODBCSQLLICENSETERMS=YES`, which Fleet's default MSI script
does not pass, so this ships a small custom install script. It is
deliberately a **separate file** from driver 17's rather than a shared
path, following the repo's one-script-per-app convention and keeping the
two PRs independently mergeable.

The icon comes from the MSI's own `ARPPRODUCTICON` stream. As with
#50342 it is natively 32×32, so the 128×128 asset is an upscale — happy
to drop it in favour of the generic fallback if reviewers prefer. The
icon map key also needed the same manual correction (the generator
derives it from the slug, which omits "for sql server").

The manifest declares a `Microsoft.VCRedist.2015+.x64` dependency, which
the ingester ignores; we ship `vc-redist-x64/windows` and the
redistributable is present on most hosts.

# Checklist for submitter

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


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

* **New Features**
* Added Microsoft ODBC Driver 18 for SQL Server to the maintained
Windows software catalog.
* Added support for version 18.6.2.1, including installation, upgrade,
uninstall, detection, and license acceptance handling.
  * Added the software’s icon and catalog display details.
* Included support for SQL Server and Azure SQL connectivity scenarios.
* Installation now provides appropriate handling for successful
completion, restart requirements, and installation failures.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

Co-authored-by: Allen Houchins <allenhouchins@mac.com>
2026-08-03 09:44:54 -05:00
Carlo DiCelico 01bf4b88be patch when closed UI 2026-08-03 10:27:54 -04:00
Allen Houchinsandcoderabbitai[bot] a4d058384c Add CrystalDiskMark as a Windows FMA (#50415)
**Related issue:** Resolves #50322

Adds CrystalDiskMark as a Windows Fleet-maintained app, from winget
`CrystalDewWorld.CrystalDiskMark` (9.0.3, Inno Setup, machine scope,
x64). Found in a customer's ManageEngine ServiceDesk Plus Windows
deployment catalog with no Fleet equivalent.

## Identity — read out of the Inno header, not the manifest

The winget manifest carries no `AppsAndFeaturesEntries`, so the ARP
identity had to come from the installer itself. I LZMA-decompressed the
Inno setup-data block and read the header directly:

| Header field | Value |
|---|---|
| `AppName` | `CrystalDiskMark` |
| `AppVerName` | `CrystalDiskMark 9.0.3` |
| `AppVersion` | `9.0.3` |
| `AppPublisher` | `Crystal Dew World` |
| `AppId` | `CrystalDiskMark9` |
| `UninstallDisplayName` | *(empty)* |
| `DefaultDirName` | `{pf}\CrystalDiskMark9` |

With `UninstallDisplayName` empty, Inno falls back to `AppVerName` for
the ARP `DisplayName` — so this registers as **`CrystalDiskMark
9.0.3`**, version-suffixed, and the exists query is a prefix match
(`fuzzy_match_name: true`).

That the name is version-suffixed isn't inferred from "Inno usually does
this." The Aoi edition's header sets `AppVerName` to `CrystalDiskMark
9.0.3 Aoi Edition` while its `AppName` is `CrystalDiskMark Aoi Edition`
— the compiler's synthesized default would have been `CrystalDiskMark
Aoi Edition 9.0.3`, so the script is setting `AppVerName` deliberately,
and Setup will write exactly that string.

`AppPublisher` matches the winget locale `Publisher` verbatim, so no
`program_publisher` override is needed, and `DisplayVersion` is
`AppVersion` = `9.0.3`, which reconciles with the FMA version with no
validator exception.

Generated query:

```sql
SELECT 1 FROM programs WHERE name LIKE 'CrystalDiskMark %' AND publisher = 'Crystal Dew World';
```

## Silent flags — the `[Run]` entries were decoded, not assumed

The header contains three `[Run]` entries with
`{cm:LaunchProgram,CrystalDiskMark9}` descriptions (one per
architecture), which is exactly the shape that has hung silent Inno
installs for us before. I parsed the entry structure through to the flag
bytes:

- wait enum = `1` → `nowait`
- flags = `0x14` → bit 2 `postinstall` + bit 4 `skipifsilent`

So `/VERYSILENT /SUPPRESSMSGBOXES /NORESTART` will not launch the GUI,
and there is no post-install hang to work around. The install script
still uses the poll-and-kill wrapper rather than `-Wait`, plus an
ARP-registration wait, since the installer can return before the
registry entry lands.

`/ALLUSERS` is deliberately omitted: `DefaultDirName` is `{pf}`, which
requires admin install mode already, so the switch would be a no-op.

## Uninstall

`UninstallString` is Inno's quoted `unins000.exe` path, but the script
uses the three-branch defensive parser (quoted / unquoted-with-spaces /
bare token) anyway. Two app-specific bits:

- The 12 `DiskMark*.exe` binaries are stopped first — the uninstaller
won't proceed while the `CrystalDiskMark9` mutex is held.
- The script waits for the registry entry to disappear rather than
trusting the exit code. Inno's uninstaller relaunches itself from a temp
copy and the original process returns early, so its exit code is not a
completion signal.

## Icon

The setup exe's `MAINICON` is Inno's stock CD-and-box artwork, not the
app's, so the icon was extracted from `DiskMark64.exe`'s own resources
(`innoextract` → `wrestool -t 14 -n 130` → `icotool`, 256×256 32-bit).

## Two things for reviewers

1. **This carries a shared-code change to the winget ingester**
(`normalizeSourceForgeURL`). A bare SourceForge project file URL serves
non-browser clients a 133KB HTML landing page with a 200, so the first
validator run downloaded that instead of the installer and failed on the
hash. Only the `.../download` form serves the binary. WinSCP works today
only because its manifest happens to carry the suffix, so the fix
normalizes in the ingester rather than depending on manifest authors.
WinSCP regenerates byte-identical and is the only other
SourceForge-hosted app in the catalog; `TestNormalizeSourceForgeURL`
covers both shapes. Details in [this
comment](https://github.com/fleetdm/fleet/pull/50415#issuecomment-5162501140).
2. **The Aoi and Shizuku editions share this package's `AppId` and
install directory.** They occupy the same ARP slot
(`CrystalDiskMark9_is1`), can't be co-installed, and will match the
exists query as `CrystalDiskMark 9.0.3 <Edition>`. I treated that as
correct rather than something to exclude — it is the same product at the
same version — but flagging it in case we'd rather pin to the plain
edition.

## Verification

- Inno header dumped offline; `AppVerName` / `AppPublisher` /
`AppVersion` read directly, `[Run]` flag bytes decoded.
- Generated SHA matches the winget installer manifest
(`1a255154…917e5e`), and the download was verified through the exact
code path the validator uses (`maintained_apps.DownloadInstaller` with
`http.DefaultClient`) — 4,523,144 bytes, hash matches.
- `apps.json` valid, description filled, icon generated and inserted
alphabetically in `index.ts` under the key `crystaldiskmark`.
- `go test ./ee/maintained-apps/...` passes; `GOOS=windows go build
./cmd/maintained-apps/validate/` builds; `gofmt`/`go vet` clean. `make
lint-go-incremental` could not run in my environment (`custom-gcl` fails
to clone golangci-lint, pre-existing and unrelated).
- First validator run failed on the download issue above and is fixed;
the full validator pass (install → detect → uninstall on a Windows host)
still needs to go green before this leaves draft.

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

## Testing

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


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

* **New Features**
* Added CrystalDiskMark as a supported Windows application, including
installation, uninstallation, detection, categorization, and software
catalog details.
  * Added CrystalDiskMark branding to the software interface.
* Improved SourceForge installer URL handling by automatically appending
download paths when needed.

* **Bug Fixes**
* Preserved existing download URLs, query parameters, and unsupported or
malformed URLs during normalization.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2026-08-03 09:03:24 -05:00
Steven Palmesano e86fa44965 Show button if there's only one action, instead of an actions dropdown (#48337) 2026-08-03 06:57:14 -07:00
kitzy 86f4619faf Add Microsoft ODBC Driver 17 for SQL Server as a Windows FMA (#50342)
**Related issue:** Resolves #50326

Adds Microsoft ODBC Driver 17 for SQL Server as a Windows
Fleet-maintained app, from winget `Microsoft.msodbcsql.17` (17.11.1.1,
MSI, machine scope, x64, en-US). Found in a customer's ManageEngine
ServiceDesk Plus Windows deployment catalog with no Fleet equivalent.

## The install would fail without a custom script

The MSI refuses to install unless `IACCEPTMSODBCSQLLICENSETERMS=YES` is
passed. This is not just a winget convention — the MSI carries the
condition and the matching error string:

```
IACCEPTMSODBCSQLLICENSETERMS ~=
IACCEPTMSODBCSQLLICENSETERMS=YES command-line parameter is missing.
```

Fleet's default MSI install script passes only `/quiet /norestart /i`,
so without the small custom script in this PR every install would fail.
Uninstall is still the auto-generated upgrade-code script, which is
correct as-is.

## Verification

Identity read from the MSI Property table:

```
ProductName    Microsoft ODBC Driver 17 for SQL Server
Manufacturer   Microsoft Corporation
ProductCode    {ACBA503E-64A9-4A8A-A6CC-63656F395618}
UpgradeCode    {0123A210-9B73-46E7-B5CE-7F33630300E7}
ALLUSERS       1
```

- Installer SHA confirmed against a local download (`0f642870…bd4e`).
- `ALLUSERS=1` means it always installs per-machine.
- The generated uninstall script correctly picked up the **x64**
UpgradeCode — note the x86 build uses a different one, so an arch mix-up
here would silently fail to uninstall.

**No version pinning is needed in the exists query.** When I scoped this
I expected to need `AND version LIKE '17.%'` the way the Amazon Corretto
FMAs do, but the `ProductName` already carries the major version, so
`Microsoft ODBC Driver 17 for SQL Server` and `...18...` are naturally
distinct entries. Simple equality is correct and unambiguous.

## Two notes for reviewers

**Icon quality.** The MSI's `ARPPRODUCTICON` stream tops out at 32×32,
so the 128×128 asset here is an upscale and looks soft. It is the
authentic Add/Remove Programs icon, but if we would rather fall back to
the generic software icon than ship a blurry one, drop the icon files
and I will regenerate without them.

**Icon map key needed a manual fix.** The generator derives its key from
the slug and produced `"microsoft odbc driver 17"`, but lookups use the
lowercased catalog name — `"microsoft odbc driver 17 for sql server"`.
Corrected by hand. Same generator gap hit Paint.NET in #50340.

**Dependency.** The manifest declares `Microsoft.VCRedist.2015+.x64`.
The ingester ignores winget `Dependencies`, but unlike HandBrake
(#50323) we do ship a matching FMA (`vc-redist-x64/windows`), and the
redistributable is present on most Windows hosts already. Noting it
rather than treating it as a blocker.

# Checklist for submitter

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


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

## Summary by CodeRabbit

* **New Features**
* Added Microsoft ODBC Driver 17 for SQL Server to the maintained
software catalog.
* Added Windows installation and upgrade support for version 17.11.1.1.
  * Added the software’s icon and catalog display details.
* Included silent installation, logging, license acceptance, and reboot
handling.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 00:30:07 -05:00