<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
## Testing
- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#15744
# 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
- [ ] 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
Manually inserted 10k hosts and random emails associated to them.
Response times were always below 200ms locally.
We already have covering indexes so we don't need a migration.
https://github.com/user-attachments/assets/721db4f1-f3c9-4ede-ba62-499ac30c4a02
SQL used:
```sql
-- Seed 10k hosts for performance testing email search.
-- Requires: SET cte_max_recursion_depth = 10000;
--
-- Distribution (by osquery_host_id suffix):
-- 1-2500: Chrome profile email only
-- 2501-5000: IdP email only
-- 5001-7500: Both Chrome profile and IdP emails
-- 7501-10000: No email association
-- Generate 10k hosts using a recursive CTE
INSERT INTO hosts (osquery_host_id, node_key, hostname, uuid, platform, detail_updated_at, label_updated_at, policy_updated_at)
WITH RECURSIVE seq AS (
SELECT 1 AS n
UNION ALL
SELECT n + 1 FROM seq WHERE n < 10000
)
SELECT
CONCAT('perf-osq-', n),
CONCAT('perf-nk-', n),
CONCAT('perf-host-', n),
CONCAT('perf-uuid-', n),
'darwin',
NOW(),
'2000-01-01 00:00:00',
'2000-01-01 00:00:00'
FROM seq;
-- Populate display names so that hosts are visible in the UI.
INSERT INTO host_display_names (host_id, display_name)
SELECT id, hostname
FROM hosts
WHERE osquery_host_id LIKE 'perf-osq-%';
-- 1-2500: Chrome profile email only
INSERT INTO host_emails (host_id, email, source)
SELECT id, CONCAT('chrome-', id, '@example.com'), 'google_chrome_profiles'
FROM hosts
WHERE osquery_host_id LIKE 'perf-osq-%'
AND CAST(SUBSTRING(osquery_host_id, 10) AS UNSIGNED) BETWEEN 1 AND 2500;
-- 2501-5000: IdP email only
INSERT INTO host_emails (host_id, email, source)
SELECT id, CONCAT('idp-', id, '@example.com'), 'mdm_idp_accounts'
FROM hosts
WHERE osquery_host_id LIKE 'perf-osq-%'
AND CAST(SUBSTRING(osquery_host_id, 10) AS UNSIGNED) BETWEEN 2501 AND 5000;
-- 5001-7500: Both Chrome profile and IdP emails
INSERT INTO host_emails (host_id, email, source)
SELECT id, CONCAT('chrome-', id, '@example.com'), 'google_chrome_profiles'
FROM hosts
WHERE osquery_host_id LIKE 'perf-osq-%'
AND CAST(SUBSTRING(osquery_host_id, 10) AS UNSIGNED) BETWEEN 5001 AND 7500;
INSERT INTO host_emails (host_id, email, source)
SELECT id, CONCAT('idp-', id, '@example.com'), 'mdm_idp_accounts'
FROM hosts
WHERE osquery_host_id LIKE 'perf-osq-%'
AND CAST(SUBSTRING(osquery_host_id, 10) AS UNSIGNED) BETWEEN 5001 AND 7500;
-- 7501-10000: no emails (nothing to insert)
-- Cleanup:
-- DELETE FROM host_emails WHERE host_id IN (SELECT id FROM hosts WHERE osquery_host_id LIKE 'perf-osq-%');
-- DELETE FROM host_display_names WHERE host_id IN (SELECT id FROM hosts WHERE osquery_host_id LIKE 'perf-osq-%');
-- DELETE FROM hosts WHERE osquery_host_id LIKE 'perf-osq-%';
```
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#40054
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Updated internal logging infrastructure across Mobile Device
Management (MDM) service modules to improve code consistency and
maintainability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Fixes#34068 Adds automatic retries (up to 3 attempts) for failed software installs from host details, self-service, and setup experience across all installer types.
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#40124
# Details
Implements the proposal in
https://docs.google.com/document/d/16qe6oVLKK25nA9GEIPR9Gw_IJ342_wlJRdnWEMmWdas/edit?tab=t.0#heading=h.nlw4agv1xs3g
Allows doing e.g.
```go
logger.WarnContext(logCtx, "The `team_id` param is deprecated, use `fleet_id` instead", "log_topic", "deprecated-field-names")
```
or
```go
if logging.TopicEnabled("deprecated-api-params") {
logging.WithLevel(ctx, slog.LevelWarn)
logging.WithExtras(
ctx,
"deprecated_param",
queryTagValue,
"deprecation_warning",
fmt.Sprintf("'%s' is deprecated, use '%s'", queryTagValue, renameTo),
)
}
```
Topics can be disabled at the app level, and enabled/disabled at the
command-line level.
# 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
No logs have this in prod yet, but I added some manually in a branch and
verified that I could enable/disable them via CLI options and env vars,
including enabling topics that were disabled on the server. Tested for
both server and `fleetctl gitops`.
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **New Features**
* Added per-topic logging control to enable or disable logging for
specific topics via configuration and CLI flags.
* Added context-aware logging methods (ErrorContext, WarnContext,
InfoContext, DebugContext) to support contextual logging.
<!-- 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#39858
~~Also implements the idea from this comment:
https://github.com/fleetdm/fleet/issues/37802#issuecomment-3715729822~~
Decided to move the FMA name overriding idea to another PR.
## Changes
- `getOrGenerateSoftwareInstallerTitleID` now attempts to find existing
titles by name or by upgrade code if possible. It will update the
upgrade code if possible.
- also updated `addSoftwareTitleToMatchingSoftware` to match _only_ by
upgrade code if the installer has an upgrade code
These are the assumptions (and tests mostly) I made:
| installer | existing title | result |
|------------------|-----------------------------------|----------------------------------------------------------------------------|
| no upgrade code | same name, no upgrade code | uses existing |
| no upgrade code | same name, has upgrade code | uses existing,
existing upgrade code stays |
| has upgrade code | same name, no upgrade code | uses existing,
existing title is updated with the incoming upgrade code |
| has upgrade code | same name, different upgrade code | new title is
created with same name |
| has upgrade code | same name, same upgrade code | uses existing |
| has upgrade code | different name, same upgrade code | uses existing,
~~existing title's name is updated~~ |
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
## Testing
- [x] Added/updated automated tests
- [ ] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)
- [ ] QA'd all new/changed functionality manually
- Tested having the title `7-Zip 23.01 (x64)` with an upgrade code in
the db, added 7-Zip FMA, title became the existing `7-Zip 23.01 (x64)`
title with the same upgrade code.
- Trying to add it again fails with the correct error message
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#34370
<img width="932" height="1152" alt="Screenshot 2026-02-20 at 8 23 49 AM"
src="https://github.com/user-attachments/assets/c7b6d0ae-a20e-4115-835d-5d5fb01c12bb"
/>
- [x] Changes file added for user-visible changes in `changes/`
- [x] QA'd all new/changed functionality manually
https://github.com/shogo82148/rdsmysql/pull/222
Adds AWS GovCloud RDS CA certificates (us-gov-east-1, us-gov-west-1) to
the rdsmysql TLS bundle, improving compatibility for Fleet deployments
in AWS GovCloud regions.
Transitive dependency updates pulled in by rdsmysql v2.5.0:
- github.com/aws/aws-sdk-go-v2 and related submodules (minor bumps)
- github.com/go-sql-driver/mysql v1.9.1 -> v1.9.3
- filippo.io/edwards25519 v1.1.0 -> v1.1.1
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves
https://github.com/fleetdm/fleet/issues/40148
## Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [x] QA'd all new/changed functionality manually
— dependency bump only; ran full local test suite across all affected
packages (`server/platform/mysql`, `server/logging`, `server/config`,
`server/mail`) with no regressions. `go mod verify` passed.
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#40028
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Release Notes
* **Bug Fixes**
* Fixed telemetry misclassification where client-side errors were
incorrectly reported as server errors. Client-side errors and request
cancellations are now properly categorized for improved error tracking
and observability.
* **Tests**
* Added test coverage for client error detection and context
cancellation handling.
<!-- 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:** For #39344
# Details
This PR builds on the previous PR
(https://github.com/fleetdm/fleet/pull/39847) which added `renameto`
tags to certain API parameters to mark them as deprecated. How this is
used:
### In requests
* When decoding requests, log a warning if a `json` or `query` param is
used that has a `renameto` tag, e.g. if a `team_id` param is sent but
the related struct has `renameto:"fleet_id"` in it.
* If the `renamedto` version (e.g. `fleet_id`) is sent in the request,
rewrite it to the deprecated name so that it can be unmarshalled into
the struct
* If both versions are sent (e.g. `team_id` AND `fleet_id`), throw an
error and quit
* URLs with deprecated terms have new aliases using `WithAltPaths` --
warning on using old URLSs a TODO that will be handled in a subsequent
PR.
### In responses
* Output _both_ the deprecated and new names for fields that have
`renameto` tags, so that we don't break existing workflows expecting the
old keys. Uses a shared `DuplicateJSONKeys` to do the duplication.
* Most API responses are handled in `EncodeCommonResponse`. Exceptions
are activities, failing policy webhooks and the streaming "list hosts"
endpoints which call the function directly.
### In fleetctl
* Similar to requests, log warnings when deprecated keys are used and
rewrite the new keys internally so that they can be unmarshalled.
* For `fleetctl get` and `fleetctl generate-gitops`, _only_ output the
new names
* The set of keys to replace is hardcoded in `fleetctl` rather than
being dynamically generated as it is for API endpoints. Given the
mixture of typed and untyped data and the level of nesting, dynamic map
generation was very fragile and error-prone.
### Performance considerations
* The biggest performance hit is the addition of the JSON key rewriter
to the request pipeline. The rewriter buffers the entire request into
memory before eventually passing it to the decoder than unmarshals the
data into structs. I tried implementing this as a true streaming
rewriter but encountered issues where the request would hang if the
downstream reader (the decoder) encountered any errors. It's possible we
could implement this in a streaming fashion if we replace our [current
request
decoder](https://github.com/fleetdm/fleet/blob/da43bf8371695382c4af0972d5da456c6b94bdaf/server/service/endpoint_utils.go#L108)
with the v2 version, which is a bigger change requiring more thoughtful
discussion in the engineering team. As it stands, memory usage for
requests with deprecated fields will double while the request is being
decoded.
* The "alias rules" used to determine the old and new key names are
cached per struct type and for most endpoints are generated on server
start, so no performance impact is expected.
* Some `fleetctl` commands may have an extra unmarshal/marshal step but
as these are user-initiated and not performed in tight loops, the impact
should be minimal.
### TODO
* Log deprecation warnings when old URLs like "/fleet/teams" are used
* Update API fields that the front-end uses to avoid deprecation
warnings
* Update `fleetctl apply` to accept/return `kind: fleet` rather than
`kind: team`
* Find/update any fleet server config vars with old language
* Update all error messages that use old language
# 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)
## 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
* Clicking around the front-end, no broken pages due to request
ingestion errors or bad responses
* Looking in network tab to verify that responses have both the old and
new keys
* Running `fleetctl generate-gitops` and verifying that the output looks
correct and can be ingested by `fleetctl gitops`
* Running `fleetctl get` and `fleetctl apply`
---------
Co-authored-by: kiloconnect[bot] <240665456+kiloconnect[bot]@users.noreply.github.com>
#39921
Summary of fixes:
- Removed unnecessary calls to `BulkSetPendingMDMHostProfiles` when
settings are unchanged.
- Removed 3 unnecessary calls to `BulkSetPendingMDMHostProfiles` when
the Apple OS updates are unset.
- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
- [X] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
## Testing
- [X] Added/updated automated tests
- [X] QA'd all new/changed functionality manually
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#37306
I think we should actually solve this at the osquery level, but this is
just an alternative solution.
# 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
#### Setup
On a macOS VM:
1. Generated a certificate with Cyrillic characters in CN and O fields:
```bash
openssl req -x509 -newkey rsa:2048 -keyout newkey.pem -out newcert.pem -days 365 -nodes -utf8 -subj "/CN=АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯа/O=АБВГДЕЖЗИКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯа"
```
2. Installed the certificate:
```bash
sudo security add-trusted-cert -d -r trustRoot -k /Library/Keychains/System.keychain newcert.pem
```
#### Before
Refetched vitals and observed certificate field too long error logs:
```
ts=2026-02-18T21:50:47Z level=error msg="truncating certificate field" err="certificate field too long" field=subject_org host_id=32 original_length=304 max_length=255 truncated_value=\xC3\x90\xC2\xA2\xC3\x90\xC2\xB5\xC3\x91\xC2\x81\xC3\x91\xC2\x82\xC3\x90\xC2\xBE\xC3\x90\xC2\xB2\xC3\x90\xC2\xB0\xC3\x91\xC2\x8F\xC3\x90\xC2\x9E\xC3\x91\xC2\x80\xC3\x90\xC2\xB3\xC3\x90\xC2\xB0\xC3\x90\xC2\xBD\xC3\x90\xC2\xB8\xC3\x90\xC2\xB7\xC3\x90\xC2\xB
ts=2026-02-18T21:50:47Z level=error msg="truncating certificate field" err="certificate field too long" field=subject_common_name host_id=32 original_length=304 max_length=255 truncated_value=\xC3\x90\xC2\xA2\xC3\x90\xC2\xB5\xC3\x91\xC2\x81\xC3\x91\xC2\x82\xC3\x90\xC2\xBE\xC3\x90\xC2\xB2\xC3\x90\xC2\xB0\xC3\x91\xC2\x8F\xC3\x90\xC2\x9E\xC3\x91\xC2\x80\xC3\x90\xC2\xB3\xC3\x90\xC2\xB0\xC3\x90\xC2\xBD\xC3\x90\xC2\xB8\xC3\x90\xC2\xB7\xC3\x90\xC2\xB
ts=2026-02-18T21:50:47Z level=error msg="truncating certificate field" err="certificate field too long" field=issuer_org host_id=32 original_length=304 max_length=255 truncated_value=\xC3\x90\xC2\xA2\xC3\x90\xC2\xB5\xC3\x91\xC2\x81\xC3\x91\xC2\x82\xC3\x90\xC2\xBE\xC3\x90\xC2\xB2\xC3\x90\xC2\xB0\xC3\x91\xC2\x8F\xC3\x90\xC2\x9E\xC3\x91\xC2\x80\xC3\x90\xC2\xB3\xC3\x90\xC2\xB0\xC3\x90\xC2\xBD\xC3\x90\xC2\xB8\xC3\x90\xC2\xB7\xC3\x90\xC2\xB
ts=2026-02-18T21:50:47Z level=error msg="truncating certificate field" err="certificate field too long" field=issuer_common_name host_id=32 original_length=304 max_length=255 truncated_value=\xC3\x90\xC2\xA2\xC3\x90\xC2\xB5\xC3\x91\xC2\x81\xC3\x91\xC2\x82\xC3\x90\xC2\xBE\xC3\x90\xC2\xB2\xC3\x90\xC2\xB0\xC3\x91\xC2\x8F\xC3\x90\xC2\x9E\xC3\x91\xC2\x80\xC3\x90\xC2\xB3\xC3\x90\xC2\xB0\xC3\x90\xC2\xBD\xC3\x90\xC2\xB8\xC3\x90\xC2\xB7\xC3\x90\xC2\xB
ts=2026-02-18T21:50:47Z level=error msg="truncating certificate field" err="certificate field too long" field=subject_org host_id=32 original_length=256 max_length=255 truncated_value=\xD0\x90\xD0\x91\xD0\x92\xD0\x93\xD0\x94\xD0\x95\xD0\x96\xD0\x97\xD0\x98\xD0\x9A\xD0\x9B\xD0\x9C\xD0\x9D\xD0\x9E\xD0\x9F\xD0\xA0\xD0\xA1\xD0\xA2\xD0\xA3\xD0\xA4\xD0\xA5\xD0\xA6\xD0\xA7\xD0\xA8\xD0\xA9\xD0\xAA\xD0\xAB\xD0\xAC\xD0\xAD\xD0\xAE\xD0\xAF\xD0\xB
ts=2026-02-18T21:50:47Z level=error msg="truncating certificate field" err="certificate field too long" field=subject_common_name host_id=32 original_length=256 max_length=255 truncated_value=\xD0\x90\xD0\x91\xD0\x92\xD0\x93\xD0\x94\xD0\x95\xD0\x96\xD0\x97\xD0\x98\xD0\x9A\xD0\x9B\xD0\x9C\xD0\x9D\xD0\x9E\xD0\x9F\xD0\xA0\xD0\xA1\xD0\xA2\xD0\xA3\xD0\xA4\xD0\xA5\xD0\xA6\xD0\xA7\xD0\xA8\xD0\xA9\xD0\xAA\xD0\xAB\xD0\xAC\xD0\xAD\xD0\xAE\xD0\xAF\xD0\xB
ts=2026-02-18T21:50:47Z level=error msg="truncating certificate field" err="certificate field too long" field=issuer_org host_id=32 original_length=256 max_length=255 truncated_value=\xD0\x90\xD0\x91\xD0\x92\xD0\x93\xD0\x94\xD0\x95\xD0\x96\xD0\x97\xD0\x98\xD0\x9A\xD0\x9B\xD0\x9C\xD0\x9D\xD0\x9E\xD0\x9F\xD0\xA0\xD0\xA1\xD0\xA2\xD0\xA3\xD0\xA4\xD0\xA5\xD0\xA6\xD0\xA7\xD0\xA8\xD0\xA9\xD0\xAA\xD0\xAB\xD0\xAC\xD0\xAD\xD0\xAE\xD0\xAF\xD0\xB
ts=2026-02-18T21:50:47Z level=error msg="truncating certificate field" err="certificate field too long" field=issuer_common_name host_id=32 original_length=256 max_length=255 truncated_value=\xD0\x90\xD0\x91\xD0\x92\xD0\x93\xD0\x94\xD0\x95\xD0\x96\xD0\x97\xD0\x98\xD0\x9A\xD0\x9B\xD0\x9C\xD0\x9D\xD0\x9E\xD0\x9F\xD0\xA0\xD0\xA1\xD0\xA2\xD0\xA3\xD0\xA4\xD0\xA5\xD0\xA6\xD0\xA7\xD0\xA8\xD0\xA9\xD0\xAA\xD0\xAB\xD0\xAC\xD0\xAD\xD0\xAE\xD0\xAF\xD0\xB
```
https://github.com/user-attachments/assets/31b80643-34fb-42ee-b3a1-19d54fe1d516
#### After
https://github.com/user-attachments/assets/d49c1643-0920-4607-a2f1-fa6bb658c16b
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#38699
The fix will only apply to new Fleet instances. To fix existing Fleet
instances, we need to support rotation:
https://github.com/fleetdm/fleet/issues/40080
# 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
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#38351
# 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
- Including Okta conditional access
## 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`).
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **New Features**
* Device authentication tokens now remain valid after automatic refresh,
keeping your Device page URL accessible
* Device tokens are automatically generated when needed during
conditional access authentication
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
**Related issue:** Resolves#35528
Potentially #38983
I avoided adding a migration to fix existing bad platform data. However
a small migration is needed to convert software titles with the source
"pkg_packages" that have a bundle id, to the source "apps".
### Changes
To get an installer with the wrong platform fixed:
- Remove then add back the .pkg installer that showed the wrong platform
to see it create a new title with the correct platform
To get hosts that report the wrong platform in inventory/library fixed:
- Devices would still show the app with the wrong platform in
inventory/library. This happens because there are still entries in
`software` that match the incorrect previous title. All of these entries
need to be deleted for this bug to be fixed. One way for this to happen
is for all hosts with that app to remove it then wait for refetch and
the `vulnerabilities` cron, or be deleted directly in the database where
they should get restored after new refetches.
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
- [ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [ ] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes
## Testing
- [x] Added/updated automated tests
- [ ] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)
- [x] QA'd all new/changed functionality manually
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#39871
# 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)
- [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)
- [ ] QA'd all new/changed functionality manually
# 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
For unreleased bug fixes in a release candidate, one of:
- [x] Confirmed that the fix is not expected to adversely impact load
test results
Note: this solves https://github.com/fleetdm/fleet/issues/39832
---------
Co-authored-by: Scott Gress <scott@fleetdm.com>
Co-authored-by: Scott Gress <scottmgress@gmail.com>
**Related issue:** Resolves#38955
The query that was causing the lock contention was identified as `DELETE
FROM host_mdm_apple_profiles WHERE ( profile_identifier , host_uuid ) IN
( (...) /* , ... */ )` which corresponds to the query we use to delete
the Apple profiles in Bulk. The query was refactored to utilize the
primary key: (profile_uuid, host_uuid), which removes any kind of table
scanning.
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#39260
# Details
Fixes the banner displayed when a team has no enroll secrets to match
similar, non-dismissible warning banners, and corrects the padding
between text and button in the "Add enroll secret" modal empty state.
<img width="773" height="221" alt="image"
src="https://github.com/user-attachments/assets/490f49f1-ccaa-47c7-8ba3-a7de2896d932"
/>
---
<img width="662" height="380" alt="image"
src="https://github.com/user-attachments/assets/0f73b9b8-d625-4f40-ac8d-edb71e9f2a22"
/>
# 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
- [ ] Added/updated automated tests
n/a, styling only
- [X] QA'd all new/changed functionality manually
See screenshots above
**Related issue:** Resolves#38654
# Checklist for submitter
This fixes an issue where the status name was wrapping at smaller
viewport sizes on the mdm card of the dashboard page.
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
- [x] QA'd all new/changed functionality manually
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#39745
Needed to add a custom matching rule because the Notepad CPE does not
exist in NVD (yet?).
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Added detection and resolution tracking for CVE-2026-20841 affecting
Windows Notepad, resolved in version 11.2510.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This PR changes 3 things.
1. Validate `admin_url` + all URLs for HTTPS/non-private
2. Add custom `DialContext` hook in fleethttp.NewClient(), this is
needed for DNS-rebinding protection at connection time
3. Validate Smallstep SCEP challenge endpoint
# **IMPORTANT**
There are two validations occurring.
1. `CheckURLForSSRF`
2. `SSRFDialContext`
## Why?
`CheckURLForSSRF` checks the hostname. It resolves DNS, validates the
ip, and then returns an error to the user. It protects certificate
authority create/update API endpoints. But then
`GetSmallstepSCEPChallenge` calls `http.NewRequest(http.MethodPost,
ca.ChallengeURL, ...)` with the original hostname
This is where `SSRFDialContext` comes into play. It fires when an actual
HTTP request is attempted. Meaning Fleet would first build the request,
encode the body, set up TLS, etc., before being blocked at the dial.
`CheckURLForSSRF` stops the operation before any of that work happens.
`SSRFDialContext` protects the actual challenge fetch that happens later
at enrollment time. They're not always called together. The dial-time
check is the only thing protecting the enrollment request and DNS
rebinding.
## Should we remove `CheckURLForSSRF`
This is debatable and I don't have a strong opinion. Removing
`CheckURLForSSRF` would still provide the same protection. However, it
would return a generic connection error from the HTTP client which would
make it slightly hard to diagnose why it is broken.
## What's next
I implemented this for certificate authorities. I am sure there are
other places in the code base that take user submitted urls and could
also use this check. That is outside the scope of this particular PR.
But worthy to investigate in the near future.
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
* **Security**
* Added SSRF protections for validating external URLs and blocking
private/IP-metadata ranges; dev mode can bypass checks for local testing
* **New Features**
* Introduced an SSRF-protected HTTP transport and an option to supply a
custom transport per client
* **Tests**
* Added comprehensive tests covering SSRF validation, dialing behavior,
and resolution edge cases
<!-- 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#39228
Manually tested by triggering a failover on loadtest.
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Health checks now detect a primary DB becoming read-only and report
failure so the service restarts and reconnects to a writable primary.
* Write failures due to DB read-only state now trigger immediate fatal
handling to prompt graceful shutdown and recovery.
* Improved detection and handling of read-only DB conditions to increase
stability during failovers.
<!-- 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#39794
Before –> After
<img width="2015" height="479" alt="Screenshot 2026-02-16 at 1 28 11 PM"
src="https://github.com/user-attachments/assets/5f54b3d0-94d4-4881-8364-d22398289f18"
/>
- [x] Changes file added for user-visible changes in `changes/
- [x] QA'd all new/changed functionality manually
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#35561
<img width="647" height="655" alt="Screenshot 2026-02-13 at 4 24 57 PM"
src="https://github.com/user-attachments/assets/b191f8bb-e6b7-4f3d-8819-eccf23a408f8"
/>
- Spot checked all relevant instances of `InputField` (`type="textarea"
and `enableCopy`)
- [x] Changes file added for user-visible changes in `changes/`
- [x] QA'd all new/changed functionality manually
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#35044
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Prevented parallel execution of vulnerability jobs when one job runs
longer than two hours, improving job reliability and preventing
concurrent conflicts.
* **Chores**
* Enhanced cron job lock management to better handle long-running
scheduled tasks and prevent premature expiration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
**Related issue:** Resolves#31633.
Main change is stop relying on `who` command output to get the value of
the DISPLAY variable on X11 sessions (old distributions), and instead
search the value of the `DISPLAY` variable in processes that are owned
by the target user.
- [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
## fleetd/orbit/Fleet Desktop
- [x] Verified compatibility with the latest released version of Fleet
(see [Must
rule](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/workflows/fleetd-development-and-release-strategy.md))
- [x] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes
- [x] Verified that fleetd runs on macOS, Linux and Windows
- [x] Verified auto-update works from the released version of component
to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Bug Fixes**
* Enhanced X11 session detection for improved support in multi-session
environments, providing more reliable display variable identification in
complex session configurations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
**Related issue:** Resolves#29076
# 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)
## 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**
* Vulnerability webhooks are now available for free-tier users.
* **Improvements**
* Refined webhook payload display for free-tier users by removing
certain advanced vulnerability metrics.
* Updated UI text descriptions in automation management to reflect
free-tier vulnerability scanning behavior.
* Simplified permission requirements for accessing automation management
features.
<!-- 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#38889
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
* **Refactor**
* Updated internal logging infrastructure to improve standardization and
maintainability. Logging functionality remains unchanged from an
end-user perspective.
<!-- 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#38431
Attempts to get the ManualAgentInstall config from `ds.TeamLite` in the
case of software installers. In the VPP case, it attempts to get it from
either `ds.TeamByName` or from global `ds.AppConfig` if no team name is
provided.
I had to add some mock functions for TeamLite that were missing, or
missing for the team 0 case. Also added
FLEET_INTEGRATION_TESTS_DISABLE_LOG to disable logs in gitops
integration tests.
# Checklist for submitter
If some of the following don't apply, delete the relevant line.
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
- [ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [ ] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes
## Testing
- [x] Added/updated automated tests
- [ ] Where appropriate, [automated tests simulate multiple hosts and
test for host
isolation](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/reference/patterns-backend.md#unit-testing)
(updates to one hosts's records do not affect another)
- [x] QA'd all new/changed functionality manually
<!-- Add the related story/sub-task/bug number, like Resolves#123, or
remove if NA -->
**Related issue:** Resolves#36355
Docs PR: #39830
# Checklist for submitter
- [x] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
## Testing
- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit
## Bug Fixes
* Fixed a database error that could occur when requesting large activity
lists without specifying pagination parameters
* Enforced a maximum limit of 10,000 items per request for activities
endpoints to improve API stability
## Tests
* Added validation test to ensure the per_page limit is properly
enforced
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
---------
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>