**Related issue:** Resolves#44798
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.
## Testing
- [x] Added/updated automated tests
- [x] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Performance Improvements**
* Optimized Windows MDM profile removal operations for improved
performance when managing device profiles.
* **Bug Fixes**
* Enhanced Windows profile handling during host team transfers to ensure
correct profiles are properly installed and removed based on team
configuration.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45203)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Resolves#42930
- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
Ready for review, pending
[this](https://fleetdm.slack.com/archives/C084F4MKYSJ/p1778593457182719)
UX question.
## 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**
* Host activity details are now recorded and displayed for every attempt
— including queued and pending retries — of script executions and
software installations triggered by policy automations.
* **Tests**
* Integration tests updated to assert activity creation for each failed
attempt and retry flows.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45233)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Closes#45024
## Summary
- Fixed the MDM SSO callback handler returning a `"missing profile:
missing profile"` error when an Android device enrolls via SSO (OTA
enrollment) on a Fleet instance that does **not** have Apple MDM
configured.
- Refactored all MDM SSO initiator magic strings (`"ota_enroll"`,
`"setup_experience"`, `"account_driven_enroll"`) into named constants
(`fleet.SSOInitiatorOTAEnroll`, etc.) to prevent typos and missed cases
— which is the class of bug that caused this issue.
## Code walkthrough
### The bug
The bug is in `ee/server/service/mdm.go` in
`mdmSSOHandleCallbackAuth()`.
**The flow:**
1. Android enrollment hits `/enroll?enroll_secret=xxx` → frontend calls
`InitiateMDMSSO` with initiator `"ota_enroll"`
(`server/service/frontend.go:248`)
2. User authenticates at the SAML IdP
3. The SSO callback arrives at `MDMSSOCallback` → calls
`mdmSSOHandleCallbackAuth`
4. After successful SAML auth, the function checks early-exit
conditions:
- Line 1133: account-driven enrollment (`originalURL ==
appleMDMAccountDrivenEnrollmentUrl`) → **no match** for OTA
- Line 1139: `Initiator != "setup_experience"` → **true** for
`"ota_enroll"` → enters the block
5. Line 1140: calls `getAutomaticEnrollmentProfile()` → returns `nil`
because **no Apple MDM is configured**
6. Line 1144–1146: `depProf == nil` → **returns `"missing profile"`
error**
Note that `MDMSSOCallback` (the caller) already has a guard at line 931
that correctly skips the Apple MDM verification for `/enroll?` paths:
```go
if !strings.HasPrefix(originalURL, "/enroll?") && ssoRequestData.Initiator != "setup_experience" {
if err := svc.VerifyMDMAppleConfigured(ctx); err != nil { ... }
}
```
But `mdmSSOHandleCallbackAuth` was missing the equivalent guard — it
unconditionally tried to fetch the Apple DEP profile for any
non-`setup_experience` initiator.
### The fix
Adds an early return for OTA enrollments (where `originalURL` starts
with `/enroll?`), matching the existing pattern for account-driven
enrollments right above it. OTA enrollments don't use the Apple DEP
profile token.
### The refactor
Replaced all raw initiator string literals across the backend with named
constants defined in `server/fleet/app.go`:
| Constant | Value | Used by |
|---|---|---|
| `fleet.SSOInitiatorOTAEnroll` | `"ota_enroll"` | `/enroll` page
(Android, BYOD iPhone/iPad) |
| `fleet.SSOInitiatorSetupExperience` | `"setup_experience"` | Orbit
agent (macOS Setup Assistant) |
| `fleet.SSOInitiatorAccountDrivenEnroll` | `"account_driven_enroll"` |
Apple account-driven MDM enrollment |
Constants are in `server/fleet/` (not `server/sso/`) so orbit can import
them without pulling in Redis dependencies.
**Files changed:**
- `ee/server/service/mdm.go` — 6 string replacements (switch cases +
comparisons)
- `server/service/frontend.go` — 1 replacement
- `orbit/cmd/orbit/orbit.go` — 1 replacement
- `server/service/testing_client.go` — 1 replacement
- `server/service/integration_mdm_test.go` — 1 replacement
## Local reproduction
### Setup
1. Started dev server: `build/fleet serve --dev --dev_license`
2. Infrastructure: MySQL, Redis, SimpleSAML IdP via `docker compose up`
3. Created admin user and enroll secret
4. Configured MDM SSO (`entity_id: mdm.test.com`, SimpleSAML IdP at
`localhost:9080`)
5. Set `enable_end_user_authentication: true` directly in DB (API blocks
this without Apple MDM — matches customer state)
6. **Did NOT configure Apple MDM** — only SSO + EUA, simulating
Android-only instance
### Steps
1. `GET https://localhost:8080/enroll?enroll_secret=test_enroll_secret`
→ 303 redirect to SimpleSAML IdP
2. Completed SAML login programmatically (user: `sso_user`, pass:
`user123#`)
3. `POST https://localhost:8080/api/v1/fleet/mdm/sso/callback` with the
SAMLResponse
### Before fix
```
=== CALLBACK RESULT ===
Status: HTTP/2 303
Location: /mdm/sso/callback?error=true
=== SERVER LOGS ===
ts=2026-05-08T16:53:49Z level=error component=http method=POST
uri=/api/v1/fleet/mdm/sso/callback took=12.148708ms
err="missing profile: missing profile"
```
### After fix
```
=== CALLBACK RESULT ===
Status: HTTP/2 303
Location: /enroll?enroll_secret=test_enroll_secret&enrollment_reference=7c67326c-...&initiator=ota_enroll&profile_token=
=== SERVER LOGS ===
ts=2026-05-08T17:27:54Z level=info component=http method=POST
uri=/api/v1/fleet/mdm/sso/callback took=15.973ms
```
No errors. Successful redirect back to the enrollment page with the
enrollment reference.
## Integration test
Added `TestOTAEnrollSSOWithoutAppleDEPProfile` which:
1. Configures SSO and creates a team with IdP enabled
2. **Deletes all Apple DEP enrollment profiles** to simulate an
Android-only instance
3. Runs the full OTA enrollment SSO flow (GET `/enroll` → SAML IdP login
→ callback)
4. Verifies the callback redirects to `/enroll?...` with
`enrollment_reference` and `initiator=ota_enroll` (not `?error=true`)
Confirmed the test **fails without the fix** (`err="missing profile:
missing profile"`) and **passes with the fix**.
Also added a `LoginOTAEnrollSSOUser` test helper that drives the
complete OTA SSO flow starting from `GET /enroll` through SAML IdP login
to the callback, using a single cookie jar.
## Test plan
- [ ] Verify Android SSO enrollment works on an instance with **only**
Android MDM configured (no Apple MDM)
- [ ] Verify Apple DEP enrollment with SSO still works (the DEP profile
path is unchanged)
- [ ] Verify Apple OTA enrollment with SSO still works (also uses
`/enroll?` path)
- [ ] Verify account-driven enrollment with SSO still works (has its own
early return)
- [ ] Verify setup experience SSO still works (uses `Initiator ==
"setup_experience"`)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Resolved a regression where OTA enrollment via SSO could return a
"missing profile" error on Android when Apple MDM is not configured; OTA
SSO now redirects correctly to the enrollment flow.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45046)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Magnus Jensen <magnus@fleetdm.com>
## Summary
- Adds a new "Why think like a historian?" section to the [Why this
way?](https://fleetdm.com/handbook/company/why-this-way) handbook page.
- Explains why docs, issues, and plans should include context beyond
bare task descriptions — making them more discoverable in search, more
accessible for others to understand and contribute to, and more useful
for the company now and in the future.
- Includes a concrete before/after example: an agenda for a meeting
improved from "Write up scavenger hunt" to "Write up scavenger hunt for
SF party on May 12 celebrating launch."
Built for [Mike
McNeil](https://fleetdm.slack.com/archives/C03U703J0G5/p1778589572377249?thread_ts=1778588885.302819&cid=C03U703J0G5)
by [Kilo for Slack](https://kilo.ai/slack)
---------
Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
Co-authored-by: Mike McNeil <mikermcneil@users.noreply.github.com>
During the confirmation and celebration, we received feedback that the
current copy is confusing.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Clarified timeout/failure messaging for app installs: the modal now
states the install "took longer than {timeout}, so Fleet marked it as
failed," and the follow-up text clarifies the status will update if the
install finishes later.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45138)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
First PR in the staged plan from
[#33370](https://github.com/fleetdm/fleet/issues/33370#issuecomment-4394807680).
Adds unit tests for several testable helpers in `cmd/fleet/serve.go` —
argument stringification, TLS profile config, license initialization,
and the missing-migrations warning.
The migrations-warning test required threading `io.Writer` through
`printMissingMigrationsWarning` so it can pass `*bytes.Buffer` instead
of mutating `os.Stdout`. The other two database-state print functions
stay as-is since they aren't tested in this PR.
**Related issue:** Part of #33370 (intentionally not using auto-close
keywords since this is the first of multiple PRs against this issue).
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
## Testing
- [x] Added/updated automated tests
## Database migrations
_N/A — no database migrations in this PR._
## New Fleet configuration settings
_N/A — no new configuration settings._
## fleetd/orbit/Fleet Desktop
_N/A — no agent code changes._
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#44456
# 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**
* Dry-run now performs Apple config profile payload scope conflict
validation and reports unknown Fleet variables for all profile types
before completing.
* **Tests**
* Added tests covering Apple config profile scope-conflict validation
and dry-run/batch profile workflows to ensure conflicts are detected in
both dry-run and live flows.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45139)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Automated ingestion of latest Fleet-maintained app data.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Chores**
* Updated ChatGPT Atlas macOS package metadata with new version and
installer information
* Updated Cloudflare WARP macOS package metadata with new version and
installation scripts
* Updated Discord Windows package metadata with new version and
installer information
* Updated OpenVPN Connect macOS installation script configuration
* Updated pgAdmin4 macOS package metadata with new version and installer
information
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45209)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Co-authored-by: allenhouchins <32207388+allenhouchins@users.noreply.github.com>
Add OpenVPN Connect to maintained apps: create a Homebrew input manifest
and add an apps.json entry. Add a darwin output with version 3.8.1
(installer URL, sha256) plus install/uninstall script refs that handle
quitting/relaunching and cleanup. Add frontend icon component and
register it in the icon map, and include the app icon asset. Default
category set to Productivity.
Closes: https://github.com/fleetdm/fleet/issues/45126
Closes: https://github.com/fleetdm/fleet/issues/45128
Changes:
- Updated the styles and layout of the homepage hero to match the latest
wireframes
- Removed the box-shadow from the website masthead and added a bottom
border.
- Added a new variable to colors.less `@core-fleet-black-5`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Style**
* Redesigned homepage hero layout and typography for improved responsive
behavior across desktop, tablet, and mobile.
* Reorganized quote and statistics into a unified responsive block with
updated spacing, padding, and stacking.
* Adjusted hero background sizing and hero-area height/padding for small
screens.
* Updated hero subtitle wording for clarity.
* Refined header bottom color and removed header shadow.
* Added a subtle new color token to the site palette.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45198)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
**Related issue:** Resolves#42613
Dedupes errors that report HTTP 408 (request timeouts). As of now, I
believe this only fires for timeouts on the
**/api/v1/osquery/distributed/write** endpoint.
This is so that we have a unique error hash with an incrementing count,
instead of thousands of entries each with count: 1, which produces a
huge JSON payload when passed to
https://fleetdm.com/api/v1/webhooks/receive-usage-analytics for
processing.
Trade-off:
- Before: every occurrence got its own Redis entry so thousands of
near-identical examples coexisted.
- After: they collapse into one entry whose :json value still contains a
representative example, but we'd only keep the last IP+Port instead of
all of them.
# 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
Build a ~5 MB JSON body in a temporary file:
```bash
{ printf '{"node_key":"'; head -c 5000000 /dev/zero | tr '\0' 'x'; printf '"}'; } > /tmp/distwrite-body.json
```
Clear out redis:
```bash
docker exec fleet-redis-1 redis-cli FLUSHDB
```
Send a dummy request and throttle the upload at 100 KB/s → ~50s to send,
read timeout fires at 25s.
I sent this 3 times and got the "request body read error" error back
after each request.
```bash
curl -sk --limit-rate 100K -X POST -H 'Content-Type: application/json' --data-binary @/tmp/distwrite-body.json https://127.0.0.1:8080/api/v1/osquery/distributed/write
{
"error": "request body read error: i/o timeout",
"uuid": "95937f50-1008-4625-9423-bc19c7be6818"
}
```
Count the error keys containing "request body read error" as the value.
```bash
docker exec fleet-redis-1 sh -c 'for k in $(redis-cli --scan --pattern "error:*:json"); do v=$(redis-cli GET "$k"); echo "$v" | grep -q "request body read error" && echo "$k count=$(redis-cli GET "${k%:json}:count")"; done'\
error:{Cco_JmAdBVVVJI9k0XjNNUCmG0z1IKguMQD4VDaejfc=}:json count=3
```
Notice the single entry and count=3 (since I ran the dummy request 3
times).
Running this on main outputs three entries each with count=1.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Network error deduplication for request-timeout errors now normalizes
socket addresses, preventing the usage statistics cron from failing when
many similar network errors accumulate.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45142)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Clarify the user-facing resolution to instruct users to install Okta
Verify from Self-service, click Refetch, and contact #help-it if issues
persist. Also enable automatic installation by changing install_software
to true so Fleet can install the managed app when needed.
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#45160
Issue and fix: https://www.youtube.com/watch?v=Ow9GAFedEnQ
# Checklist for submitter
## Testing
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Bug Fixes**
* Enhanced error handling in the admin user creation process to ensure
immediate failure on errors, preventing incomplete operations during
user account creation or group membership assignment.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45176)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#44801
Note there is a related bug:
https://github.com/fleetdm/fleet/issues/45170
# 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] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* End user authentication can now be enabled for Windows-only and
Linux-only fleets without requiring macOS MDM configuration.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45162)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#43598
# 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
- [X] added a script file `some-*-script[].sh` and referred to it in a
gitops file using `path:`. Failed on main; on this branch it
successfully uploaded the script
- [X] still got expected error message when using `path: ` with a value
that had glob characters that _didn't_ match an actual file
- [X] `paths:` still worked and uploaded multiple files, including
`some-*-script[].sh`
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed path validation in fleetctl gitops so path values containing
glob metacharacters (e.g., brackets, asterisks, question marks) are
accepted when a literal file with that name exists on disk; missing
files still produce the appropriate error.
* **Tests**
* Added regression tests covering glob metacharacter handling in path
validation.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44547)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#42503
# 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
- [X] setting `software:` under `macos_setup` or `setup_experience`
triggers the expected warning.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Deprecations**
* Using setup_experience.software or macos_setup.software now emits a
deprecation warning. Migrate by setting setup_experience: true on
individual software items (packages, App Store apps, or fleet-maintained
apps).
* **Tests**
* Added test coverage to verify the deprecation warning is emitted when
applicable and absent otherwise.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44549)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves #
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [X] Added/updated automated tests
- [X] QA'd all new/changed functionality manually
- [X] omitted `name:` from a file without `org_settings:`, got:
```
* No `name` was provided in /tmp/testback/fleets/third-fleet.yml. If this file is intended to define org-level settings, add `org_settings:` as a top-level key. Otherwise, use `name` to specify the fleet name.
```
- [X] omitted `name:` from a file with `org_settings:`, got no error.
- [X] omitted `name:` from `no-team.yml`, got:
```
* `name` must be `No Team` for `no-team.yml`
```
- [X] omitted `name:` from `unassigned.yml`, got:
```
* `name` must be `Unassigned` for `unassigned.yml`
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved error messages when GitOps YAML files omit the required
`name` field, with specific remediation guidance tailored to each
configuration file type
* Enhanced validation error messaging when top-level `org_settings` is
missing or incorrectly placed, providing clearer instructions on
required YAML structure
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#43721
# 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
Added a Google Calendar integration to gitops .yml with `client_email`
missing from the `api_json_key`.
- [X] on main, got error:
```
Error: applying fleet config: PATCH /api/latest/fleet/config received status 422 Validation Failed: client_email is required (API time: 13ms)
```
- [X] on this branch, got:
```
Error: applying fleet config: Validation Failed: client_email is required (API time: 134ms)
```
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Cleaner CLI error messages: removed extraneous HTTP path/status-code
details from GitOps-related errors, making output easier to read.
* **Tests**
* Added tests to verify the improved error message handling and
nil/non-wrapped error behavior.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44555)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#42886
# 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
- [X] gitops run with extra keys (besides `client_email` and
`private_key` in `api_key_json` fails on main, passes on this branch
- [X] gitops run with missing `client_email` or `private_key` in
`api_key_json` still fails gitops (including dry run)
- [X] gitops run with extra keys sibling to api_key_json still fails as
expected
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Corrected GitOps validation so Google Calendar API key JSON no longer
rejects valid nested keys; required-field validation for the integration
still enforced.
* **Tests**
* Added test coverage to ensure nested unknown keys are accepted while
sibling-level unknown fields are reported as validation errors.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/44556)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Tim Lee <timlee@fleetdm.com>
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#43646
<img width="809" height="149" alt="image"
src="https://github.com/user-attachments/assets/cf7b55ae-4d79-4686-a9e5-e9e68e4b2e65"
/>
<img width="851" height="190" alt="image"
src="https://github.com/user-attachments/assets/0c70a2b6-091c-4222-b9a9-c4d46f9b0f5b"
/>
# 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] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Fixed alignment inconsistency for premium feature messages in Fleet
settings. Premium notifications across Disk Encryption and Passwords
controls now display with proper alignment on Fleet Free tier.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45125)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Relocate the Safari extensions report to a macOS-specific directory and
update the fleet manifest to reference the new path. Also clean up
report descriptions by removing embedded compliance/mapping lines from
multiple reports (Chromium, Firefox, listening ports, local user
accounts, USB devices, and Safari) — queries and report logic unchanged.
Closes: https://github.com/fleetdm/fleet/issues/45155
Changes:
- Added auto-patching to the "What will you be using Fleet for?"
question on the contact page
- Included an auto-generated layout.ejs change
Updated the URL for the PSSO local account guide to include the platform
SSO section.
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#30674
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Improved navigation shortlink to direct users to a more specific
section on the setup guide page.
[](https://app.coderabbit.ai/change-stack/fleetdm/fleet/pull/45143)
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Closes#42522
## Changes
When `labels:` appears in a no-team/unassigned GitOps file, log a
warning and skip label parsing. This matches the existing pattern used
by `agent_options` and `reports` in no-team files.
A warning (not an error) is used intentionally to avoid breaking
existing customer GitOps pipelines that may already have `labels:` in
their no-team file.
**After fix:**
```
[!] 'labels' is not supported in unassigned.yml. This key will be ignored.
```
## Testing
### Manual testing
Built `fleetctl` from the fixed branch against a local Fleet server
(premium license).
| Scenario | Result |
|---|---|
| `unassigned.yml` dry-run | Warning printed, succeeds |
| `unassigned.yml` real run | Warning printed, succeeds |
| `no-team.yml` dry-run | Warning printed, succeeds |
| `no-team.yml` real run | Warning printed, succeeds |
| `unassigned.yml` without labels | No warning, succeeds (no regression)
|
### Unit tests
- **`TestLabelsIgnoredInNoTeamFile`**: Sub-tests for both `no-team.yml`
and `unassigned.yml` assert: (1) no error, (2) `LabelsPresent` is true,
(3) no labels parsed, (4) warning logged.
---------
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>