Commit Graph
5430 Commits
Author SHA1 Message Date
Magnus Jensen c905e69228 improve validation error messages for custom activations (#50753)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves nothing, just something I caught while doing
test plan and PR review.

# 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. part of a bigger story.

- [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**
  * Improved validation messages for custom activations.
* Clarified that standard configurations must reference exactly one
configuration profile.
* Added a documentation link for the single-profile reference
requirement.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-07 19:03:07 +02:00
Magnus Jensen dd3fda3f3c always update Apple enrollment type correctly (#50689)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #45217

# Checklist for submitter

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

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

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

## Testing

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

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

- **Bug Fixes**
- Fixed Apple device re-enrollment so enrollment types and statuses
update correctly when switching between manual, automated, and personal
enrollment.
- Improved handling of Apple Business Manager assignment changes during
enrollment.
- Preserved existing third-party MDM information while updating
enrollment details.
- Correctly records devices installed through automated enrollment and
keeps enrollment state consistent across check-ins, restores, and
over-the-air enrollment.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-07 19:01:45 +02:00
Carlo 3e166ac42b Fix gofmt formatting in teams_test.go (#50769)
**Related issue:** NA

`main` is currently failing the `lint` job on a stray double blank line
in `server/datastore/mysql/teams_test.go`:

```
server/datastore/mysql/teams_test.go:1209:1: File is not properly formatted (gofmt)
```

This is the `gofmt -w` output and nothing else — one blank line removed,
no code change.

# Checklist for submitter

## Testing

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

Whitespace-only change to a test file; no behaviour to QA. Verified
`gofmt -l` on the file is empty and `go vet ./server/datastore/mysql/`
is clean.
2026-08-07 11:51:12 -03:00
Nico 5a1365dc41 40493 webhooks for host activities (#50595)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #40493

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

# Checklist for submitter

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

## Testing

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



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



## New Fleet configuration settings

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

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

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
- [x] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [x] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)
- [x] Verified that any relevant UI is disabled when GitOps mode is
enabled

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

## Summary by CodeRabbit

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

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

# Checklist for submitter

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

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

## Testing

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



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



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



## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).


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

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

---------

Co-authored-by: Lucas Manuel Rodriguez <lucas@fleetdm.com>
2026-08-07 09:49:14 -03:00
Lucas Manuel Rodriguez 3de43c84af Bump out-of-order migrations not included in v4.90.0 (#50690)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->

Two migrations merged to `main` were not included in the v4.90.0 release
but have timestamps older than
`20260723181411_MultipleCustomPackagesPerTitle` (the latest migration
shipped in v4.90.0). Databases already on v4.90.0 would never apply
them, since goose only runs migrations newer than the current (highest
applied) version.

Bumped both to current timestamps via `tools/bump-migration`:

- `20260721090128_AddTokenInvalidToABMTokens` →
`20260806154139_AddTokenInvalidToABMTokens`
- `20260721160351_AddHostMDMWindowsProfilesStatus` →
`20260806154150_AddHostMDMWindowsProfilesStatus`

No schema or logic changes — only the file names,
`Up_`/`Down_`/`TestUp_` function names, and the regenerated `schema.sql`
(`migration_status_tables` versions). Verified that none of the other
unreleased migrations (20260724+) depend on the schema these two create,
so applying them last is safe.

# Checklist for submitter

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

## Testing

- [x] Added/updated automated tests (existing migration tests renamed
and re-run against MySQL)

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [x] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).


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

- **Database Updates**
  - Added support for tracking whether ABM tokens are invalid.
- Added Windows MDM profile status tracking and backfilled existing
records.
- **Maintenance**
- Updated database migration identifiers and status records to ensure
migrations are applied consistently.
- **Tests**
- Updated migration verification tests to match the revised migration
identifiers.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-07 08:40:19 -03:00
Rajendra Kadam 25cfac309c Let an edit clear a declaration's activation (#50711)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #

Raised by the frontend while building the Edit modal: there was no way
to clear a declaration's custom activation. An absent `activation` field
meant "keep it" on a labels-only edit but "delete it" when the profile
contents were replaced, so clearing wasn't expressible and an ordinary
content edit silently dropped the activation.

The field is now three-state:

| Request | Result |
|---|---|
| no `activation` key | stored activation left alone |
| `activation` as an empty value | removed |
| `activation` as a file | replaced |

Multipart has no null, so an empty value stands in for one.

Note this changes one existing behaviour: replacing a profile's contents
without sending an activation used to delete it, and now preserves it.
Removal has to be explicit.

Anything ambiguous is rejected rather than guessed at, since every
ambiguous form would otherwise resolve to deleting the stored
activation:

| Request | Result |
|---|---|
| `activation` as a nonempty value | 422 — more likely a malformed
upload than a request to delete |
| `activation` as a zero-byte file | 422 — a failed upload shouldn't
delete anything |
| `activation` sent as both a file and a value | 422 — one says replace,
the other says remove |

The unsupported-profile check also keys on the field being present
rather than on it carrying content, so clearing an activation on a
Windows, Android or mobileconfig profile is rejected instead of quietly
succeeding.

On the datastore side, `SetOrUpdateMDMAppleDeclaration` now takes an
explicit action (`MDMAppleActivationKeep` / `MDMAppleActivationApply`)
instead of inferring intent from the struct. The write is a full
replace, so "keep" has to be stated — otherwise preserving the
activation would mean reading it back and handing it to the write, which
also risked dropping its Fleet variable associations. As a side effect
the OS updates cron no longer fires a DELETE for an activation it never
had.

# Checklist for submitter

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

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

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

## Testing

- [x] Added/updated automated tests

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

Integration test covers all three states end to end through the
multipart decoder, plus service-level tests for preserve and explicit
removal.


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

* **New Features**
* Apple MDM declaration updates now support preserving, replacing, or
explicitly removing activation settings.
* Omitted activation fields leave existing settings unchanged, while
empty fields remove them.
  * Apple OS update declarations retain activation settings by default.

* **Bug Fixes**
* Labels-only updates no longer unintentionally carry forward activation
data.
* Invalid, empty, or conflicting activation uploads now receive clear
validation errors.
  * Unsupported profile types now reject activation updates.

* **Tests**
* Added coverage for activation preservation, replacement, removal, and
integration scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-07 15:36:31 +05:30
Dante Catalfamo 3c8df41762 Deduplicate Android MDM Pub/Sub deliveries and protect against reordering (#49792)
**Related issue:** Resolves #43502
2026-08-06 17:24:54 -04:00
Juan Fernandez e29210e6f6 Software inventory & vulnerabilities: Add Adobe plugins
Resolves #45414 

- Added Adobe plugins to software inventory: Fleet now detects Adobe Creative Cloud plugins (CEP and UXP extensions) on macOS and Windows hosts and lists them on the Software page and host details with the software type "Plugin (Adobe)", including version and host count.
- Adobe plugins are excluded from vulnerability scanning, so no vulnerabilities are reported for them. No vulnerability data source maps an Adobe CEP or UXP extension to a CVE; Adobe files CVEs against the host application (Photoshop, Acrobat, and so on), which Fleet already scans.
2026-08-06 17:01:07 -04:00
Victor Lyuboslavsky 3d186bd172 Clear the escrowed managed local account password on MDM re-enrollment (#50596)
Fixed unreleased bug where admin password was still shown on a wiped
host after re-enrollment.

Add a `deleted` column and soft-delete the row on re-enrollment,
mirroring host_recovery_key_passwords.

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

# Checklist for submitter

## Testing

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

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.

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

## Summary by CodeRabbit

* **New Features**
* Added support for safely retiring managed local account passwords
during device re-enrollment.
* Retired credentials are excluded from retrieval, status updates,
command operations, and automatic rotation.
* Successfully escrowing a password can restore a previously retired
record.

* **Bug Fixes**
  * Re-enrollment cleanup now clears stale password rotation state.
* Cleanup failures stop reset or re-enrollment processing to prevent
incomplete credential changes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 15:03:46 -05:00
Jordan Montgomery 133e4a3832 Tweak manual enroll profile permissions (#50688)
<!-- 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.

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

## Testing

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

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

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

## Summary by CodeRabbit

* **Bug Fixes**
* Restricted access to manual MDM enrollment profiles to global or team
administrators and maintainers.
* Prevented unauthenticated, roleless, observer, and GitOps users from
viewing enrollment profile data.
* Updated authorization documentation to reflect the required
permissions.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 14:00:49 -04:00
Rajendra Kadam a2aec82466 Support custom DDM activations in GitOps (#50557)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #49972

Adds custom DDM activations to the GitOps workflow. A profile entry can
point at an activation file with a new `activation` key, the batch
endpoint validates and stores it through the same code as the
single-profile upload, and `fleetctl generate-gitops` exports it back
out.

```yaml
controls:
  macos_settings:
    custom_settings:
      - path: ./lib/profiles/passcode.json
        activation: ./lib/activations/passcode.json
```

`activation` is only valid on a declaration (`.json`) profile, and can't
be combined with `paths:` because an activation names exactly one
declaration. Removing the key removes the stored activation.

# Checklist for submitter

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

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

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

## Testing

- [x] Added/updated automated tests

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

Verified on an ADE-enrolled Mac: exported an existing declaration and
its custom activation with `generate-gitops`, removed everything by
applying a config with no profiles, then re-applied the exported files.
All three declarations came back with the correct scopes, the activation
attached to only its own declaration, and the predicate was reported
correctly on the host.

## New Fleet configuration settings

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
- [x] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [x] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)
2026-08-06 23:10:13 +05:30
Rajendra Kadam 984b09cc7f Serve custom DDM activations to devices (#50421)
**Related issue:** Resolves #49971

Serves the custom activations stored by #49970 to devices. Stacked on
#50280.

- The manifest advertises a custom activation's own identifier; the
fetch serves its stored JSON with the predicate intact. Secrets and host
variables are expanded at delivery, like configurations.
- `activation_updated_at` folds into the token, so editing only a
predicate re-syncs the host even though the declaration's content didn't
change.
- Management declarations are served under the manifest's `Management`
section, have their own endpoint, and report status.
- Predicate outcomes map per the Figma dev note: `Info.Predicate` →
verified with an explanation, `Error.ActivationFailed` → failed.

### Three things to look at

**Generated activations are renamed to `<declaration
uuid>.activation`.** Removes the collision between an admin-chosen
identifier and one Fleet generates, and collapses the fetch into a
single lookup rather than match-then-trim. Note this differs from the
CoS wording of "byte-for-byte identical to today".

Existing hosts will see their activations renamed once. The sync token
doesn't move for the rename alone — activation identifiers aren't part
of it, confirmed in `MDMAppleDDMDeclarationsToken` — so it happens
lazily on the next real DDM change rather than all at once.

**`activation_updated_at` is not the `max()` the issue describes.** The
issue asks for `max(activation uploaded_at, latest variable change)`.
Variable changes stay on `variables_updated_at`; this is
`GREATEST(uploaded_at, secrets_updated_at)`. Same outcome, since
`EffectiveDDMToken` hashes all the timestamps together, but each signal
stays independently comparable, which is what keeps the reconciler
idempotent.

**The token is computed in three places, not two.** SQL in
`MDMAppleDDMDeclarationsToken`, Go in `EffectiveDDMToken`, and a third
independent copy building the manifest-level token in
`handleDeclarationItems`. All three now carry the new term in the same
order. `ActivationUpdatedAtFoldsIntoToken` asserts the SQL and Go agree
with it populated — they only agreed for the nil case before.

# Checklist for submitter

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

## Testing

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

Tested on an ADE-enrolled Mac (macOS 26.5.1) against a local server: the
custom activation is advertised and fetched by its own identifier, an
activation-only edit re-syncs the device even though the declaration is
unchanged, a true predicate enforces the policy on the host, and a false
one comes back verified with the explanation.

That turned up two bugs, both fixed here and both invisible to the test
suite:

- `MDMAppleStoreDDMStatusReport` computed the matching token with
`activation_updated_at` but never selected the column, so it was always
nil. Every status report was silently dropped and profiles sat in
verifying forever.
- Apple splits a predicate outcome across two arrays — the activation
reports `Info.Predicate`, the configuration it gates reports
`Error.ActivationFailed`. Reading only the configuration made a host the
predicate excluded look failed. Now correlated via the activation
identifier in the failure details.

The test payloads for the second one are the real reports the Mac sent,
not hand-written.

Note for anyone testing in the UI: the OS settings tooltip for a
verified profile is hardcoded to "The host applied the setting. Fleet
verified." and doesn't read `detail` yet, so a predicate-excluded
profile reads wrong there. Backend stores the right message; rendering
it is #49973.

New cases in `apple_mdm_ddm_test.go`: the token agreement above; a
custom activation advertised and served with its predicate, with the
generated name no longer resolving for it; a declaration without one
still getting the synthesized activation; management routing plus the
endpoint type guard; the three predicate status outcomes; and a host
outside a declaration's scope getting an empty manifest and an error
fetching the activation by name.

13 existing assertions moved from `<identifier>.activation` to
`<uuid>.activation`.

The `GeneratedActivationStillServedWhenNoCustomOne` case caught a real
bug on its first run: the `LEFT JOIN` returns NULL for declarations
without a custom activation, which `json.RawMessage` can't scan, so
every non-custom activation fetch would have 500'd. That's the
no-regression path.



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

* **New Features**
* Added Apple DDM management declarations and custom activation
delivery.
* Added host-scoped activation resolution, activation identifiers, and
activation update timestamps.
* Added support for activation variables, secrets, assets, and separate
management and configuration endpoints.

* **Bug Fixes**
* Declarations are now redelivered when activation predicates change or
are removed.
* Improved status reporting for predicate exclusions, activation
failures, and management declarations.
* Improved synchronization token updates when variables, assets, or
activations change.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 23:02:20 +05:30
Dhvanit a6b541d029 Fix error handling on the os_versions API endpoint (#49899)
**Related issue:** Resolves #49483

## What & why

The `/os_versions` API endpoint returned misleading success responses
for three invalid inputs. This PR makes each return a proper error:

1. **Invalid `platform` filter** (e.g. `?platform=notrealplatform`)
previously returned `count: 0` with `200 OK`, indistinguishable from "no
matching OS versions." It now returns a `422` validation error listing
the supported platforms (`darwin`, `windows`, `linux`, `chrome`, `ios`,
`ipados`, `android` — matching the documented filter values).

2. **Unknown OS version id** (e.g. `/os_versions/99999`) previously
returned `200 OK` with a null/zero-filled `os_version` object. It now
returns a not-found (`404`) error.

3. **Negative `max_vulnerabilities`** (e.g. `?max_vulnerabilities=-5`)
returned a message reading `must be >= 0` — Go's JSON encoder
HTML-escapes `>`. The message is reworded to `max_vulnerabilities cannot
be negative`, which is clearer and avoids the escaped character.

### ⚠️ Note for reviewer (fix #2)
The single-version handler previously swallowed the datastore's
not-found error and returned an empty result on purpose, with the
comment: *"It is possible the os version exists, but the aggregation job
has not run yet."* This PR removes that swallow so a missing id returns
`404`. If you'd prefer to preserve the empty-result behavior for the
"not yet aggregated" case, I'm happy to adjust — flagging so the change
is intentional and visible.

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`.
- [x] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented.

## Testing

- [x] Added/updated automated tests (`TestOSVersionsErrorHandling` in
`server/service/hosts_test.go`, covering all three cases).
- [x] QA'd all new/changed functionality manually

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

* **Bug Fixes**
* Unsupported OS platform filters now return a clear validation error
instead of an empty-like result.
* Unknown OS version IDs now return HTTP **404 Not Found** rather than a
success response with null/zero fields.
* `max_vulnerabilities` validation now rejects negative values with an
accurate, readable message and consistent HTTP **422** responses.
* Error responses for OS versions endpoints now reflect the correct
status codes.
* **Tests**
* Updated and added coverage to assert the new error-handling and HTTP
status expectations.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 12:08:04 -03:00
Carlo aac22ec9bc Align software installer authorization (#50630)
Software title details now return installer scripts and managed app
configuration only to users who can read the installer. Uninstalling
software from the My device page now applies the same self-service and
label scope rules as installing.

# 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


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

* **Security & Permissions**
* Restricted installer scripts, managed-app settings, and related
configuration to authorized viewers.
* Preserved package metadata while hiding sensitive installation details
from unauthorized roles.
* Improved access handling for requests without an assigned team or
involving inaccessible fleets.

* **Bug Fixes**
* Updated device-initiated software removal to honor self-service
eligibility and label scope.
* Added clearer errors when software is unavailable for self-service or
outside the device’s scope.
* Prevented software titles from inaccessible fleets from appearing in
results.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 11:04:31 -04:00
Lucas Manuel Rodriguez 58a7679144 Add support for nested Entra groups in IdP vitals (#50469)
Resolves #48886.

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

## Database migrations

- [X] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [X] Confirmed that updating the timestamps is acceptable, and will not
cause unwanted side effects.
- [X] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).

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

* **New Features**
  * Added support for nested groups in Entra IDP vitals.
* SCIM groups can now include child groups and resolve membership across
multiple levels.
* Host filters and group-based access now account for inherited group
memberships.
* Added validation and duplicate prevention for nested group membership
updates.

* **Bug Fixes**
* Corrected membership updates and removals to keep nested group
relationships synchronized.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 11:28:43 -03:00
Magnus Jensen 479c4da287 AULD: Backend OS update cron + variable resolution (#50573)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #47715 

# Checklist for submitter

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

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

## Testing

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

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

* **New Features**
  * Added automatic Apple OS update synchronization and reconciliation.
* Apple devices can receive targeted minimum OS versions and enforcement
deadlines.
  * Host details now display applicable Apple OS update requirements.
* Updates are selected based on device compatibility, platform, and team
configuration.
* Cached update information is refreshed and stale entries are removed.
  * Pending targets are retried, with declarations resent when resolved.
* **Bug Fixes**
  * Improved handling of unavailable targets and unsupported devices.
* Prevented unresolved update declarations from being incorrectly marked
as failed.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 15:47:22 +02:00
Jordan Montgomery 5813dd268b 47865: Update exclude/include all label logic for unknown label status (#50493)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #47865 

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

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


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

- **Bug Fixes**
- Improved MDM profile and declaration reconciliation for Android,
Apple, and Windows devices when dynamic label membership is temporarily
unknown.
- Existing installations are preserved while awaiting authoritative
label results.
  - New installations are withheld until label membership is confirmed.
- Confirmed label changes continue to trigger the appropriate
installation or removal actions.
  - Improved handling of combined include and exclude label rules.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-06 09:13:55 -04:00
Rachael Shaw bfa766e9b7 v4.90.0 doc changes (#48141) 2026-08-05 20:38:39 -05:00
Magnus Jensen c348feb0d5 fix asset reference issue on ddm upsert with no change (#50638)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves nothing, just something I found.

# 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. (None, as editing profiles is only just released)

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


TO test upload a DDM profile referencing an asset, then try to edit that
profile with identical DDM contents and see mysql error, this PR fixes
that.

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

* **Bug Fixes**
* Improved Apple device management declaration updates to preserve the
existing declaration identity.
* Correctly synchronizes linked asset references when declarations are
updated, including removing outdated references and clearing all
references when none remain.
* **Tests**
* Added coverage for creating, preserving, updating, removing, and
clearing declaration asset references.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 23:50:47 +02:00
Jonathan Katz a0805e49d8 Add software installer file size check before upload (#50475)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #42735 
- Exposes max_software_package_size in the `GET /api/v1/fleet/config`
endpoint
- Add frontend logic to use it to deny files that are too big before
they get uploaded

# Checklist for submitter

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

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

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

## Testing

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

- [x] QA'd all new/changed functionality manually
  - Tested on Chrome, Safari, and Firefox on macOS


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

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

* **Tests**
* Added coverage for upload validation, boundary conditions, size
formatting, and configuration responses.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 15:57:20 -04:00
Magnus Jensen 1abeb175f3 AULD: Enrollment insert and backfill osquery query (#50131)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #47714 

# Checklist for submitter

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

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

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

## Testing

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

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

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

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

## Testing

- [x] Added/updated automated tests

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


## New Fleet configuration settings

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

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

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`

- [x] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)


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

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

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

---------

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

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

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

### Custom activations

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

What an edit does to a stored activation:

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

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

### Management declarations

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

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

### Notes for review

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

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

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

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

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

# Checklist for submitter

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

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

## Testing

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

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

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

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

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

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


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

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

- **Validation**
- Added checks for declaration matching, supported profile types, file
limits, and Premium licensing.
- Clear errors are provided when activations are used with management
declarations or non-DDM profiles.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-05 15:29:52 +05:30
Victor Lyuboslavsky a4af4d896c Add default fleet for new Windows MDM enrollments (#41787) (#49922)
Demo: https://www.youtube.com/watch?v=cWxZlu9WuwA
Guide updates: https://github.com/fleetdm/fleet/pull/49603/changes

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

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

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

# Checklist for submitter

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

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

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

## Testing

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

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

## Database migrations

- [x] Checked schema for all modified table for columns that will
auto-update timestamps during migration.
- [x] Ensured the correct collation is explicitly set for character
columns (`COLLATE utf8mb4_unicode_ci`).

## New Fleet configuration settings

- [x] Verified that the setting is exported via `fleetctl
generate-gitops`
- [x] Verified the setting is documented in a separate PR to [the GitOps
documentation](https://github.com/fleetdm/fleet/blob/main/docs/Configuration/yaml-files.md#L485)
- [x] Verified that the setting is cleared on the server if it is not
supplied in a YAML file (or that it is documented as being optional)
- [x] Verified that any relevant UI is disabled when GitOps mode is
enabled

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

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

* **Documentation**
  * Documented default-fleet assignment for Windows enrollment.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 16:30:02 -05:00
Victor Lyuboslavsky bd601fff84 Fixed nilaway issues (#50405)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #50404 

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

# Checklist for submitter

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

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

## Testing

- [x] Added/updated automated tests

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


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

* **Improvements**
* Improved software inventory filtering for self-service and macOS
applications, producing more accurate results.
* Improved application configuration updates so saved settings and
related system changes are processed more reliably.
* **Quality**
* Added automated checks to identify overly complex functions and help
maintain code quality.
* Updated static analysis tooling and expanded validation coverage with
new tests.
* **Documentation**
* Added a changelog entry describing the latest reliability and
maintainability improvements.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 15:41:18 -05:00
Dante Catalfamo f17c8cbd8d Bound Google Workspace directory sync pagination (#50092)
**Related issue:** Resolves #49365
2026-08-04 11:36:02 -04:00
Juan Fernandez 60ad78f897 Add Omarchy as a supported Linux platform
Resolves #50069

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

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

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

Also add a fleetd test container, built on archlinux since Omarchy
publishes no image.
2026-08-04 10:32:44 -04:00
Juan Fernandez d92b7284d0 Trigger software_checksum_migration on startup
Relates #36365

Makes the software_checksum_migration cron to run
automatically on server startup.
2026-08-04 09:35:36 -04:00
Lucas Manuel Rodriguez f053a9fd49 Allow enabling/disabling software inventory per-fleet via the API (#50481)
Resolves #45735.

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

## Testing

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

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

## Summary by CodeRabbit

* **New Features**
* Team settings can now enable or disable Software Inventory through API
updates.
* Partial updates preserve existing settings when the Software Inventory
option is omitted.
* Software Inventory configuration can be re-enabled after being
disabled.

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

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

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

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

# Checklist for submitter

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

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

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

## Testing

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

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

- **Bug Fixes**
- Fixed Apple MDM profile handling for devices that respond with “Not
Now” by ensuring the response is issued only on first delivery and
doesn’t trigger repeated retries.
- Improved reconciliation so superseded InstallProfile commands are
properly canceled and cleanup is correct for user-scoped and pending
installs.
- When host verification fails after an acknowledged install, devices
now receive the appropriate RemoveProfile operation.
- **Tests**
- Added regression integration coverage for “Not Now” cancellation,
scope changes, profile edits, undelivered installs, and failed
verification cleanup.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-04 09:40:20 +02:00
Sharon Katz 301e0e009b Improve Windows profile LocURI content validation (#49715)
**Related issue:** Resolves fleetdm/confidential#16881

# 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.
- [ ] Timeouts are implemented and retries are limited to avoid infinite
loops
- [ ] If paths of existing endpoints are modified without backwards
compatibility, checked the frontend/CLI for any necessary changes

## Testing

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

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

For unreleased bug fixes in a release candidate, one of:

- [ ] Confirmed that the fix is not expected to adversely impact load
test results
- [ ] Alerted the release DRI if additional load testing is needed

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

* **Bug Fixes**
* Improved Windows MDM validation for `LocURI`, ensuring full values are
considered before checks.
  * Rejects empty or whitespace-only `LocURI` entries.
* Strengthens `LocURI` validation for Fleet-reserved, SCEP-specific, and
BitLocker-related formats after complete assembly.

* **Tests**
* Added new test cases for malformed BitLocker `LocURI` values split
across CDATA and XML comment boundaries.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 13:39:38 -04:00
Victor Lyuboslavsky 05bc7be89e Add Windows managed local admin account support to fleetd (#50088)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #48723 

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

## Testing

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

## fleetd/orbit/Fleet Desktop

- [x] 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 (did not do
macOS, but should be the same as Linux)
- [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

* **New Features**
* Added support for Fleet-managed local administrator accounts on
Windows.
* When enabled, creates or updates a hidden `_fleetadmin` account,
securely generates a password, and escrows it to Fleet.
* Reports provisioning errors and supports safe retries without blocking
other configuration updates.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 11:15:20 -05:00
Victor Lyuboslavsky 98060b08a6 Add Windows managed local account server flow (#48721) (#49924)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #48721 

Part 2 of https://github.com/fleetdm/fleet/issues/43488

# Checklist for submitter

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

## Testing

- [x] Added/updated automated tests

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

## Database migrations

- [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**
* Windows devices can now create and securely escrow managed local
account passwords during enrollment.
* Added Windows managed local account status and password availability
to host details.
  * Device-reported setup errors are surfaced with helpful details.
* Account creation is automatically requested when supported by the
device, plan, and configuration.
* **Bug Fixes**
  * Windows accounts are excluded from password rotation workflows.
  * Re-enrollment correctly triggers account creation when needed.
  * Passwords remain available when settings change after enrollment.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-03 09:03:27 -05:00
Juan Fernandez 6c3de12f69 Base Orbit enrollment end user auth on server policy
EnrollOrbit now determines end user authentication requirements from
server policy rather than the client-supplied X-Fleet-Capabilities
header, which is treated as an informational hint.
    
Adds the mdm.allow_orbit_end_user_auth_bypass setting (enabled by
default) controlling whether hosts that do not complete end user
authentication may enroll into a team that requires it; set it to false
to strictly enforce end user auth. The setting also governs installers
built with fleetctl package --bypass-end-user-auth.
2026-08-03 07:40:48 -04:00
Lucas Manuel Rodriguez 001b57cb9d Optimize memory usage in CVE chart cron job (#50385)
Resolves #50266.

At production numbers the table looks like this - 20,691 CVEs × 83,000
hosts, ~268M raw (cve, host) rows (software + OS joins combined):
```
┌─────────────────────────┬─────────────────────────┬───────────────────────┐
│    Shape of host IDs    │ Old (map[string][]uint) │ New (roaring bitmaps) │
├─────────────────────────┼─────────────────────────┼───────────────────────┤
│ Dense (contiguous runs) │ 2,479 MB                │ 4.5 MB                │
├─────────────────────────┼─────────────────────────┼───────────────────────┤
│ Sparse (random)         │ 2,488 MB                │ 282 MB                │
└─────────────────────────┴─────────────────────────┴───────────────────────┘
```

A few things worth noting about how these map to your real data:

- The old cost is shape-independent: ~2.5 GB retained just for the
result map (268M rows × 8 bytes plus append slack), and the peak during
collection is higher still because append doubling leaves garbage
behind. That's the number that was blowing up the cron.
- The new sparse figure is an overstated worst case. Your 268M rows
include duplicates — multiple vulnerable software rows per host for the
same CVE (the multi-kernel case) and overlap between the software and OS
joins. The old code retained every raw row; the bitmap dedupes on Add,
so it's bounded by unique pairs, and real fleets with AUTO_INCREMENT
host IDs sit much closer to the dense row than the sparse one.
- The new representation also has a hard ceiling the old one doesn't: a
roaring bitmap over 83k host IDs maxes out around 16 KB per CVE
regardless of contents, so even a pathological dataset caps at ~330 MB
for all 20,691 CVEs — versus the old form growing linearly with join
rows, unbounded.

TL;DR: At scale the change is roughly a 550× reduction in the realistic
(dense) case, and at minimum ~9× in the theoretical worst case.

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

For unreleased bug fixes in a release candidate, one of:

- [X] Confirmed that the fix is not expected to adversely impact load
test results
- [X] Alerted the release DRI if additional load testing is needed

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

## Summary by CodeRabbit

- **Performance**
  - Reduced memory usage for CVE chart data collection.
- Improved efficiency when processing large CVE and affected-host
datasets.

- **Bug Fixes**
- Preserved correct CVE filtering, duplicate-host handling,
disabled-fleet exclusions, and empty-result behavior.
- Added coverage for CVEs sourced from both software and
operating-system data.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-02 14:16:34 -03:00
Victor Lyuboslavsky f7ffc07062 Improved software ingestion performance (#50354)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #50305 

# Checklist for submitter

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

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

## Testing

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

For unreleased bug fixes in a release candidate, one of:

- [x] Alerted the release DRI if additional load testing is needed


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

## Summary by CodeRabbit

* **Performance Improvements**
* Improved software ingestion performance by optimizing software title
lookups.
* Reduced unnecessary database scanning while preserving matching for
bundle identifiers, names, and Windows upgrade codes.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-08-01 07:20:05 -05:00
Jonathan Katz 45abf8c9ad Add software installer upload/download progress to GitOps runs (#50250)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** Resolves #45728
Changes:
- Adds a new redis key to keep track of downloaded packages. It starts
out with an empty list and gets filled with each download. Each update
writes the entire struct at once to the key.
- Adds logging in the fleetctl gitops client to show which packages were
downloaded
- Fixes the categories key potentially expiring 

# Checklist for submitter

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

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

- [ ] Input data is properly validated, `SELECT *` is avoided, SQL
injection is prevented (using placeholders for values in statements), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.
-  Timeouts are implemented and retries are limited to avoid infinite
loops
- Right now the batch will write the whole slice of all packages to a
single redis key for every package in the loop. Looks like performance
is acceptable for now (500 packages), but maybe this will need to be
limited.
- [ ] 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



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

## New Features
- Added per-package software download progress in fleetctl GitOps.
- Progress now reports downloading, completed, skipped, and failed
packages during real and dry runs.
- Installation output now distinguishes applying and applied stages.

## Bug Fixes
- Improved download error messages and cached-package handling.
- Prevented duplicate progress messages and ensured tracking issues do
not interrupt successful software batches.

## Tests
- Expanded coverage for progress reporting, failures, dry runs, package
types, and authorization scenarios.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 21:36:44 -04:00
Dante Catalfamo 2fd2a02e2d Split MDM platform helpers by Android semantics (#50185)
**Related issue:** Resolves #46118
2026-07-31 15:52:19 -04:00
Luke Heath cb44e287f2 Fix high-severity CodeQL and Scorecard code scanning alerts (#50333) 2026-07-31 14:46:31 -05:00
Lucas Manuel Rodriguez 0dc8c382c5 Add 'linux' as platform for labels (#50270)
Resolves #44088.

- [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), JS
inline code is prevented especially for url redirects, and untrusted
data interpolated into shell scripts/commands is validated against shell
metacharacters.

## Testing

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

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

* **New Features**
  * Added Linux as a label platform option.
* Linux labels now apply across supported distributions, including
Ubuntu, Debian, RHEL, CentOS, and generic Linux hosts.
  * Updated platform names for improved clarity and consistency.

* **Bug Fixes**
* Improved platform matching so Linux labels apply consistently to
compatible hosts.
  * Removed the obsolete Zorin platform option.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 15:02:57 -03:00
Bas Bleijerveld 60e6827071 Fix Apple built-in label memberships during ADE (#50287)
**Related issue:** Resolves #50285

## Summary

- Restore the `All Hosts` and Apple platform built-in label memberships
in the same transaction that clears stale host state during Automated
Device Enrollment (ADE).
- Backfill missing built-in memberships for existing macOS, iOS, and
iPadOS hosts.
- Add regression coverage confirming that an iPadOS update declaration
remains targeted and reaches verified status after the enrollment reset.

# 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), 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 host's records do not affect another)
- [ ] QA'd all new/changed functionality manually

Automated verification:

```sh
MYSQL_TEST=1 go test -run 'TestMDMApple/MDMAppleResetOnReenrollment' ./server/datastore/mysql
MYSQL_TEST=1 go test -run TestUp_20260731100711 ./server/datastore/mysql/migrations/tables
MYSQL_TEST=1 go test -run 'TestIntegrationsMDM/TestIPadOSUpdateDeclarationAfterMDMReset' ./server/service
go test -run TestMDMTokenUpdateResetOnReenrollment ./server/service
go vet ./server/datastore/mysql ./server/service
go build ./server/datastore/mysql/migrations/...
make test-schema
```

## Database migrations

- [x] Checked schema for all modified tables for columns that
auto-update timestamps during migration.
- [x] Confirmed that timestamp behavior is acceptable and will not cause
unwanted side effects. The migration inserts only missing memberships
and leaves existing membership timestamps unchanged.

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

## Summary by CodeRabbit

* **Bug Fixes**
* Apple devices now retain their built-in label memberships after
Automated Device Enrollment or MDM reset.
* Label-scoped profiles, software, and operating system updates can now
continue to be delivered after a reset.
* Platform-specific memberships are restored for macOS, iOS, and iPadOS
devices, including applicable hosts with unspecified platforms.
* iPadOS update declarations now reconcile successfully after an MDM
reset.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 16:50:03 +02:00
Nico 7f1b330c90 Restrict deleting a fleet to global admins (#50271)
# 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


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

* **Bug Fixes**
* Restricted fleet deletion to users with global write permissions,
including global administrators and GitOps.
* Corrected team deletion authorization to require global write access.
* Prevented global technicians, team technicians, and observer-level
users from deleting teams.
* Updated authorization behavior to consistently enforce the required
access level.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 08:43:51 -03:00
Rajendra Kadam 9d0f510a8d Add DDM custom activations schema (#50133)
**Related issue:** Resolves #49966

Adds the schema for custom DDM activations (parent story #48222).

- **Creates `mdm_apple_ddm_activations`** — stores the activation JSON
as-is (`mediumtext`, so the generated `token` column hashes the exact
stored bytes) with a `declaration_uuid` FK to `mdm_apple_declarations`
that cascades on delete.
- **Extends `mdm_configuration_profile_variables`** with
`apple_ddm_activation_uuid` so activations can carry Fleet variables
(needed by #49970).
- **Adds `activation_updated_at`** to `host_mdm_apple_declarations` so a
changed activation regenerates the declaration's effective token,
mirroring `variables_updated_at` / `assets_updated_at`.
- **Drops `mdm_apple_declaration_activation_references`** — created with
the original DDM tables in `20240327115530_AddDDMTables.go`, never
written to by any code path, so it is empty in every deployment.

### Deviations from the SQL in #49966

The `declaration_uuid` FK is the one addition, [confirmed with
@MagnusHJensen](https://github.com/fleetdm/fleet/issues/49966): it keeps
the 1:1 lifecycle enforced by the database rather than requiring cleanup
in every delete path. `configuration_identifier` is kept alongside it
for validation and DDM serving. Its unique key doubles as the FK's
backing index.

The rest are corrections needed for the specced SQL to work, all
following the precedent in `20260409153715_AddDDMVariablesSupport.go`:

- **`ck_mdm_configuration_profile_variables_exactly_one` is dropped and
re-added** to count the new column. That constraint requires exactly one
owner column to be non-null; adding a seventh without updating it means
any row setting `apple_ddm_activation_uuid` sums to 0, fails the check,
and is rejected.
- **`UNIQUE (apple_ddm_activation_uuid, fleet_variable_id)` added** to
match the six existing owner columns. That table's write path is `INSERT
... ON DUPLICATE KEY UPDATE`, which needs a unique key to collide on.
- **`activation_updated_at` is `DATETIME(6)`, not `TIMESTAMP(6)`** — its
siblings are `datetime(6)` and `EffectiveDDMToken` formats them into the
token string, so `TIMESTAMP`'s session-timezone conversion on read would
change tokens and re-push declarations to every host.
- **`team_id` gets `DEFAULT '0'`** to match `mdm_apple_declarations`,
where 0 is Unassigned.

### Note for #49970

`declaration_uuid` is `NOT NULL`, so the upload path must populate it in
addition to `configuration_identifier`. The declaration UUID prefix has
no separator (`MDMAppleDeclarationUUIDPrefix = "d"`, 1 char + 36-char
UUID = the full `varchar(37)`).

# Checklist for submitter

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

No changes file: this sub-task adds schema only and ships no
user-visible behavior.

## Testing

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

`TestUp_20260729115013` covers: the stale table is present before and
gone after; pre-existing `mdm_configuration_profile_variables` rows
survive the check constraint replacement (that `ADD CONSTRAINT`
revalidates every existing row); an activation attaches to a declaration
and gets its generated token; the 1:1 unique key and the FK both reject
bad inserts; a variable row binds to an activation (the case the old
constraint would have rejected); the constraint still rejects two-owner
and zero-owner rows; and deleting the declaration cascades to the
activation and through it to the activation's variable rows.

Also ran the full migrations suite (`MYSQL_TEST=1 go test
./server/datastore/mysql/migrations/...`) to confirm no other migration
is disturbed, and verified the regenerated `schema.sql` diff contains
only changes from this migration.

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

Neither modified table has an `ON UPDATE CURRENT_TIMESTAMP` column, so
no rows have their timestamps touched.


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

## Summary by CodeRabbit

* **New Features**
  * Added support for Apple DDM custom activations.
* Added activation-specific tokens and timestamps to support reliable
declaration updates.
* Enabled configuration variables to be associated with a specific
activation.
* Added validation to prevent duplicate or invalid activation
associations.
* Activations and related settings are now automatically removed when
their declaration is deleted.

* **Tests**
* Added coverage for activation creation, uniqueness, validation,
associations, token generation, and cascading cleanup.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-31 14:36:15 +05:30
Carlo a442d7af3a Python script-only packages: follow-on QA fixes (#50143)
**Related issues:** Resolves #50068, Resolves #50106, Resolves #50107,
Resolves #50108, Resolves #50110, Resolves #50114

Follow-on fixes from QA of #41470 (Python script-only packages):

- Software-installer validation errors are action-neutral, so the Add
and Edit flows each show the correct single verb, and the
unsupported-file error names a content/format mismatch instead of
blaming the extension (#50068, #50107).
- `.py` packages accept `setup_experience_platform` (`darwin`/`linux`),
matching `.sh` (#50106).
- A failed-to-run install script (exit code `-1`) now renders a
diagnostic instead of empty output, and orbit surfaces the underlying
execve error (#50108).
- The install-rejection message for `.sh`/`.py` packages says "macOS and
Linux hosts" instead of "linux" (#50110).
- Orbit writes each script's temp file with an extension matching its
shebang (`.py`/`.sh`/`.ps1`), so tracebacks reference the right file
type (#50114).

# Checklist for submitter

- [x] Changes file added for user-visible changes in `changes/`.

## Testing

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

## fleetd/orbit/Fleet Desktop

- [x] If the change applies to only one platform, confirmed that
`runtime.GOOS` is used as needed to isolate changes.
- [x] Verified compatibility with the latest released version of Fleet
(orbit-only change; the server↔agent `SoftwareInstallDetails` contract
is unchanged).


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

* **Bug Fixes**
* Improved installer validation and rejection messaging for
unsupported/invalid package contents (including correcting “add” vs
“edit” wording and avoiding duplicated phrasing).
* Added clearer diagnostics when install scripts fail to start
(including empty output cases).
* Corrected handling of script-only packages so Python scripts use the
proper script type/extension, reducing misleading tracebacks.
* Updated platform availability messaging so `.sh`/`.py` packages
display macOS+Linux support.
* **New Features**
* Python script-only packages can now specify macOS and Linux setup
experience platforms.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-30 14:40:24 -04:00
Carlo 294a172d11 Clarify maintained app download timeout errors (#50104)
**Related issue:** Resolves #48416

When adding a Fleet-maintained app, a large-installer download that's
canceled or times out now returns a clear message pointing at the likely
proxy/load-balancer timeout, instead of a raw `context canceled`.

# 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


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

## Summary by CodeRabbit

* **Bug Fixes**
* Improved error messages when adding Fleet-maintained apps times out or
is canceled during large installer downloads.
* Added clearer guidance for configuring server, proxy, and load
balancer timeouts.
* Properly handles additional timeout and upstream cancellation
responses, including HTTP 408, 499, and 504.


<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2026-07-30 14:39:56 -04:00
Juan Fernandez b06cbde1de Exclude non-existent host IDs from host transfer activity
The host transfer endpoint recorded raw requested host IDs in the
transferred_hosts activity verbatim, letting an authorized user inject
fabricated IDs into the audit trail. Derive the activity's host IDs and
names only from hosts that actually exist, and skip the activity when
none exist.
2026-07-30 13:59:43 -04:00
Juan Fernandez e5b0f313f9 Fix password reset accepting case-mutated tokens
Reset tokens are base64url (case-sensitive) but the
password_reset_requests.token column used case-insensitive
utf8mb4_unicode_ci, so a case-mutated token copy still matched. Switch
the column to utf8mb4_bin for byte-exact comparison.
2026-07-30 13:59:24 -04:00
George Karr 8a65ecf20b Bound Android device reconciliation pagination loop (#49615) 2026-07-30 12:08:17 -05:00