> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getprimo.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Compliance alert reference

> What each compliance alert status means, why macOS and Windows devices trigger it, and how to bring them back to a compliant state.

This reference explains every alert status you can encounter on the **MDM > Compliance Alerts** page: what the device is actually reporting, the causes behind it on macOS and Windows, and how to resolve it. To choose which statuses raise alerts, see [Configure compliance alert rules](/mdm/compliance/alert-rules); for the triage workflow itself, see [Monitor compliance alerts](/mdm/compliance/alerts).

Mobile platforms (iOS, iPadOS, Android) and Linux are covered by a subset of these rules — see [Supported platforms](/mdm/get-started/supported-platforms) for what applies where.

## How Primo decides a device is non-compliant

* Every time a device syncs, Primo re-runs each compliance rule and computes a status per rule — there is no separate scan.
* A device alerts only if its current status is one you toggled on in **Manage rules**. A rule with no statuses toggled never alerts.
* Alerts clear automatically on the next sync once the status improves. There is no manual acknowledge or close.

See [Compliance overview](/mdm/compliance/overview) for the full evaluation model.

## Rule out stale data first

A compliance status is a snapshot from the device's **last sync**. Before treating an alert as a real violation, check whether the data is stale:

| Situation                                 | What you see                                | What is actually happening                                                                                                                                                                                                                                       |
| ----------------------------------------- | ------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Device offline or asleep                  | Any status, frozen                          | The device keeps its last reported status until it syncs again. Fix the connectivity first — the other alerts may clear on their own.                                                                                                                            |
| Device enrolled minutes ago               | `PENDING` on several rules, `NOT_ENCRYPTED` | Controls apply progressively after enrollment — profile-delivered rules report `PENDING` until the device applies them. On macOS, FileVault only takes effect after the next restart, and the recovery key can take up to 24 hours after that restart to escrow. |
| Enrollment action just performed          | Enrollment alert still visible              | Enrollment status changes take up to **30 minutes** (the synchronization period) to reflect in the dashboard.                                                                                                                                                    |
| Windows device late on an update          | `GRACE_PERIOD`                              | The device is inside the grace window you configured. No action is needed until the window ends.                                                                                                                                                                 |
| Every SentinelOne device alerting at once | `NOT_PROTECTED` fleet-wide                  | The SentinelOne service user token has expired: the integration stops syncing and protection statuses go stale. Renew the token in **Settings > Integrations > SentinelOne**.                                                                                    |
| Persistent low-value alerts               | `OFFLINE` on healthy devices                | The rule is stricter than your reality. Alert on **Offline 7+ days** instead of **Offline** — short check-in gaps are normal.                                                                                                                                    |

## Enrollment Status

A global rule that applies to every managed device. It checks whether the device is fully enrolled and whether the MDM agent still communicates with the server.

| Status                  | Meaning                                                                                                          |
| ----------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `MDM_OFF`               | The device is not enrolled or MDM is inactive.                                                                   |
| `MISSING_AGENT`         | The agent is installed but no longer sending data to the server.                                                 |
| `MDM_ON_IN_ANOTHER_MDM` | The device is currently managed by a different MDM.                                                              |
| `READY_ZTD`             | The device is configured and waiting for Zero-Touch Deployment. Expected for in-stock devices — not an incident. |

### Why devices drift out of enrollment

Causes that apply to both platforms:

* The employee did not complete all the enrollment steps, or did not stay connected long enough to finish synchronization.
* The agent was uninstalled manually, or a system update or configuration error corrupted the installation.
* The `osqueryd` service used by the agent has stopped, or the agent fails to start due to permission issues.
* The device sits on a network that blocks access to the MDM server — a proxy or firewall cuts the communication. See [Network requirements](/mdm/network-requirements).

<Tabs>
  <Tab title="macOS">
    - An admin user can remove an **unlocked MDM profile** from System Settings. The device then reports `MDM_OFF` even though the agent may still respond.
    - An expired or revoked **APNs token** prevents the device from validating its profile — the profile becomes invalid without anyone touching the device.
    - A `turn off mdm` action executed from the MDM server side removes management.
    - The Fleet agent installation is incomplete — the most common cause of partial enrollment on macOS.
  </Tab>

  <Tab title="Windows">
    * The device is still enrolled in a previous MDM and reports `MDM_ON_IN_ANOTHER_MDM` — migrate it out of the old MDM before re-enrolling.
    * A proxy or corporate firewall blocking the server connection leaves an installed agent silent (`MISSING_AGENT`).
  </Tab>
</Tabs>

### Resolve enrollment alerts

* **`MISSING_AGENT`** — in the device panel, click the device status button to remotely trigger the agent installation. If that fails, ask the employee to open their Primo enrollment page, click their assigned device, and download the agent.
* **`MDM_ON_IN_ANOTHER_MDM`** — migrate the device from the previous MDM first.
* **`MDM_OFF`** — ask the employee to re-enroll. You can automate this: in **Settings > MDM**, enable **Auto-Unenrollment** and the option to automatically resend MDM invitations to employees whose devices were purged.

Allow up to 30 minutes for the status to update after the fix. Full detail: [Resolve enrollment issues](/mdm/guides/resolve-enrollment-issues).

## Online Status

A global rule tracking whether the device checks in with the server.

| Status           | Meaning                                           |
| ---------------- | ------------------------------------------------- |
| `OFFLINE`        | The device missed its recent check-ins.           |
| `OFFLINE_7_DAYS` | The device has not checked in for 7 days or more. |

### Why devices go offline

* The device is powered off or asleep — an employee on leave, or a spare sitting in a drawer.
* The network blocks the agent's connection to the server (VPN, proxy, firewall rules). See [Network requirements](/mdm/network-requirements).
* The agent is no longer running. A device that appears offline **while actively used by an employee** typically indicates a missing agent or a network issue, not a genuinely offline device — check the Enrollment Status alert for the same device.

### Resolve online alerts

Confirm with the employee whether the device is in use. If it is, treat it as a `MISSING_AGENT` case (see above). If the noise comes from short gaps, alert on **Offline 7+ days** only.

## Platform support

A global rule that checks the device's OS against the baseline Primo supports as an MDM signal source. A device below that baseline cannot reliably enroll, report telemetry, or honor policies — this alert is your upgrade list.

| Status                   | Meaning                                                                                                                  |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------ |
| `BELOW_MINIMUM_VERSION`  | The OS version is older than the minimum Primo supports on that platform.                                                |
| `UNSUPPORTED_OS_EDITION` | The OS edition is not supported — typically Windows Home / Family, which cannot run BitLocker or most security policies. |

`MEETS_REQUIREMENTS` is the compliant status. The rule stays silent until the device has reported its OS information, so a freshly enrolled device is never flagged as unknown.

### Resolve platform support alerts

* **`BELOW_MINIMUM_VERSION`** — upgrade the OS. The current baselines per platform are listed in [Supported platforms](/mdm/get-started/supported-platforms).
* **`UNSUPPORTED_OS_EDITION`** — upgrade the edition, not just the version: see [Manage Windows Home devices](/mdm/policies/manage-windows-home) and [Upgrade to Windows 11](/mdm/guides/upgrade-windows-11).

## Encryption

Checks full-disk encryption: **FileVault** on macOS, **BitLocker** on Windows. Encryption is not on by default — it starts when you enable the **Disk Encryption** control, which applies globally to enrolled devices once created.

| Status                 | Meaning                                                                                                                             |
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| `NOT_ENCRYPTED`        | The disk is not encrypted.                                                                                                          |
| `ACTION_REQUIRED`      | The control is waiting on the employee — typically entering their login password so the recovery key can be generated and escrowed. |
| `MISSING_RECOVERY_KEY` | The disk is encrypted, but Primo holds no recovery key for it.                                                                      |

`ENCRYPTED` is the compliant status. iOS and iPadOS devices always report `ENCRYPTED` — their storage is hardware-encrypted by design. A Windows Home device raises no encryption status at all: it cannot run BitLocker and surfaces under [Platform support](#platform-support) as `UNSUPPORTED_OS_EDITION` instead.

<Tabs>
  <Tab title="macOS">
    * FileVault turns on once the Disk Encryption control targets the device, but **encryption only takes effect after the next restart**. A Mac that never restarts stays `NOT_ENCRYPTED` — ask the employee to reboot.
    * The recovery key is escrowed **within 24 hours after that restart**. A freshly encrypted Mac showing `MISSING_RECOVERY_KEY` in that window resolves on its own.
    * A Mac **encrypted before enrollment** has a key Primo never saw — escrow is not retroactive. The employee must enter their password when prompted so a new key can be generated and escrowed (`ACTION_REQUIRED`).
  </Tab>

  <Tab title="Windows">
    * BitLocker starts encrypting as soon as the control reaches the device, with no restart required, and the key is stored as soon as encryption activates. A Windows device stuck on `NOT_ENCRYPTED` usually has a blocker, not a delay.
    * BitLocker needs a working **TPM**. A missing or firmware-disabled TPM makes encryption fail to start.
  </Tab>
</Tabs>

Control details: [Disk encryption](/mdm/policies/disk-encryption).

## OS Update

Checks that devices install required OS updates by the deadline you enforce.

| Status           | Meaning                                                                                                   |
| ---------------- | --------------------------------------------------------------------------------------------------------- |
| `NOT_UP_TO_DATE` | A required update is past its deadline and not installed.                                                 |
| `GRACE_PERIOD`   | Windows only — the device is late but inside the grace window you configured before forced restart.       |
| `PENDING`        | The update policy itself has not been applied by the device yet — the same delivery state as any profile. |

`UP_TO_DATE` is the compliant status. Between an update's release and its deadline, the device stays compliant — `NOT_UP_TO_DATE` only fires once the deadline has passed. A device whose OS is too old for Primo itself is a [Platform support](#platform-support) alert, not an OS Update one.

### Why devices fall behind on updates

* **The deadline counts from the update's availability date, not from when you configured the policy.** Enabling the policy on a fleet running older versions flags those devices immediately — expect a wave of alerts on day one.
* **Low disk space** blocks the update on every platform, and none of them frees space automatically. On macOS 14+ the employee sees a system notification; on macOS 13 and earlier the Nudge window keeps reappearing while the download fails; on Windows the employee is told the update failed. An administrator may need to step in.
* **The device was off when the deadline passed.** On macOS 14+ the update is scheduled for 1 hour after it turns back on; on Windows the employee gets the configured grace period before the automatic restart.
* The employee keeps deferring within the allowed window — pressure increases as the deadline approaches (hourly notifications 24 hours before, more frequent in the final hour).

### Resolve update alerts

Have the employee free disk space if that is the blocker, then let the enforcement flow run — it escalates on its own. Details and the exact notification schedule per platform: [Enforce OS updates](/mdm/policies/enforce-minimum-os-version).

## Endpoint protection (SentinelOne, ThreatDown)

Available once the corresponding integration is connected. Checks that the endpoint protection agent is installed and reporting.

| Status           | Meaning                                                                              |
| ---------------- | ------------------------------------------------------------------------------------ |
| `NOT_PROTECTED`  | The protection agent is not installed, not running, or not reporting on this device. |
| `OFFLINE_7_DAYS` | ThreatDown only — the agent has not reported to the console for 7 days or more.      |

`ACTIVE` is the compliant status for both tools.

### Why devices show as unprotected

* The control was just enabled — the agent installs on the device's next sync.
* The agent was uninstalled locally or is not running.
* **The integration itself is stale.** SentinelOne service user tokens expire; once the token lapses, syncing stops and protection statuses go stale fleet-wide. Renew the token in **Settings > Integrations > SentinelOne**.
* The device is offline, so its real protection state is unknown.

Setup and remediation: [SentinelOne](/mdm/endpoint-protection/sentinelone), [ThreatDown](/mdm/endpoint-protection/threatdown).

## Admin accounts (Admin User Management, Admin Password Rotation)

Checks that the managed local administrator account exists, holds the expected privileges, and rotates its password on schedule.

| Status             | Meaning                                                                                          |
| ------------------ | ------------------------------------------------------------------------------------------------ |
| `CREATION_PENDING` | The admin account creation was sent but the device has not applied it yet.                       |
| `CREATION_FAILED`  | The device could not create the account — for example, the username already exists locally.      |
| `DEMOTION_PENDING` | **Demote non-matching accounts** is enabled, but one or more accounts have not been demoted yet. |

### Why admin account actions stall

* `CREATION_PENDING` on an offline device resolves once it syncs.
* On macOS, demotion waits until the **Primo-managed admin account itself holds a SecureToken** — the token FileVault depends on. Primo deliberately demotes nobody before that, so the device is never left without a token-holding admin, and `DEMOTION_PENDING` persists (the device logs the event `ADMIN_DEMOTION_BLOCKED_SECURE_TOKEN_NOT_GRANTED`). The managed admin receives its token at its **first login** on the device — have someone log into that account once, or grant the token manually. See [SecureToken rules](/mdm/policies/secure-token).
* The dashboard can take up to 24 hours to refresh the local account status in the device's **Users** tab — verify on the device before concluding a failure.

The **Admin Password Rotation** rule reports its own statuses: `PENDING`, `SUCCESS`, `ERROR`. `SUCCESS` is compliant; `PENDING` clears once the device applies the rotation, so `ERROR` is the status worth alerting on.

Control details: [Admin management](/mdm/policies/manage-admin-accounts).

## iCloud Lock (Activation Lock)

**macOS only** — Activation Lock also exists on iOS and iPadOS, but this compliance rule only evaluates Macs. It checks that when Activation Lock is on, Primo holds the bypass code, so the device can be recovered after a wipe without the employee's Apple Account.

| Status                | Meaning                                                         |
| --------------------- | --------------------------------------------------------------- |
| `MISSING_BYPASS_CODE` | Activation Lock is on, but no bypass code is escrowed in Primo. |

`ENABLED` (lock on, code escrowed) and `DISABLED` (lock off) are both compliant. The rule produces no status while the device is not fully enrolled or its lock state is still unknown.

### Why a bypass code is missing

Escrow happens at the moment Activation Lock activates — **it is not retroactive**. All of these must be true for the code to escrow:

* The device is supervised via MDM.
* The device was enrolled **before** Activation Lock was enabled. If the employee turned on Find My before enrollment, the code cannot be retrieved — the only recovery path is their Apple Account credentials.
* The device is company-owned (BYOD devices are not eligible).
* The MDM profile is installed at the system level (user-approved enrollment without ABM does not reliably escrow codes).

Scenario-by-scenario analysis and remediation: [Activation Lock bypass code escrow](/mdm/guides/activation-lock-bypass).

## Recovery OS

macOS only. Checks that the recoveryOS protection configuration is applied. Only **Apple Silicon** Macs are evaluated — Intel Macs cannot support recoveryOS protection and produce no status at all.

| Status    | Meaning                                                                |
| --------- | ---------------------------------------------------------------------- |
| `PENDING` | The device has not applied the recoveryOS configuration yet.           |
| `FAILED`  | The device reported that the recoveryOS configuration failed to apply. |

`PROTECTED` is the compliant status. Full enforcement requires the device to be enrolled with the appropriate supervision level — an unsupervised Mac is the first thing to check on `FAILED`. Control details: [recoveryOS protection](/mdm/policies/recoveros-protection).

## Profile-delivered controls

Firewall, Password Policy, Wi-Fi, USB Blocking, App Blocking, Screen Capture, Disable AirDrop, Lock Profiles Pane, Google Chrome, Device Naming, Custom Configuration File, Web Clip, AirPrint, Software Update (macOS), and the SSO controls (Entra SSO, Okta SSO, Primo SSO) all work the same way: Primo delivers a configuration to the device, and the device reports back. They share the same delivery statuses:

| Status    | Meaning                                                                   |
| --------- | ------------------------------------------------------------------------- |
| `PENDING` | The configuration is on its way — the device applies it on the next sync. |
| `ERROR`   | The configuration did not apply correctly on the device.                  |

`ENFORCED` is the compliant status.

### Why a configuration fails to apply

<Tabs>
  <Tab title="macOS">
    * An admin user removed the MDM profile carrying the configuration (unless **Lock Profiles Pane** prevents it).
    * APNs issues stop the device from receiving or validating profiles — check the Enrollment Status alert for the same device.
    * The control targets a capability the device lacks: Platform SSO controls require recent macOS versions (Primo SSO needs macOS 14+), and the employee must complete the identity provider registration prompt in their session.
  </Tab>

  <Tab title="Windows">
    * **Windows Home / Family** only partially applies security policies — several configurations require Pro, Enterprise, or Education, and fail without an explicit error on Home. See [Manage Windows Home devices](/mdm/policies/manage-windows-home).
    * A conflicting setting from a previous MDM or a local group policy overrides the delivered value.
  </Tab>
</Tabs>

`PENDING` that persists usually means the device is offline — fix connectivity first. For `ERROR`, open the device drawer, jump to the related MDM control to verify its configuration, and re-apply.

## Remote Access (RustDesk)

Unlike the profile-delivered controls, the Remote Access rule tracks a **software installation**, not a configuration profile.

| Status    | Meaning                                                |
| --------- | ------------------------------------------------------ |
| `PENDING` | The RustDesk agent is not installed on the device yet. |

`INSTALLED` is the compliant status. A persistent `PENDING` usually means the device is offline or the installation is still queued — check the [software installation status](/mdm/software-installation-status) from the device panel, then let the next sync clear the alert.

## Resolve any alert: the general loop

<Steps>
  <Step title="Open the device drawer">
    Click the alert row on **MDM > Compliance Alerts**. Review the device's full status across every rule — several alerts on one device often share a single root cause (offline, agent missing, profile removed).
  </Step>

  <Step title="Separate stale from real">
    Check when the device last synced. If it has been offline, resolve connectivity before anything else.
  </Step>

  <Step title="Fix the root cause">
    Use the sections above. Remediation actions (push profile, lock, wipe) are available from the device drawer — see [Manage your devices](/mdm/guides/wiping-devices).
  </Step>

  <Step title="Let the alert clear itself">
    Alerts resolve automatically on the next device sync once the status improves. If an alert should never have fired, remove that status from the rule in **Manage rules** instead.
  </Step>
</Steps>

## Permissions

| Action                | Permission  |
| --------------------- | ----------- |
| View alerts and rules | `MDM_READ`  |
| Edit alert rules      | `MDM_WRITE` |

## Next steps

<CardGroup cols={2}>
  <Card title="Configure compliance alert rules" icon="sliders" href="/mdm/compliance/alert-rules">
    Choose which of these statuses count as a violation for your fleet.
  </Card>

  <Card title="Monitor compliance alerts" icon="bell" href="/mdm/compliance/alerts">
    Work through the live list of devices currently in violation.
  </Card>
</CardGroup>
