Breeze RMM v0.120.0: backups to S3 written only through short-lived storage sessions, integrity-checked restores, consent prompts that report whether they were shown, the remote desktop start fence on by default, and the first two waves of the AI model registry.
⚠️ Backups to S3 now need agent v0.119.0 or later, and HTTPS.
- What changed. Scheduled, SQL Server and Hyper-V backups to S3 or S3-compatible storage are written only through a short-lived, write-scoped storage session. No backup command carries the storage destination or its keys.
- Who is refused:
- A device whose backup component reports it cannot write this way: "Update the Breeze agent on this device, then try again."
- An
http://storage endpoint. - An agent API address over plain
http://, or an unsetPUBLIC_API_URL.
- No fallback. Local and NAS destinations are unchanged.
- Before upgrading, update every device that backs up to S3 and move storage endpoints and the agent API to HTTPS. See HTTPS for Backups (#7566).
⚠️ Behaviour changes that need attention. Details are under Self-Hosting / Upgrade Notes.
- The remote desktop start fence (
REMOTE_DESKTOP_FENCE_REQUIRED) now defaults to on for new installs. Existing installs keep their current setting until they change.env(#7564). - The default AI model is now Claude Sonnet 5.5 with adaptive thinking. If you route AI through a gateway alias, update the alias (#7593).
- Under a Require consent policy, a signed-in user who cannot be shown the prompt is now always refused. Unanswered prompts on macOS and Linux are refused. Update the server before agents; the normal order already does this (#7560, #7562).
- Breeze Assist on Windows now works in the console session only (#7556).
Security: hardening
This release includes security hardening across:
- backup storage access;
- restore integrity;
- Windows restore file handling;
- remote desktop session starts and consent;
- the Breeze Assist credential;
- customer portal sign-out;
- device restore limits;
- enrollment key lookups;
- dependency updates for upstream advisories.
Self-hosters are encouraged to upgrade the server and let agents and Breeze Assist update to 0.120.0. (#7566, #7565, #7561, #7564, #7575, #7560, #7562, #7556, #7558, #7549, #7548, #7546, #7563)
Summary
- Backups to S3 use storage sessions only. Every S3 backup is written through a short-lived, write-scoped session (#7566).
- The Backup policy's Destination section has a new card. It lists the storage keys your S3 destinations used before this release, and keeps each one listed until it has been replaced and disabled with your storage provider.
- Check old key asks the storage provider. I disabled this key records your confirmation.
- Restores are checked against the snapshot's integrity record (#7565, #7561, #7568).
- What is checked. The server sends each snapshot's integrity expectations with every restore, verify, test restore, VM restore and bare-metal recovery. The updated backup helper checks the manifest and every restored file against them before anything is installed.
- What is refused. A snapshot that failed its integrity check is refused.
- Snapshots without an attestation. They still restore, and the result is labelled unattested.
- Windows restores are stricter about what they write (#7561).
- Reserved names. Path components that Windows reserves (
CON,NUL,COM1and the like), or that contain:or end in.or a space, are refused. - Unrecognised security descriptors. A restored security descriptor whose accounts the machine doesn't recognise is replaced with a restrictive one: owner Administrators, access for SYSTEM and Administrators only. The result lists those paths.
bmr_recoveris files-only on Windows. It restores files only. System state is applied by a bare-metal rebuild.
- Reserved names. Path components that Windows reserves (
- Consent prompts report whether they were shown and answered (consent prompt protocol 2) (#7560, #7562, #7575).
- What the agent knows. The agent, Breeze Assist and the native dialogs now report whether the prompt was actually on screen, and whether anyone is signed in to the session being viewed.
- What the technician sees. A specific message for each outcome.
- What the audit log records. The detail of each outcome.
- The WebSocket desktop fallback now follows the same start rules as WebRTC (#7564).
- Starting a session. It honours the session start fence, notify mode and the consent prompt.
- Ending a session. End stops it immediately.
- AI model registry, waves 1 and 2 (#7643, #7665).
- Admin page. A platform model catalog with a new Admin → AI models page (
/admin/ai-models) for prices, offered models and the platform default. - Discovery. A daily Anthropic model discovery job flags new models for review and never enables, prices or removes anything on its own.
- Partner-level tables. They are backfilled from each partner's current setup, and a shadow usage ledger is added.
- Routing and billing are unchanged in this release.
- Admin page. A platform model catalog with a new Admin → AI models page (
- AI chat usage is counted correctly on multi-turn chats (#7669). Each turn of a chat was being charged the running total of the conversation so far, which inflated session cost, budgets, AI credit deductions and the Office per-user ledger. Each turn is now charged its own cost. This covers main chat, Office chat, helper chat and the script builder. Earlier records are not rewritten.
Added
- Storage key card and API (#7566).
GET /backup/storage-credentials,POST /backup/storage-credentials/:id/checkandPOST /backup/storage-credentials/:id/confirm-disabled.- Check limits. Checks are limited to 10 per organization per 10 minutes.
- Audit and access. Both actions are audited, and no AI tool can run them.
- Admin → AI models (#7643). Platform admins set prices, fast-mode rates, option support, plan gate, prompt profile, offered models and the default. Changes require MFA. Refresh queues a discovery sync.
- Recovery result codes and restricted-descriptor details in the restore and Recovery views (#7568).
- Metrics:
- Agent heartbeat capability
securityCapabilities.desktopWsFenceProtocolVersion(#7564). The server accepts it and does not require it yet.
Improved
-
Default AI model is Claude Sonnet 5.5 with adaptive thinking at effort
medium(#7593).- Existing chats keep their model.
POST /ai/sessionsnow rejects a model that isn't offered (400 invalid_model).- Raw one-shot calls (script reviewer, patch-test analysis, ticket and email drafts) cap thinking so short answers are not truncated.
- Pricing has rows for Sonnet 5.5, Opus 5.5 and Fable 5.1.
-
Backup helper capability reporting (#7558). When the agent can't ask its backup component which features it supports, it now reports "unknown" instead of "none". Retries run after 1, 2 and 4 minutes, then every 5 minutes. A brief probe failure no longer makes a current helper look outdated. The waiting message now names the backup component.
-
Windows registry hives are flushed before the VSS snapshot, so recent registry changes are in system-state backups and rebuilt machines (#7408).
-
DR plans: a Bare metal rebuild step now waits up to 24 h by default (was 4 h) (#7418).
-
Topology: turning on materialization now imports each site's first snapshot automatically. Sites no longer stay on "Building the topology map" (#7559).
-
Breeze Assist on Windows receives its credential only over the agent's local channel. It is no longer written to
agent.yaml. On upgrade the agent moves any token it finds there into its protected secrets file and rotates the credential once (#7556). -
API error codes (#7435). Five codes from device and agent routes now use the standard uppercase form:
SCHEME_NOT_ALLOWEDINVALID_CUSTOM_FIELD_VALUE(wasinvalid-custom-field-value)RACE_LOSTRE_ENROLLMENT_REQUIREDSOFTWARE_INVENTORY_LOCK_TIMEOUT
HTTP statuses and messages are unchanged. Update integrations that match on the old lowercase codes.
Fixed
- Remote desktop. The WebSocket fallback no longer refuses every start under a notify (default) or consent policy (#7564).
- Remote desktop. A start result the server could not read now fails the session with a clear message instead of leaving it "connecting" (#7575).
- Patches. The device Patches tab shows ring-aware approval state, not "Pending approval" on every patch (#7637).
- Alerts. The built-in Patch job failures and Reboot pending too long rules, and other built-in rules, can be switched off. An inactive rule raises nothing (#7639).
- Monitoring. Recommended → Attach to policy works on a policy that has no monitors link yet (#7633).
- Add Device. The CLI command and its copy button appear only once a token exists. The setup wizard's enroll step does the same (#7631).
- Agent (Windows).
breeze-agent service startsucceeds when the service is already running, so re-running the install one-liner no longer fails (#7497). - Custom fields. Editing a field without options (Text, Number, Boolean, Date) saves (#7496).
- Restore results. A bare-metal recovery's
failedFilescount is accepted. Advisory warnings (unattested snapshot, vault fallback, files-only recovery) are no longer shown as failures (#7568). - Customer portal. Sign-out is now recorded durably and holds across cache restarts (#7549).
- Devices. Restoring a removed device counts against the partner device limit, like enrollment (#7548).
- Enrollment keys. Key-id routes answer
404 "Enrollment key not found"for a key outside the caller's sites (#7546). - Binary downloads. Backup, watchdog, user-helper and recovery-media downloads read the same storage keys that binary sync writes (#7555).
- Compose. The audit-chain settings now reach the API container (#7641). These are
AUDIT_ANCHOR_SIGNING_KEY,AUDIT_CHAIN_ANCHOR_ENABLED,AUDIT_CHAIN_VERIFY_*andAUDIT_ADMIN_DATABASE_URL. The production Compose file also gains theDEVICE_COMMAND_QUEUE_*deadlines. - Release. arm64 recovery media builds on a native arm64 runner (#7419).
- AI models admin. The
/admin/ai-modelsprice drawer edits prices in dollars, the same unit the table shows (#7699). - Dependencies. axios 1.20.0 and @grpc/grpc-js 1.14.5 (#7563).
Known issues
- Deleting a backup destination that has job history returns an error. Disable the destination instead for now (#7622).
- A crash-consistent Hyper-V backup of a VM that is turned off fails; application-consistent backup of the same VM works (#7623).
- Breeze Assist on Windows does not run in RDP or other non-console sessions (#7542).
- Windows Quick Support cannot start for a standard (non-admin) user (#7620).
- Binary sync: if an S3 upload fails at boot, the previous release's object stays in place until the next successful sync (#7574).
Self-Hosting / Upgrade Notes
Upgrade command. Check how your install pins its images: grep '^BREEZE_API_IMAGE_REF=' .env.
- Digest-pinned (value ends in
@sha256:…, everyguided-setup.shinstall from v0.112.0): fetch the currentguided-setup.shfrommain, then runbash guided-setup.sh --upgrade 0.120.0. It verifies the signed image inventory, updatesBREEZE_VERSIONand all four image digests, then pulls and restarts. - Tag-form (value ends in
:${BREEZE_VERSION}): setBREEZE_VERSION=0.120.0, then rundocker compose pull api web portal && docker compose up -d. - Do not edit only
BREEZE_VERSIONon a digest-pinned install. It re-pulls the images you already run. guided-setup.sh --upgradedoes not edit yourdocker-compose.yml. The changes it doesn't pick up are listed below.- See the Upgrade Guide.
Breaking changes and required actions.
- Backups to S3: agent ≥ 0.119.0 and HTTPS, before you upgrade (#7566).
- Who is refused:
- A device whose backup component has reported it cannot write through a storage session is refused (
409 helper_update_requiredon the on-demand SQL Server and Hyper-V routes; scheduled jobs fail with the same message). - Devices that have not reported yet are held until their first heartbeat, as before.
http://storage endpoints, a plain-http://agent API or a missingPUBLIC_API_URL, and providers other than S3 and local are refused, as they already are for restores.
- A device whose backup component has reported it cannot write through a storage session is refused (
- What to do:
- Update every device that backs up to S3.
- Switch MinIO and other S3-compatible endpoints to HTTPS. Keep the same host and port; only the scheme changes.
- Make sure agents reach the API over HTTPS.
- Unaffected: local and NAS destinations.
- After the upgrade: open each Backup policy's Destination section and work through the storage key card. Replace each listed key with your provider, disable the old one, then use Check old key or I disabled this key.
- The
manage_backup_configsAI tool now accepts only thes3andlocalproviders.
- Who is refused:
- Remote desktop start fence on by default (#7564).
- What it does. Remote desktop starts only on agents that report the session start fence, which is v0.114.0 and later. On an older agent the technician sees "Remote desktop needs an agent update on this device …" (
503 agent_upgrade_required). Terminal and Files are unaffected. - Existing installs keep their current setting. The v0.119.0
.env.examplecontainedREMOTE_DESKTOP_FENCE_REQUIRED=false, and the v0.119.0docker-compose.ymlpasses${REMOTE_DESKTOP_FENCE_REQUIRED:-false}, so an existing install keeps the fence off after the upgrade. - To turn it on, set
REMOTE_DESKTOP_FENCE_REQUIRED=truein.envonce every agent is on v0.114.0 or later, or remove the line and update your Compose file from this release. - New installs get it on.
- Boot check. A value other than true/false, 1/0, yes/no or on/off now refuses boot.
- What it does. Remote desktop starts only on agents that report the session start fence, which is v0.114.0 and later. On an older agent the technician sees "Remote desktop needs an agent update on this device …" (
- Default AI model changed to
claude-sonnet-5-5with adaptive thinking (#7593).- If AI runs through a LiteLLM or other gateway alias: Breeze now requests
claude-sonnet-5-5and sendsthinking: {type: "adaptive"}withoutput_config.effort. - To keep working, do one of these:
- Add an alias for
claude-sonnet-5-5and let the gateway accept or drop those parameters (LiteLLMdrop_params). - Set
ANTHROPIC_MODELto your backend's model id. An unrecognised id is sent with thinking disabled, as before.
- Add an alias for
BREEZE_AI_SCRIPT_REVIEWER_MODELdefaults to the same model.- Existing chats keep their stored model.
- If AI runs through a LiteLLM or other gateway alias: Breeze now requests
- Consent prompt protocol 2. Update the server before agents (#7560, #7562).
- Order. A server older than this release refuses consent- and notify-mode starts on updated agents with "update the agent". Upgrading the server first, then letting agents update, is the normal order.
- Only devices whose remote access policy uses the consent prompt are affected, in three ways:
- A signed-in user who cannot be shown the prompt is now always refused, whatever "If no one can respond" says. Causes include Breeze Assist not running and a native dialog failing. That setting still applies when nobody is signed in, and when a prompt the user could see went unanswered.
- On macOS and Linux an unanswered prompt is refused, because only Windows reports the lock state reliably.
- Update Breeze Assist along with the agent. An older Assist still handles Allow and Deny, but its unanswered prompts are refused.
- Audit log. Consent events gain
consentOutcome,consentOccupancyandconsentProtocol, plus the reasonsno_user_sessionandhelper_unreachable.
- Breeze Assist on Windows is console-session only (#7556).
- Credential handling. The agent delivers Assist's credential only over its local channel to the active console session, and no longer stores it in
agent.yaml. Assist in an RDP or other non-console session shows that it has not received its credentials (#7542 tracks support). - On first start the agent moves any credential it finds in
agent.yamlinto its protected secrets file and rotates it once. - Unaffected: macOS and Linux.
- Credential handling. The agent delivers Assist's credential only over its local channel to the active console session, and no longer stores it in
WebSocket desktop fallback.
- Start handshake. The session stays
connectinguntil the agent confirms the stream started, which comes after the consent prompt when one applies. - New viewer error codes:
CONSENT_DENIED,AGENT_START_FAILED,START_TIMEOUT,START_REFUSEDandSESSION_ENDED. - Older agents. Agents v0.114.0–v0.119.x keep working on this transport.
Database.
- 12 migrations. They are idempotent and apply automatically on boot via
autoMigrate(unlessAUTO_MIGRATE=false). - No large rewrites:
- New tables: portal session revocations, backup storage key history, and the AI model registry tables (
ai_platform_models,partner_ai_connections,partner_ai_models,ai_model_assignments,ai_invocations). - Small data writes: a seed of 10 platform models, one registry connection copied per partner AI provider config, and a model pin for partners on a provider-catalog endpoint with no model set.
- New tables: portal session revocations, backup storage key history, and the AI model registry tables (
ai_sessionsgains three nullable columns. Its constraints are added without a scan, then validated with reads and writes allowed. Its index is built withCREATE INDEX CONCURRENTLYoutside a transaction (2026-11-14-100600-ai-sessions-offering-idx.sql).- If that index build is interrupted, the next start refuses with "ai_sessions offering index build left INVALID index". Run
DROP INDEX CONCURRENTLY public.ai_sessions_offering_idx;and restart the API. - First start after the upgrade. The API records the storage key each S3 destination uses, and builds the AI registry from your current AI settings. Both log one
[startup]line.
Environment variables.
- Required: no new required environment variables.
- Changed default:
REMOTE_DESKTOP_FENCE_REQUIREDnow defaults totrue, and an unrecognised value refuses boot. See above for existing installs.BREEZE_AI_SCRIPT_REVIEWER_MODELnow follows the new default model.
- New, optional (mapped in both Compose files of this release):
AI_INVOCATIONS_RETENTION_DAYS, default 400.AI_INVOCATIONS_RETENTION_BATCH_SIZE.AI_INVOCATIONS_RETENTION_MAX_BATCHES.
- Now passed to the API by Compose (#7641). These were previously ignored on Compose installs even when set in
.env. All are optional; unset keeps today's behaviour.AUDIT_ANCHOR_SIGNING_KEY: a base64 32-byte Ed25519 seed,openssl rand -base64 32. When set, the API logs the key id and public key at boot.AUDIT_CHAIN_ANCHOR_ENABLED.AUDIT_CHAIN_VERIFY_ENABLED,AUDIT_CHAIN_VERIFY_MODEandAUDIT_CHAIN_VERIFY_RESCAN_SLICES.AUDIT_ADMIN_DATABASE_URL.DEVICE_COMMAND_QUEUE_*(production Compose file).
- If you keep your own
docker-compose.yml, copy theseapienvironment entries from this release's file. Setting them in.envalone has no effect unless Compose maps them. HELPER_BINARY_DIR: when unset it now means the agent binaries directory (AGENT_BINARY_DIR). Both shipped Compose files set it explicitly (#7555).
Behaviour changes and flags.
- Binary downloads (S3-backed binary hosting): backup, watchdog, user-helper and recovery-media downloads are served from the
agent/prefix, and the Breeze Assist installer is synced tohelper/at boot. Thebackup/,watchdog/,user-helper/andrecovery-iso/prefixes are no longer read and can be deleted. No manual copy step is needed on upgrade (#7555). - AI model registry. It is visible to platform admins at
/admin/ai-models. A daily discovery job (06:38 UTC) lists new Anthropic models for review using your platform key, and it is skipped whenANTHROPIC_BASE_URLpoints at a gateway. Routing, pricing and billing still come from the existing settings in this release. - No feature flag changes.
Agent release notes (0.120.0; agents and Breeze Assist update through the normal channel):
- Backup helper: integrity protocol 2.
- What it checks. The helper checks restores against the snapshot's integrity record, and installs a file only after it matches.
- Windows. It refuses reserved Windows names and restricts unrecognised security descriptors.
bmr_recoveris files-only, with codesystem_state_requires_rebuild. - Linux. Package reinstall during bare-metal recovery validates package names.
- Helper capability probe failures are reported as unknown, with retries.
- Consent prompt protocol 2. This covers the agent, Breeze Assist and the native dialogs on Windows, Linux and macOS. One prompt runs at a time per user, and End withdraws a pending prompt.
- WebSocket desktop stream. It keeps a revocation lease, shows the notify notice and indicator, and stops on
stop_desktop. - Assist credential (Windows). It is delivered only over local IPC, removed from
agent.yaml, and rotated once. - Registry hives are flushed before VSS snapshots.
service start(Windows) succeeds when the service is already running.
Full Changelog: v0.119.0...v0.120.0
What's Changed
- fix(enrollment-keys): key-id routes answer 404 for a key the caller can't see by @ToddHebebrand in #7546
- fix(devices): restoring a removed device respects the partner device limit by @ToddHebebrand in #7548
- fix(portal): portal sign-out is durable by @ToddHebebrand in #7549
- chore(release): clear the next-release draft and the one-time #7351 note after v0.119.0 by @ToddHebebrand in #7553
- fix(deps): axios 1.20.0 and @grpc/grpc-js 1.14.5 for new HIGH advisories by @ToddHebebrand in #7563
- fix(binaries): downloads read the S3 keys sync writes — one key per staged file (#7515) by @ToddHebebrand in #7555
- fix(topology): bootstrap first-snapshot import automatically once materialization is on (#7557) by @ToddHebebrand in #7559
- feat(remote): server accepts consent prompts that report whether they were shown and answered (protocol v2) by @ToddHebebrand in #7560
- feat(backup): show recovery result codes and restricted-descriptor details by @ToddHebebrand in #7568
- feat(backup): deliver snapshot integrity expectations with every restore and bind file indexes to attestations by @ToddHebebrand in #7565
- fix(remote): fail unreadable desktop start results and require consent markers backed by their outcome by @ToddHebebrand in #7575
- feat(backup): backups to S3 storage use storage sessions only; storage key history by @ToddHebebrand in #7566
- feat(ai): default to Sonnet 5.5 with adaptive thinking; current-model pricing; validate session model (#7587) by @ToddHebebrand in #7593
- fix(api): accept null options when editing a custom field (#7476) by @bdunncompany in #7496
- fix(agent): service start succeeds when the Windows service is already running (#7474) by @bdunncompany in #7497
- docs(ai): AI model registry spec + W01–W03 plans (#7598) by @ToddHebebrand in #7592
- chore(deps): bump the github-actions group with 4 updates by @dependabot[bot] in #7554
- fix(web): hide the Add Device CLI command until a token exists (#7628) by @ToddHebebrand in #7631
- fix(monitoring): omit featurePolicyId when Recommended attach creates a monitors link (#7627) by @ToddHebebrand in #7633
- fix(alerts): built-in patch alert rules can be switched off (#7626) by @ToddHebebrand in #7639
- fix(compose): pass audit-chain env vars to the API + guard operator-facing env reads (#7470) by @ToddHebebrand in #7641
- fix(remote): the WebSocket desktop fallback honours start generation, stop and notify like WebRTC by @ToddHebebrand in #7564
- fix(agent): deliver the Assist token over the local IPC channel only by @ToddHebebrand in #7556
- fix(agent): report backup helper capabilities as unknown when the helper probe fails by @ToddHebebrand in #7558
- feat(backup-helper): check restores against snapshot attestations; Windows restore hardening by @ToddHebebrand in #7561
- feat(remote): consent prompts report whether they were shown and answered (protocol v2) by @ToddHebebrand in #7562
- feat(ai): model registry W01 — platform model catalog, discovery, /admin/ai-models (#7599) by @ToddHebebrand in #7643
- fix(dr): default BARE_METAL_REBUILD wait timeout to 24 h (#7087) by @ToddHebebrand in #7418
- fix(release): build arm64 recovery media on a native arm64 runner (#6731) by @ToddHebebrand in #7419
- feat(api,web): adopt ERROR_CODES for remaining devices/agents routes (E2c) by @fabicarvano in #7435
- docs(portal): advanced per-family visibility spec (#7450) by @fabicarvano in #7642
- fix(agent/backup): flush registry hives before the VSS snapshot (#7367) by @ToddHebebrand in #7408
- fix(patches): ring-aware approval state on the device Patches tab (#7625) by @ToddHebebrand in #7637
- feat(ai): model registry W02 — registry tables, legacy backfill, /ai/provider on the registry (#7600) by @ToddHebebrand in #7665
- docs(ai): model registry W05 resume spike findings (#7603) by @ToddHebebrand in #7666
- docs(ai): model registry W04 plan — settings UI + AI usage (#7602) by @ToddHebebrand in #7668
- fix(ai): bill each SDK chat turn's own cost, not the running total (#7667) by @ToddHebebrand in #7669
- docs(ai): model registry W10 plan — chargeback (#7608) by @ToddHebebrand in #7685
- docs(ai): model registry W05 plan — chat picker + switching (#7603) by @ToddHebebrand in #7688
- docs(ai): model registry W09 plan — failover + escalation (#7607) by @ToddHebebrand in #7686
- docs(ai): model registry W06 + W07 plans — OpenAI-compatible and cloud providers (#7604 #7605) by @ToddHebebrand in #7689
- fix(web): /admin/ai-models price drawer edits dollars like the table (#7692) by @ToddHebebrand in #7699
- test: pre-release sweep v0.119.0 → main (93982bc) + two small fixes by @ToddHebebrand in #7694
- chore(web): What's New for 0.120.0 by @ToddHebebrand in #7683
Full Changelog: v0.119.0...v0.120.0