Skip to content

v0.124.0

Latest

Choose a tag to compare

@github-actions github-actions released this 20 Oct 02:31
· 44 commits to main since this release
0c7b16e

Breeze RMM v0.124.0 — a fuller Trust Center, connection health that tells you when an integration breaks, and Huntress and SentinelOne deployed from policy. Also in this release: an AI data & privacy policy, verified Microsoft 365 identity actions, Windows System Restore checkpoints taken by the agent, and faster navigation between customers.

⚠️ Breaking: rolling back to v0.123.0 is a database restore, not an image rollback. 2026-12-30-200000-ai-model-registry-legacy-drop.sql archives the legacy AI model storage into ai_model_registry_legacy_archive and drops it (#9130). 2026-12-31-160000-drop-policy-patch-auto-approve.sql drops two policy-level patch columns that v0.123.0 still reads (#9188). With the workspace extension enabled, the v0.123.0 image's boot tripwire also refuses to start while the new archive table exists. Take a database backup (or note a PITR point) before you upgrade. Details under Database.

⚠️ Behaviour change: CALLER_VERIFICATION_ENABLED now defaults to true. Microsoft 365 password resets and account disables now need a fresh caller verification of the pinned Entra account (#9140). Earlier .env.example files shipped CALLER_VERIFICATION_ENABLED=false. Before this release that line meant "dark". Now it hides the workflow and refuses every M365 reset and disable. Check your .env before upgrading. Details under Behaviour changes and feature flags.

Summary

  • Trust Center, second release (#9042, #9059, #9055, #9056, #9061, #9063, #9058, #9060, #9054, #9040, #9109, #9064, #9053, #9094). The published customer security page gains the following:
    • Declared controls. Practices Breeze can't measure, such as training, an incident response plan or cyber insurance, can be declared by a named user. Each declaration expires after 365 days, with a reminder 30 days before.
    • Documents on request, with email confirmation, MSP approval and a 7-day download link.
    • Framework views (NIST CSF 2.0 by default), subprocessors, an FAQ and a 90-day "controls met" history.
    • A partner-wide template that every org page inherits.
    • A signed, machine-verifiable attestation (ES256 JWT + JWKS), an iframe embed for allowlisted websites, and CSV/JSON questionnaire export.
    • Customer self-edit of the draft from the portal. Publishing stays with the MSP.
    • The public page is translated into 8 locales. The CIS Controls framework view is behind BREEZE_TRUST_CIS_FRAMEWORK_VIEW (default off).
  • Connection health notifications (#8936, #9011, #9045, #9047). A Connection Health panel on Integrations lists every broken integration with a fix link and recent recoveries. Admins who can fix an incident get a daily digest email, with an opt-out and one-click unsubscribe. New signals: failing webhooks, stalled syncs and a Google Workspace probe. Notices to customer org admins are opt-in, off by default (partner default, org override). Incidents also publish integration.health_opened / integration.health_resolved events.
  • AI data & privacy policy (#8866, #9010, #9044, #9046). A partner default and org override (the org can only tighten) control two things:
    • Device file reads: Off, Excludes user profile folders (the default), or Any path with approval. The level is enforced for chat, agent runs, MCP, the helper and the script builder.
    • Tool-output retention: 30 days by default. Blank keeps outputs forever. A nightly job replaces older outputs with an "Output expired" marker.
    • Device file contents, command output and registry values now reach the model as fenced, untrusted text.
  • Verified Microsoft 365 identity actions (#9140, #9012). Password resets and account disables are pinned to one Entra account. Each needs a fresh link-tier caller verification (SMS or email link, callback attestation, or an administrative disable with MFA step-up). "This is not me" opens an incident and fences undispatched actions. Eight more M365 identity actions are available through AI with four-eyes approval: revoke sessions, assign/remove licence, add to/remove from group, retire an Intune device, create user, set auto-reply. They need a one-time re-consent to the new actions permission set.
  • Huntress and SentinelOne from a configuration policy, first usable release (#8923, #9194, #9244, #9251). Turn a vendor on in the policy's Security Agents tab. Every in-scope device whose org is mapped in that vendor's integration gets the agent with its own keys. Per-device coverage reads Covered, Gap, Vendor only, Vendor offline, Mismatched org, Not applicable or Pending. Gaps raise alerts. SentinelOne needs the partner's uploaded SentinelOne MSI with {s1_site_token} in its install arguments.
  • Windows System Restore checkpoints, agent side (#8506, #9160, #9232). With this release's agent, Windows devices take one restore point per command, before the first change a patch run, script or software install makes. The outcome is reported back, so the System Protection policy from v0.123.0 stops reading "Awaiting the device". Checkpoints are best-effort: a restore point that cannot be created is reported, and the command still runs. A command that changes nothing spends no restore point. Needs agent 0.124.0.
  • Faster navigation between customers (#9009, #9006, #8994, #8992, #9100, #9114, #9131, #9125, #9104, #9072):
    • The header org switcher becomes Customer › Page, with live counts (devices online/offline, open tickets, critical alerts).
    • Org, site, device and ticket names link to their record everywhere.
    • A Recent list sits in the sidebar and on the dashboard.
    • An Attention column on the devices list shows open alerts and tickets.
    • Org records lead with fleet health.
    • Bulk reboot or lock asks for confirmation first.

Added

  • Trust Center (#8768 W02/W03):
    • Declared controls with expiry reminders (#9059), and an MFA-enforced control derived from Microsoft 365 Conditional Access policies (#9055).
    • Gated documents with access requests and optional NDA clickwrap text (#9056).
    • A framework picker with coverage summaries (#9061), plus CIS v8 hardening safeguards behind the CIS gate (#9094).
    • Subprocessors (with suggestions from detected tools), an FAQ and a controls-met history (#9063).
    • A partner-wide template under Settings → Partner → Trust Center, with "Inherited" badges and reset (#9058).
    • Portal i18n in 8 locales (#9060).
    • Home-flag rules, serving-set self-heal and an AI trust status tool (#9054).
    • GET /api/v1/trust/attestation/jwks.json and per-page attestation JWTs, plus a trust:signing-key rotation CLI (#9040).
    • An embed card with a live allowlist of up to 10 https:// origins (#9109).
    • CSV/JSON questionnaire export from the editor (#9064).
    • Customer trust page editing, a new Customer Portal → Portal features toggle that is off by default and is not part of Enable all (#9053).
  • Connection health (#8844):
    • Sources for Huntress, SentinelOne, Pax8, UniFi, backup providers, EDR, accounting, DNS filtering, M365 connections and sync, and ticket mailboxes (#8936).
    • The daily digest: an hourly job sends between 08:00 and 11:59 partner-local, at most one per user per day. It has a My Account → Email notifications toggle and RFC 8058 List-Unsubscribe (#9011).
    • Webhook, stale-sync and Google Workspace signals, plus a liveness card on /admin/system → Connections (#9045).
    • The Health notifications card (customer admins) and integration.health_* events (#9047).
    • Retention for webhook_deliveries (#9193).
  • AI data & privacy cards on Partner settings → AI Features and on the org AI tab. APIs: GET/PUT /api/v1/ai/data-policy and /api/v1/partner/ai/data-policy (#8866). Enforcement in the tool gate (#9010), nightly retention (#9044), and an orphaned-transcript sweeper (#9133).
  • Caller verification enforcement for m365_reset_password and m365_disable_user (#9140):
    • targets pinned to Entra tenant + object id on action_intents;
    • an administrative-disable step-up (POST /orgs/:orgId/caller-verifications/administrative);
    • typed caller_verification_required refusals in chat, MCP and the release worker.
  • M365 identity write catalog (#9012): eight session-only four-eyes actions with read-side effect probes, and permission profile v3 for customer-graph-actions. Connections consented to v2 keep running the actions they already cover. A new action refuses with consent_upgrade_required until the tenant re-consents.
  • Security agents (#6960):
    • Huntress preflight and the generated, read-only managed software policy (#8923).
    • Coverage state, a reconciler and gap alerts. The coverage UI is on the software policy compliance view (#9194).
    • SentinelOne as a managed vendor (#9244), and endpoints the S1 console no longer returns marked absent (#9251).
  • System Restore:
    • an agent systemrestore package that confirms each point by its WMI identity (#8506);
    • the restore-point block honoured on all three paths (#9160);
    • a list_device_restore_point_attempts AI tool (#8941);
    • daily retention for the attempts ledger, 90 days by default (#8939).
  • Tickets:
    • save a ticket's checklist as a template, duplicate a template, and n/m steps progress in the queue (#9230);
    • Link device / Change device on an existing ticket (#9227).
  • Device filters: Device Group "does not equal" / "is not one of". Saving a dynamic group that references itself, directly or through a cycle, is refused (#9215).
  • Agent: names Zscaler Client Connector, GlobalProtect, Cisco Secure Client, FortiClient and Netskope as VPN providers (#9186).
  • Script library: Delete Printer by Name and Delete All Printers Except Listed (Windows), each with a dry run (#9183).
  • Agreements: Record signed agreement files an agreement the client signed elsewhere (DocuSign, wet ink, email) with its evidence snapshot (#9250, #9236, #9189).
  • AI tools and MCP:
    • an OpenAPI (REST) tool-source kind for the Tool Catalog (#9106);
    • API keys and OAuth grants limited to chosen MCP tool areas, plus a whoami MCP tool (#9135);
    • EDR push hints and a sync_edr_data AI tool (#8937);
    • generate_report accepts the business report types (#9240);
    • query_devices honours the tags filter (#9191).
  • Auth pages: an optional "Report abuse" / "Security" footer and /.well-known/security.txt, from three new web variables (#8873).
  • Partner trust review emails ("request received", "account approved") when PARTNER_TRUST_MODE=enforce (#8767).
  • Groundwork, not yet usable from the UI:
    • Network Proxy dedicated tunnel origin: API host mode and web support, off until TUNNEL_ORIGIN_TEMPLATE is set (#9096, #9150);
    • per-root backup GC, reconcile and janitor, with the prefixed writer still off (#8925);
    • YARA rule sets and the agent YARA-X engine, dark (#9112, #9156, #9161);
    • PAM ownership-epoch transfer, behind a flag (#9134).

Improved

  • AI Providers & Models: a partner can hold more than one Anthropic connection. Only the first takes over features that used the platform key. Models found on a later connection arrive disabled (#9130).
  • Patch approval: policy-level auto-approve is gone from every surface. Auto-approve and per-app rules live only on the Update Ring (#9188). A soft-deleted ring now counts as an invalid reference, and its policies hold patches (#8906).
  • Agent reliability:
    • The watchdog treats a heartbeat answered with 503/429 as liveness and no longer restarts a healthy agent (#9146).
    • The WebSocket backs off after a server-initiated close and honours Retry-After (#9145).
    • The reconnect loop exits when Stop lands during a dial (#9245).
    • Windows DHCP state is read in process, not with a PowerShell spawn per heartbeat (#8912).
    • A superseded start_desktop is refused (#9138).
    • Windows toasts are raised in process via WinRT with no console flash, and fall back when notifications are disabled (#8878, #9207).
    • Collector strings with control characters keep the previous value (#9148).
  • Linux maintenance-window reboots get the same prompt, deferral and deadline as Windows, with a wall broadcast when no one is signed in (#9216).
  • Org records and device pages (UI flow #8985):
    • Org records: billing address and site columns, a Devices tab with search and filters, a "work here" state, and keyboard-operable menus (#8994, #9114, #9092).
    • Device detail: an "Offline · last seen …" header, a cue when the device belongs to another org, phone-width layout, and an accessible Back control (#9125, #9097).
    • Devices list: a column chooser and clearer empty states (#9131, #9157).
  • Partner settings:
    • card autosave keeps unsaved edits elsewhere on the page (#9205);
    • a scrollable sticky rail (#9206);
    • a confirm before turning a module off (#9174);
    • Security limits can be cleared (#9142).
    • App shell polish: an 11px type floor, Cmd+K contrast and a compact MFA banner (#9095, #9144). The sign-in logo is larger (#9208).
  • PAM: moving or merging a device's org expires its live, un-actuated elevation requests with an audit row. A nightly job deletes aged evidence from held org-merge shells. It is on by default with a 400-day retention (#9134).
  • IOC scan threats are now attributed to the provider "Breeze IOC scan" instead of the device's antivirus product (#9112).
  • Error messages: field-level validation errors read as plain sentences, with no regex text (#8917). API error copy is translated in 6 more locales (#9102).
  • Heavier requests stay off the database pool: per-user and MFA step-up rate limits run before the request transaction opens (#9110). safeFetch runs outside held transactions on the boot-media and macOS installer-link routes (#9111).

Fixed

  • Remote desktop over a TURN relay: ICE candidates now trickle both ways, so a session that can only connect through a relay no longer fails when the relay candidate arrives late. Needs this release's agent and viewer (#9237).
  • Device policies after an org move: cached helper, event-log, hardware, monitoring and PAM configuration is bound to the device's org. A device no longer gets its previous org's config for up to 2 minutes (#9123).
  • Agents on Windows:
    • Windows 10 1507 (build 10240) no longer crash-loops on the missing GetIfEntry2Ex (#9238);
    • instant boot fails visibly when bcdboot fails (#8921);
    • MSI custom actions run without a console window (#9000);
    • a redelivered user-helper script is refused before its checkpoint (#9232);
    • the installer checks OS and file type before downloading (#9195).
  • Agents on macOS and Linux:
    • macOS permission checks never capture the screen (#8755);
    • Docker containerd-store local builds are reported as local (#9068);
    • the Linux viewer turns off WebKitGTK DMA-BUF on NVIDIA (#8919).
  • Breeze Viewer: dev builds no longer claim breeze:// or outrank releases (#9136).
  • Billing:
    • partner MRR counts advance-billed final terms (#9242);
    • a bundle with an uncosted component shows "Margin unknown" (#9241);
    • quote line unit cost carries into the invoice cost basis (#9239);
    • invoice detail leads with the deposit due and pre-fills Record payment (#9001);
    • invoice PDFs keep their frozen paper size (#9088);
    • the org document footer overrides the partner default (#8930).
  • Reports:
    • template dialogs ask for recipients, and editing the report keeps them (#8913);
    • the backup status report previews on the edit page (#9153).
  • Alerts and compliance:
    • Mute → Undo lifts the suppression server-side (#9071);
    • /alerts?orgId= switches the working org (#9167);
    • compliance shows distinct device counts and a not-evaluated state (#9090);
    • the audit log splits comma-separated filters (#9070).
  • Microsoft 365: intra-tenant mail to a ticket mailbox is verified from Exchange's organization stamp (#8915).
  • Devices:
    • servers that network discovery had demoted to workstations are repaired (#8507);
    • the "Logs silent" badge is gone (#8405);
    • the device-detail page shows an error panel instead of going blank (#8984);
    • the topology cross-org site link survives an org switch (#9151).
  • Smaller fixes:
    • partner users with several orgs can create saved filters (#8918);
    • Create Role asks for its scope (#8922);
    • DNS policy create takes the owner org from the integration (#8920);
    • customer emails show the public ticket number (#9089);
    • dynamic groups re-evaluate on Fleet Design role apply and rollback (#9098);
    • Change password is hidden for accounts with no password (#9147);
    • the custom-field cache clears on org switch (#9101);
    • remote pages show toasts (#9155);
    • Monaco editor styles survive SPA navigation (#8979);
    • one hashchange listener is shared across hooks (#9152);
    • monitor conversion contention reports conversion_contended (#9231);
    • the monitor preview scope hash is order-independent (#8933);
    • filesystem-analysis scan generations are released on any failure (#9103, #9149, #8911);
    • one failed row keeps the rest of an agent change batch (#8905);
    • the reaper grace includes the restore-point budget (#9190);
    • registry.k8s.io is allowlisted for image currency (#9137);
    • the remote-access policy read runs in a savepoint (#9066).
  • From the pre-release sweep (#9270, #9297):
    • editing a negated Device Group filter chip no longer flips it to "is any of";
    • the report edit page no longer wipes stored extra recipients;
    • an empty CLAUDE_CONFIG_DIR from Compose is treated as unset, so the transcript sweeper and retention job actually delete transcripts;
    • the Record signed agreement dialog shows the locked contract's name.
  • Mobile app (source only): the iOS project adopts the UIScene lifecycle so the app launches on iOS 27. This ships with the next App Store build, not with this server release (#9300).

Security

This release includes security hardening across:

  • capability URLs (/verify/*, public invoices, unsubscribe), which now keep Referrer-Policy: no-referrer through the API, web middleware and docker/Caddyfile.prod;
  • AI tool results, which fence device-originated text as untrusted data under a new guardrail;
  • AI device file reads, which fail closed when the owning partner cannot be established;
  • MCP grants, which can be narrowed to tool areas, and MCP 401s, which now carry WWW-Authenticate metadata;
  • backup provider and EDR credential changes that would move a connection to a different vendor root, which are now refused under a row lock and audited;
  • SentinelOne installs whose arguments lack {s1_site_token}, which are refused at dispatch;
  • caller-verification retries for rejected rows, which are now bounded;
  • device-keyed policy caches, now bound to the device's org;
  • per-user rate limits, evaluated before a database connection is held;
  • an RFC 9116 security.txt and an abuse contact, for operators who set them;
  • viewer dependency advisories (zip, zbus).

Self-hosters are encouraged to upgrade. (#9069, #9046, #9010, #9135, #8900, #9219, #9244, #9065, #9123, #9110, #8873, #9004, #9192)

Self-Hosting / Upgrade Notes

Upgrade command. Check how your install pins its images: grep '^BREEZE_API_IMAGE_REF=' .env.

  • Digest-pinned (the value ends in @sha256:…; every guided-setup.sh install from v0.112.0): fetch the current guided-setup.sh from main, then run bash guided-setup.sh --upgrade 0.124.0. It verifies the signed image inventory and updates BREEZE_VERSION and all four image digests together. Then it pulls and restarts.
  • Tag-form (the value ends in :${BREEZE_VERSION}): bump BREEZE_VERSION=0.124.0, then run docker compose pull api web portal && docker compose up -d (and pnpm install if you build from source).
  • Do not edit only BREEZE_VERSION on a digest-pinned install. That re-pulls the images you already run.
  • --upgrade does not change your docker-compose.yml. To set any of this release's new optional variables, add their lines to the right service's environment: block, or take the v0.124.0 docker-compose.yml / deploy/docker-compose.prod.yml, which already map them. A value only in .env does not reach the container.
  • Replace every API instance in the same deploy. An instance still on v0.123.0 fails patch-settings reads and writes once the patch migration has run (#9188).
  • Running the Microsoft 365 Graph actions executor yourself? Roll the executor build that accepts object-id-only requests before the API. The API now sends only the Entra object id for the two protected actions (#9140).
  • See the Upgrade Guide.

Breaking changes and stricter behaviour. This is not a no-breaking-changes release:

  • Rollback is a database restore (#9130, #9188). v0.123.0 reads the patch columns this release drops. With the workspace extension enabled, its boot tripwire also refuses to start while ai_model_registry_legacy_archive exists. Back up first.
  • CALLER_VERIFICATION_ENABLED defaults to true (#9140). An inherited CALLER_VERIFICATION_ENABLED=false now refuses every M365 reset and disable. Remove the line, or set it to true. Approved reset or disable intents created before the upgrade are not pinned to a target. They fail at release with subject_unmatched, so recreate them.
  • Partner API configuration export (#9188): patch feature settings no longer include autoApprove, autoApproveSeverities, autoApproveDeferralDays or apps. The keys are absent, not empty, so every exported patch policy's revision changes once. Read per-app rules from the Update Ring's appRules. A policy write that still sends these fields is accepted, and the fields are ignored.
  • Direct-SQL reports that select the dropped objects fail after the upgrade. Those objects are partner_llm_configs, ai_model_registry_state, partner_ai_connections.legacy_default_model, ai_budgets.allowed_models, ai_script_policies.reviewer_model, client_ai_org_policies.allowed_models, ai_agents.model, config_policy_patch_settings.auto_approve and auto_approve_severities.
  • Manual SentinelOne deploys (#9244): a software version whose install arguments lack {s1_site_token} (blank, generic msiexec, or a hard-coded literal token) is now refused at dispatch with SentinelOne install arguments must include SITE_TOKEN={s1_site_token}. Before, it installed unregistered or enrolled every org into one site.
  • Upgrading straight from v0.121.x or older with your own M365 executors (#9187): the v1 consent path is removed. M365 Customer Graph consent is unavailable until both the API and the executors are on v0.124.0. Upgrade them together, or step through v0.122.1. No data is lost.

Database.

  • 28 migrations. They are idempotent and apply automatically on boot via autoMigrate unless AUTO_MIGRATE=false. Expect [auto-migrate] Applied 28 migration(s) from v0.123.0. None was modified or removed. One read-only preflight file under migrations/preflight/ got a comment-only edit; it is never applied automatically. All 28 applied as a non-superuser role and re-applied cleanly in the pre-release sweep.
  • AI model registry legacy drop (2026-12-30-200000-ai-model-registry-legacy-drop.sql, #9130). This is step two of the two-step migration (step one shipped in v0.123.0).
    • It copies every legacy value into ai_model_registry_legacy_archive and logs per-source counts as [auto-migrate] warnings.
    • Then it drops partner_llm_configs, ai_model_registry_state, five legacy columns and the one-Anthropic-connection index.
    • API key copies in the legacy table are not archived. Live keys are in AI Providers & Models.
    • Tenant data never stops the migration; a column already gone is skipped. Back up before upgrading: restoring the dropped data needs a backup taken before the deploy.
    • The archive query is in the Upgrade Guide ("legacy AI model columns archived and dropped").
  • Policy-level patch auto-approve dropped (2026-12-31-160000-drop-policy-patch-auto-approve.sql, #9188).
    • It drops config_policy_patch_settings.auto_approve and auto_approve_severities, and strips four keys from patch feature links' stored settings.
    • It runs under system scope and briefly takes the configuration-family partner-export locks.
    • It logs drop_policy_patch_auto_approve inline_links_stripped=<n>. Each link whose stored apps no valid ring enforces is logged as unenforced_app_rules link=… policy=… ring_ref=… apps=…. Recreate those rules on the ring when you repair the link; the migration keeps no other copy.
  • System-scope backfills and deletes over existing rows:
    • 2026-12-31-170000-m365-consent-sessions-v2-only.sql (#9187) deletes leftover flow_version = 1 M365 consent sessions (expired by now), then requires flow_version = 2.
    • 2026-12-31-210000-agreement-requests.sql (#9236) adds the agreement request tables and 14 columns on contract_documents (source_kind NOT NULL DEFAULT 'quote'). It backfills each signed document's evidence snapshot from quote_acceptances, one row per signed document.
    • 2026-12-30-120300-trust-center-w2.sql (#9042) deletes trust_page_documents links with no disclosure confirmation and logs a warning with the count. Every linked document now needs one. It also makes five trust_pages settings nullable (NULL = inherit the partner template).
    • 2026-12-30-140000-repair-discovery-demoted-server-roles.sql (#8507) sets device_role = 'server' / device_role_source = 'auto' on servers that discovery had demoted, writing a device.role.repaired audit row each. It is bounded to rows whose role was last written by discovery and whose OS says server.
    • 2026-12-30-130000-connection-health-event-outbox.sql (#9047) baselines existing incidents once, so they emit no events.
  • Trust signing keys (2026-12-30-110500-trust-signing-keys.sql, #9040): a deployment-wide key table with no explicit GRANT in the file. breeze_app gets access from ensureAppRole at boot, as for other new tables. The first key is minted on first use, only when the table is empty.
  • Concurrent index builds (2026-12-30-120100-connection-health-w4-indexes.sql, @no-transaction, #9045): two partial indexes on webhook_deliveries (failed rows only) and two on google_workspace_connections. They do not block writes. If an interrupted build leaves an INVALID index, the next start refuses with a message naming it. Run DROP INDEX CONCURRENTLY <name>; and restart.
  • Privileged DDL (2026-12-30-210000-pam-epoch-transfer-flag.sql, #9134): a one-row switch table revoked from breeze_app, SECURITY DEFINER functions, and guarded grants to breeze_audit_admin. It applies as a non-superuser owner.
  • No large-table rewrite. New NOT NULL columns carry constant defaults (metadata-only), and the restore-point status CHECK is replaced in place (#9160). One-way enum addition: security_provider gains breeze (#9112).

Environment variables.

  • Required: none. No new required environment variables.
  • New, optional. Each is mapped in both shipped Compose files unless noted. With a custom Compose file, add it to the named service's environment: block.
    • web: PUBLIC_ABUSE_CONTACT, PUBLIC_SECURITY_CONTACT, PUBLIC_SECURITY_POLICY_URL (all empty by default) (#8873). They render the auth-page "Report abuse" / "Security" footer and /.well-known/security.txt; unset publishes nothing. Point them at a mailbox that receives mail.
    • api: CALLER_VERIFICATION_WORKSTATION_ENABLED (default false, dark) (#9140). While it is off, policies cannot require tier 3 for password reset, and tier 3 for account disable needs administrative disable allowed.
    • api: BREEZE_TRUST_CIS_FRAMEWORK_VIEW (default false) (#9061). It unlocks the CIS Controls framework view and CIS hardening safeguards (#9094). Leave it off unless you have confirmed your CIS licensing; the flag does not replace the written CIS confirmation.
    • api: AI_TRANSCRIPT_SWEEPER_ENABLED (runs by default only when NODE_ENV=production), AI_TRANSCRIPT_SWEEPER_CRON (38 4 * * *) and AI_TRANSCRIPT_SWEEPER_GRACE_HOURS (24) (#9133). The sweeper runs on BREEZE_ROLE=api/all only, each container sweeping its own disk. CLAUDE_CONFIG_DIR is now passed through, and an empty value means ~/.claude.
    • api: AI_TOOL_OUTPUT_RETENTION_CRON (33 4 * * *), _BATCH_SIZE and _MAX_BATCHES (#9044).
    • api: WEBHOOK_DELIVERY_RETENTION_DAYS (90, 1–365), _BATCH_SIZE and _MAX_BATCHES (#9193).
    • api: RESTORE_POINT_ATTEMPT_RETENTION_DAYS (90, max 365), _BATCH_SIZE (5000) and _MAX_BATCHES (50) (#8939).
    • api: PAM_EVIDENCE_RETENTION_ENABLED (on when empty) and PAM_EVIDENCE_RETENTION_DAYS (400, floor 30) (#9134).
    • api: MCP_INSUFFICIENT_SCOPE_HTTP_403 (off): an OAuth insufficient_scope 403 step-up (#9135).
    • caddy: TUNNEL_SITE_ADDRESS, TUNNEL_TLS_DIRECTIVE and TUNNEL_HOST_SUFFIX. Their defaults match nothing, so Network Proxy host mode stays off. Host mode also needs the API's TUNNEL_ORIGIN_TEMPLATE / TUNNEL_FRAME_ANCESTOR from v0.123.0 (#9096).
    • deploy/docker-compose.prod.yml now also maps MIGRATION_WINDOW_MAX_DAYS, MIGRATION_WINDOW_DEFAULT_WRITES_PER_HOUR and MIGRATION_WINDOW_MAX_WRITES_PER_HOUR.
    • Not in Compose (add them to api yourself if you need them): PAM_OWNERSHIP_EPOCH_TRANSFER (off; transfer also needs the database switch pam_epoch_transfer_config.enabled) (#9134), and the YARA kill switch BREEZE_YARA_BUILTIN_PACK_DISABLED (#9161).
  • CALLER_VERIFICATION_ENABLED keeps its name. Only its Compose default changed, to ${CALLER_VERIFICATION_ENABLED:-true}. It accepts only the exact value true as on.

Behaviour changes and feature flags.

  • Caller verification is on and enforced (#9140). Before the upgrade:
    • Establish Entra bindings for the accounts you reset or disable, and attest imported contact destinations. Until then those actions return caller_verification_required.
    • Explicit false hides the workflow and refuses protected actions. It is never a bypass.
    • A failed dispatch does not restore a consumed verification.
    • The workstation tier (agent + Breeze Assist) is dark behind CALLER_VERIFICATION_WORKSTATION_ENABLED.
  • Connection-health digest: expect a one-time burst (#9011). After the first deploy, every admin or owner with an open connection incident (including incidents opened under v0.123.0) receives a digest email when the hourly job reaches 08:00–11:59 partner-local. After that, an incident appears daily for 7 days, then on Mondays only. Customer-admin notices are off by default (#9047). Note that the built-in Org Admin role is reached for only 4 of 14 incident kinds (#9268, below).
  • Connection-health W04 signals (#9045). The webhook and Google Workspace sources seed silently on first deploy, then notify for dead webhooks and stalled syncs. The Google probe makes at most one Directory API call per Google-connected org every 6 hours, impersonating the org admin. A Google outage maps to unknown and opens nothing.
  • AI tool-output retention: first nightly scrub (#9044). At the first run (default 04:33 UTC), tool outputs older than 30 days are replaced with an "Output expired" marker for every partner with no AI data policy row. Affected chats lose their resumable model context. The setting ships in this release, so a partner who wants to keep history must set Keep AI tool outputs for (days) to blank ("keep forever") after the upgrade and before that run, or move the first run with AI_TOOL_OUTPUT_RETENTION_CRON.
  • AI device file reads default to Excludes user profile folders (#9010). With no policy row, AI tools refuse paths under C:\Users\*, /home/*, /Users/* and /root. Set Any path with approval to allow them.
  • New retention jobs, all deleting only terminal rows:
    • webhook_deliveries older than 90 days, daily at 22:13 UTC (#9193);
    • restore-point attempts older than 90 days (#8939);
    • PAM evidence on held org-merge shells older than 400 days (#9134).
  • System Restore (#9160). With agent 0.124.0, one restore point is taken per patch run, script or install, just before its first change, and the outcome is reported on the command. The policy is reporting-only: a point that cannot be created never stops the command. A command that makes no change reports skipped_no_mutation.
  • SentinelOne (#9244). Turning S1 on in a policy needs a latest SentinelOne MSI version with {s1_site_token} in its install arguments. Without it, the write returns 400 security_agents_binary_missing with a /software#versions=… setup path. An org with no S1 site mapping reads org_not_mapped.
  • EDR web actions (isolate, release, scan, the action history, the push switch) and the Security page's EDR summary and coverage panel sit behind the web build-time flag PUBLIC_ENABLE_EDR_INTEGRATIONS. The published web image does not set it. Coverage is also on the software policy compliance view, which needs no flag (#8937, #9194).
  • Trust Center:
    • Customer trust page editing is a per-org portal toggle, off by default and not set by Enable all (#9053).
    • The embed allowlist is live and reserves the partner slug embed (#9109).
    • Trust attestation JWTs are cached in Redis and served at /api/v1/trust/attestation/*. That needs no ingress change and uses the existing /api rule (#9040).
  • Self-hosted docker/Caddyfile.prod copies (#9069, #9096): Referrer-Policy is now set only when upstream did not set one (?Referrer-Policy), and a new tunnel-host site block is driven by TUNNEL_*. Carry both over if you maintain your own copy.
  • YARA and endpoint messaging ship dark.
    • YARA: the API image now includes breeze-yarac, and the built-in rule pack (500 permissively licensed rules) is upserted at boot when RELEASE_ARTIFACT_MANIFEST_PUBLIC_KEYS lets it verify the pack. There is no rule UI until a later release. Rule sets go only to agents ≥ 0.124.0 (#9112, #9156, #9161).
    • Endpoint messaging and live chat: the agent carries the handlers, but ENDPOINT_MESSAGING_MIN_AGENT_VERSION, ENDPOINT_MESSAGE_RETRACT_MIN_AGENT_VERSION and ENDPOINT_CHAT_MIN_AGENT_VERSION remain at the 999.0.0 placeholder, so every send or chat returns agent_unsupported. The gates will be lifted server-side in a later release, without another agent update. The sidebar Messages page is visible to roles with endpoint_messages:read and shows an empty history; PUBLIC_ENABLE_ENDPOINT_MESSAGING only reveals the send entry points.
  • API contract changes:
    • GET /api/v1/desktop-ws/:id/viewer/session returns agentIceCandidates, and POST /desktop-ws/:id/viewer/ice is new (#9237).
    • GET /api/v1/devices/attention-counts takes at most 100 ids (#9100).
    • A correctly signed v1 M365 consent cookie now answers consent_state_mismatch (#9187).
    • Per-user rate limits run before permission and validation middleware, so a rejected request still spends one unit (#9110).

Agents. Agents, Breeze Assist and Breeze Viewer update to 0.124.0 through your normal update channel. If your fleet never moved to 0.123.0, this promote lands two agent generations at once: v0.123.0's ECH, retain-state and watchdog-install work, plus this release.

Agent-side changes in 0.124.0:

  • System Restore checkpoints (#8506, #9160);
  • trickle ICE (#9237);
  • watchdog, WebSocket back-off and reconnect fixes (#9146, #9145, #9245);
  • DHCP in process (#8912);
  • the start_desktop fence (#9138);
  • WinRT toasts (#8878, #9207);
  • VPN client detection (#9186);
  • Linux maintenance reboots (#9216);
  • the installer type check (#9195);
  • the Windows 10 1507 fallback (#9238);
  • macOS permission checks (#8755);
  • MSI custom actions without a console window (#9000);
  • the YARA-X engine, dark (#9112). It adds about 6.6 MB to the agent binary.

Known gaps in this release

  • YARA-X does not start when the agent runs as a Windows service (#9253). The log shows GetFileType /dev/stderr: The handle is invalid, so Windows scans fall back to engine=legacy with rule_set_errors=[engine_unavailable]. Linux scans use engine=yara. YARA has no rule UI yet, so nothing user-facing depends on it.

  • Endpoint messaging and live chat are dark (see above). Do not expect sends to reach devices in this release.

  • Not verified on real hardware before the tag (no lab rig):

    • NVIDIA Linux viewer rendering (#8919);
    • instant-boot bcdboot failure (#8921);
    • the macOS permission probe (#8755);
    • System Restore checkpoints on Windows 10 / Server 2025 (#8265). Only the unsupported and skipped paths were exercised, on Server 2022, which has no System Restore.
    • Windows 10 1507 (#9238);
    • the iOS papercuts build (#8885);
    • MSI custom actions, which need the signed release MSI (#9000);
    • the viewer dev-build breeze:// handler (#9136);
    • Docker containerd-store local builds (#9068).

    If one of these regresses, report it on the linked issue.

  • Connection health "Notify customer admins" reaches the built-in Org Admin role for only 4 of the 14 incident kinds. The others gate on organizations:write (#9268, needs a decision).

  • On an install with no email transport, the trust access-request Approve/Resend toasts and the quote accept-on-behalf dialog still say an email was sent (#9256).

  • Record signed agreement without a file dead-ends on templates that use quote variables ("Provide a value for: quote.number"). Attach the signed copy instead (#9296).

  • Customer "Withdraw the page" in the portal keeps the recorded trust-page authorization, so the MSP can republish in one click (#9255, needs a decision).

What's Changed

Full Changelog: v0.123.0...v0.124.0