Skip to content

Software Policies

Software Policies let you define what software is permitted or prohibited across your managed devices and automatically detect violations during inventory scans. Policies support three modes – allowlist (only approved software may be installed), blocklist (specific software is prohibited), and audit (detect violations without enforcement) – and can be configured to automatically remediate violations by uninstalling unauthorized software or alerting operators for manual review.

The system consists of three layers: policy definitions that describe the rules, compliance checks that evaluate device inventories against those rules, and remediation actions that respond to detected violations. Compliance checks run automatically through BullMQ workers every 15 minutes and can also be triggered on demand. On Windows endpoints, the winget package manager integration enables automated install and uninstall operations through user-context IPC.


An allowlist policy defines the software that is permitted. Any software found on a device that is not matched by at least one rule in the allowlist is flagged as an unauthorized violation. This is the most restrictive mode, suitable for locked-down environments such as kiosks, point-of-sale terminals, or compliance-sensitive workstations.

The allowUnknown flag (default: not set) controls whether software that does not match any rule is considered a violation. When set to true, only software explicitly matched by a deny-style rule is flagged.

A blocklist policy defines software that is not permitted. Any software found on a device that matches a rule in the blocklist is flagged as an unauthorized violation. Software not matching any rule is implicitly allowed. This mode is useful for banning known-bad applications (cryptocurrency miners, unauthorized remote access tools, torrent clients) without restricting the full software catalog.

Audit mode evaluates the same rules as allowlist or blocklist but does not support automated remediation. Violations are detected and recorded, but no enforcement actions are taken. Use audit mode to understand the current state of your fleet before switching to enforced allowlist or blocklist policies.


Policy Ownership: Organization vs. Partner-Wide

Section titled “Policy Ownership: Organization vs. Partner-Wide”

A software policy is owned at one of two scopes, chosen when the policy is created and fixed for the life of the policy:

  • This organization only — the policy applies only to devices in the organization it was created for. This is the default.
  • All organizations (partner-wide template) — the policy applies to devices in every organization you manage, including organizations created later. Use this for standards you want enforced fleet-wide (e.g. “no unauthorized remote access tools”) without recreating the policy per customer.

In the web UI, the owner scope is a Scope selector shown only when creating a new policy as a partner-level user — choose All organizations or This organization only. The selector is not shown when editing an existing policy, because ownership cannot change after creation.

Creating, editing, or deleting a partner-wide policy requires a partner-level user with full access to every organization under the partner (not a user restricted to a subset of organizations). Users without that access can still see partner-wide policies (they appear in compliance results and violation lists for their organizations) but cannot modify or delete them.

Violations and remediation on a partner-wide policy are always attributed to the device’s own organization in the audit log and route audit trail, while the policy-specific audit record (software_policy_audit) also carries the owning partner — so both the affected organization’s admin and the partner admin can see the same events.

Field Type Required Description
ownerScope enum No organization (default) or partner. Create-only — set once and immutable afterward. With partner, the policy is partner-wide and orgId is ignored; the partner is always derived from your own login, never from the request
orgId UUID Yes* Organization ID. Auto-resolved for org-scoped tokens. Not used when ownerScope is partner
name string Yes Policy name (max 200 characters)
description string No Description of the policy’s purpose (max 4,000 characters)
mode enum Yes allowlist, blocklist, or audit
rules object Yes Rule definitions (see below)
enforceMode boolean No Enable automated enforcement. Default false
remediationOptions object No Remediation configuration (see below)
Terminal window
POST /software-policies
Content-Type: application/json
Authorization: Bearer <token>
{
"orgId": "uuid",
"name": "Prohibited Software",
"description": "Block known-bad applications across all endpoints.",
"mode": "blocklist",
"rules": {
"software": [
{
"name": "BitTorrent",
"vendor": "BitTorrent Inc.",
"reason": "Unauthorized P2P software"
},
{
"name": "TeamViewer",
"reason": "Use Breeze Remote Access instead"
},
{
"name": "CryptoMiner*",
"reason": "Cryptocurrency mining software prohibited"
}
]
},
"enforceMode": true,
"remediationOptions": {
"autoUninstall": true,
"gracePeriod": 24,
"cooldownMinutes": 120
}
}
Terminal window
POST /software-policies
Content-Type: application/json
Authorization: Bearer <token>
{
"orgId": "uuid",
"name": "Approved Software Only",
"description": "Only these applications are permitted on POS terminals.",
"mode": "allowlist",
"rules": {
"software": [
{
"name": "Google Chrome",
"vendor": "Google",
"minVersion": "120.0"
},
{
"name": "Microsoft Edge",
"vendor": "Microsoft"
},
{
"name": "Breeze Agent",
"vendor": "Breeze"
}
],
"allowUnknown": false
},
"enforceMode": false
}
Terminal window
POST /software-policies
Content-Type: application/json
Authorization: Bearer <token>
{
"ownerScope": "partner",
"name": "MSP Standard Blocklist",
"description": "Baseline block rules applied to every managed organization.",
"mode": "blocklist",
"rules": {
"software": [
{ "name": "TeamViewer", "reason": "Use Breeze Remote Access instead" }
]
},
"enforceMode": true
}

No orgId is sent — the partner is derived from the caller’s token, and the policy is immediately in scope for every organization under that partner.

When a policy is created, a compliance check is automatically scheduled through BullMQ. If Redis is unavailable, the policy is still created but a warning field is included in the response indicating the check could not be scheduled.


Each policy contains a rules object with a software array of individual rule definitions and an optional allowUnknown flag.

Field Type Required Description
name string Yes Software name pattern to match (max 500 characters)
vendor string No Vendor/publisher name to match (max 200 characters)
minVersion string No Minimum acceptable version (inclusive)
maxVersion string No Maximum acceptable version (inclusive)
catalogId UUID No Link to a software catalog item for precise matching
reason string No Explanation for the rule (max 1,000 characters, shown in violation reports)
  • Name matching: Rules match against the software name as reported by the operating system’s package manager or installer registry. The comparison is performed during compliance evaluation by the worker.
  • Vendor matching: When a vendor field is specified, both the name and vendor must match for the rule to apply.
  • Version range: When minVersion and/or maxVersion are specified, the installed software version must fall within the range. Software outside the version range is flagged.
  • Catalog linking: When catalogId is provided, the rule is linked to a specific software catalog entry, enabling precise matching by catalog-managed identifier rather than name string matching.

For allowlist policies, the allowUnknown flag determines how software not covered by any rule is handled:

allowUnknown Behavior
false or unset Any software not matching a rule is flagged as unauthorized
true Only software explicitly matched by a blocklist-style rule is flagged

This flag is only meaningful for allowlist policies. Blocklist policies implicitly allow all software not matched by a rule.


  1. Policy evaluation is scheduled – either automatically (every 15 minutes via BullMQ repeatable job) or on-demand via POST /software-policies/:id/check.

  2. Target devices are resolved – The worker determines which devices are subject to the policy. Devices can be targeted explicitly via targetIds or resolved through configuration policy assignments.

  3. Software inventory is loaded – For each target device, the worker retrieves the current software inventory from the software_inventory database table.

  4. Rules are evaluated – Each installed software item is compared against the policy’s rules. For blocklist policies, any match is a violation. For allowlist policies, any item not covered by a rule is a violation (unless allowUnknown is true).

  5. Compliance status is upserted – Results are written to the software_compliance_status table. Each device gets a per-policy record with status compliant or violation, the list of violations, and timestamps.

  6. Auto-remediation is triggered – If the policy has enforceMode: true and remediation options are configured, devices with new violations are queued for remediation through the software remediation worker.

Type Description
unauthorized Software is installed that is not permitted by the policy (blocklist match or allowlist miss)
missing Required software defined in an allowlist is not installed on the device

Each violation within a compliance status record contains:

Field Type Description
type enum unauthorized or missing
software.name string Name of the violating software
software.version string Installed version (if applicable)
software.vendor string Software vendor (if known)
rule.name string Name pattern from the matching rule
rule.minVersion string Minimum version from the rule (if set)
rule.maxVersion string Maximum version from the rule (if set)
rule.reason string Reason text from the rule
severity enum low, medium, high, or critical
detectedAt ISO 8601 When the violation was first detected

Get a fleet-wide summary of compliance status:

GET /software-policies/compliance/overview
Authorization: Bearer <token>

Response:

{
"total": 150,
"compliant": 142,
"violations": 6,
"unknown": 2
}

The overview aggregates per-device worst-case status across all active policies. A device with any violation status is counted as a violation, regardless of how many policies it complies with.

List all devices with active violations:

GET /software-policies/violations?policyId=uuid&deviceId=uuid&limit=100
Parameter Description
policyId Filter violations to a specific policy
deviceId Filter violations to a specific device
limit Max results (default 100, max 500)

The response includes device details (hostname, status, OS type) alongside violation data and remediation status.


Field Type Default Description
autoUninstall boolean false Automatically uninstall violating software
notifyUser boolean Notify the device user before remediation (not yet implemented)
gracePeriod integer Hours to wait before enforcing remediation (max 2,160 hours / 90 days)
cooldownMinutes integer Minimum minutes between remediation attempts on the same device (max 129,600 / 90 days)
maintenanceWindowOnly boolean Only remediate during maintenance windows (not yet implemented)
  1. Compliance check detects violations on one or more devices.

  2. If enforceMode is true and autoUninstall is enabled, the compliance worker schedules remediation jobs through the software remediation BullMQ worker.

  3. Cooldown check – If the device was remediated within the cooldownMinutes window, the remediation is deferred.

  4. Grace period check – If a gracePeriod is configured and the violation was first detected less than gracePeriod hours ago, remediation is deferred.

  5. Remediation executes – The worker dispatches uninstall commands to the target devices. On Windows, this uses the winget provider through user-context IPC.

  6. Status update – The compliance status record is updated with remediationStatus, lastRemediationAttempt, and any remediationErrors.

Trigger remediation manually for a specific policy:

Terminal window
POST /software-policies/:id/remediate
Content-Type: application/json
Authorization: Bearer <token>
{
"deviceIds": ["uuid1", "uuid2"]
}

If deviceIds is omitted, remediation targets all devices with active violations for this policy (up to 500 devices per request). The endpoint validates that the requesting user has access to the specified devices and that the policy is not in audit mode.

Status Description
none No remediation has been attempted
pending Remediation is scheduled but has not started
in_progress Remediation is actively running on the device
completed Remediation finished successfully
failed Remediation encountered an error

On Windows endpoints, Breeze integrates with the Windows Package Manager (winget) for software management operations. Because winget requires user-context execution (it cannot run in Session 0 where the Breeze service lives), all winget commands are dispatched through IPC to a user helper process.

  1. The Breeze agent service (running in Session 0) receives a software management command from the API.

  2. The service checks for a connected user helper session. If no helper is available, read-only operations (scan, list) return empty results, while mutating operations (install, uninstall) return an error.

  3. Commands are dispatched via IPC to the user helper process, which executes winget.exe with the appropriate arguments.

  4. Results are returned through IPC back to the service, which reports them to the API.

Operation Command Timeout Description
Scan upgrades winget upgrade 120s List available upgrades for installed packages
List installed winget list 120s Enumerate all winget-managed installed packages
Install winget install --exact --id <ID> --silent 300s Install a specific package by winget ID
Uninstall winget uninstall --exact --id <ID> --silent 300s Remove a specific package by winget ID

All winget commands include --accept-source-agreements, --accept-package-agreements, and --disable-interactivity flags to ensure fully unattended operation.

Winget package IDs are validated against the pattern ^[a-zA-Z0-9][a-zA-Z0-9._\-]{0,255}$ before any operation. This prevents command injection and ensures only valid winget identifiers are used in install and uninstall operations.

After a successful install, the winget provider checks the output for keywords indicating a reboot is required (restart or reboot). If detected, the result’s RebootRequired flag is set to true, which the API can use to schedule or notify about pending reboots.


Policies have an isActive boolean field that controls whether they are evaluated by the compliance worker. Setting isActive: false pauses all compliance checks and remediation for the policy without deleting it.

Terminal window
PATCH /software-policies/:id
Content-Type: application/json
{
"isActive": false
}
Terminal window
DELETE /software-policies/:id

Deleting a policy performs two operations in a transaction:

  1. Sets the policy’s isActive to false
  2. Deletes all associated software_compliance_status records

The policy record itself is retained (soft delete via isActive: false) so that audit trail references remain valid.

Each policy has a priority field (default: 50) that determines evaluation order when multiple policies target the same device. Higher-priority policies (lower numeric value) take precedence.

All policy operations are recorded in two audit systems:

  1. Route audit – Standard Breeze audit log entries with action types like software_policy.create, software_policy.update, software_policy.delete, software_policy.check, and software_policy.remediate.

  2. Policy-specific audit – Detailed records in the software_policy_audit table with actions like policy_created, policy_updated, policy_deleted, compliance_check_requested, and remediation_requested. These records include the actor type (user or system), actor ID, and a details JSONB column.


Method Path Description
GET /software-policies List policies (?mode=&isActive=&limit=&offset=). Partner-scoped tokens also see their own partner-wide policies
POST /software-policies Create a new policy. Accepts ownerScope: "organization" (default) or "partner"
GET /software-policies/:id Get policy by ID
PATCH /software-policies/:id Update policy fields. Does not accept ownerScope — ownership is immutable. Editing a partner-wide policy requires full partner org access
DELETE /software-policies/:id Soft-delete policy and clear compliance records. Deleting a partner-wide policy requires full partner org access
Method Path Description
GET /software-policies/compliance/overview Fleet-wide compliance summary
GET /software-policies/violations List devices with violations (?policyId=&deviceId=&limit=)
Method Path Description
POST /software-policies/:id/check Trigger on-demand compliance check (optional deviceIds array)
POST /software-policies/:id/remediate Trigger remediation for violating devices (optional deviceIds array)

“orgId is required for this scope” when creating a policy. Partner-scoped tokens that manage multiple organizations must specify orgId in the request body (or use ownerScope: "partner" to create a partner-wide policy instead, which doesn’t need an orgId). If the partner token has access to exactly one organization, orgId is auto-resolved. Use an organization-scoped token or explicitly pass the orgId field.

“Partner-wide software policies require full partner org access” when creating, editing, or deleting a partner-wide policy. Only a partner-level user with access to every organization under the partner (not a subset) can create, edit, or delete a partner-wide policy. A user restricted to selected organizations can still view partner-wide policies and their compliance results but cannot modify them.

Compliance check shows no violations but unauthorized software is clearly installed. Verify the policy’s mode matches your intent. A blocklist only flags software that matches a rule; a missing or misspelled rule name will not match. For allowlist policies, check whether allowUnknown is set to true – this suppresses violations for unmatched software. Also ensure the policy’s isActive is true and that the device’s software inventory has been recently updated by the agent.

Remediation returns “Remediation is not available for audit-only policies”. Audit mode is observation-only. Change the policy mode to allowlist or blocklist using PATCH /software-policies/:id with { "mode": "blocklist" } before triggering remediation.

Winget install fails with “requires a connected user helper session”. Winget cannot run in Session 0 (the Windows service context). The Breeze agent dispatches winget commands through IPC to a user helper process running in an active user session. If no user is logged in or the helper process is not running, winget operations will fail. Verify that a user session is active on the target Windows device and that the Breeze user helper is connected.

Compliance check was scheduled but never completed. Compliance checks run through BullMQ and require Redis. Verify Redis is accessible. Check the API logs for [SoftwareComplianceWorker] messages. If you see “withSystemDbAccessContext unavailable”, the worker may not have the database context it needs. Also verify that the policy has target devices – if no devices match the policy’s scope, the worker has nothing to evaluate.

Policy created successfully but warning field appears in the response. The warning field indicates that the initial compliance check could not be scheduled, typically because Redis is unavailable. The policy itself was created and persisted. The compliance check will run on the next worker cycle (every 15 minutes) once Redis becomes available, or you can trigger it manually with POST /software-policies/:id/check.

Remediation completes but violations reappear on the next scan. If the user reinstalls the software after remediation, the next compliance check will detect it again. Consider using cooldownMinutes in the remediation options to prevent rapid repeated remediation. For persistent violations, investigate why the software is being reinstalled (GPO, user behavior, or another deployment system) and address the root cause.

On-demand compliance check returns 503 “Failed to schedule compliance check”. This indicates BullMQ/Redis is unavailable. The 503 status code is intentional – the check cannot be queued without the job system. Retry after confirming Redis is running and accessible from the API server.

Delete returns success but the policy is still visible in the list. Policy deletion is a soft delete – it sets isActive: false and clears compliance records. The policy record remains in the database for audit trail purposes. Filter your list query with ?isActive=true to exclude deleted policies.