Skip to content

Surface failed-remove errors for Windows MDM profiles #44233

Description

@ksykulev

UPDATE: @noahtalerman: Closed this request because I pulled it into this separate request:


Problem

Windows MDM profile removal is treated as best-effort, but there is no mechanism to surface failed-remove errors to admins. When a remove operation fails with an unusual error code (not 200/404/405/500), the failure is silently discarded — the row is deleted from host_mdm_windows_profiles with no record that the removal failed.

Apple's equivalent flow has an ignore_error column on host_mdm_apple_profiles that controls this: failed removes persist by default (with detail = "Failed to remove: ..."), and are only silently cleaned up when ignore_error = true. Windows has no such column.

Impact

Admins have no visibility into Windows profile removals that genuinely fail. While most remove errors are benign (404, 405, 500 are all mapped to "verified" by WindowsResponseToDeliveryStatusForRemove), a real failure (e.g., an unexpected CSP error) is silently dropped. There is no audit trail or UI indication that a profile may still be active on the device.

Proposed fix

Add an ignore_error column to host_mdm_windows_profiles (matching host_mdm_apple_profiles), and update updateMDMWindowsHostProfileStatusFromResponseDB to:

  • Delete failed-remove rows when ignore_error = true (best-effort, current behavior for all removes).
  • Persist failed-remove rows when ignore_error = false, with detail = "Failed to remove: ..." prefix (mirrors Apple's UpdateOrDeleteHostMDMAppleProfile).

Downstream consumers would also need updates:

  • windowsHostProfileStatusSubquery (~line 1813): filter out operation_type = 'remove' rows from failed-status aggregation, or only count them when ignore_error = false.
  • GetHostMDMWindowsProfiles (~line 3292): include failed-remove rows in per-host profile listings when ignore_error = false.

Status comparison table

Remove status Apple behavior Previous Windows behavior Current Windows behavior (#44189) Future Windows behavior (with ignore_error)
Verified DELETE row UPSERT then DELETE (redundant write) DELETE row (skip UPSERT) DELETE row (no change)
Verifying DELETE row UPSERT (kept) UPSERT (kept; never occurs in practice) UPSERT (kept; never occurs in practice)
Failed + ignore_error DELETE row N/A (no ignore_error column) N/A (no ignore_error column) DELETE row (Apple parity)
Failed (no ignore_error) UPDATE, row persists with detail = "Failed to remove: ..." UPSERT, row persists (no detail prefix) DELETE row (best-effort, silent discard) UPDATE, row persists with detail = "Failed to remove: ..." (Apple parity)
Pending UPDATE, row persists UPSERT (kept) UPSERT (kept, no change) UPSERT (kept, no change)
nil UPDATE, row persists UPSERT (kept) UPSERT (kept, no change) UPSERT (kept, no change)

Evidence

  • Apple parity reference: UpdateOrDeleteHostMDMAppleProfile in server/datastore/mysql/apple_mdm.go:3513-3532 — checks ignore_error before deciding to DELETE vs UPDATE for failed removes.
  • ignore_error column exists on host_mdm_apple_profiles but not on host_mdm_windows_profiles.
  • Current Windows behavior after Skip UPSERT for verified-remove ACKs in Windows MDM (Apple parity) #44189: all terminal removes (verified and failed) are deleted, with no visibility into failures.

Metadata

Metadata

Assignees

No one assigned

    Labels

    #g-power-to-pcPower to the PC working groupstoryA user story defining an entire feature

    Type

    No type

    Projects

    Status
    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions