Commit Graph
26665 Commits
Author SHA1 Message Date
ecdf1ff003 Add TeamViewer Host as a Windows Fleet-maintained app (#50553)
**Related issue:** Resolves #50332

Adds **TeamViewer Host** as a Windows Fleet-maintained app.

## The issue's premise was wrong — this needed no new capability

#50332 was blocked on "not in winget." It is in winget:
`TeamViewer.TeamViewer.Host`, published continuously since **June 2023**
(v15.42.8), currently **15.80.4** (merged upstream as
microsoft/winget-pkgs#409335, 2026-07-29). I downloaded the live x64
installer and its SHA256 matches that manifest byte-for-byte.

It reads as absent because it's nested a level deeper than you'd expect
— `manifests/t/TeamViewer/TeamViewer/Host/`, a sibling of the full
client's *version* directories rather than of the publisher's package
directories.

Consequence: this comes off the dependency on #50364, and that FR loses
one of its three examples. The other two (#50328, #50329, OLE DB Driver
18/19) still hold — there is no OLE DB package under any winget
publisher.

## Identity verified against the installer, not winget metadata

Per the `new-fma` golden rule, from the x64 MSI's `Property` and
`Registry` tables:

| Field | Value | Evidence |
|---|---|---|
| `unique_identifier` | `TeamViewer Host` | MSI `ProductName`; no
`ARPDISPLAYNAME`, empty `Registry` table, so this is the ARP DisplayName
|
| publisher | `TeamViewer` | MSI `Manufacturer`, equal to the winget
locale `Publisher` → no `program_publisher` override |
| `installer_scope` | `machine` | `ALLUSERS=1` |
| bootstrapper? | No | no `ARPSYSTEMCOMPONENT` |

Corroborated independently by [silentinstallhq's PSADT
script](https://silentinstallhq.com/teamviewer-host-install-and-uninstall-powershell/),
which detects the app with `Get-InstalledApplication -Name 'TeamViewer
Host'` and uses `/S` for both install and uninstall.

Generated exists query:

```sql
SELECT 1 FROM programs WHERE name = 'TeamViewer Host' AND publisher = 'TeamViewer';
```

No collision with the existing `teamviewer/windows` FMA, which generates
an exact `name = 'TeamViewer'`.

## Why exe + `ignore_hash`, matching the full client

winget offers Host as an NSIS exe and as a nested `wix` MSI inside a
zip. The ingester can't select the zip (`installer.InstallerType` is
`zip`, which never normalizes to `msi`), so the exe is the only
reachable installer.

TeamViewer publishes no version-pinned Host exe —
`TeamViewer_Host_Setup_x64_15.80.4.exe` and the x86 equivalent both 404
— so the manifest's URL is the unpinned `TeamViewer_Host_Setup_x64.exe`
and `ignore_hash: true` is required. This is vendor asymmetry, not a
fixable winget defect: the *full* client does publish pinned exe URLs.
Same reason `teamviewer/windows` already sets `ignore_hash`.

## Correcting the coexistence note in #50332

The issue assumed Host and the full client can co-exist. They can't. The
Host MSI's `LaunchCondition` table blocks the install outright:

> Error 25001: An incompatible TeamViewer package was detected that
conflicts with the current MSI package: TeamViewer_Full 64-bit. Please
manually uninstall this package.

…plus equivalents for Full 32-bit/ARM64, Host ARM64, and the NSIS
installs. **Relevant to validation: the validator host must not already
have `teamviewer/windows` installed.**

## Icons

No `index.ts` change needed — `matchLoosePrefixToKey` treats keys as
whole words at the start, so `"teamviewer host"` matches the existing
`teamviewer` key and inherits the TeamViewer brand icon. Verified
against the real 1,163-key map.

The website resolves its icon from the slug
(`app-icon-${slug}-60x60@2x.png`) with no such fallback, so
`app-icon-teamviewer-host-60x60@2x.png` is added — a copy of the
existing TeamViewer brand asset, since Host ships the same logo.

## Two things for review

1. **The PowerShell is unverified.** Authored on macOS with no
PowerShell available, so install/uninstall have not been executed. The
uninstall script searches ARP by DisplayName instead of a hardcoded key,
and uses the three-shape `UninstallString` parser (TeamViewer's is
unquoted and contains a space in `C:\Program Files\...`, which the older
`.Split('"')` approach in `teamviewer_uninstall.ps1` mishandles).
Validator run is the real check.
2. **Category mismatch with the macOS side.** This uses `Communication`,
matching the merged `teamviewer/windows`. #47121 adds
`teamviewer-host/darwin` with `Productivity`. Worth reconciling — and
that PR will want this same website PNG, so expect a trivial conflict.

`name` is `TeamViewer Host`, matching #47121 so both platforms group
together in the FMA library.

## Testing

- [x] `go test ./cmd/maintained-apps/... ./ee/maintained-apps/...`
passes
- [x] Generator is idempotent — re-running produces no diff and
preserves the `apps.json` description
- [x] `apps.json` is valid JSON with no empty descriptions
- [x] Live installer SHA256 confirmed against the winget manifest
- [ ] FMA validator: install → detect → uninstall on a Windows host
**(pending — needs a host without the full TeamViewer client)**

No shared code changed.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Co-authored-by: Allen Houchins <allenhouchins@mac.com>
2026-08-05 14:04:49 -05:00
Allen Houchins 92aaf1de81 Fix Steam patch policy comparing an empty bundle_short_version (#50428)
**Related issue:** Resolves #50408

## What changed

Steam.app ships without a `CFBundleShortVersionString`, so osquery's
`apps.bundle_short_version` is an empty string:

```
$ /usr/libexec/PlistBuddy -c "Print :CFBundleShortVersionString" /Applications/Steam.app/Contents/Info.plist
Print: Entry, ":CFBundleShortVersionString", Does Not Exist
$ /usr/libexec/PlistBuddy -c "Print :CFBundleVersion" /Applications/Steam.app/Contents/Info.plist
6.0
```

The generated patch policy compared that column, and
`version_compare('', '6.0')` returns `-1`, so the `< 0` predicate was
always true. The "Steam up to date" policy could never pass on **any**
host with Steam installed, at any version. Meanwhile software inventory
falls back to `bundle_version` and correctly showed Steam as up to date,
so the two features disagreed about the same app on the same host — and
with `install_software: true` the policy repeatedly reinstalled a
version that was already installed.

This adds a per-app override in the homebrew ingester comparing
`bundle_version` (CFBundleVersion `6.0`, which the cask version tracks),
following the pattern already used for `sonos` and the Firefox
pre-release channels:

```diff
-version_compare(bundle_short_version, '6.0') < 0
+version_compare(bundle_version, '6.0') < 0
```

`ee/maintained-apps/outputs/steam/darwin.json` was regenerated with `go
run ./cmd/maintained-apps -slug steam/darwin` — one line changed, no
upstream version drift pulled in.

## Why scoped to one app

The issue suggested changing the shared darwin version column in
`pkg/patch_policy` to `COALESCE(NULLIF(bundle_short_version, ''),
bundle_version)`. I didn't do that. It would be a no-op for the ~300
macOS FMAs that do set a short version, but that generator is
load-bearing for every one of them, and the blast radius isn't justified
by a single broken app. The per-app override is the established
mechanism for exactly this.

Side note for a possible follow-up: `patch_policy_path` exists in both
the homebrew and winget input structs but is never read anywhere — a
dead field. If we want a data-driven way to express these overrides
instead of token checks in Go, that's the hook.

## Reviewer note: existing deployments do not self-heal

`software_installers.patch_query` is snapshotted when the installer is
created, and only refreshes on an FMA version change or an "Edit
software" save. **Steam's cask version is a static `6.0`**, so this
manifest change alone will not fix already-deployed Steam FMAs — the
admin has to re-add or re-save the app. A GitOps re-apply doesn't help
either; `ApplyPolicySpecs` regenerates from the stale installer row.

Closing that gap means either a migration that rewrites stored patch
queries, or refreshing `patch_query` when the manifest changes at the
same version. Both are broader calls than this bug, so I left them out —
happy to file a follow-up if you want it tracked.

The exists query is unaffected — it matches on `bundle_identifier` only,
with no version predicate. That's why install detection and self-service
always worked correctly for Steam.

# 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. <sub>No new interpolation surface: the override formats
the same bundle identifier and cask version the surrounding generator
already formats.</sub>

## Testing

- [x] Added/updated automated tests <sub>New `steam` case in
`TestIngestApps` asserting both the patched and exists queries.</sub>

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

Validated with osquery **5.23.1** — the same version as in the bug
report. `version_compare('', '6.0')` returns `-1` and
`version_compare('6.0', '6.0')` returns `0`, confirming the root cause
directly.

For an end-to-end check against the real `apps` table without planting a
fake Steam.app on a Fleet-enrolled host, I used an already-installed app
with the identical shape (`com.citrix.HDXCast`: empty
`bundle_short_version`, `bundle_version` `24.05.0.3`):

| Query | Host state | Result |
|---|---|---|
| exists | app installed | row → detected  (unaffected by the bug) |
| **old** patched | up to date | **no row → policy FAILS** ← reproduces
the bug |
| **new** patched | up to date | row → policy PASSES  |
| **new** patched | genuinely outdated (available `25.0.0`) | no row →
policy FAILS  |
| **new** patched, verbatim from the regenerated manifest | Steam not
installed | row → PASSES  |

The fourth row is the important one: the fix is not a blanket pass — it
still fails hosts that are genuinely behind.

Not verified: a live host with Steam actually installed (I don't have
one). The `com.citrix.HDXCast` row has byte-identical column semantics,
so I'm confident, but a QA pass on a real Steam host would close it out.

`go test ./cmd/maintained-apps/... ./pkg/patch_policy/...
./ee/maintained-apps/...` passes; `go vet` and `gofmt` clean. I could
not run `make lint-go-incremental` locally — it builds a custom
golangci-lint via `git clone`, which my sandbox blocked, so I'm relying
on CI for that.


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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved Steam patch detection on macOS by using the correct
application version information.
* Steam updates are now accurately recognized in Fleet software
inventory and Homebrew-generated patch policies.


<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 13:38:20 -05:00
Allen Houchins b8e324383d Document the build-enforced 150-char meta description limit in content skills (#50166)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** N/A

# Checklist for submitter

This PR only edits Claude Code skill files under `.claude/` — no product
code, so most of the template below doesn't apply.

## What changed

Documents the **build-enforced 150-character limit on `<meta
name="description">`** in the content skills that generate that tag.

`website/scripts/build-static-content.js:687` throws `An article page
has an invalid description meta tag` and fails the entire production
build for any page whose description exceeds 150 characters, regardless
of category. Before this PR:

- `fleet-article-formatting` never mentioned the limit at all. It had
**no endmatter section whatsoever**, and `assets/article-template.md`
shipped `<meta name="description" value="">` with no guidance in the
placeholder.
- `fleet-guide-formatting` and
`content-style/references/content-types.md` stated "150 chars max" as
what reads like a style preference, with no indication that going over
breaks the deploy.

So a draft could satisfy every skill self-check and still fail the
build.

Changes:

- **`fleet-article-formatting/SKILL.md`** — new `### Endmatter` section
covering the 150-char limit (naming the enforcing script and the error
message), `articleTitle` matching the H1 exactly, and the no-fabrication
rule for `authorFullName`/`authorGitHubUsername`/`publishedOn`. Added a
matching self-check bullet.
- **`fleet-article-formatting/assets/article-template.md`** — filled in
the empty `description` placeholder with the constraint.
- **`fleet-guide-formatting/SKILL.md`** — the two existing 150-char
mentions now say build-enforced and name the failure mode.
- **`content-style/references/content-types.md`** — same note on the
shared endmatter block both skills point at, so it's stated once at the
source.

Each spot also says to **count** the characters rather than estimate,
which is the actual failure mode: a description that reads like one or
two natural sentences lands just over 150 more often than you'd expect.

## Why

Found the hard way. A case study drafted in
[#50152](https://github.com/fleetdm/fleet/pull/50152) had a
153-character description that read as perfectly reasonable length and
broke `npm run build-for-prod`:

```
Error: Failed compiling markdown content: An article page has an invalid description meta tag
(<meta name="description" value="Hawx automated seasonal iOS onboarding and offboarding with Fleet,
Tines, and Okta, eliminating start-of-season helpdesk floods in a one-month migration.">)
at ".../articles/hawx.md". To resolve, make sure the value of the meta description is less
than 150 characters long.
```

The limit is cheap to respect while drafting and annoying to discover at
deploy time, so it belongs in the skills that write the tag.

## Note for reviewers

The proposed `fleet-case-study-formatting` skill in
[#49917](https://github.com/fleetdm/fleet/pull/49917) is **not touched
here**, deliberately, to avoid a conflict with that open PR. Its
`assets/case-study-template.md` already says "150 chars max" in the
description placeholder, though its `SKILL.md` doesn't mention the
limit. Worth adding the build-enforcement note there before that PR
merges, in that PR rather than this one.

- [ ] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`. — N/A, Claude Code
config only, not a product change

## Testing

- [ ] Added/updated automated tests — N/A, markdown/config only
- [x] QA'd manually:
- Traced the constraint to its source at
`website/scripts/build-static-content.js:687` and confirmed the quoted
error text and the `> 150` comparison, so the skills describe real
behavior rather than a remembered rule.
- Confirmed the check applies to all categories (it runs before the
`category === 'case study'` branch), which is why the note went in the
shared `content-types.md` block too.
- Scanned every `<meta name="description">` across `articles/`, `docs/`,
and `handbook/`: **0 pages currently exceed 150 characters**, so this is
preventive documentation only and no existing content needs fixing.
- Read the edited skill files back end-to-end for correct rendering and
no contradictions with surrounding guidance.
2026-08-05 13:38:09 -05:00
Jordan Montgomery 117a7ba1f4 Fix reliability around osquery-perf MDM enrollment (#49687)
<!-- 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.

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops
- [x] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

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

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



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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved macOS, iOS, and iPadOS MDM enrollment reliability by
automatically retrying failed enrollment attempts.
* Added randomized delays between retries to support more resilient
startup behavior.
* Improved handling of user identity generation during macOS MDM
enrollment.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 14:06:58 -04:00
Konstantin Sykulev 6613872eda Terraform for mock AMAPI for loading testing (#48919)
Related issue: Resolves https://github.com/fleetdm/fleet/issues/26225

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

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

- **New Features**
  - Added an Android AMAPI mock service for load testing.
- Added configurable image version selection and optional Google API
request forwarding.
- Added routing for mock and API requests through the internal load
balancer.
- Added secure storage and optional access to Google service-account
credentials.
- Exposed the mock service endpoint for downstream load-test
configuration.
- Configured the load-testing environment to use the new internal proxy
endpoint.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 13:04:19 -05:00
Noah Talerman 34532588c6 Update community PR review process (#50601) 2026-08-05 12:34:00 -05: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
Dante Catalfamo c9001b4e46 Document Android biometric unlock behavior on BYOD work profiles (#50265)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #49655

Documentation-only change. No server behavior changes.

## What's happening

On a personally-owned work profile (BYOD), Android applies the biometric
values of `keyguardDisabledFeatures` to the work profile lock. By
default the end user has one lock for both the work profile and the host
("Use one lock"), so there is no separate work profile lock to restrict,
and Android restricts the host's lock instead. Fingerprint and face
unlock turn off for the whole host, including the end user's personal
apps.

This is documented Android behavior, per
[`setKeyguardDisabledFeatures`](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setKeyguardDisabledFeatures(android.content.ComponentName,%20int)):

> `KEYGUARD_DISABLE_FINGERPRINT`, `KEYGUARD_DISABLE_FACE` or
`KEYGUARD_DISABLE_IRIS` which affects the managed profile challenge if
there is one, **or the parent user otherwise**.

Fleet never sets `keyguardDisabledFeatures` itself. Fleet's default
Android policy sets only `StatusReportingSettings`, and admin-authored
AMAPI policy is passed through as-is. The reason this still lands on
Fleet is that the profile in the bug report is byte-for-byte the example
Fleet publishes at
`docs/solutions/android/configuration-profiles/disable-face-and-biometrics-unlock.json`,
with no note about the BYOD side effect.

## What changed

- `articles/custom-os-settings.md`: new "Biometric unlock on
personally-owned (BYOD) hosts" subsection under "Special Android
behavior", covering the behavior and the configuration that scopes the
restriction to work.
- `docs/solutions/android/configuration-profiles/README.md`: entries for
the biometrics profile (carrying the caveat) and for the new example.
-
`docs/solutions/android/configuration-profiles/require-separate-work-profile-lock.json`:
new example using `passwordScope: SCOPE_PROFILE` and
`unifiedLockSettings: REQUIRE_SEPARATE_WORK_LOCK`.

The remedy needs no Fleet change: `passwordPolicies` is already in the
Android policy field mask
(`server/mdm/android/service/androidmgmt/policy_field_mask_test.go`), so
Fleet already delivers it.

## Testing

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

Docs-only, so no automated tests were added. Verification done:

- Both the new example profile and the combined snippet in the guide
decode into the real `androidmanagement.Policy` struct with
`DisallowUnknownFields`, confirming every key and nesting level matches
the AMAPI schema Fleet ships.
- The documented status flow (`USER_ACTION` non-compliance on
`passwordPolicies` marks the profile "Failed", then "Verified" once the
end user sets the work lock) is confirmed against
`server/mdm/android/service/pubsub_test.go`.

**Not yet verified on hardware.** I have not run the repro on a physical
BYOD Android host. Before merge, this is worth confirming:

1. On a BYOD Android host with fingerprint unlock configured and a work
profile enrolled, apply `disable-face-and-biometrics-unlock.json`.
Confirm fingerprint disappears as an unlock method device-wide.
2. Add the `passwordPolicies` block from
`require-separate-work-profile-lock.json` to that profile and re-upload.
Confirm Android prompts for a separate work profile lock, and that Fleet
shows the profile "Failed" with `USER_ACTION` on **Host > OS settings**
until the end user sets it.
3. After the end user sets the work lock, confirm the profile moves to
"Verified", fingerprint unlock works again on the personal side, and the
work profile still requires PIN/password.


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

## Summary by CodeRabbit

* **New Features**
* Added an Android configuration profile option that requires a separate
lock for the work profile.
* Applies password policy settings specifically to the work profile
scope.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 13:18:26 -04:00
Allen HouchinsandClaude 5ec4c650d3 Update Evernote maintained app to 11.28.2 (#50583)
**Related issue:** Resolves #

# Checklist for submitter

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

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

## Summary

Bumps the Fleet-maintained Evernote (macOS) app from `11.27.5` to
`11.28.2`, the latest version per the [Evernote release
notes](https://evernote.com/release-notes).

- Updated `version` and the embedded `version_compare` target in the
`patched` osquery query in
`ee/maintained-apps/outputs/evernote/darwin.json`.
- `installer_url` and `sha256` are unchanged — Evernote's DMG installer
link always serves the latest build (`sha256: "no_check"`).
- `inputs/homebrew/evernote.json` is frozen and untouched, as required.

---
_Generated by [Claude
Code](https://claude.ai/code/session_015tHhSdANCAv2WdENhRF4hf)_

Co-authored-by: Claude <noreply@anthropic.com>
2026-08-05 12:18:23 -05:00
fleet-releaseandallenhouchins 935118d2ab Update Fleet-maintained apps (#50594)
Automated ingestion of latest Fleet-maintained app data.

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

## Summary by CodeRabbit

* **Updates**
* Updated Akiflow, Lulu, PDFsam Basic, and TextExpander for macOS to
their latest releases.
  * Updated Claude and Rancher Desktop for Windows to newer versions.
  * Updated Firefox Nightly for macOS to the latest nightly build.
* Refreshed installer details and verification data to support the
updated packages.

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

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
2026-08-05 12:16:24 -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
Eric 1563aeb70c Website: improve speed of deliver-talk-to-us-form-submission action (#50593)
Changes:
- Updated the model used in the prompt helper calls in the
deliver-talk-to-us-form-submission action and the get-enriched helper to
improve the speed of routing users booking a demo.

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

## Summary by CodeRabbit

* **Improvements**
* Updated location and address enrichment to use an updated language
model, improving the processing of submitted information while
preserving existing form behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 11:42:13 -05:00
c24983294e Update Fleet server config documentation for local storage (#50489)
Related: #39896

Context: 

I found that we use `FLEET_SOFTWARE_INSTALLER_STORE_DIR` env variable in
[render.yaml](https://github.com/fleetdm/fleet/blob/9b51376f83af8c7c2b2335ff0a1ab146ae13238f/render.yaml#L15).
S3 is the best practice and should be used in production, we even have a
[log](https://github.com/fleetdm/fleet/blob/9d0f510a8db6a470ecf83cc0076680c4d518ea7e/cmd/fleet/serve.go#L568)
that says that.

Since we officially support Render deployment, and Render doesn't
support S3, I think we should document this exception.

More context:
https://fleetdm.slack.com/archives/C051QJU3D0V/p1785496835774739

---------

Co-authored-by: Noah Talerman <47070608+noahtalerman@users.noreply.github.com>
Co-authored-by: Robert Fairburn <8029478+rfairburn@users.noreply.github.com>
2026-08-05 11:22:55 -05:00
RachelElysia 8d616e31cb Fleet UI: Flush Self-service search right without Install all button (#50534) 2026-08-05 09:15:15 -07:00
Noah Talerman 30c8362e0e Update sprint review ritual (#50580)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **Documentation**
* Updated the Product Design review ritual guidance to cover Drafting
board cleanup, milestone updates, and Feature fest board preparation.
* Removed outdated steps related to unestimated and discontinued
stories.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 12:08:55 -04:00
fleet-releaseandallenhouchins d2fe9be461 Update Fleet-maintained apps (#50584)
Automated ingestion of latest Fleet-maintained app data.

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

## Summary by CodeRabbit

* **Updates**
  * Updated Graphviz for Windows to version 15.1.1.
  * Updated PDFsam Basic for Windows to version 6.0.5.0.
  * Updated Visual Studio Code for macOS to version 1.132.0.
  * Updated Wavebox for macOS ARM to version 151.2.148.2.
  * Updated WhatsApp for macOS to version 26.31.19.
  * Refreshed installer details and version checks where applicable.

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

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
2026-08-05 10:23:17 -05:00
fleet-releaseandallenhouchins 72c224bd78 Update Fleet-maintained apps (#50574)
Automated ingestion of latest Fleet-maintained app data.

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

## Summary by CodeRabbit

* **Updates**
* Refreshed supported macOS and Windows application packages to their
latest releases, including Asana, Chrome, Dropbox, Microsoft 365,
Postman, Thunderbird, Todoist, and many others.
* Updated version detection so devices recognize the new releases and
receive applicable upgrades.
  * Refreshed installer downloads and verification data where required.
* Updated installation instructions for selected applications, including
Duo Desktop, Microsoft Office, Nextcloud, Nudge, Santa, and Tailscale.

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

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
2026-08-05 09:14:46 -05:00
Magnus Jensen 1abeb175f3 AULD: Enrollment insert and backfill osquery query (#50131)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #47714 

# 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. (Will be part of another PR)

- [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**
* Collect and persist macOS software update device identifiers for hosts
during both manual and OTA enrollment flows.
* Added an osquery detail/query to derive the identifier from hardware
properties and upsert it into datastore.
* **Bug Fixes**
* Host deletion now also removes related Apple macOS OS update records.
* **Improved Device Recognition**
* Enhanced Mac model identifier parsing and refined Apple Silicon
detection with expanded test coverage.
* **Reliability**
* Enrollment profile delivery remains unaffected if saving the
identifier fails (errors are logged).
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 15:37:05 +02:00
Andrew MellorandMagnus Jensen 192ac4eb51 48093 auld api gitops latest os version (#50213)
**Related issue:** Resolves #48093

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


## 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 that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)


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

* **New Features**
* Added “latest” version enforcement for macOS, iOS, and iPadOS updates
using required `deadline_days`.
* Updates dynamically target each device’s available OS version and
deadline.
  * Configuration and GitOps outputs now include `deadline_days`.

* **Bug Fixes**
* Improved validation when switching update modes or omitting deadline
settings.
* GitOps updates now clear previously stored deadline values when
omitted.
  * Changes to `deadline_days` are detected and applied consistently.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Magnus Jensen <magnus@fleetdm.com>
2026-08-05 12:37:11 +01:00
Rajendra Kadam 5e95589554 Support custom activations and management declarations for DDM profiles (#50280)
**Related issue:** Resolves #49970

Adds custom activations to the single-profile paths for declaration
(DDM) profiles — create, edit, delete and read — and unblocks management
declarations. Part of #48222.

Batch/GitOps is #49972; serving the custom activation to devices is
#49971.

### Custom activations

- `POST /configuration_profiles` and `PATCH
/configuration_profiles/{uuid}` accept an optional `activation` file
part, rejected for any profile type other than an Apple declaration.
- Validation requires an activation `Type` (any
`com.apple.activation.*`, so future Apple types need no Fleet change),
an `Identifier`, and exactly one `StandardConfigurations` entry naming
the configuration it ships with. `Predicate` and every other key are
stored and served verbatim for the device to evaluate.
- Premium-only, unconditionally. `parseAndValidateAppleDeclaration`
requires premium only when a fleet or labels are involved, so an
unassigned unlabeled DDM profile is free today; the activation carries
its own gate.
- The activation's Fleet variables are validated against
`fleetVarsSupportedInDDMDeclarations` — already exactly the set
specified for activations — and associated via
`mdm_configuration_profile_variables.apple_ddm_activation_uuid`.
- Returned base64-encoded on both the list and single-profile endpoints,
per the API reference draft (#49768), and omitted entirely when absent.

What an edit does to a stored activation:

| Request | Result |
| --- | --- |
| activation supplied | replaces the stored one |
| new profile content, no activation | stored one is cleared — this is
how it's removed |
| labels-only edit | stored one is carried forward |

The third row matters: the datastore clears the activation of any
declaration written without one, so a labels-only edit rebuilding the
declaration from the existing row would otherwise silently wipe it.
`GetMDMAppleDeclaration` loads the activation so it can be carried
forward, and there's a test asserting it.

### Management declarations

`com.apple.management.*` uploads are unblocked via a prefix check, so
future management declarations work without a product change. Types to
block go in the existing `ForbiddenDeclTypes` deny list, which is
already evaluated ahead of the prefix. An activation supplied alongside
a management declaration is rejected — those are never activated.

Routing them to the manifest's Management section is #49971's work.

### Notes for review

**Where the non-declaration guard lives differs by path, deliberately.**
Create resolves the profile type in the endpoint from the uploaded file;
edit resolves it in the service from the UUID prefix. The check sits
wherever the type becomes known. Both use the same message so the
mistake reads identically.

**Endpoint-level errors must be returned from behind an authz check.**
The create-path guard originally returned the error straight from the
endpoint, which skips authorization and surfaces to the client as a bare
`forbidden` rather than the validation message. It now goes through
`NewMDMActivationUnsupportedProfile`, alongside the existing
`NewMDMUnsupportedConfigProfile` and `NewMDMInvalidJSONConfigProfile`,
which exist for the same reason. This was caught by the integration
tests, not the unit tests — service-level tests bypass the authz
middleware.

**Activation rows are keyed on `declaration_uuid`, not inserted fresh.**
An edit reuses the row, so the Fleet variable associations hanging off
it survive. The UUID is read back after the upsert rather than reusing
the generated one, since `ON DUPLICATE KEY UPDATE` keeps the existing
row.

**Secrets are expanded for validation but stored unexpanded**, so
validation runs against the document the device receives without
persisting secret values.

`MDMAppleCustomActivation` is the storage type; `MDMAppleDDMActivation`
was already taken by Apple's wire format.

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

No changes file: the feature isn't reachable by users until the DDM sync
work in #49971 lands.

## Testing

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

**Unit** (`server/fleet`): `GetRawActivationValues` and
`ValidateUserProvided` — valid activation, unknown type under the
activation prefix, missing `Type`, a configuration type supplied as an
activation, missing `Identifier`, zero/multiple/mismatched
`StandardConfigurations`, all problems reported at once, plus
`IsManagementDeclaration`.

**Service** (`server/service`): activation accepted, mismatched
configuration rejected, malformed JSON rejected, rejected on a
management declaration, supported Fleet variables recorded, unsupported
rejected, premium required even where the declaration is free. On edit:
activation-only edit keeps content, labels-only edit preserves the
activation, new content without an activation clears it, and exactly one
`edited_declaration_profile` activity fires.

**Datastore** (`server/datastore/mysql`): write, read-back through list
and single get, edit reusing the row, Fleet variable association, and
removal cascading to the variable rows.

**Integration** (`integration_mdm_ddm_test.go`): multipart upload with
an activation, read back and asserted base64-decoded against the raw
response body; the key omitted entirely for a declaration without one;
two management declarations uploaded and coexisting; activation on a
`.mobileconfig` rejected on both create and edit; activation-only
`PATCH` replacing the activation while leaving the declaration
untouched.

The multipart test helper now supports more than one file part — nothing
could build that request before, which is why the decode path was
previously untested. Single-file callers are unchanged.


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

- **New Features**
- Added optional custom activations for Apple DDM configuration
declarations.
- Activations support secrets, Fleet variables, and custom host vitals.
- Activation data appears when viewing or downloading applicable
profiles.
- Activation files can be added, updated, preserved during label-only
edits, or removed during content replacement.
- Management declarations can coexist with supported configuration
declarations.

- **Validation**
- Added checks for declaration matching, supported profile types, file
limits, and Premium licensing.
- Clear errors are provided when activations are used with management
declarations or non-DDM profiles.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 15:29:52 +05:30
33b4efe9c1 Update install script and Fleet-maintained apps (#50499)
Automated ingestion of latest Fleet-maintained app data.

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

## Chores

* Updated numerous maintained application definitions with newer
releases, download links, version checks, and checksums across Windows
and macOS.
* Improved Windows installation reliability by recognizing successful
installations that require a restart.
* Corrected installer log-path handling for paths containing spaces.
* Refreshed metadata for applications including Firefox, Docker Desktop,
Discord, Tailscale, and many others.
* Adjusted Google Credential Provider validation settings to support its
installer distribution.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
Co-authored-by: Allen Houchins <allenhouchins@mac.com>
2026-08-04 22:16:49 -05:00
Eric 85692f8238 Website: set historical event source (#50546)
Changes:
- Updated the website's createHistoricalEvent helper to accept an
eventSource input that is used to set the historical event source on
created records.
- Updated places where we create historical events to set a historical
event source
- Updated the accepted contact sources values in the receive-from-clay
webhook
- Updated the deliver-gitops-workshop-request action to log a warning
when a campaign member record cannot be created

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

- **Improvements**
- Improved activity tracking for newsletter subscriptions, signups,
contact forms, workshop requests, webinars, gated content, and page
views.
- Added clearer source details to records for more accurate attribution.
- Expanded support for website, webinar, event, LinkedIn, prospecting,
and GitHub activity sources.
- **Bug Fixes**
- Workshop requests now continue successfully if campaign updates
encounter an error.
- Corrected warning messages and preserved relevant submission details
for troubleshooting.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 18:26:14 -05: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
Victor Lyuboslavsky bd601fff84 Fixed nilaway issues (#50405)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #50404 

- Refactored `ListHostSoftware` and `ModifyAppConfig` functions beeing
too big for nilaway
- Added a hard check to make sure all our funcitons/packages are being
analyzed by nilaway

# Checklist for submitter

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

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

## Testing

- [x] Added/updated automated tests

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


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

* **Improvements**
* Improved software inventory filtering for self-service and macOS
applications, producing more accurate results.
* Improved application configuration updates so saved settings and
related system changes are processed more reliably.
* **Quality**
* Added automated checks to identify overly complex functions and help
maintain code quality.
* Updated static analysis tooling and expanded validation coverage with
new tests.
* **Documentation**
* Added a changelog entry describing the latest reliability and
maintainability improvements.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 15:41:18 -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
Lucas Manuel Rodriguez 967d5e69b5 Add lucasmrod to orchestration understanding host vitals (#50492)
Adding myself to help review the changes to the Understanding Host
Vitals documentation (sometimes blocking PRs from being merged).

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

## Summary by CodeRabbit

* **Chores**
* Updated review ownership for the host vitals documentation to include
an additional required reviewer.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 16:10:27 -03:00
Sharon Katz a5199593fb Update community contributions process for AI-driven workflow (#50258) 2026-08-04 13:07:39 -05:00
George Karrandtest 1a1e76b012 adding watch for npm publish to release script (#50093)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

* **New Features**
* Added an option to resume release publishing after changelog
generation fails.
* Added registry verification to confirm package availability before
continuing publication.

* **Workflow Improvements**
* Release publishing now provides manual instructions for package login
and publishing.
* Supports checking package availability under the selected release tag.

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

Co-authored-by: test <test@test.com>
2026-08-04 13:05:25 -05:00
dependabot[bot] 49c0e80b77 Bump fast-uri from 3.1.4 to 3.1.5 in /tools/fleet-slackbot (#50505) 2026-08-04 13:04:16 -05:00
dependabot[bot] f9b9fefed1 Bump fast-uri from 3.1.4 to 3.1.5 (#50501) 2026-08-04 13:03:58 -05:00
dependabot[bot] 4e7cebf5ac Bump hono from 4.12.32 to 4.13.0 in /tools/fleet-slackbot (#50500) 2026-08-04 13:03:30 -05:00
Gray WilliamsandRachael Shaw be48a82d16 Update fleet-server-configuration.md adding allow_private_network (#50422)
Adds the `server_allow_private_network_integrations` flag information

For #49727

---------

Co-authored-by: Rachael Shaw <r@rachael.wtf>
2026-08-04 11:54:18 -05:00
Lucas Manuel Rodriguez e35e30751c Remove stale Prometheus example config link from reference architectures doc (#50302)
Removes the link to the example Prometheus config
(`tools/app/prometheus.yml`) from the reference architectures doc, since
that file is being removed in #50053.

Split out of #50053 so the docs change can be reviewed separately.

# Checklist for submitter

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

- [x] Documentation-only change; no changes file, tests, or QA needed.
2026-08-04 11:49:46 -05:00
Dante Catalfamo f17c8cbd8d Bound Google Workspace directory sync pagination (#50092)
**Related issue:** Resolves #49365
2026-08-04 11:36:02 -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
dependabot[bot] 09d2431055 Bump ip-address from 10.2.0 to 10.4.0 in /tools/fleet-slackbot (#50480) 2026-08-04 09:56:38 -05:00
Luke Heath 7cd67856aa Fix medium-severity code scanning alerts (#50346) 2026-08-04 09:56:00 -05:00
Allen Houchins 4d6dbf8639 Fix Gpg4win FMA ingest panic after winget relabeled 5.1.0 as x64 (#50494)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** NA — caught from a failing `Update Fleet-maintained
apps` ingest run.

# What this does

Changes `installer_arch` from `x86` to `x64` for the Gpg4win Windows
FMA, and regenerates its output (5.0.2 → 5.1.0).

## Why the ingest was failing

```
{"level":"INFO","msg":"ingesting winget app","name":"Gpg4win"}
panic: ingesting winget app: failed to find installer for app
```

This is **not** a removed winget package — Gpg4win is still published as
`GnuPG.Gpg4win`. The manifest was fetched and parsed fine; the failure
is the `selectedInstaller == nil` check in
`ee/maintained-apps/ingesters/winget/ingester.go`, which means no
installer entry matched all four selector fields from our input.

Upstream flipped the architecture label between versions:

| | 5.0.2 (last ingested) | 5.1.0 (new) |
|---|---|---|
| `Architecture` | **x86** | **x64** |
| Manifest generator | `wingetcreate 1.10.3.0` | `YamlCreate.ps1
Dumplings Mod` |

Our input pinned `x86` to match 5.0.2, so nothing matched once 5.1.0
landed in `winget-pkgs` (2026-08-03 18:11 UTC,
microsoft/winget-pkgs#409397). The ingester only walks to an older
version directory on a genuine 404 of the installer manifest — never
because the newest version's installer failed to match — so it panics
instead of falling back.

## The new x64 label is the correct one

Verified against the real installer rather than trusting either
manifest:

- The NSIS stub's PE header is i386, which is very likely what
`wingetcreate` guessed `x86` from. Installer stubs are almost always
32-bit, so stub arch says nothing about the payload.
- The payload ships 64-bit binaries in `bin/` (PE machine `0x8664`)
alongside a 32-bit `bin_32/` compatibility set.

So 5.0.2's `x86` was the inaccurate manifest and the bot corrected it.
Regenerated `sha256` also matches a fresh download of
`gpg4win-5.1.0.exe` bit-for-bit (`9682f282…20a2e`).

## Blast radius

Worth flagging: this one field blocked **the entire FMA ingest**, not
just Gpg4win. `failed to find installer for app` isn't matched by
`isTransientGitHubError`, so it returns up to `panic(err)` in
`cmd/maintained-apps/main.go`, which aborts the process before
`processOutput` writes *any* app's manifest. Because the `ingesters` map
is iterated in random order, this could take out the homebrew side too.
Any future upstream flip of `installer_arch` / `installer_scope` /
`installer_type` / `installer_locale` on any single app will do the same
thing — worth a follow-up to make non-transient per-app ingest errors
skip-and-report instead of fatal.

## Why no changes file

The net user-visible effect is a routine FMA version bump (Gpg4win
5.1.0), which the scheduled ingest PR delivers without changelog
entries. Happy to add one if you'd rather it be called out.

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

- `go run ./cmd/maintained-apps -slug gpg4win/windows` completes with no
panic (previously fatal).
- Diff is scoped to the two expected files; `outputs/apps.json` is
untouched, since name/description didn't change.
- Regenerated `sha256` matches a fresh download of the upstream
installer.
- Install/uninstall scripts need no changes — both already enumerate the
native *and* `Wow6432Node` registry views across `HKLM`/`HKCU`, so
detection survives the 32→64-bit flip.
- `installer_arch` is only a manifest selector plus CI runner routing in
`.github/scripts/partition-fma-apps.sh`, where x64/x86/neutral all land
on the same x64 runner. No routing change, and the field is never
written into `outputs/`, so no user-visible arch claim changes.

Still needs the FMA validator's install/uninstall run on a Windows
runner to confirm 5.1.0 installs and is detected — that's what the draft
is for.
2026-08-04 09:50:53 -05: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
Juan Fernandez d92b7284d0 Trigger software_checksum_migration on startup
Relates #36365

Makes the software_checksum_migration cron to run
automatically on server startup.
2026-08-04 09:35:36 -04:00
melpike 8a11bd58db [Route] Update routes.js (#50472)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #48894 

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

## Summary by CodeRabbit

* **New Features**
* Added a redirect from `/learn-more-about/removal-behavior` to the
relevant section of the custom OS settings guide.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 07:11:56 -06:00
Marko Lisica 678d8b77ff Add notify command to Fleet Desktop for patch notification toasts (#50211)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** #49325

# Checklist for submitter

- [x] Timeouts are implemented and retries are limited to avoid infinite
loops

## Testing

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

## fleetd/orbit/Fleet Desktop

- [x] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes

macOS-only by construction — this is the native macOS app, which has no
other platform build.

No changes file: this app ships on its own release channel
(fleet-desktop-macos-v* → download.fleetdm.com), not the Fleet server
changelog, matching every previous PR to apps/fleet-desktop-macos/.


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

* **New Features**
  * Added macOS notification support through the `notify` command.
* Notifications appear as bottom-right toast messages with loading,
dismissal, timeout, and error handling.
* Added URL validation, clear usage guidance, and meaningful
command-line exit statuses.
  * Notification commands can run without opening the main app.

* **Bug Fixes**
* Improved single-instance handling for background notification
processes.
  * Improved detection of Fleet-rendered error pages.

* **Tests**
* Added developer tools for notification smoke testing and local
invocation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 14:54:10 +02: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
Lucas Manuel Rodriguez f053a9fd49 Allow enabling/disabling software inventory per-fleet via the API (#50481)
Resolves #45735.

- [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**
* Team settings can now enable or disable Software Inventory through API
updates.
* Partial updates preserve existing settings when the Software Inventory
option is omitted.
* Software Inventory configuration can be re-enabled after being
disabled.

* **Bug Fixes**
* Invalid or null Software Inventory values are handled correctly
without affecting global or Unassigned settings.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 08:48:32 -03:00
Juan Fernandez e529d97897 Fix duplicate software inventory entries from v4.76.0 checksum change
Resolves #36365

The v4.76.0 checksum change (#34097) reordered the fields hashed into
`Software.ComputeRawChecksum` for non-`apps` sources, so software rows
created before the upgrade no longer matched re-ingested rows and got
duplicated (same name/version/source, split host counts).

- Make `ComputeRawChecksum` the sole source of truth and delete the
drifted parallel SQL checksum formula that caused the mismatch.
- Add `ReconcileSoftwareChecksums`, a one-shot migration that merges
existing duplicates onto the canonical row (batched host_software
repointing) and logs each merge. Runs once after startup; re-run with
`fleetctl trigger --name software_checksum_migration`
2026-08-04 07:12:16 -04:00
Magnus Jensen 6ce0f70ebc Not Now edge case fixes for Apple profiles (#50044)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #47411 (Speculative, but we will keep
investigating if we get new reports)

# Checklist for submitter

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

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

- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.
- [x] Timeouts are implemented and retries are limited to avoid infinite
loops
- [x] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

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

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

- **Bug Fixes**
- Fixed Apple MDM profile handling for devices that respond with “Not
Now” by ensuring the response is issued only on first delivery and
doesn’t trigger repeated retries.
- Improved reconciliation so superseded InstallProfile commands are
properly canceled and cleanup is correct for user-scoped and pending
installs.
- When host verification fails after an acknowledged install, devices
now receive the appropriate RemoveProfile operation.
- **Tests**
- Added regression integration coverage for “Not Now” cancellation,
scope changes, profile edits, undelivered installs, and failed
verification cleanup.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 09:40:20 +02:00
Allen HouchinsandEric 19af21dd1a Upgrade query-generator SQL step to Claude Sonnet 5 (#49187)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** N/A

## What this does

The `/query-generator` page's osquery-SQL-generation step
([get-llm-generated-sql.js](website/api/controllers/query-generator/get-llm-generated-sql.js))
was on `claude-sonnet-4-6`, which is now one generation behind. This PR:

- Bumps that call to `claude-sonnet-5`. The schema-filtration step stays
on `claude-haiku-4-5`, which is already the latest Haiku release, so no
change needed there.
- Adds `effort` support to the shared [`ai.prompt`
helper](website/api/helpers/ai/prompt.js), forwarded as
`output_config.effort` on Anthropic requests, and sets it to `"low"` for
the SQL-generation call. Effort controls how much the model deliberates
(and how many tokens/how much latency that costs). `"low"` was chosen
because the Haiku pre-filtering step already narrows the osquery schema
down to relevant tables, so the Sonnet step isn't starting from scratch
and doesn't need to spend much effort re-deriving that context.
- Bumps `max_tokens` in the Anthropic branch of the helper from 4096 to
8192. Claude Sonnet 5 turns on adaptive thinking by default when the
`thinking` param is omitted (which this helper does), and `max_tokens`
is a hard cap on *total* output including thinking tokens — at 4096
there was a real risk of thinking tokens eating into the budget and
truncating the JSON response the SQL step needs to return.
- **Fixes a pre-existing bug found while making the above changes:** the
`sqlReport` call passed the system prompt as a bare object-shorthand key
named `systemPromptForQueryGeneration`, but the `ai.prompt` helper's
declared input is `systemPrompt`. Sails silently drops unrecognized keys
passed to `.with(...)`, so the "Return ONLY a raw JSON object..." system
prompt was never actually reaching the model for this call. This has
been broken since the query generator was switched to Anthropic
(`f7c20c4731`); the sibling `filteredTables` call above it was
unaffected since it passes `systemPrompt` positionally. Now fixed to
`systemPrompt: systemPromptForQueryGeneration`.

## Why

Claude Sonnet 5 follows structured/constrained instructions (don't alias
tables, use `LIKE` with wildcards, only reference documented columns,
etc.) more literally than 4.6, which should make the generated SQL more
reliable. It's priced the same or cheaper than 4.6 during the current
introductory period.

## Trade-offs called out for review

- Thinking being on by default adds some latency versus the old
(thinking-off) behavior on 4.6. This call is not currently streamed
(`sails.helpers.http.post`, single blocking call over a socket), so any
added thinking time is invisible wait time for the user rather than a
visible "thinking" indicator. `effort: "low"` should keep this modest,
but worth confirming with a manual QA pass on a few representative
questions before merging.
- Only the SQL-generation call was migrated. The schema-filtration call
also runs on an Anthropic model, but Haiku 4.5 doesn't support
`output_config.effort` (added `effort` is a no-op if passed to it), so
it was left as-is.

# 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
- [ ] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

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

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


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

* **Improvements**
  * Improved AI-generated SQL responses with an updated language model.
  * Added adaptive effort controls for supported AI requests.
* Increased response capacity to support more detailed generated
results.
* Improved handling of AI responses to provide more reliable results
when content includes different response formats.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Eric <eashaw@sailsjs.com>
2026-08-03 21:39:40 -05:00