Skip to content

Add Windows support for "Require all software" during setup experience.#44519

Open
getvictor wants to merge 5 commits intomainfrom
victor/42854-require-software-frontend
Open

Add Windows support for "Require all software" during setup experience.#44519
getvictor wants to merge 5 commits intomainfrom
victor/42854-require-software-frontend

Conversation

@getvictor
Copy link
Copy Markdown
Member

@getvictor getvictor commented Apr 30, 2026

Added a checkbox for the setup experience page.

Related issue: Resolves #42854

image --- image --- image

Checklist for submitter

Testing

  • Added/updated automated tests
  • QA'd all new/changed functionality manually

Summary by CodeRabbit

  • New Features

    • Added Windows support to the MDM setup experience so admins can require all software during Windows device setup, saved independently from macOS.
  • UI

    • Checkbox label clarified to "Cancel setup if software fails".
    • Windows checkbox is disabled when Windows MDM is not configured and shows a contextual tooltip.
  • Tests

    • Added tests covering Windows UI states and save behavior.

- Refactored `InstallSoftwareForm.tsx` to include Windows logic alongside macOS.
- Added `require_all_software_windows` configuration to global settings, teams, and API.
- Updated UI tests and components for platform-specific behavior.
- Enhanced checkbox logic for macOS and Windows setup flows.
@getvictor
Copy link
Copy Markdown
Member Author

@coderabbitai full review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

✅ Actions performed

Full review triggered.

@getvictor
Copy link
Copy Markdown
Member Author

/agentic_review

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects Bot commented Apr 30, 2026

Code Review by Qodo

🐞 Bugs (3) 📘 Rule violations (0)

Grey Divider


Action required

1. Windows require-all not used 🐞 Bug ≡ Correctness
Description
InstallSoftwareForm can save require_all_software_windows, but the device-user setup experience UI
only reads global_config.mdm.require_all_software_macos for Apple hosts and the device API only
returns that field, so Windows devices won’t enter the failure flow based on this setting.
Code

frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[R187-197]

+        if (platform === "windows") {
+          await mdmAPI.updateRequireAllSoftwareWindows(
+            currentTeamId,
+            requireAllSoftwareWindows
+          );
+        } else {
+          await mdmAPI.updateRequireAllSoftwareMacOS(
+            currentTeamId,
+            requireAllSoftwareMacOS
+          );
+        }
Evidence
The PR adds a Windows-specific save path, but the device-user UI’s requireAllSoftware prop is
hard-coded to Apple-only and the device API response struct only includes
require_all_software_macos, so there is no way for Windows to reflect/use the new flag.

frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[184-209]
frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx[628-642]
server/fleet/app.go[1723-1735]
server/service/devices.go[206-229]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The admin UI persists `require_all_software_windows`, but the device-user setup experience can’t read/apply it for Windows because:
1) the device API `global_config.mdm` payload only includes `require_all_software_macos`, and
2) `DeviceUserPage` only uses that macOS flag for Apple hosts.
### Issue Context
This makes the Windows setting effectively write-only from the frontend: it can be toggled in the Setup Experience admin UI, but it won’t affect the device-user setup experience failure flow for Windows.
### Fix Focus Areas
- server/fleet/app.go[1723-1735]
- server/service/devices.go[206-229]
- frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx[628-642]
- frontend/interfaces/config.ts[103-108]
### What to change
- Extend the device API response (`DeviceGlobalMDMConfig`) to include `require_all_software_windows` (and populate it from the effective team/global config for the host).
- Update `frontend/interfaces/config.ts` (`IDeviceGlobalConfig`) to include `require_all_software_windows`.
- Update `DeviceUserPage` to pass `requireAllSoftware` for Windows hosts using `globalConfig.mdm.require_all_software_windows` (and keep macOS using `require_all_software_macos`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Deprecated setup endpoint used 🐞 Bug ☼ Reliability ⭐ New
Description
mdmAPI.updateRequireAllSoftwareWindows PATCHes endpoints.MDM_SETUP (/fleet/mdm/apple/setup),
which the server explicitly marks as deprecated in favor of /fleet/setup_experience. This adds new
Windows functionality on a route that may be removed, risking future breakage of the Windows
setup-experience setting update.
Code

frontend/services/entities/mdm.ts[R271-277]

+  updateRequireAllSoftwareWindows: (teamId: number, isEnabled: boolean) => {
+    const { MDM_SETUP } = endpoints;
+    return sendRequest("PATCH", MDM_SETUP, {
+      fleet_id: teamId,
+      require_all_software_windows: isEnabled,
+    });
+  },
Evidence
The frontend method for Windows require-all updates uses MDM_SETUP, which is defined as
/fleet/mdm/apple/setup. The server router documents that PATCH /mdm/apple/setup is deprecated
and replaced by PATCH /setup_experience, and the frontend already defines MDM_SETUP_EXPERIENCE
for that replacement endpoint.

frontend/services/entities/mdm.ts[263-290]
frontend/utilities/endpoints.ts[186-215]
server/service/handler.go[602-606]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`updateRequireAllSoftwareWindows` is implemented using `endpoints.MDM_SETUP` (`/fleet/mdm/apple/setup`), but the server explicitly marks that endpoint as deprecated and replaced by `/fleet/setup_experience`. This creates avoidable risk that the Windows require-all setting breaks when the deprecated route is removed.

### Issue Context
The frontend already has `MDM_SETUP_EXPERIENCE` (`/fleet/setup_experience`) and an `updateSetupExperienceSettings` helper that PATCHes that endpoint.

### Fix Focus Areas
- frontend/services/entities/mdm.ts[263-290]
- frontend/utilities/endpoints.ts[186-215] సూచ
- server/service/handler.go[602-606]

### What to change
- Update `updateRequireAllSoftwareWindows` (and ideally the existing macOS equivalent for consistency) to PATCH `MDM_SETUP_EXPERIENCE` (`/fleet/setup_experience`) instead of `MDM_SETUP`.
- Ensure the request body uses the same `fleet_id` semantics as other setup-experience updates (including the `API_NO_TEAM_ID` case, if applicable).
- Adjust/extend typings if you decide to route this through `updateSetupExperienceSettings` (e.g., add `require_all_software_windows` to the update body type).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Windows MDM gating missing 🐞 Bug ☼ Reliability
Description
The Windows “Cancel setup if software fails” checkbox is shown/enabled regardless of Windows MDM
configuration, but the backend rejects enabling require_all_software_windows when Windows MDM isn’t
configured, causing save attempts to fail.
Code

frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[R299-310]

+        {platform === "windows" && (
+          <div className={`${baseClass}__windows_options`}>
+            <Checkbox
+              disabled={gitOpsModeEnabled}
+              value={requireAllSoftwareWindows}
+              onChange={handleChangeRequireAllWindows}
           >
-              <TooltipWrapper tipContent="If any software fails, the end user won't be let through, and will see a prompt to contact their IT admin. Remaining software installs will be canceled.">
-                Cancel setup if software install fails
+              <TooltipWrapper tipContent="If any software fails, the end user will be prompted to restart setup. Remaining software installs will be canceled.">
+                Cancel setup if software fails
             </TooltipWrapper>
           </Checkbox>
         </div>
Evidence
The backend validates RequireAllSoftwareWindows and returns ErrWindowsMDMNotConfigured when
Windows MDM is not enabled/configured. The frontend Windows checkbox is only disabled for GitOps
mode (no check of windows_enabled_and_configured), and the Install Software card only shows an
“MDM required” empty state for Apple/Android, not Windows.

ee/server/service/mdm.go[343-360]
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[299-310]
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/InstallSoftware.tsx[153-165]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The UI allows enabling `require_all_software_windows` even when Windows MDM is not configured, but the backend rejects that update. This results in avoidable save errors and a confusing setup experience.
### Issue Context
Backend validation fails when `RequireAllSoftwareWindows` is set true and `WindowsEnabledAndConfigured` is false.
### Fix Focus Areas
- ee/server/service/mdm.go[343-360]
- frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/InstallSoftware.tsx[153-165]
- frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[299-310]
### What to change
- In the Windows tab, gate the form similarly to Apple/Android:
- If `globalConfig.mdm.windows_enabled_and_configured` is false, render an EmptyState / call-to-action to configure Windows MDM (or disable the checkbox with a tooltip explaining why).
- Optionally improve the error flash message to specifically mention Windows MDM not configured when that error is returned.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Previous review results

Review updated until commit 906fa4e

Results up to commit 0e4d2f0


🐞 Bugs (2) 📘 Rule violations (0)


Action required
1. Windows require-all not used 🐞 Bug ≡ Correctness
Description
InstallSoftwareForm can save require_all_software_windows, but the device-user setup experience UI
only reads global_config.mdm.require_all_software_macos for Apple hosts and the device API only
returns that field, so Windows devices won’t enter the failure flow based on this setting.
Code

frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[R187-197]

+        if (platform === "windows") {
+          await mdmAPI.updateRequireAllSoftwareWindows(
+            currentTeamId,
+            requireAllSoftwareWindows
+          );
+        } else {
+          await mdmAPI.updateRequireAllSoftwareMacOS(
+            currentTeamId,
+            requireAllSoftwareMacOS
+          );
+        }
Evidence
The PR adds a Windows-specific save path, but the device-user UI’s requireAllSoftware prop is
hard-coded to Apple-only and the device API response struct only includes
require_all_software_macos, so there is no way for Windows to reflect/use the new flag.

frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[184-209]
frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx[628-642]
server/fleet/app.go[1723-1735]
server/service/devices.go[206-229]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The admin UI persists `require_all_software_windows`, but the device-user setup experience can’t read/apply it for Windows because:
1) the device API `global_config.mdm` payload only includes `require_all_software_macos`, and
2) `DeviceUserPage` only uses that macOS flag for Apple hosts.

### Issue Context
This makes the Windows setting effectively write-only from the frontend: it can be toggled in the Setup Experience admin UI, but it won’t affect the device-user setup experience failure flow for Windows.

### Fix Focus Areas
- server/fleet/app.go[1723-1735]
- server/service/devices.go[206-229]
- frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx[628-642]
- frontend/interfaces/config.ts[103-108]

### What to change
- Extend the device API response (`DeviceGlobalMDMConfig`) to include `require_all_software_windows` (and populate it from the effective team/global config for the host).
- Update `frontend/interfaces/config.ts` (`IDeviceGlobalConfig`) to include `require_all_software_windows`.
- Update `DeviceUserPage` to pass `requireAllSoftware` for Windows hosts using `globalConfig.mdm.require_all_software_windows` (and keep macOS using `require_all_software_macos`).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended
2. Windows MDM gating missing 🐞 Bug ☼ Reliability
Description
The Windows “Cancel setup if software fails” checkbox is shown/enabled regardless of Windows MDM
configuration, but the backend rejects enabling require_all_software_windows when Windows MDM isn’t
configured, causing save attempts to fail.
Code

frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[R299-310]

+        {platform === "windows" && (
+          <div className={`${baseClass}__windows_options`}>
+            <Checkbox
+              disabled={gitOpsModeEnabled}
+              value={requireAllSoftwareWindows}
+              onChange={handleChangeRequireAllWindows}
            >
-              <TooltipWrapper tipContent="If any software fails, the end user won't be let through, and will see a prompt to contact their IT admin. Remaining software installs will be canceled.">
-                Cancel setup if software install fails
+              <TooltipWrapper tipContent="If any software fails, the end user will be prompted to restart setup. Remaining software installs will be canceled.">
+                Cancel setup if software fails
              </TooltipWrapper>
            </Checkbox>
          </div>
Evidence
The backend validates RequireAllSoftwareWindows and returns ErrWindowsMDMNotConfigured when
Windows MDM is not enabled/configured. The frontend Windows checkbox is only disabled for GitOps
mode (no check of windows_enabled_and_configured), and the Install Software card only shows an
“MDM required” empty state for Apple/Android, not Windows.

ee/server/service/mdm.go[343-360]
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[299-310]
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/InstallSoftware.tsx[153-165]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The UI allows enabling `require_all_software_windows` even when Windows MDM is not configured, but the backend rejects that update. This results in avoidable save errors and a confusing setup experience.

### Issue Context
Backend validation fails when `RequireAllSoftwareWindows` is set true and `WindowsEnabledAndConfigured` is false.

### Fix Focus Areas
- ee/server/service/mdm.go[343-360]
- frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/InstallSoftware.tsx[153-165]
- frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx[299-310]

### What to change
- In the Windows tab, gate the form similarly to Apple/Android:
 - If `globalConfig.mdm.windows_enabled_and_configured` is false, render an EmptyState / call-to-action to configure Windows MDM (or disable the checkbox with a tooltip explaining why).
- Optionally improve the error flash message to specifically mention Windows MDM not configured when that error is returned.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Qodo Logo

@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 30, 2026

Codecov Report

❌ Patch coverage is 73.07692% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.80%. Comparing base (13cec63) to head (b40ae04).
⚠️ Report is 6 commits behind head on main.

Files with missing lines Patch % Lines
frontend/services/entities/mdm.ts 0.00% 5 Missing ⚠️
...onents/InstallSoftwareForm/InstallSoftwareForm.tsx 90.47% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main   #44519   +/-   ##
=======================================
  Coverage   66.79%   66.80%           
=======================================
  Files        2637     2637           
  Lines      212132   212151   +19     
  Branches     9555     9565   +10     
=======================================
+ Hits       141690   141718   +28     
+ Misses      57576    57567    -9     
  Partials    12866    12866           
Flag Coverage Δ
frontend 54.85% <73.07%> (+0.06%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

Caution

Review failed

An error occurred during the review process. Please try again later.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d029a706-7f1b-412d-84b6-3b190b339355

📥 Commits

Reviewing files that changed from the base of the PR and between 906fa4e and b40ae04.

📒 Files selected for processing (3)
  • frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tests.tsx
  • frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx
  • frontend/services/entities/mdm.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/services/entities/mdm.ts

Walkthrough

Adds Windows support for the Setup Experience "require all software" option: extends IMdmConfig and ITeam with require_all_software_windows, updates the default mock config, surfaces Windows state and UI in InstallSoftware and InstallSoftwareForm (including MDM-dependent enable/disable behavior), updates mdmService with updateRequireAllSoftwareWindows to PATCH the MDM setup-experience endpoint, and adds/adjusts tests for the Windows checkbox and related API calls.

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning PR description is minimal and lacks most required checklist sections; includes only issue reference and test checkboxes without migration, validation, or database considerations. Complete the PR description by adding checked items for all applicable checklist sections: database migrations, new configuration settings (especially GitOps exclusion), and security validation. Provide detailed testing and migration notes.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the primary change: adding Windows support for the 'Require all software' feature during setup experience.
Linked Issues check ✅ Passed All implementation requirements from issue #42854 appear to be met: checkbox added for Windows, API method implemented, state handlers created, and save paths wired.
Out of Scope Changes check ✅ Passed All changes directly support the Windows 'require all software' feature implementation and remain within the scope of issue #42854.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch victor/42854-require-software-frontend

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 7/8 reviews remaining, refill in 7 minutes and 30 seconds.

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tests.tsx (1)

165-192: ⚡ Quick win

Add a save-path interaction test for Windows API invocation.

These assertions validate rendering, but not that Save actually triggers mdmAPI.updateRequireAllSoftwareWindows(...) after checkbox interaction. Adding that test would catch regressions in the core behavior this PR introduces.

Proposed test addition
+import mdmAPI from "services/entities/mdm";
...
+it("calls Windows require-all API on Save when checkbox is changed", async () => {
+  const updateRequireAllSoftwareWindowsSpy = jest
+    .spyOn(mdmAPI, "updateRequireAllSoftwareWindows")
+    .mockResolvedValue({});
+
+  const { user } = render(
+    <InstallSoftwareForm
+      savedRequireAllSoftwareWindows={false}
+      currentTeamId={1}
+      softwareTitles={[createMockSoftwareTitle()]}
+      hasManualAgentInstall={false}
+      platform="windows"
+      router={createMockRouter()}
+      refetchSoftwareTitles={noop}
+    />
+  );
+
+  await user.click(
+    screen.getByRole("checkbox", { name: /Cancel setup if software fails/i })
+  );
+  await user.click(screen.getByRole("button", { name: "Save" }));
+
+  await waitFor(() => {
+    expect(updateRequireAllSoftwareWindowsSpy).toHaveBeenCalledWith(1, true);
+  });
+});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tests.tsx`
around lines 165 - 192, Add a test that verifies the checkbox interaction calls
the Windows API: render InstallSoftwareForm with savedRequireAllSoftwareWindows
set, mock mdmAPI.updateRequireAllSoftwareWindows, use
screen.getByRole("checkbox", { name: /Cancel setup if software fails/ }) to
click/toggle the checkbox (using userEvent or fireEvent) and await/assert that
mdmAPI.updateRequireAllSoftwareWindows was called with the expected payload
(teamId/currentTeamId and new boolean value). Ensure the test imports/mocks
mdmAPI.updateRequireAllSoftwareWindows and uses the same platform="windows" and
softwareTitles setup as the existing test so it only adds the
interaction/assertion for updateRequireAllSoftwareWindows.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In
`@frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tests.tsx`:
- Around line 165-192: Add a test that verifies the checkbox interaction calls
the Windows API: render InstallSoftwareForm with savedRequireAllSoftwareWindows
set, mock mdmAPI.updateRequireAllSoftwareWindows, use
screen.getByRole("checkbox", { name: /Cancel setup if software fails/ }) to
click/toggle the checkbox (using userEvent or fireEvent) and await/assert that
mdmAPI.updateRequireAllSoftwareWindows was called with the expected payload
(teamId/currentTeamId and new boolean value). Ensure the test imports/mocks
mdmAPI.updateRequireAllSoftwareWindows and uses the same platform="windows" and
softwareTitles setup as the existing test so it only adds the
interaction/assertion for updateRequireAllSoftwareWindows.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 5cfff4d9-a5e8-4786-aa5a-7edfa82ec9ac

📥 Commits

Reviewing files that changed from the base of the PR and between f94b66f and 0e4d2f0.

📒 Files selected for processing (7)
  • frontend/__mocks__/configMock.ts
  • frontend/interfaces/config.ts
  • frontend/interfaces/team.ts
  • frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/InstallSoftware.tsx
  • frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tests.tsx
  • frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx
  • frontend/services/entities/mdm.ts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Windows support for the “Require all software” (cancel setup on software failure) setting within the Setup Experience “Install software” flow, wiring the new config field through UI state, API calls, and typed config objects.

Changes:

  • Added a new MDM service method to PATCH require_all_software_windows.
  • Extended InstallSoftwareForm to support Windows checkbox state + save behavior, and updated copy/tests.
  • Plumbed the new require_all_software_windows field through config/team interfaces and mocks.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
frontend/services/entities/mdm.ts Adds API method to update require_all_software_windows.
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx Adds Windows checkbox + state and routes save to the new API method.
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tests.tsx Updates copy expectations and adds a Windows render test for the checkbox.
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/InstallSoftware.tsx Passes the saved Windows flag from global/team config down into the form.
frontend/interfaces/team.ts Adds require_all_software_windows to the team MDM setup_experience type.
frontend/interfaces/config.ts Adds require_all_software_windows to the global MDM setup_experience type.
frontend/mocks/configMock.ts Updates mock config to include require_all_software_windows.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread frontend/services/entities/mdm.ts Outdated
- Included Windows logic in MDM configuration checks.
- Updated UI to display platform-specific messaging for Windows MDM setup.
- Added Windows-related test case for software setup validation.
- Updated MDM logic to exclude Windows from mandatory setup experience MDM requirements.
- Added conditional checks to disable "Require all software" when Windows MDM is not configured.
- Updated UI messaging for clarity in Windows-specific setup scenarios.
- Introduced and validated test cases for Windows checkbox behavior and platform-specific configurations.
@getvictor
Copy link
Copy Markdown
Member Author

@coderabbitai full review

@getvictor
Copy link
Copy Markdown
Member Author

/agentic_review

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 30, 2026

✅ Actions performed

Full review triggered.

@qodo-free-for-open-source-projects
Copy link
Copy Markdown

qodo-free-for-open-source-projects Bot commented Apr 30, 2026

Persistent review updated to latest commit 906fa4e

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
frontend/services/entities/mdm.ts (1)

271-277: ⚡ Quick win

Prefer the setup-experience endpoint constant for this new updater.

This new method is part of setup-experience writes, but it targets MDM_SETUP while neighboring setup-experience mutations use MDM_SETUP_EXPERIENCE. Using the newer endpoint constant here improves consistency and avoids coupling new code to legacy route naming.

Suggested diff
-  updateRequireAllSoftwareWindows: (teamId: number, isEnabled: boolean) => {
-    const { MDM_SETUP } = endpoints;
-    return sendRequest("PATCH", MDM_SETUP, {
+  updateRequireAllSoftwareWindows: (teamId: number, isEnabled: boolean) => {
+    const { MDM_SETUP_EXPERIENCE } = endpoints;
+    return sendRequest("PATCH", MDM_SETUP_EXPERIENCE, {
       fleet_id: teamId,
       require_all_software_windows: isEnabled,
     });
   },
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/services/entities/mdm.ts` around lines 271 - 277, The
updateRequireAllSoftwareWindows function is using the legacy endpoint constant
MDM_SETUP; change it to use MDM_SETUP_EXPERIENCE so the mutation aligns with
other setup-experience writes—locate updateRequireAllSoftwareWindows in
frontend/services/entities/mdm.ts and replace the MDM_SETUP reference with
MDM_SETUP_EXPERIENCE in the sendRequest call while keeping the same HTTP method
and payload.
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx (1)

79-92: ⚡ Quick win

Use a safer default for isWindowsMdmEnabled.

Defaulting this prop to true can silently enable the Windows checkbox if a caller forgets to pass it. A false default is safer for enforcement gating.

Suggested diff
-  isWindowsMdmEnabled = true,
+  isWindowsMdmEnabled = false,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx`
around lines 79 - 92, The InstallSoftwareForm component currently defaults the
prop isWindowsMdmEnabled to true which can accidentally enable the Windows MDM
checkbox; change the default in the InstallSoftwareForm parameter destructuring
to isWindowsMdmEnabled = false so the safer disabled state is used when callers
omit the prop (keep the prop optional in the props type and ensure any logic
using isWindowsMdmEnabled in InstallSoftwareForm and related render/validation
branches continues to treat it as a boolean).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tests.tsx`:
- Around line 195-225: The test creates a spy updateRequireAllSoftwareWindowsSpy
that is only restored at the end of the test, which can leak if the test fails;
fix by ensuring the spy is always cleaned up—either wrap the spy usage in a
try/finally and call updateRequireAllSoftwareWindowsSpy.mockRestore() in
finally, or add a global cleanup like afterEach(() => jest.restoreAllMocks())
for this test file so updateRequireAllSoftwareWindows (and any other spies) are
reliably restored; locate the spy in the "calls the Windows require-all API on
Save when the Windows checkbox is toggled" test and apply one of these cleanup
approaches.

---

Nitpick comments:
In
`@frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx`:
- Around line 79-92: The InstallSoftwareForm component currently defaults the
prop isWindowsMdmEnabled to true which can accidentally enable the Windows MDM
checkbox; change the default in the InstallSoftwareForm parameter destructuring
to isWindowsMdmEnabled = false so the safer disabled state is used when callers
omit the prop (keep the prop optional in the props type and ensure any logic
using isWindowsMdmEnabled in InstallSoftwareForm and related render/validation
branches continues to treat it as a boolean).

In `@frontend/services/entities/mdm.ts`:
- Around line 271-277: The updateRequireAllSoftwareWindows function is using the
legacy endpoint constant MDM_SETUP; change it to use MDM_SETUP_EXPERIENCE so the
mutation aligns with other setup-experience writes—locate
updateRequireAllSoftwareWindows in frontend/services/entities/mdm.ts and replace
the MDM_SETUP reference with MDM_SETUP_EXPERIENCE in the sendRequest call while
keeping the same HTTP method and payload.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7d30ad4a-fd23-44db-8a78-650ae2dfa015

📥 Commits

Reviewing files that changed from the base of the PR and between f94b66f and 906fa4e.

📒 Files selected for processing (7)
  • frontend/__mocks__/configMock.ts
  • frontend/interfaces/config.ts
  • frontend/interfaces/team.ts
  • frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/InstallSoftware.tsx
  • frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tests.tsx
  • frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx
  • frontend/services/entities/mdm.ts

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds Windows parity for the Setup Experience “require all software” behavior (UI label: “Cancel setup if software fails”), wiring through frontend config types, UI state/save logic, and a new MDM API helper.

Changes:

  • Added updateRequireAllSoftwareWindows to the frontend MDM service and wired it into the Install Software setup experience form.
  • Extended setup experience config/team interfaces and mocks to include require_all_software_windows.
  • Updated/added UI tests to cover Windows rendering, disabled behavior, and save behavior.

Reviewed changes

Copilot reviewed 7 out of 7 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
frontend/services/entities/mdm.ts Adds Windows PATCH helper to update require_all_software_windows.
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tsx Adds Windows checkbox/state + save path + platform gating.
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/components/InstallSoftwareForm/InstallSoftwareForm.tests.tsx Adds Windows-focused rendering/API/disabled tests and updates label text.
frontend/pages/ManageControlsPage/SetupExperience/cards/InstallSoftware/InstallSoftware.tsx Plumbs saved Windows setting + Windows MDM enabled flag into the form.
frontend/interfaces/team.ts Adds require_all_software_windows to team setup experience typing.
frontend/interfaces/config.ts Adds require_all_software_windows to global config typing.
frontend/mocks/configMock.ts Adds default mock value for require_all_software_windows.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@getvictor
Copy link
Copy Markdown
Member Author

@claude review once

Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Flagged one correctness issue inline — the new Windows checkbox persists to the backend but the device-user setup-experience UI can't read require_all_software_windows because it isn't on the device API/types, so the failure flow never triggers on Windows hosts.

Extended reasoning...

Overview

This PR wires up a Windows tab and require_all_software_windows checkbox in the Setup Experience admin form, including: a new updateRequireAllSoftwareWindows service (now correctly using MDM_SETUP_EXPERIENCE rather than the deprecated apple-only endpoint), Windows-MDM-gated disabled state with appropriate tooltips, and supporting type/mock updates in IMdmConfig/ITeam/configMock.ts. Tests cover the new Windows checkbox visibility, the disabled state when Windows MDM is off, and that Save calls the new API.

Security risks

None observed. This is a UI/admin-config change touching frontend state and a single PATCH to an existing endpoint. No auth, crypto, or permission boundaries are modified.

Level of scrutiny

Moderate — small frontend surface, but it is the user-facing wiring for an end-to-end feature whose backend support landed in earlier PRs (#43011, #44285, #44061). Because the value of this PR is the full round-trip behavior on Windows, the read side matters as much as the write side.

Other factors

The inline finding is the most consequential issue on this PR: the admin UI lets you toggle and save require_all_software_windows, but DeviceGlobalMDMConfig (server/fleet/app.go) and IDeviceGlobalConfig.mdm (frontend/interfaces/config.ts) don't expose the Windows flag, and DeviceUserPage short-circuits the prop on isAppleHost. Net effect on Windows: the checkbox is functionally write-only and the failure flow never runs. Qodo and Copilot flagged the same issue. Other Copilot/Qodo nits in the timeline (deprecated endpoint, missing SCSS, Windows MDM gating, GitOps tooltip) all appear to have been addressed in 36181ad/906fa4e — only the device-side read path remains. Deferring to a human to confirm the device API extension is in scope for this PR vs. a follow-up.

Comment on lines +184 to 200
// 2. "require all software" update (macOS or Windows)
if (shouldUpdateRequireAll) {
try {
await mdmAPI.updateRequireAllSoftwareMacOS(
currentTeamId,
requireAllSoftwareMacOS
);
if (platform === "windows") {
await mdmAPI.updateRequireAllSoftwareWindows(
currentTeamId,
requireAllSoftwareWindows
);
} else {
await mdmAPI.updateRequireAllSoftwareMacOS(
currentTeamId,
requireAllSoftwareMacOS
);
}
hadSuccess = true;
setTouchedRequireAll(false);
} catch (e) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 The new Windows checkbox in InstallSoftwareForm persists require_all_software_windows on the backend, but the device-user setup-experience UI never reads it: IDeviceGlobalConfig.mdm (frontend/interfaces/config.ts:103-107) and DeviceGlobalMDMConfig (server/fleet/app.go:1732-1735) only expose require_all_software_macos, and DeviceUserPage (frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx:636-639) gates the value on isAppleHost, so for Windows hosts requireAllSoftware is always false. The new admin checkbox is therefore functionally write-only — fix by extending DeviceGlobalMDMConfig/IDeviceGlobalConfig with require_all_software_windows and updating DeviceUserPage to use it for Windows hosts.

Extended reasoning...

What the bug is

The PR adds an admin-side write path for require_all_software_windows (the new Windows checkbox in InstallSoftwareForm.tsx, plus mdmAPI.updateRequireAllSoftwareWindows), but it does not add the corresponding read path for the device-user setup experience. As a result, no matter how the admin sets the Windows checkbox, the device-user UI on a Windows host can never observe it, and the failure-on-software-install flow that is the whole point of this feature can never trigger for Windows.

The exact code path

  1. frontend/interfaces/config.ts:103-107IDeviceGlobalConfig.mdm only declares enabled_and_configured and require_all_software_macos. No Windows field was added in this PR.
  2. server/fleet/app.go:1732-1735 — the backend DeviceGlobalMDMConfig (the device-facing payload) likewise only has RequireAllSoftware (json: require_all_software_macos). The Windows flag exists on AppConfig but is never copied into the device payload.
  3. frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx:636-639 passes:
    requireAllSoftware={
      (isAppleHost && globalConfig?.mdm?.require_all_software_macos) ?? false
    }
    For a Windows host, isAppleHost is false, so the short-circuit always yields false.
  4. frontend/pages/hosts/details/DeviceUserPage/components/SettingUpYourDevice/SettingUpYourDevice.tsx:36:
    const failedSoftware = requireAllSoftware
      ? getFailedSoftwareInstall(setupSteps)
      : null;
    With requireAllSoftware === false, failedSoftware is always null, so the failure UI never renders.

Why existing code does not prevent it

Windows IS routed through SettingUpYourDeviceDeviceUserPage.tsx:356-359 includes host?.platform === "windows" in isSetupExperienceSoftwareEnabledPlatform. So the component renders; it just receives requireAllSoftware=false regardless of the saved setting. The PR also did not touch DeviceUserPage.tsx, IDeviceGlobalConfig, or DeviceGlobalMDMConfig, so the read side is unchanged from before this PR.

Step-by-step proof

  1. Admin visits Setup Experience → Install Software → Windows tab and checks "Cancel setup if software fails", then clicks Save.
  2. InstallSoftwareForm calls mdmAPI.updateRequireAllSoftwareWindows(teamId, true), which PATCHes /setup_experience with { require_all_software_windows: true }. Backend persists this on AppConfig.MDM.MacOSSetup.RequireAllSoftwareWindows.
  3. A Windows host enrolls. The device-user UI loads /api/_version_/fleet/device/{token}/desktop (or equivalent) and gets back a DeviceGlobalConfig whose mdm payload is { enabled_and_configured, require_all_software_macos } only — no require_all_software_windows field is serialized (server/fleet/app.go:1732-1735).
  4. DeviceUserPage evaluates requireAllSoftware = (isAppleHost && globalConfig?.mdm?.require_all_software_macos) ?? false. isAppleHost is false for Windows → expression evaluates to false ?? falsefalse.
  5. SettingUpYourDevice receives requireAllSoftware={false}. Even if a software install fails, failedSoftware stays null, so the user is never shown "Device setup failed" and setup is never canceled.

Net effect: the Windows checkbox is functionally write-only on the frontend, which directly contradicts the PR title "Add Windows support for Require all software during setup experience".

Impact

The core feature this PR claims to deliver does not work end-to-end on Windows. Admins can toggle the setting and the value will persist, but no Windows device will ever experience the failure flow it controls. Shipping this as-is would be misleading and likely require a follow-up bug report once a customer notices.

How to fix

  • Backend: add RequireAllSoftwareWindows bool json:"require_all_software_windows"`` to DeviceGlobalMDMConfig in `server/fleet/app.go` and populate it from the effective team/global config when building the device response (see `server/service/devices.go` around lines 206-229).
  • Frontend types: add require_all_software_windows: boolean | null to IDeviceGlobalConfig.mdm in frontend/interfaces/config.ts.
  • Frontend UI: in DeviceUserPage.tsx:636-639, change the prop to something like:
    requireAllSoftware={
      ((isAppleHost && globalConfig?.mdm?.require_all_software_macos) ||
       (host?.platform === "windows" && globalConfig?.mdm?.require_all_software_windows)) ?? false
    }

This was independently flagged by Qodo in the same PR review as "Windows require-all not used".

🔬 also observed by qodo

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The MDM BYOD setup experience will be handled in a separate PR/story.

@getvictor getvictor marked this pull request as ready for review April 30, 2026 20:42
@getvictor getvictor requested a review from a team as a code owner April 30, 2026 20:42
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

WCS (phase 2): Frontend changes for "Cancel setup if software fails" on Windows Setup Experience software page

3 participants