Commit graph

1398 commits

Author SHA1 Message Date
Victor Lyuboslavsky
aaac4b1dfe
Changes needed before gokit/log to slog transition. (#39527)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38889

PLEASE READ BELOW before looking at file changes

Before converting individual files/packages to slog, we generally need
to make these 2 changes to make the conversion easier:
- Replace uses of `kitlog.With` since they are not fully compatible with
our kitlog adapter
- Directly use the kitlog adapter logger type instead of the kitlog
interface, which will let us have direct access to the underlying slog
logger: `*logging.Logger`

Note: that I did not replace absolutely all uses of `kitlog.Logger`, but
I did remove all uses of `kitlog.With` except for these due to
complexity:
- server/logging/filesystem.go and the other log writers (webhook,
firehose, kinesis, lambda, pubsub, nats)
- server/datastore/mysql/nanomdm_storage.go (adapter pattern)
- server/vulnerabilities/nvd/* (cascades to CLI tools)
- server/service/osquery_utils/queries.go (callback type signatures
cascade broadly)
- cmd/maintained-apps/ (standalone, so can be transitioned later all at
once)

Most of the changes in this PR follow these patterns:
- `kitlog.Logger` type → `*logging.Logger`
- `kitlog.With(logger, ...)` → `logger.With(...)`
- `kitlog.NewNopLogger() → logging.NewNopLogger()`, including similar
variations such as `logging.NewLogfmtLogger(w)` and
`logging.NewJSONLogger(w)`
- removed many now-unused kitlog imports

Unique changes that the PR review should focus on:
- server/platform/logging/kitlog_adapter.go: Core adapter changes
- server/platform/logging/logging.go: New convenience functions
- server/service/integration_logger_test.go: Test changes for slog

# 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`.
  - Was added in previous PR

## 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**
* Migrated the codebase to a unified internal structured logging system
for more consistent, reliable logs and observability.
* No user-facing functionality changed; runtime behavior and APIs remain
compatible.
* **Tests**
* Updated tests to use the new logging helpers to ensure consistent test
logging and validation.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-11 10:08:33 -06:00
Victor Lyuboslavsky
61f635dd44
Activity bounded context: Complete read operations (#38555)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38534

moved `/api/_version_/fleet/hosts/{id:[0-9]+}/activities` endpoint and
`MarkActivitiesAsStreamed` to activity bounded context

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

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

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

## Summary by CodeRabbit

* **New Features**
* Added new endpoint to retrieve host-specific past activities with
pagination metadata.
  
* **Refactor**
* Refactored activity service architecture and authorization layer to
improve data provider integration and activity streaming capabilities.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-09 15:29:12 -06:00
Noah Talerman
52f8ba3c72
fleet-gitops tests: Remove Workstations (canary) enroll secret (#39550)
- Workstations (canary) team no longer exists:
https://github.com/fleetdm/fleet-gitops/tree/main/teams
2026-02-09 13:20:36 -05:00
Nico
e5849ee720
Show Manage Automations disabled button with tooltip on Queries page (#39302)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #39303 (child of #25080).

- Added `inherited_query_count` to `ListQueriesResponse` (thought of
adding a brand new endpoint just for counting, but felt like extending
the current one was good enough). In the parent task, [it was
suggested](https://github.com/fleetdm/fleet/issues/25080#issuecomment-3326071574)
to `"Depend on team list entity endpoint's count field / team entity
count endpoint for whether or not to disable the manage automations
button"`, which Rachael approved, so I went for this approach.
- The `ManageQueryAutomationsModal` now fetches its own data with
`merge_inherited = false` (meaning it only fetches non-inherited queries
only). Previously, queries were passed down as props to it, which would
not show the queries available to automate if the first page of queries
were all inherited and the second page contained queries for that team
(the user would have to navigate to the second page for the button to be
enabled).


^ The fact that the modal fetches its own data is similar behavior to
what is currently done in `Policies`. For queries, I noticed that we
would need to add pagination within the `Manage Automations` modal, but
that can be a follow-up.

<img width="2480" height="1309" alt="Screenshot 2026-02-04 at 11 48
42 AM"
src="https://github.com/user-attachments/assets/ebac79a5-a793-4708-9313-d9a697dfd7de"
/>


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



https://github.com/user-attachments/assets/119f03b9-dde1-4bb9-9fee-6204b1a58879
2026-02-09 15:16:28 -03:00
Jordan Montgomery
9d3164113f
Add entra tenant IDs migration (#39420)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #39264 

# 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

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).
2026-02-09 12:48:19 -05:00
Juan Fernandez
4657a6979e
Add activity for modified enroll secrets (#39292)
Resolves #36755 

When an user edits (add, updates or deletes) an enroll secret, then a
global activity should be generated.
2026-02-07 09:21:10 -04:00
Victor Lyuboslavsky
a10f05486f
Added OTEL log export support (#39279)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38607

Contributor docs update:
https://github.com/fleetdm/fleet/pull/39285/changes
Another contributor docs update:
https://github.com/fleetdm/fleet/pull/39402/changes

Also:
- renamed OtelHandler to OtelTracingHandler
- made "opentelemetry" be the default when tracing is enabled
- updated OTEL dependencies

# 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

## New Fleet configuration settings

- [x] Setting(s) is/are explicitly excluded from GitOps

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

## Summary by CodeRabbit

* **New Features**
* Added OpenTelemetry log export capability, enabling logs to be sent to
OpenTelemetry collectors.
* New configuration option `logging.otel_logs_enabled` (requires tracing
to be enabled).

* **Chores**
* Updated OpenTelemetry dependencies to v1.40.0 with latest OTLP
exporters and logging support.
* Updated dependencies including gRPC (v1.78.0), Google libraries, and
cryptography packages.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-06 18:57:28 -06:00
Jordan Montgomery
a251e8e766
Fix broken test (#39498)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves # no ticket however
More context here:
https://fleetdm.slack.com/archives/C019WG4GH0A/p1770295767905349
And here
https://fleetdm.slack.com/archives/C019WG4GH0A/p1770389045550669
# Checklist for submitter

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

## Testing

- [x] Added/updated automated tests
2026-02-06 14:19:44 -05:00
Lucas Manuel Rodriguez
7c9713d08f
Fix panic in gRPC launcher API handler (#39409)
- [X] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.

## Testing

- [X] QA'd all new/changed functionality manually
2026-02-06 09:31:14 -03:00
Lucas Manuel Rodriguez
ba88a37a3a
Authenticate carve block endpoint before parsing the "data" field (#39353)
- [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] 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

---------

Co-authored-by: Magnus Jensen <magnus@fleetdm.com>
2026-02-05 15:55:03 -03:00
Magnus Jensen
da43bf8371
Request body limits (#39080)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves
https://github.com/fleetdm/confidential/issues/13934

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

## Testing

- [x] Added/updated automated tests
- [ ] QA'd all new/changed functionality manually
2026-02-05 10:29:53 -05:00
Tim Lee
e12552e5fb
Bugfix: gitops-generate panics when google calendar config is set (#39237) 2026-02-04 14:04:08 -07:00
Victor Lyuboslavsky
8e07f166d8
Created kitlog adapter wrapping slog (#38890)
<!-- 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

* **New Features**
* Structured logging with selectable JSON/text output and optional trace
correlation (trace_id, span_id).
* Backward-compatible output (ts timestamp, lowercase levels) and
adapter to interoperate with existing logging calls.

* **Refactor**
* Simplified logger initialization and centralized slog-based logging
infrastructure.

* **Tests**
* Extensive tests and a test handler for logging behavior, formats,
levels, and trace injection.

* **Chores**
  * Added package-level dependency check for the logging package.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-02-03 20:37:17 -06:00
Scott Gress
e3fc20df50
Update test expectations after changes to fleet-gitops (#39261)
Due to [recent changes to the fleet-gitops
repo](https://github.com/fleetdm/fleet-gitops/pull/91), some tests need
to be updated to match the expected # of teams.
2026-02-03 14:08:02 -06:00
Martin Angers
b25c9522e4
Remove obsolete assertions to fix failing tests (#39249) 2026-02-03 13:01:49 -05:00
Magnus Jensen
471d200b3d
Only default update_new_hosts key if not explicitly set (#39202)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #39048 

# 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
2026-02-03 12:41:52 -05:00
Dante Catalfamo
40f6546de7
Add conditional access already bypassed check (#39037)
**Related issue:** Resolves #37281
2026-02-02 10:35:55 -05:00
Allen Houchins
ea6345f483
Add WhatsApp installer URL transformer (#38823)
Introduces WhatsAppInstallerURL to override the installer URL and set
SHA256 to 'no_check' for WhatsApp on Darwin. Updates the function map to
apply both WhatsAppVersionShortener and WhatsAppInstallerURL for
WhatsApp manifests.

<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38816
2026-01-29 17:33:43 -06:00
Jahziel Villasana-Espinoza
e36790baac
account for all teams as a value for vpp teams (#39013)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38975 

# 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
2026-01-29 17:04:02 -05:00
Ian Littman
5c11a9feb7
Expose VPP metadata bearer token as public config, interact directly with Apple when set (#38817)
Resolves #38622.

# 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

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

## New Fleet configuration settings

- [x] Setting(s) is/are explicitly excluded from GitOps
2026-01-27 16:50:40 -06:00
Ian Littman
2f25580c3a
Only allow FLEET_DEV_* env vars when --dev is passed, allow overriding configs one at a time in dev (#38652)
Resolves #38484. This includes a CI job change to make sure we don't
introduce any more env vars that don't get proxied (and thus turned off
outside `--dev`).

# 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

Manual QA touched hot paths, but did _not_ manually test every
FLEET_DEV_* environment variable change.

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

* **New Features**
* Centralized dev-mode environment management for consistent FLEET_DEV_*
handling and test-friendly overrides.
* Dev-mode allows targeted overrides for certain dev-only configuration
when running with --dev.

* **Chores**
* Migrated environment access to the centralized dev-mode helper across
the codebase.
  * Added CI checks to enforce proper usage of FLEET_DEV_* variables.

* **Documentation**
  * Added guidance on dev-mode environment variable rules and overrides.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Victor Lyuboslavsky <2685025+getvictor@users.noreply.github.com>
2026-01-27 14:32:56 -06:00
Scott Gress
9a6a366b3b
Improve performance when recording schedule query results (#38524)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #35603

# Details

This PR aims to optimize the system for recording scheduled query
results in the database. Previously, each time a result set was received
from a host, the Fleet server would count all of the current result rows
in the db for that query before deciding whether to save more. This
count becomes more expensive as the DB size grows, until it becomes the
"long" pole in the recording process. With this PR, the system changes
in the following ways:

* When result rows are received from the host, no count is immediately
taken. Instead, a Redis key is checked which holds a current approximate
count of rows in the table. If the count is over the configured row
limit, no rows are saved. Otherwise, rows are saved and the count is
adjusted accordingly (it can go down, e.g. if a host previously returned
5 rows for a query and now returns 3). Keep in mind that we only store
one set of results per host for a scheduled query; when a host reports
results for a query, we delete that hosts previous results and write the
new ones if there's room.
* As an additional failsafe against runaway queries, if a result set
contains more than 1000 rows, it is rejected.
* Once a minute, a cron job runs which deletes all rows over the limit
for each query and resets the counter for all queries to the actual # of
rows in the table.

The end result is:

* No more expensive counts on every distributed write request for
scheduled queries
* Results for a single query can burst to over the limit for a short
time, but will get cleaned up after a minute
* Because of concurrency and race issues where multiple hosts might get
the same count from Redis before inserting rows, the actual # of results
in the db can burst higher than the limit. In testing w/ osquery-perf
with 1000 hosts started simultaneously, sending 500 rows at a time, a
50,000 row limit and a query running every 10 seconds, I saw the table
get up to 60,000 rows at times before being cleaned up. This is a very
bad case; in the real world we'd have a lot more jitter in the
reporting, and queries would not typically return this many rows.

# 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
Added a new test to verify that results are still discarded if table
size is > limit, updated existing 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
Ran osquery-perf with 1000 hosts and a 50,000 row limit per query, using
queries that returned 1, 500 and 1000 rows at a time. Verified that the
limits were respected (subject to the amount of flex discussed above).
I'm doing some A/B tests now using local MySQL metrics and will report
back.


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

* **New Features**
* Automated periodic cleanup of excess query results to retain recent
data and free storage
  * Redis-backed query result counting to track per-query result volumes

* **Performance Improvements**
  * Optimized recording of scheduled query results for reduced overhead
* Cleanup runs in configurable batches to lower database contention and
balance storage use

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-27 10:33:47 -06:00
Tim Lee
4ce3988eb7
Obfuscate calendar key (#38687) 2026-01-26 16:59:13 -07:00
Ian Littman
72e55a4459
Optionally output database table sizes after migrations complete (#38620)
Resolves #35314.

# 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] QA'd all new/changed functionality manually
2026-01-26 17:55:55 -06:00
Victor Lyuboslavsky
07949df530
Improved OpenTelemetry error handling (#38757)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38756 

- Changed to NOT mark many client errors as exceptions
- Instead, added client_error and server_error metrics that can be used
to alert on unusual error rates

# 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

* **New Features**
* Added separate metrics for distinguishing between client and server
errors, enhancing observability and monitoring capabilities.

* **Bug Fixes**
* Client request errors no longer incorrectly appear in error tracking
as exceptions; improved accuracy of error reporting to external
services.
* Adjusted logging levels for authentication and enrollment operations
to provide clearer diagnostics.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-26 17:07:32 -06:00
Noah Talerman
4bbd4ee370
Update usage description for fleetctl apply (#38131)
- To mirror the docs:
https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/cli/fleetctl-apply.md

<img width="1102" height="148" alt="Screenshot 2026-01-09 at 4 15 19 PM"
src="https://github.com/user-attachments/assets/1b8bc5c4-312c-44ae-9fa3-b737b6795ad0"
/>

- Context: https://github.com/fleetdm/fleet/issues/38130
2026-01-26 16:37:38 -05:00
Victor Lyuboslavsky
063c16cffd
Added conditional_access.cert_serial_format server option to allow specifying the Okta conditional access certificate serial format. (#38697)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38549

Associated documentation update PR:
https://github.com/fleetdm/fleet/pull/38702

# Checklist for submitter

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



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

* **New Features**
* Introduced conditional_access.cert_serial_format to choose certificate
serial number format (hex or decimal); hex is default.
  * SSO certificate serial parsing now respects the configured format.

* **Bug Fixes**
* Improved parsing and error handling for certificate serial numbers
across formats.

* **Tests**
* Added unit tests for configuration validation and serial-number
parsing for both hex and decimal.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-26 12:21:10 -06:00
Magnus Jensen
5656dcf801
improve missing label error message (#38636)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #37183 

Software request:
```json
{
    "message": "Bad request",
    "errors": [
        {
            "name": "base",
            "reason": "Couldn't update. Label \"non-existing-label\" doesn't exist. Please remove the label from the software."
        }
    ],
    "uuid": "3a9a4da3-d7af-4ed5-8b39-73e9f465f103"
}
```

Config profile:
```json
{
    "message": "Bad request",
    "errors": [
        {
            "name": "base",
            "reason": "Couldn't update. Label \"non-existent-label\" doesn't exist. Please remove the label from the configuration profile."
        }
    ],
    "uuid": "ea842e7b-d4eb-4b59-bf24-32ad66d538dd"
}
```

# 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
2026-01-26 12:55:26 -05:00
Konstantin Sykulev
c513b3f518
Optimizing certificate template batch delete auth (#38650)
- [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

* **Bug Fixes**
* Enhanced authorization validation for certificate template batch
deletion operations, ensuring all templates belong to the specified team
before allowing deletion.

* **Tests**
* Added authorization verification tests for certificate template
deletion to prevent cross-team unauthorized access.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-24 17:47:17 -06:00
Victor Lyuboslavsky
7deade8057
Activity bounded context: /api/latest/fleet/activities (2 of 2) (#38478)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #37806 

Removed `ds.ListActivities` from the legacy datastore and updated
code/tests to use the new activity bounded context instead.

The changes to `cron.go` and most changes to `mysql/activities_test.go`
will eventually be migrated to the activity bounded context. The current
changes are an intermediate step.

The issues tracked by https://github.com/fleetdm/fleet/issues/38234 will
be addressed in additional/parallel PRs shortly.

# Checklist for submitter

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

## 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**
* Migrated activity retrieval from direct datastore calls to a
service-based architecture for improved maintainability and consistency.
* Enhanced system context handling for background automation tasks to
ensure proper authorization during scheduled operations.
* Streamlined activity recording for automated processes with dedicated
system identity tracking.

* **Tests**
* Updated test infrastructure with new helpers for activity service
integration across test suites.

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

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

---------

Co-authored-by: Ian Littman <iansltx@gmail.com>
2026-01-23 07:42:09 -06:00
Juan Fernandez
1480ffa432
Alternative browser host gitops (#38516)
**Related issue:** Resolves #38096

The work required for this was done in
[here](https://github.com/fleetdm/fleet/pull/38409) - this just
adds/updates related tests. While QA'ing this I noticed a discrepancy
between the UI and the Figma specs, instead of opening a new PR, the
issue was patched here.
2026-01-21 10:12:48 -04:00
Jahziel Villasana-Espinoza
64ed89c41d
make generate-gitops export FMAs correctly (#38420)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #32619

# 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

## New Fleet configuration settings

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
2026-01-20 16:31:41 -05:00
Dante Catalfamo
76aca6c586
Conditional Access bypass config and activity (#38453)
**Related issue:** Resolves #37275
2026-01-20 15:20:24 -05:00
Jonathan Katz
902b5a5d6a
Contributor API docs update (#38517)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #37264 
Adds a fleet maintained app example with the new `slug` field in the
response for `/software/batch/:request_uuid` from #38497
See the PR above for an explanation on why this was added.

---------

Co-authored-by: Marko Lisica <83164494+marko-lisica@users.noreply.github.com>
2026-01-20 14:57:15 -05:00
Victor Lyuboslavsky
7b00d40f57
Improved OpenTelemetry tracing (#38483)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38479

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

## Testing

- [x] QA'd all new/changed functionality manually
2026-01-20 12:22:20 -06:00
Jonathan Katz
7f0a10268c
Use custom icons in GitOps for Fleet Maintained Apps (#38497)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #37264
When batch adding icons, the difference between the batch request and
batch results response is compared, but only by hash/URL, which fleet
maintained apps don't provide in a GitOps file. This means the GitOps
code has no way to compare between the FMA it provided and the hash/url
it got. This PR adds Slug to `SoftwarePackageResponse` to be able to
compare fleet maintained apps to their respective software titles that
get uploaded.

# Checklist for submitter

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

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

- [ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements)
- [ ] 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
2026-01-20 11:56:40 -05:00
Juan Fernandez
b95d3cbfd7
Ability to set fleet desktop alternative browser host in org settings (#38409)
Resolves #33762 & #38094 

Added a new `alternative-browser-host` global config property for Fleet Desktop, if set, Fleet Desktop will use it over the `--fleet-desktop-alternative-browser-host` env variable to open any Fleet Desktop related links (i.e. My Device, etc).
2026-01-19 16:25:22 -04:00
Ian Littman
a394596fbf
Bump installer max size, make configurable (#38122)
Resolves #37464.

# 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

## New Fleet configuration settings

- [x] Setting(s) is/are explicitly excluded from GitOps
2026-01-19 13:36:01 -06:00
Nico
5196521586
Delete Fleet users when deleted from IdP: Server changes for SCIM handling of deletion (#38321)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #38087 

More context:
https://fleetdm.slack.com/archives/C084F4MKYSJ/p1768336339026999 and
https://fleetdm.slack.com/archives/C084F4MKYSJ/p1768512354275959.

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

### Okta

NOTE: Okta does not send `DELETE` requests when deleting a user.
Therefore, we decided to perform Fleet users deletion when the
deactivation happens (`PUT` request).
There's an edge case where a `deactivated` user in Okta is `activated`
back again: Okta sends a `POST` request as if a new user was created --
due to this I added an extra check on the `UserHandler Create` function
so that we don't attempt to create a duplicate SCIM user and instead
replace the existing record (basically, the only change should be
`active=0` -> `active=1`).

What I tested:

- [x] Deactivating user in Okta switches `scim_users` record to `active
= 0` and deletes matching `users` records.
- [x] Activating a deactivated user in Okta switches `scim_users` record
to `active = 1`. Note that a `users` record is not created
automatically. For this, there are two alternatives that we'll mention
in the documentation:

1. Manually create a user from the **Users page**.
2. Log in to Fleet using SSO (must have SSO and the **Create user and
sync permissions on login** setting enabled). Note that an activation
email is sent and the user must provide a new password, or an admin in
the Okta dashboard can set up a one-time password and share it with the
user.


https://github.com/user-attachments/assets/5262a581-41f0-4a88-aa73-40768064f8f5
2026-01-19 11:35:42 -03:00
Victor Lyuboslavsky
6019fa6d5a
Activity bounded context: /api/latest/fleet/activities (1 of 2) (#38115)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #37806 

This PR creates an activity bounded context and moves the following HTTP
endpoint (including the full vertical slice) there:
`/api/latest/fleet/activities`

NONE of the other activity functionality is moved! This is an
incremental approach starting with just 1 API/service endpoint.

A significant part of this PR is tests. This feature is now receiving
significantly more unit/integration test coverage than before.

Also, this PR does not remove the `ListActivities` datastore method in
the legacy code. That will be done in the follow up PR (part 2 of 2).

This refactoring effort also uncovered an activity/user authorization
issue: https://fleetdm.slack.com/archives/C02A8BRABB5/p1768582236611479

# 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

## Release Notes

* **New Features**
* Activity listing API now available with query filtering, date-range
filtering, and type-based filtering
* Pagination support for activity results with cursor-based and
offset-based options
* Configurable sorting by creation date or activity ID in ascending or
descending order
* Automatic enrichment of activity records with actor user details
(name, email, avatar)
* Role-based access controls applied to activity visibility based on
user permissions

<sub>✏️ Tip: You can customize this high-level summary in your review
settings.</sub>

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-01-19 09:07:14 -05:00
Konstantin Sykulev
a5e3c4f5f4
Added cdhash, executable_path and executable_sha256 values to osquery-perf (#38457)
**Related issue:** #33522, #25545

https://github.com/fleetdm/fleet/pull/38118 added `executable_path` and
`executable_sha256` columns to `host_software_installed_paths`.
https://github.com/fleetdm/fleet/pull/29280 added `cdhash_sha256` column
to `host_software_installed_paths`

In order to keep osquery perf realistic, we need to mock this data.

---------

Co-authored-by: Ian Littman <iansltx@gmail.com>
2026-01-16 17:52:02 -08:00
Lucas Manuel Rodriguez
e7759a41c1
Add integration tests for VPP app auto updates (#38337)
Resolves #38111.

I made sure almost all of `handleScheduledUpdates` has coverage:
<img width="1084" height="1078" alt="Screenshot 2026-01-14 at 6 41
14 PM"
src="https://github.com/user-attachments/assets/7899e954-5e89-494d-bc78-2facd09999e0"
/>


0. Checkout this branch.
1. Download
[coverage.txt](https://github.com/user-attachments/files/24625544/coverage.txt)
2. Run `go tool cover -html=coverage.txt`.
2026-01-15 17:03:58 -03:00
Ian Littman
260cadb908
Match VPP proxy client behavior to revised spec (#38215)
# 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)

## Testing

- [x] Added/updated automated tests
- [x] QA'd all new/changed functionality manually
2026-01-14 09:48:58 -06:00
Scott Gress
3907243881
Rename auto-update keys (#38100)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** For #33391

## Testing

- [X] Added/updated automated tests
there's a number of tests for this, if they still pass we're in good
shape
- [X] QA'd all new/changed functionality manually
I tested the front-end successfully, and saw an auto-update go through
on an ipad. Also verified that the activity metadata is correct.
2026-01-12 11:08:26 -06:00
Nico
227bcdf46f
GitOps support for scheduled auto updates settings (#37851)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #35457

# Checklist for submitter

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

### `fleetctl generate-gitops`

**UI**

<img width="1866" height="787" alt="Screenshot 2026-01-07 at 1 14 45 PM"
src="https://github.com/user-attachments/assets/ccb585ee-3074-4ebf-9aaf-6dbdb885cf89"
/>

**Generated YAML**

<img width="694" height="354" alt="Screenshot 2026-01-07 at 1 15 23 PM"
src="https://github.com/user-attachments/assets/3867b63d-265d-43bc-bd60-31fb14e83409"
/>

### `fleetctl gitops`

**Source YAML**

I set the start_time to 18:30 and end_time to 19:30 for the first app

<img width="359" height="354" alt="Screenshot 2026-01-07 at 1 18 33 PM"
src="https://github.com/user-attachments/assets/4cde31e3-aa93-4b75-b296-cc101f507c2a"
/>


After the command ran, verified both on the UI and DB that the new
values were set

<img width="790" height="185" alt="Screenshot 2026-01-07 at 1 18 56 PM"
src="https://github.com/user-attachments/assets/30d9806c-b26c-4f17-b505-facb7fd0df15"
/>

<img width="1432" height="708" alt="Screenshot 2026-01-07 at 1 19 15 PM"
src="https://github.com/user-attachments/assets/5e123f94-ea69-4403-bba3-abf917cc1a01"
/>


## New Fleet configuration settings

- [ ] Setting(s) is/are explicitly excluded from GitOps

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

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
- [x] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485):
a79ff22d84/docs/Configuration/yaml-files.md (L538-L540)
- [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)
- [ ] Verified that any relevant UI is disabled when GitOps mode is
enabled

## fleetd/orbit/Fleet Desktop

- [ ] 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))
- [ ] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes
- [ ] Verified that fleetd runs on macOS, Linux and Windows
- [ ] Verified auto-update works from the released version of component
to the new version (see [tools/tuf/test](../tools/tuf/test/README.md))
2026-01-09 12:17:03 -03:00
Jahziel Villasana-Espinoza
9f29fd1ce9
33509 feature branch (#38038)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #33509

All changes were approved in PRs to this feature branch.

---------

Co-authored-by: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
Co-authored-by: Ian Littman <iansltx@gmail.com>
Co-authored-by: jacobshandling <61553566+jacobshandling@users.noreply.github.com>
Co-authored-by: George Karr <georgekarrv@users.noreply.github.com>
2026-01-08 16:37:46 -05:00
Tim Lee
65adddb000
Renew android certificates backend (#37959) 2026-01-08 13:02:33 -07:00
Zach Wasserman
fac84e5e9b
Use empty values in software last_opened_at when not supported (#38007)
**Related issue:** Resolves #33512 

# 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
2026-01-08 11:36:06 -08:00
Ian Littman
b1915800e2
Add custom VPP app support (#37969)
Resolves #32481 for Fleet server-side work.

# 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
2026-01-08 13:13:04 -06:00
edwardsb
37a2547e79
Fix fleetctl config help display for missing arguments (#37769)
Replace cli.ShowCommandHelp with cli.ShowSubcommandHelp to properly show
usage information when fleetctl config get/set are called without
required arguments. Previously displayed confusing "No help topic for
'get'" error, now shows helpful command help matching --help behavior.
Fixes #36702

## Fix: `fleetctl config get/set` now shows helpful usage information

Fixed the issue where running `fleetctl config get` or `fleetctl config
set` without proper arguments would show a confusing error message.
These commands now display helpful usage information, matching the
behavior of `--help`.

### Before the fix

Running `fleetctl config get` without arguments:

```bash
$ fleetctl config get
Error: No help topic for 'get'
exit status 1
```

### After the fix

Now running the same commands shows helpful usage information:

#### `fleetctl config get` (without arguments)

```bash
$ fleetctl config get
NAME:
   fleetctl config get - Get a config option

USAGE:
   fleetctl config get [options]

OPTIONS:
   --config value   Path to the fleetctl config file (default: "/home/ben/.fleet/config") [$CONFIG]
   --context value  Name of fleetctl config context to use (default: "default") [$CONTEXT]
   --help, -h       show help
```

#### `fleetctl config get invalidkey` (invalid key)

```bash
$ fleetctl config get invalidkey
NAME:
   fleetctl config get - Get a config option

USAGE:
   fleetctl config get [options]

OPTIONS:
   --config value   Path to the fleetctl config file (default: "/home/ben/.fleet/config") [$CONFIG]
   --context value  Name of fleetctl config context to use (default: "default") [$CONTEXT]
   --help, -h       show help
```

#### `fleetctl config set` (without flags)

```bash
$ fleetctl config set
NAME:
   fleetctl config set - Set config options

USAGE:
   fleetctl config set [options]

OPTIONS:
   --config value                                   Path to the fleetctl config file (default: "/home/ben/.fleet/config") [$CONFIG]
   --context value                                  Name of fleetctl config context to use (default: "default") [$CONTEXT]
   --address value                                  Address of the Fleet server [$ADDRESS]
   --email value                                    Email to use when connecting to the Fleet server [$EMAIL]
   --token value                                    Fleet API token [$TOKEN]
   --tls-skip-verify                                Skip TLS certificate validation (default: false) [$INSECURE]
   --rootca value                                   Specify RootCA chain used to communicate with Fleet [$ROOTCA]
   --url-prefix value                               Specify URL Prefix to use with Fleet server (copy from server configuration) [$URL_PREFIX]
   --custom-header value [ --custom-header value ]  Specify a custom header as 'Header:Value' to be set on every request to the Fleet server (can be specified multiple times for multiple headers, note that this replaces any existing custom headers). Note that when using the environment variable to set this option, it must be set like so: 'CUSTOM_HEADER=Header:Value,Header:Value', and the value cannot contain commas. [$CUSTOM_HEADER]
   --help, -h                                       show help
```

#### Normal operation still works as expected

```bash
$ fleetctl config get address
  default.address => http://test.local

$ fleetctl config get --help
NAME:
   fleetctl config get - Get a config option

USAGE:
   fleetctl config get [options]

OPTIONS:
   --config value   Path to the fleetctl config file (default: "/home/ben/.fleet/config") [$CONFIG]
   --context value  Name of fleetctl config context to use (default: "default") [$CONTEXT]
   --help, -h       show help
```


**Related issue:** Resolves #36702

# Checklist for submitter

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

## Testing

- [X] Added/updated automated tests

- [X] QA'd all new/changed functionality manually
2026-01-08 09:55:18 -05:00