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_resolvedevents. - 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.jsonand per-page attestation JWTs, plus atrust:signing-keyrotation 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-policyand/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_passwordandm365_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_requiredrefusals in chat, MCP and the release worker.
- targets pinned to Entra tenant + object id on
- 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 withconsent_upgrade_requireduntil 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:
- Tickets:
- 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
whoamiMCP tool (#9135); - EDR push hints and a
sync_edr_dataAI tool (#8937); generate_reportaccepts the business report types (#9240);query_deviceshonours 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_TEMPLATEis 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).
- Network Proxy dedicated tunnel origin: API host mode and web support, off until
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_desktopis 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
wallbroadcast 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).
safeFetchruns 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
bcdbootfails (#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).
- Windows 10 1507 (build 10240) no longer crash-loops on the missing
- Agents on macOS and Linux:
- 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:
- Alerts and compliance:
- Microsoft 365: intra-tenant mail to a ticket mailbox is verified from Exchange's organization stamp (#8915).
- Devices:
- 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.iois 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_DIRfrom 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 keepReferrer-Policy: no-referrerthrough the API, web middleware anddocker/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-Authenticatemetadata; - 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.txtand 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:…; everyguided-setup.shinstall from v0.112.0): fetch the currentguided-setup.shfrommain, then runbash guided-setup.sh --upgrade 0.124.0. It verifies the signed image inventory and updatesBREEZE_VERSIONand all four image digests together. Then it pulls and restarts. - Tag-form (the value ends in
:${BREEZE_VERSION}): bumpBREEZE_VERSION=0.124.0, then rundocker compose pull api web portal && docker compose up -d(andpnpm installif you build from source). - Do not edit only
BREEZE_VERSIONon a digest-pinned install. That re-pulls the images you already run. --upgradedoes not change yourdocker-compose.yml. To set any of this release's new optional variables, add their lines to the right service'senvironment:block, or take the v0.124.0docker-compose.yml/deploy/docker-compose.prod.yml, which already map them. A value only in.envdoes 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_archiveexists. Back up first. CALLER_VERIFICATION_ENABLEDdefaults totrue(#9140). An inheritedCALLER_VERIFICATION_ENABLED=falsenow refuses every M365 reset and disable. Remove the line, or set it totrue. Approved reset or disable intents created before the upgrade are not pinned to a target. They fail at release withsubject_unmatched, so recreate them.- Partner API configuration export (#9188): patch feature settings no longer include
autoApprove,autoApproveSeverities,autoApproveDeferralDaysorapps. The keys are absent, not empty, so every exported patch policy's revision changes once. Read per-app rules from the Update Ring'sappRules. 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_approveandauto_approve_severities. - Manual SentinelOne deploys (#9244): a software version whose install arguments lack
{s1_site_token}(blank, genericmsiexec, or a hard-coded literal token) is now refused at dispatch withSentinelOne 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
autoMigrateunlessAUTO_MIGRATE=false. Expect[auto-migrate] Applied 28 migration(s)from v0.123.0. None was modified or removed. One read-only preflight file undermigrations/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_archiveand 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").
- It copies every legacy value into
- Policy-level patch auto-approve dropped (
2026-12-31-160000-drop-policy-patch-auto-approve.sql, #9188).- It drops
config_policy_patch_settings.auto_approveandauto_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 storedappsno valid ring enforces is logged asunenforced_app_rules link=… policy=… ring_ref=… apps=…. Recreate those rules on the ring when you repair the link; the migration keeps no other copy.
- It drops
- System-scope backfills and deletes over existing rows:
2026-12-31-170000-m365-consent-sessions-v2-only.sql(#9187) deletes leftoverflow_version = 1M365 consent sessions (expired by now), then requiresflow_version = 2.2026-12-31-210000-agreement-requests.sql(#9236) adds the agreement request tables and 14 columns oncontract_documents(source_kind NOT NULL DEFAULT 'quote'). It backfills each signed document's evidence snapshot fromquote_acceptances, one row per signed document.2026-12-30-120300-trust-center-w2.sql(#9042) deletestrust_page_documentslinks with no disclosure confirmation and logs a warning with the count. Every linked document now needs one. It also makes fivetrust_pagessettings nullable (NULL = inherit the partner template).2026-12-30-140000-repair-discovery-demoted-server-roles.sql(#8507) setsdevice_role = 'server'/device_role_source = 'auto'on servers that discovery had demoted, writing adevice.role.repairedaudit 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 explicitGRANTin the file.breeze_appgets access fromensureAppRoleat 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 onwebhook_deliveries(failed rows only) and two ongoogle_workspace_connections. They do not block writes. If an interrupted build leaves an INVALID index, the next start refuses with a message naming it. RunDROP INDEX CONCURRENTLY <name>;and restart. - Privileged DDL (
2026-12-30-210000-pam-epoch-transfer-flag.sql, #9134): a one-row switch table revoked frombreeze_app,SECURITY DEFINERfunctions, and guarded grants tobreeze_audit_admin. It applies as a non-superuser owner. - No large-table rewrite. New
NOT NULLcolumns carry constant defaults (metadata-only), and the restore-point status CHECK is replaced in place (#9160). One-way enum addition:security_providergainsbreeze(#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(defaultfalse, 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(defaultfalse) (#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 whenNODE_ENV=production),AI_TRANSCRIPT_SWEEPER_CRON(38 4 * * *) andAI_TRANSCRIPT_SWEEPER_GRACE_HOURS(24) (#9133). The sweeper runs onBREEZE_ROLE=api/allonly, each container sweeping its own disk.CLAUDE_CONFIG_DIRis now passed through, and an empty value means~/.claude. - api:
AI_TOOL_OUTPUT_RETENTION_CRON(33 4 * * *),_BATCH_SIZEand_MAX_BATCHES(#9044). - api:
WEBHOOK_DELIVERY_RETENTION_DAYS(90, 1–365),_BATCH_SIZEand_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) andPAM_EVIDENCE_RETENTION_DAYS(400, floor 30) (#9134). - api:
MCP_INSUFFICIENT_SCOPE_HTTP_403(off): an OAuthinsufficient_scope403 step-up (#9135). - caddy:
TUNNEL_SITE_ADDRESS,TUNNEL_TLS_DIRECTIVEandTUNNEL_HOST_SUFFIX. Their defaults match nothing, so Network Proxy host mode stays off. Host mode also needs the API'sTUNNEL_ORIGIN_TEMPLATE/TUNNEL_FRAME_ANCESTORfrom v0.123.0 (#9096). deploy/docker-compose.prod.ymlnow also mapsMIGRATION_WINDOW_MAX_DAYS,MIGRATION_WINDOW_DEFAULT_WRITES_PER_HOURandMIGRATION_WINDOW_MAX_WRITES_PER_HOUR.- Not in Compose (add them to
apiyourself if you need them):PAM_OWNERSHIP_EPOCH_TRANSFER(off; transfer also needs the database switchpam_epoch_transfer_config.enabled) (#9134), and the YARA kill switchBREEZE_YARA_BUILTIN_PACK_DISABLED(#9161).
- web:
CALLER_VERIFICATION_ENABLEDkeeps its name. Only its Compose default changed, to${CALLER_VERIFICATION_ENABLED:-true}. It accepts only the exact valuetrueas 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
falsehides 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.
- Establish Entra bindings for the accounts you reset or disable, and attest imported contact destinations. Until then those actions return
- 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
unknownand 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:
- 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 400security_agents_binary_missingwith a/software#versions=…setup path. An org with no S1 site mapping readsorg_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/apirule (#9040).
- Self-hosted
docker/Caddyfile.prodcopies (#9069, #9096):Referrer-Policyis now set only when upstream did not set one (?Referrer-Policy), and a new tunnel-host site block is driven byTUNNEL_*. 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 whenRELEASE_ARTIFACT_MANIFEST_PUBLIC_KEYSlets 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_VERSIONandENDPOINT_CHAT_MIN_AGENT_VERSIONremain at the999.0.0placeholder, so every send or chat returnsagent_unsupported. The gates will be lifted server-side in a later release, without another agent update. The sidebar Messages page is visible to roles withendpoint_messages:readand shows an empty history;PUBLIC_ENABLE_ENDPOINT_MESSAGINGonly reveals the send entry points.
- YARA: the API image now includes
- API contract changes:
GET /api/v1/desktop-ws/:id/viewer/sessionreturnsagentIceCandidates, andPOST /desktop-ws/:id/viewer/iceis new (#9237).GET /api/v1/devices/attention-countstakes 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_desktopfence (#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 toengine=legacywithrule_set_errors=[engine_unavailable]. Linux scans useengine=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
bcdbootfailure (#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
- feat(backup): destination key root W02 — per-root GC, reconcile, janitor, dedupe base (#8732) by @ToddHebebrand in #8925
- feat(integrations): connection health W02 — integration sources + Connection Health panel (#8846) by @ToddHebebrand in #8936
- feat(web): Recent — mixed sidebar list and dashboard card (UI flow W04) by @ToddHebebrand in #8992
- feat(web): org record address, site columns, Devices tab fixes, device crumb (UI flow W01) by @ToddHebebrand in #8994
- docs(qa): v0.123.0 pre-cut lab pass by @ToddHebebrand in #8999
- docs(trust-center): W02 and W03 implementation plans + spec §19 amendments 25–36 by @ToddHebebrand in #9003
- fix(web): lead invoice detail with the deposit due and pre-fill it when recording a payment (#8786) by @ToddHebebrand in #9001
- fix(viewer): resolve Cargo Audit for zip RUSTSEC-2026-0367/0368/0369 by @ToddHebebrand in #9004
- feat(messaging): W02 — persistence, batch status, retention, retract, AI tool (#8742) by @ToddHebebrand in #8931
- docs: v0.123.0 docs sync + clear next-release-draft by @ToddHebebrand in #9002
- feat(web): EntityLink and cross-link sweep — org, site, device, ticket names link everywhere (UI flow W03) by @ToddHebebrand in #9006
- feat(web): org switcher Customer › Page columns with live counts (UI flow W02) by @ToddHebebrand in #9009
- fix(mobile): iOS papercuts — back nav, Face ID cover flash, plan-first approval, model picker by @ToddHebebrand in #8885
- docs(specs): UI flow — record the W02 lg breakpoint amendment (#8985) by @ToddHebebrand in #9015
- docs(release-skill): enumerate feature parents before writing release bullets by @ToddHebebrand in #9016
- feat(ai): AI data & privacy policy — table, resolver, routes, settings cards (#8852 W01) by @ToddHebebrand in #8866
- feat(edr): W03 PR-B — webhook push hints, sync_edr_data, web actions (#8167) by @ToddHebebrand in #8937
- fix(messaging): site-scope gate on message detail, retract, resend (#9014) by @ToddHebebrand in #9017
- feat(connection-health): W3 daily digest email, opt-out, RFC 8058 unsubscribe (#8847) by @ToddHebebrand in #9011
- feat(ai): enforce the AI data policy device file read level in the executeTool gate (#8852 W02) by @ToddHebebrand in #9010
- test(agent): deflake TestMessageCardTimeoutRetractsBeforeNativeFallback under -race (#9018) by @ToddHebebrand in #9039
- docs(release-notes): next-release draft — connection-health digest, AI file policy by @ToddHebebrand in #9043
- feat(trust-center): signed attestation (ES256 JWT + JWKS), key rotation CLI, cross-origin badge fix (W03b) by @ToddHebebrand in #9040
- feat(trust-center): W2 foundation — tables, payload v2, frozen config v2, sub-wave seams (W02a) by @ToddHebebrand in #9042
- feat(ai): nightly AI tool output retention — tombstones, captures, SDK sessions (#8852 W03) by @ToddHebebrand in #9044
- feat(connection-health): W4 missing signals — webhooks, sync staleness, Google probe, reconcile nudges (#8848) by @ToddHebebrand in #9045
- docs(release-notes): next-release draft — AI output retention, connection-health W04 by @ToddHebebrand in #9051
- feat(ai): fence device file contents, command output and registry values as untrusted text (#8852 W04) by @ToddHebebrand in #9046
- feat(messaging): W03 — ad-hoc live chat with the device user (#8743) by @ToddHebebrand in #9041
- feat(trust-center): MFA enforcement control from M365 CA policies (W02c) by @ToddHebebrand in #9055
- test(api): deflake edr push-hint microsecond CAS assertion by @ToddHebebrand in #9057
- feat(trust-center): portal self-edit of the trust page draft (W03d) by @ToddHebebrand in #9053
- feat(trust-center): gated documents and access requests (W02d) by @ToddHebebrand in #9056
- feat(trust-center): portal i18n for public trust page, 8 locales (W02h) by @ToddHebebrand in #9060
- feat(trust-center): declared controls — declare, expire, remind, render (W02b) by @ToddHebebrand in #9059
- feat(trust-center): partner-wide trust page template and inheritance UI (W02g) by @ToddHebebrand in #9058
- feat(trust-center): framework view, picker and CIS gate (W02e) by @ToddHebebrand in #9061
- feat(trust-center): home-flag rule, self-heal, AI status tool, dashboard link, slug warning (W02i) by @ToddHebebrand in #9054
- feat(trust-center): CSV/JSON questionnaire export from the editor (W03c) by @ToddHebebrand in #9064
- feat(security-agents): W02 — Huntress preflight, managed policy generator, authoring tab (#8736) by @ToddHebebrand in #8923
- fix(installer): run every MSI custom action without a console window (#8877) by @ToddHebebrand in #9000
- feat(recipes): operator recipe library W05 — M365 identity write catalog, effect probes, permission profile v2 (#6170) by @ToddHebebrand in #9012
- feat(trust-center): subprocessors, FAQ and controls-met history (W02f) by @ToddHebebrand in #9063
- fix(security): route-level no-referrer wins on capability URLs (#8964) by @ToddHebebrand in #9069
- docs(plan): MCP modernization B-W02 — per-grant tool domains (#6154) by @ToddHebebrand in #9073
- docs(billing): standalone agreement signing — approved spec + W1 plan (#8865) by @ToddHebebrand in #9074
- test(web): settle TicketsPage mount before the hashchange filter test (#8880) by @ToddHebebrand in #8898
- fix(backup): refuse provider credential changes that move vendorRootId (#8656) by @ToddHebebrand in #8900
- fix(api): keep the rest of an agent change batch when one row fails (#8301) by @ToddHebebrand in #8905
- fix(patches): treat a soft-deleted update ring as an invalid reference (#8678) by @ToddHebebrand in #8906
- test(topology): pin presence-day tests inside one UTC day (#8761) by @ToddHebebrand in #8907
- fix(maintenance-reboot): report refused reboot dispatches with tags that survive scrubbing (#8022) by @ToddHebebrand in #8908
- fix(api): report filesystem_analysis result drops with event codes, not contentless exceptions (#8024) by @ToddHebebrand in #8911
- fix(agent): read Windows DHCP state in-process, not via PowerShell per heartbeat (#7765) by @ToddHebebrand in #8912
- fix(reports): template dialogs ask for recipients; edit shows the template form (#8796) by @ToddHebebrand in #8913
- fix(backup): resolve an origin's recorded root once in recovery downloads (#8665) by @ToddHebebrand in #8914
- fix(viewer): disable WebKitGTK DMA-BUF renderer on NVIDIA Linux (#8764) by @ToddHebebrand in #8919
- fix(api): DNS policy create takes the owner org from the integration (#8329) by @ToddHebebrand in #8920
- fix(agent): fail instant boot when bcdboot fails (#7494) by @ToddHebebrand in #8921
- fix(web,api): Create Role asks for its scope instead of reading the header org (#8370) by @ToddHebebrand in #8922
- chore(security): renew braces audit exception, drop dead http-cache-semantics one (#7862, #7863) by @ToddHebebrand in #8926
- fix(agent/backup): deterministic upload.lease refresh in lease test (#8828) by @ToddHebebrand in #8927
- fix(billing): org document footer overrides the partner default; say what partner currency does (#7510) by @ToddHebebrand in #8930
- test(api): guard device org-move disposition + document move-delete list (#8634) by @ToddHebebrand in #8932
- fix(monitors): order-independent preview scope hash (#6888) by @ToddHebebrand in #8933
- chore(deps): Bump dotenv from 18.0.5 to 18.0.7 in /e2e-tests by @dependabot[bot] in #8694
- fix(caller-verify): send an absolute deadline so a late command clamps its countdown (#8668) by @ToddHebebrand in #8935
- feat(api): daily retention for device_restore_point_attempts (#8581) by @ToddHebebrand in #8939
- chore(deps): Bump the go-minor-patch group across 1 directory with 9 updates by @dependabot[bot] in #8789
- chore(deps): Bump serde_json from 1.0.151 to 1.0.154 in /apps/helper/src-tauri by @dependabot[bot] in #8804
- fix(devices): repair server roles already demoted by network discovery (#7971) by @ToddHebebrand in #8507
- chore(deps): Bump vitest from 5.0.3 to 5.0.4 in /e2e-tests by @dependabot[bot] in #8809
- chore(deps): Bump @sentry/react-native from 8.27.0 to 8.30.0 by @dependabot[bot] in #8818
- feat(connection-health): customer-admin delivery setting + integration.health_* events (W5) (#8849) by @ToddHebebrand in #9047
- ci(codeql): tune SAST — exclude tests, security-extended, actions scanning, breeze gid guard by @ToddHebebrand in #8929
- fix(audit): split comma-separated action/resource filters (#8975) by @ToddHebebrand in #9070
- fix(agent): raise Windows toasts in-process via WinRT; no console flash by @ToddHebebrand in #8878
- fix(web,api): partner users with several orgs can create saved filters (#8330) by @ToddHebebrand in #8918
- fix(invoices): render invoice PDF on its frozen paper size (#8969) by @ToddHebebrand in #9088
- fix(compliance): distinct device counts, plurals, not-evaluated state (#8967) by @ToddHebebrand in #9090
- docs(plan): tag registry + bulk edit tags/custom fields (#8837, #8833) by @ToddHebebrand in #9093
- test(agent/backup): deterministic time budget in the partial-count tests (#8765) by @ToddHebebrand in #8901
- fix(alerts): Mute Undo lifts the suppression server-side (#8966) by @ToddHebebrand in #9071
- fix(heartbeat): remote-access policy read in a savepoint (#8997) by @ToddHebebrand in #9066
- fix(web): org record More menu keyboard handling + tabpanel (#9021) by @ToddHebebrand in #9092
- feat(web): abuse/security contact footer on auth pages + /.well-known/security.txt by @ToddHebebrand in #8873
- fix(web): confirm bulk device commands before sending (#9032) by @ToddHebebrand in #9072
- fix(agent): macOS permission checks never capture the screen (#8390) by @ToddHebebrand in #8755
- fix(web): app shell polish — 11px floor, Cmd+K contrast, compact MFA banner (#9031) by @ToddHebebrand in #9095
- feat(trust-center): hardening safeguards behind the CIS gate (W03e) by @ToddHebebrand in #9094
- fix(web): device detail Back control and accessible actions menus (#9025) by @ToddHebebrand in #9097
- fix(fleet-design): re-evaluate dynamic groups on role apply/rollback (#8943) by @ToddHebebrand in #9098
- test(agent/websocket): deflake TestWSConnect_UpgradesOverECHEndToEnd (#9005) by @ToddHebebrand in #9099
- fix(tickets): customer emails show ticket_number, not internal_number (#8965) by @ToddHebebrand in #9089
- fix(filesystem): release scan generation on any failed/timeout result (#8945) by @ToddHebebrand in #9103
- fix(web): translate ERROR_CODES copy in 6 locales (#8977) by @ToddHebebrand in #9102
- feat(web): org record Overview leads with fleet health (#9020) by @ToddHebebrand in #9104
- feat(network-proxy): tunnel origin W02 — API host mode (#8158) by @ToddHebebrand in #9096
- feat(web,api): Attention column on the devices list — batched alert/ticket counts (#9038) by @ToddHebebrand in #9100
- feat(ai): Tool Catalog W02 — OpenAPI source kind (#5217) by @ToddHebebrand in #9106
- test(api): explicit timeout for refundAllocation property test (#8940) by @ToddHebebrand in #9107
- fix(api): evaluate user and /mfa/step-up rate limiters before the request transaction opens (#8334) by @ToddHebebrand in #9110
- fix(api): keep safeFetch out of the held request tx on boot-media and macOS installer-link (#8333) by @ToddHebebrand in #9111
- docs(plan): EDR W04 — Emsisoft cloud EMC adapter (#8164) by @ToddHebebrand in #9115
- docs(plan): device lifecycle state + assigned contact (#8836, #8835) by @ToddHebebrand in #9116
- docs(plan): custom-field reports/export + device form factor (#7324, #8834) by @ToddHebebrand in #9124
- docs(release-notes): next-release draft — pipeline hand-off items by @ToddHebebrand in #9132
- fix(agents): bind device-keyed policy caches to the device org (#8257) by @ToddHebebrand in #9123
- feat(ai)!: model registry W08b — archive then drop the legacy AI model config (#7606) by @ToddHebebrand in #9130
- feat(ai): restore-point attempts AI list tool + inline-badge route/RLS tests (#8584) by @ToddHebebrand in #8941
- fix(api): bound caller-verification rejected-row retries (#8998) by @ToddHebebrand in #9065
- fix(viewer): dev builds no longer claim breeze:// or outrank releases (#8956) by @ToddHebebrand in #9136
- fix(image-currency): allowlist registry.k8s.io redirect host (#8549) by @ToddHebebrand in #9137
- fix(agent): refuse a superseded start_desktop when two arrive back to back (#8955) by @ToddHebebrand in #9138
- ci(perf): nightly storm-suite with warn-only gates (#8642) by @ToddHebebrand in #9141
- fix(settings): partner Security scalar limits can be cleared (#8976) by @ToddHebebrand in #9142
- fix(web): device detail critique cluster — header state, scope cue, phone width, overview order, polish (#9026 #9027 #9028 #9029 #9030) by @ToddHebebrand in #9125
- docs(plan): Tool Catalog W03 — flows document, validator, read UI (#5215) by @ToddHebebrand in #9143
- fix(web): clear custom-field cache on org/partner switch (#8946) by @ToddHebebrand in #9101
- fix(web): app shell leftovers from #9031 — sidebar shadow-only transition, help panel header not a nested card by @ToddHebebrand in #9144
- fix(agent/websocket): back off after server-initiated closes and honour Retry-After (#8841) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9145
- fix(web): hide Change password for accounts with no password (#9008) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9147
- feat(trust-center): iframe embed card with live per-page allowlist (W03a) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9109
- fix(agent): watchdog treats heartbeat overload answers as liveness, not a wedge (#8934) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9146
- fix(agent): strip control characters from collector strings; keep previous service value on a corrupt CIM read (#8904) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9148
- fix(api): reaper releases timed-out filesystem_analysis scan generation (#9105) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9149
- fix(topology): cross-org site link after org switches no longer collapses to 'Choose a site' (#8335) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9151
- fix(web): share one hashchange listener across useHashState hooks (#8978) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9152
- fix(reports): backup status preview on edit page, formatted PDF snapshot time (#7506) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9153
- fix(api): verify Microsoft 365 intra-tenant mail from Exchange's organization stamp (#8299) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/8915
- fix(web): mount a toast host on bare-Layout remote pages (#9154) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9155
- fix(agent): report local builds on Docker's containerd image store as local (#8993) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9068
- feat(network-proxy): tunnel origin W03 — web (#8159) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9150
- fix(ai): sweep orphaned SDK transcripts per API process; retention covers action_intents.result (#9050) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9133
- feat(mcp): B-W02 per-grant tool domains, whoami, insufficient_scope step-up (#6156) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9135
- feat(pam): ownership epoch W6 — transfer behind a flag, OD4, evidence retention, full matrix (#8208) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9134
- feat(agent): YARA-X engine in the agent — on-device compile, fetch + cache, worker-pool scan (#6265) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9112
- feat(caller-verification): enforce verified M365 identity actions, link tier only (#6359) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9140
- feat(api): partner emails for trust review — request received + account approved (#8713) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/8767
- fix(web): error boundary on the device-detail island so a render error shows instead of blanking the page (#8982) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/8984
- fix(web): ship Monaco structural CSS with every editor consumer (approvals card rendered mangled after SPA nav) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/8979
- fix(web,api): readable field-level validation errors, no regex leak (#8369) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/8917
- feat(agent): restore checkpoint W02 — systemrestore package with WMI identity verification (#4753) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/8506
- fix(web): devices list critique cluster — link affordance, column chooser, chrome height, empty states, polish (#9033 #9034 #9035 #9036 #9037) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9131
- docs(portal): customer portal environment visibility spec by @fabicarvano in https://github.com/LanternOps/breeze/pull/8790
- docs(agent): plan Phase 2 localization and runtime branding by @fabicarvano in https://github.com/LanternOps/breeze/pull/8861
- docs(unifi): add AP radio and statistics monitoring spec (#7690) by @fabicarvano in https://github.com/LanternOps/breeze/pull/8875
- docs(plan): MCP modernization B-W03 — stateless 2026-07-28 dual-stack + CIMD (#6154) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9158
- fix(web): org record critique cluster — work-here state, sites tab, devices tab states, polish (#9019 #9022 #9023 #9024) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9114
- fix(web): quick-chip strip shows scroll buttons at a clipped edge (#9037 leftover) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9157
- feat(security): YARA W03a — rule-set tables, pre-check publishing, agent fetch route, scan refs (#6266) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9156
- fix(devices): drop the "Logs silent" badge and notice (#7067) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/8405
- feat(agent): honour the restore-point block on all three paths, one checkpoint per command (#4758) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9160
- fix(web): /alerts honours ?orgId= by switching the working org (#9108) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9167
- test(web): deflake ProxyTunnelPage cookie-blocked unknown-reason test (#9159) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9173
- fix(web): partner settings a11y, Off-mode confirm, clipped selects (#9168) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9174
- feat(security): YARA W03b — built-in pack pipeline, clean-corpus CI, boot upsert (#6266) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9161
- docs(plan): YARA W04 — detection rules UI, IOC import, rule-set picker (#6263) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9175
- docs(plan): SSO re-auth road for approver-device registration (#9007) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9184
- docs(plan): PAM user-side decision reaches the server (#8971) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9185
- feat(scripts): built-in printer cleanup scripts — delete by name, delete all except listed (#8290) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9183
- fix(scripts): reaper grace includes the restore-point checkpoint budget (#9162) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9190
- fix(ai): query_devices honours the tags filter (#9122) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9191
- chore(viewer): ignore RUSTSEC-2026-0370/0371/0372 zbus unmaintained advisories (#9113) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9192
- chore(m365): identity-first consent W4 — remove legacy v1 consent path (#7910) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9187
- docs(spec): partner settings — one save model, panel structure, inheritance panel (#9170, #9169) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9196
- refactor(agreements): W1a — shared signed-agreement freeze path + acceptance-hash verify script (#8865 W1a) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9189
- fix(agent): check installer OS/file type before downloading (#9165) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9195
- feat(patching): ring-owned approval rules W04 — contract (#1317) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9188
- docs(plan): recipe library W06 — reconcile R1 with as-built E4 (#6165) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9202
- docs(network-proxy): self-host guide for the dedicated tunnel origin (#8155 W04) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9203
- test(api): deflake workerRegistry.redisIndependent cold-import timeout (#9198) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9199
- docs(spec): dashboard click-through contract and Sites visibility (#6721, #6720) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9210
- fix(web): larger sign-in logo (#7899) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9208
- docs(plan): detect and report ISP SNI-filter hijack (#8868) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9213
- fix(web): partner settings — scrollable sticky rail, banner aligned to the container (#9171) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9206
- docs(plan): connection-health staleness detection for the D3 deferred kinds (#9127) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9211
- docs(plan): tenant-isolation bulkheads for the shared API (#8840) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9212
- docs(spec): ticketing — merge tickets, business-hours SLA, routing rules, portal updates (#8883, #8972, #8973) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9214
- docs(spec): business reports phase 2 — margin, MRR/renewals, quote win rate (#6830) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9218
- docs(plan): restore-point outcome durability across agent restart (#9163) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9217
- feat(agent): detect Zscaler and other enterprise VPN clients (#8763) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9186
- docs(spec): installer bootstrap from an unblockable artifact source (#8874) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9224
- docs(plan): Trust Center W02 follow-ups (#9087) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9225
- fix(edr): audit VENDOR_ROOT_MISMATCH refusals and lock the root re-check (#8942) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9219
- docs(plan): DNS filtering clients (Control D, NextDNS) via software deployment (#6958) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9229
- fix(patching): Linux maintenance reboots ride schedule_reboot with prompt, deferral and wall fallback (#9181) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9216
- feat(connection-health): webhook_deliveries retention job (#9128) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9193
- fix(userhelper): run the Windows toast tests in CI; fall back when notifications are disabled (#9091) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9207
- feat(tickets): link or change the device on an existing ticket (#8962) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9227
- feat(filters): Device Group does-not-equal / is-not-one-of operators (#9179) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9215
- test(web): deflake the remaining ProxyTunnelPage cookie-notice cases (#9159) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9228
- fix(monitors): conversion retry exhaustion reports conversion_contended (#8944) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9231
- fix(web): partner settings — card autosave must not discard unsaved edits (#9197) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9205
- feat(security-agents): W03 — coverage state, reconciler, gap alerts, coverage UI (#6960) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9194
- fix(agent): refuse a redelivered user-helper script before its restore-point checkpoint (#9164) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9232
- feat(tickets): checklist save-as-template, duplicate template, queue progress, note edits keep the tick (#9180) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9230
- feat(agreements): W1b — agreement_requests schema, registrations, request-aware freeze (#8865 W1b) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9236
- fix(billing): carry quote line unit cost into invoice cost basis on accept (#9221) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9239
- feat(ai): generate_report accepts the existing business report types (#9222) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9240
- fix(billing): a NULL bundle component cost makes the margin unknown, never 0 (#9223) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9241
- fix(billing): count advance-billed final terms in partner-dashboard MRR (#9220) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9242
- fix(remote): trickle ICE candidates both ways so late TURN relay candidates connect (#9182) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9237
- feat(security-agents): W04 — SentinelOne vendor (#6960) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9244
- fix(agent): fall back to GetIfEntry2 when GetIfEntry2Ex is missing on Windows 10 1507 by @bgatestmg in https://github.com/LanternOps/breeze/pull/9238
- docs(spec): trust state follows billing lapses (#8714) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9249
- fix(agent): exit the reconnect loop when Stop lands during a dial (flaky TestReconnectLoop_WaitsAfterServerClose4001) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9245
- feat(agreements): record an agreement signed elsewhere (#8865 W1c) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9250
- fix(security-agents): mark absent SentinelOne agents so decommissioned endpoints stop reading as covered (#9248) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9251
- qa: v0.124.0 pre-release sweep — 4 fixes + tracking doc (messaging gates held) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9270
- qa: v0.124.0 sweep follow-ups at the tag candidate (#9250 fix + doc) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9297
- fix(mobile): adopt the UIScene lifecycle so iOS 27 launches the app (App Review 2.1(a) on 1.0.1 (84)) by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9300
- docs(release): What's New 0.124.0 entry + clear next-release draft by @ToddHebebrand in https://github.com/LanternOps/breeze/pull/9301
Full Changelog: v0.123.0...v0.124.0