github LanternOps/breeze v0.82.0

latest releases: v0.115.0, v0.114.0, v0.113.0...
3 months ago

Breeze RMM v0.82.0 — the Quotes & Proposals suite with accept-to-pay, Pax8 + TD SYNNEX distributor integrations, AI/ML anomaly detection on rollup-backed metrics, email-to-ticket customer routing, a sharper remote-desktop experience, and a sweeping multi-tenant security hardening wave.

Upgrading from v0.81.0? Migrations auto-apply, but v0.82.0 adds a new required portal container for the customer Quotes/Invoices experience — if you adopt the v0.82.0 compose you must set BREEZE_PORTAL_IMAGE_REF or docker compose up aborts. See Self-Hosting / Upgrade Notes at the bottom for full details, new config, and behavior changes.

What's New

Billing & Quotes

  • Quotes & Proposals: build proposal documents from content blocks (headings, rich text, pricing tables) with one-time/monthly/annual recurring totals, PDF export, and a block editor. (#1455)
  • Sent quotes are now acceptable end-to-end — customers view in the portal or via a public link, e-sign with a typed signature or decline with a reason, and an accepted quote converts into an invoice automatically. (#1468)
  • Quotes now expire (and are blocked from acceptance past their expiry date), and accepting a quote immediately issues a payable invoice with a "Pay now" link on the public page and customer portal. (#1483)
  • Invoice payments moved to a per-partner Stripe API-key model (replacing Stripe Connect/OAuth): each MSP pastes their own Stripe key, charges run directly on their account, and customers are marked paid instantly on return from Checkout. (#1610)
  • Quotes and invoices now show a seller/MSP "From" contact block and combined Terms & Conditions, frozen at issue time, across PDFs, emails, the web app, and portal views. (#1651)
  • Completed the billing-catalog UI: per-organization pricing, ticket-part linking via typeahead, and an archive confirmation prompt. (#1467)
  • Dedicated "Partner Billing" and "Partner Billing Viewer" roles, with billing access removed from the broad Technician role and permission-aware UI that hides controls users can't access. Existing Technicians who handle billing must be reassigned to a billing role. (#1454)
  • Partner-wide alert templates with a full management UI — share templates across all organizations or scope to one, with scope badges and filters. (#1466)
  • Quote totals now show the "Due on acceptance" amount rather than the larger first-period total. (#1628)
  • Issuing an invoice now shows an "Issuing…" in-flight state instead of looking like a draft until the save completed. (#1460)

AI & Machine Learning

  • New anomaly-detection model (v1) runs in shadow mode alongside the existing model, with a side-by-side v0-vs-v1 comparison on the device anomaly view (gated behind a feature flag). (#1638)
  • AI metric analysis and device metric history charts now read from pre-aggregated hourly/daily rollups for faster loads, falling back to raw data when rollups aren't ready. (#1600, #1598)
  • Self-hosted operators can point the AI Agent at any Anthropic-compatible backend (locked off on hosted SaaS). (#1473)
  • Script-builder AI assistant can again search and reference the script library, and generated code is correctly inserted into the script editor. (#1457, #1453)
  • Hardened ML roadmap controls and fixed a batch of correctness issues: silently-failed alert acknowledgements no longer poison AI training data, rollups no longer corrupt on non-UTC servers, trend/anomaly detection covers the full time range, duplicate anomalies no longer create two incidents, and ML panels now surface errors and empty states. (#1595, #1607)
  • ML feature pages (User Risk, Anomalies, Alert Correlations, Capacity Forecast) load without console errors and correctly show per-org disabled states. (#1631)

Integrations

  • Pax8: syncs clients and subscription/license data, with a full connect/test/sync UI and company-to-org mapping, plus the ability to link synced license quantities to recurring contract lines. (#1594, #1635)
  • TD SYNNEX: connect your account, search products, and import them into the catalog. (#1596)
  • New Distributors tab on the Integrations page houses Pax8 and TD SYNNEX. (#1635)
  • Consolidated the legacy per-category integration pages into the tabbed /integrations hub with deep-linkable tabs and a new Notifications tab (Slack/Teams/Discord); old standalone routes (PSA, Security, Huntress, Monitoring, etc.) now redirect into the hub. (#1716)

Tickets

  • Email-to-ticket now routes mail from any customer, not just registered portal users: map a customer's sender domain to an organization (with optional password-less contact onboarding), or send unmatched mail to an opt-in triage org instead of quarantine. (#1715)

Monitoring & Alerts

  • Acknowledging or resolving an alert from the detail page now shows a clear success/failure message instead of failing silently. (#1660)
  • The Notification Channels page loads cleanly for partner users with no organization selected. (#1643)
  • Network Monitoring and Discovery tabs are now preserved in the URL (hash-based) for consistent, bookmarkable navigation. (#1645)
  • Executive summary and OS-distribution analytics now report real errors instead of silently showing empty/zero data. (#1609)

Remote & Agent

  • Remote desktop streaming reaches much sharper quality on high-resolution screens (1440p up to 30 Mbps, 4K up to 50 Mbps), with an admin option to tune the bitrate cap. (#1669)
  • Redesigned remote-desktop viewer toolbar — logically grouped controls, overflow menu, a single Quality popover, a local-fullscreen shortcut, and a polished credentials dialog. (#1641)
  • Opening a second concurrent remote session no longer freezes the Viewer app. (#1627)
  • Windows devices now report accurate BIOS, GPU, and motherboard details, with motherboard info shown on the device hardware page. (#1524)
  • Watchdog version now appears on the device details page and as an optional device-list column. (#1390)
  • The device filter's software picker now searches software names server-side for reliable results across large fleets. (#1461)
  • Foundation for a new OneDrive Helper that will auto-mount the right SharePoint libraries per user (backend only this release). (#1679)

Platform & Reliability

  • Approver registration redesign: a tech's phone provisions itself silently at login, so the first Face ID prompt is a real approval rather than setup; the web "Approval security" page lists registered phones and browsers. The static PIN was removed, and critical approvals now require fresh account re-authentication plus a hardware-backed signature. (#1433)
  • New per-user 12-hour vs 24-hour time-format preference that applies throughout the web app. (#1672)
  • Surfaced several built-but-unlinked pages in navigation — SSO, Access Reviews, Timesheets, Quarantined Devices, Third-Party Catalog, and Connected Apps now have sidebar/settings entry points (each gated by the permission its route enforces). (#1716)
  • Redesigned the Update Ring editor into a single patch-approval matrix (default rule plus per-category overrides), creatable/editable directly from the Config Policy patch tab. (#1456)
  • Customer portal (invoices and quote acceptance) is now served in production under a path prefix on the main domain. (#1474)
  • Large software-package uploads now stream to disk and have a 10-minute window, eliminating false "aborted" errors and bounding memory under concurrent uploads. (#1664, #1602)
  • Background integration sync workers (Huntress, Pax8, DNS) no longer hold database connections open across slow external calls, preventing connection-pool exhaustion. (#1703, #1704)
  • Large bulk device-connection inserts are now chunked under the database parameter limit, fixing silent loss of connection inventory. (#1698)

Security & Hardening

This release includes a large security-review hardening wave. Highlights:

  • Hardened multi-tenant site-axis isolation on alert, network, audit-baseline, peripheral-policy, DNS reporting, and AI list/audit-query endpoints so site-restricted users can't read or act on resources outside their assigned sites. (#1644, #1678, #1665, #1681, #1683, #1673, #1702, #1706, #1710)
  • All mutating tunnel endpoints (open/close/allowlist) and credential-minting/viewer-transition endpoints are now audit-logged; manual and Stripe-initiated invoice payment voids are also audit-logged. (#1700, #1705, #1708, #1701, #1707)
  • Required full agent-role authorization on security, patch, and posture-ingest endpoints, added a tenant-status gate on agent certificate renewal, and hardened the integrity of agent-reported backup/vault completion state. (#1687, #1690, #1688, #1711)
  • SSO hardening: identity-first lookup with safe just-in-time linking, honoring the IdP MFA signal, a dedicated sso:admin permission, and DNS-based domain-ownership verification. (#1671, #1680, #1691, #1695)
  • Core authentication hardening: durable session/token revocation on password change, TOTP single-use replay protection, and strict refresh-token family enforcement. (#1648, #1677, #1653, #1655)
  • Separation-of-duties enforcement on privileged-access elevation (distinct approver required, correct requester attribution). (#1662, #1682)
  • Prevented cross-organization script execution and cross-partner catalog data leaks on quotes, and scoped alert routing-rule writes correctly. (#1674, #1684, #1654)
  • Added rate limiting to VNC connect-code exchange and tunnel WebSocket upgrades, routed PSA integration requests through a safe-fetch wrapper to block SSRF, validated background automation job payloads, enforced partner org-access on ticket reads, authenticated inbound ticket-email senders, and neutralized CSV formula injection in fleet log exports. (#1670, #1659, #1661, #1667, #1666, #1699, #1692)

Security fixes are described at a high level here; any CVE/GHSA advisories are published separately after rollout.

Bug Fixes

  • Fixed a production bug where the AI agent could not run any tool — every command returned "rejected or timed out" even after approval. (#1591)
  • Fixed the Windows agent MSI installer rolling back when installed by double-click/UAC, and a false pre-flight refusal on some self-hosted reverse-proxy setups. (#1480, #1477)
  • Windows agents now auto-detect and repair incorrect log/data folder permissions at startup when the installer's hardening step was blocked. (#1613)
  • Windows devices no longer stay stuck showing "reboot required" forever in Patch Compliance. (#1478)
  • The Patches page now respects the organization switcher (approve/decline/defer, export, ring actions), requires confirmation for destructive installs, and surfaces action results. (#1636)
  • Fixed the mobile app showing a previous session's AI chat history after switching accounts, and surfaced sign-out credential-wipe failures instead of silently leaving data on the device. (#1415, #1626)
  • Fixed running a script against multiple selected devices, which previously failed with a "must contain at least one item" error. (#1590)
  • Fixed the script editor losing its color theme when navigating between scripts. (#1593)
  • Permission-restricted pages now show a clear access-denied state instead of a misleading "session expired" prompt, and the sidebar only shows items the user can use. (#1640, #1629)
  • Disabled identity integrations (Google Workspace / Microsoft 365) now show a calm "not enabled" message instead of a red error banner. (#1632)
  • Partner Settings shows a loading spinner instead of a flashed "access denied" message. (#1642)
  • Auth pages respect the saved light/dark theme on first load. (#1649)
  • Add Organization now auto-fills the URL slug from the name (still manually overridable). (#1646)
  • The Scripts "Available to" picker works again for partner-level users. (#1469)
  • Collapsed AI and Documentation side panels no longer intercept clicks. (#1463)
  • Fixed duplicate Role/Type columns on agent device rows. (#1462)
  • Corrected the stale API version shown in the sidebar footer. (#1647)

Self-Hosting / Upgrade Notes

Upgrading from v0.81.0 → v0.82.0. Standard upgrade path applies: bump BREEZE_VERSION in /opt/breeze/.env and docker compose pull api web && docker compose up -d. If you build from source, run pnpm install — dependencies changed (new @fastify/busboy, nodemailer 8→9, @anthropic-ai/claude-agent-sdk 0.2→0.3, zod 3→4).

⚠️ Action required before/after upgrade

Database: nothing required — all 31 new migrations apply automatically on boot (autoMigrate runs at startup unless AUTO_MIGRATE=false), each wrapped in its own transaction and idempotent. No new env var is required at boot by the API.

New required service — the customer portal (#1474). v0.82.0 introduces a new portal container (Astro SSR, apps/portal) that serves the customer-facing Quotes/Invoices experience under a base path (default /portal) on your main domain — no dedicated hostname/cert needed. The release pipeline now builds and publishes it to ghcr.io/lanternops/breeze/portal, and it is wired into the official compose files (docker-compose.yml, deploy/docker-compose.prod.yml).

Its image line is guarded — image: ${BREEZE_PORTAL_IMAGE_REF:?…} (prod compose: ${BREEZE_PORTAL_IMAGE_DIGEST:?…}) — so if you adopt the v0.82.0 compose you MUST set the image ref or docker compose up aborts the entire stack, not just the portal. Add to your .env:

BREEZE_PORTAL_IMAGE_REF=ghcr.io/lanternops/breeze/portal:${BREEZE_VERSION}   # base compose
# deploy/docker-compose.prod.yml instead wants a digest:
# BREEZE_PORTAL_IMAGE_DIGEST=sha256:<the v0.82.0 portal image digest>
PORTAL_BASE_PATH=/portal                 # baked into the image at build; keep in sync with the Caddyfile carve-out
PUBLIC_PORTAL_URL=https://<your-domain>/portal   # public origin for emailed quote/invoice links; defaults to https://${BREEZE_DOMAIN}/portal

Also add the /portal carve-out to your Caddyfile so the main domain routes /portal* to the portal container (the rest stays on web).

  • If you do a version-bump-only upgrade on a hand-edited compose that has no portal service: nothing breaks at up time, but public quote/invoice accept-and-pay links will 404 — Quotes is not usable until you add the portal service. There is no env flag to "disable" the portal; you either run the container or you don't have the customer portal.

Optional things you may want to do:

  • Self-hosted custom AI backend (#1473/#1412): new ANTHROPIC_BASE_URL lets you route the AI Agent at any Anthropic /v1/messages-compatible backend (local vLLM, LiteLLM gateway). It is fail-closed: the API will refuse to boot if ANTHROPIC_BASE_URL is set while IS_HOSTED is not explicitly false/0/no/off. So if you set it, you must also set IS_HOSTED=false explicitly (and thread IS_HOSTED through the api service environment: block — a value in .env alone is not enough). Leave it unset and nothing changes.

Database migrations

31 new migrations, all idempotent and auto-applied on boot. Notable ones and caveats:

  • pg_trgm extension (2026-06-17-software-inventory-name-trgm.sql): runs CREATE EXTENSION IF NOT EXISTS pg_trgm then a GIN index on software_inventory.name. pg_trgm is the only extension Breeze relies on and is present in the supported Postgres images / DO managed PG. Needs a role allowed to CREATE EXTENSION (standard setups qualify). No pgcrypto/gen_random_bytes dependency anywhere.

  • Column DROP / data loss (2026-06-15-drop-approver-pin.sql): drops the approver-PIN columns from users/approval_requests/elevation_requests. The static approver PIN is replaced by L4 fresh re-auth; these columns were no longer read/written. If you used approver PINs, approvers now step up via account re-auth.

  • Partitioned table creation (2026-06-18-metric-rollups.sql + -n-…-partitions.sql): creates the new RANGE-partitioned metric_rollups table + default partition + monthly partitions for [now-1mo, now+3mo]. The table is new, so no large-table rewrite on existing DBs.

  • New ML/anomaly/alert tables (metric_anomalies, metric_anomaly_candidates, alert_correlation_groups, ml_feedback_events, remediation_suggestions, etc.): all CREATE TABLE IF NOT EXISTS, empty, no migration-time backfill. Optional one-time backfill scripts exist (pnpm --filter @breeze/api metric-rollups:backfill, metric-anomalies:backfill) but are not run automatically and are not required.

  • role_permissions PK (2026-06-20-role-permissions-unique.sql): de-dups duplicate (role_id, permission_id) rows (logs a WARNING with the count) then adds a composite PK. Small table; no scale concern.

  • No large-table NOT NULL adds or backfills in this range. New org_id columns are on new tables only. device_hardware gets three nullable motherboard_* columns (instant). sso_providers gets trusts_idp_mfa boolean NOT NULL DEFAULT false (instant in PG11+).

  • New customer_email_domains table (2026-06-20-a-customer-email-domains.sql, #1715): partner-axis RLS + denormalized org_id, new and empty — backs the email-to-ticket sender-domain→org mapping. No backfill.

Other migrations: Quotes/Proposals schema + decline-reason + contact fields, Pax8 billing sync, TD SYNNEX Digital Bridge, OneDrive Helper (feature enum + settings/libraries/device-state), billing roles, Stripe per-partner API-key + status check, the FK-child RLS backstop, and the SSO trio (idp-mfa, admin-permission backfill, verified-domains).

New configuration

The only new var that can block a deploy is the portal image ref (compose :? guard); the rest are optional:

Name Required? Default Purpose / notes
BREEZE_PORTAL_IMAGE_REF (base compose) / BREEZE_PORTAL_IMAGE_DIGEST (prod compose) Required if you adopt the v0.82.0 compose none (:? guard) Image for the new portal container (#1474). Unset → docker compose up aborts the whole stack. Set to ghcr.io/lanternops/breeze/portal:${BREEZE_VERSION} (or the release digest).
PORTAL_BASE_PATH Optional /portal Base path the portal is served under; baked into the portal image at build, keep in sync with the Caddyfile carve-out.
PUBLIC_PORTAL_URL Optional https://${BREEZE_DOMAIN}/portal Public origin for portal links in outbound email (quote/invoice accept links); falls back to PUBLIC_APP_URL.
ANTHROPIC_BASE_URL Optional (self-host only) unset Route the AI Agent at an Anthropic-compatible backend (#1473/#1412). Boot-refuses unless IS_HOSTED is explicitly false/0/no/off; must be a valid http(s) URL. Pair with ANTHROPIC_AUTH_TOKEN.
ANTHROPIC_MODEL Optional unset Overrides the default model id for a raw vLLM endpoint (leave unset when a LiteLLM gateway aliases the model).
SSO_DOMAIN_VERIFICATION_STRICT Optional false (off) When true, every org must verify DNS domain ownership before SSO can JIT-link/provision. Off = gradual: an org is gated only once it has ≥1 verified domain. Already-linked identities are always exempt. Never blocks boot.
ML kill switches: ML_FEATURES_DISABLED / ML_OUTPUTS_DISABLED / ML_GLOBAL_KILL_SWITCH / ML_DISABLED_FLAGS Optional unset (ML on) Read at call-time (no redeploy needed) to stop ML/AI producers from writing outputs. ML_DISABLED_FLAGS is a comma list supporting ml.* wildcards.

Removed env vars (Stripe Connect → per-partner API key): STRIPE_CONNECT_CLIENT_ID and STRIPE_OAUTH_REDIRECT_URL are gone (now ignored — no action needed, but you can delete them). STRIPE_SECRET_KEY and STRIPE_WEBHOOK_SECRET remain.

Reminder: any var you set in .env must also be mapped in the api/web (and portal) service environment: block of your compose file — compose only interpolates listed vars. This applies especially to IS_HOSTED if you enable ANTHROPIC_BASE_URL.

Behavior & breaking changes

  • Agent ingest now enforces token role (#1687, #1690). Eight agent posture-ingest routes now require the main-agent role token, rejecting the lower-privilege watchdog token with 403. Normal agents are unaffected — the main agent already owns these submissions; only the watchdog (heartbeat/log-shipping) token is newly rejected, and it never legitimately used them. POST /:id/logs stays open (the watchdog ships failover journals there). No agent-side change needed; old agents continue to work.
  • SSO provider management requires sso:admin (#1691). The SSO provider-mutation routes moved from organizations:write to a new sso:admin permission. Non-breaking: the backfill migration grants sso:admin to every role that already has organizations:write, and wildcard (*:*) roles satisfy it at check time. No existing SSO admin loses access.
  • SSO domain verification ships dark (#1695). New sso_verified_domains table + DNS-TXT proof-of-ownership before SSO will JIT-link/provision new accounts. No org is gated until it verifies a domain (or you set SSO_DOMAIN_VERIFICATION_STRICT=true); already-linked identities are exempt. Pending rows are auto-seeded from existing sso_providers.allowed_domains. Admin UI is a follow-up — backend only this release.
  • SSO IdP-MFA trust is opt-in (#1680). New sso_providers.trusts_idp_mfa defaults to false; no behavior change unless a provider opts in.
  • Other auth hardening (mandatory id_token signature, identity-first JIT linking, TOTP replay protection, refresh-token fam claim enforcement, stricter password-change session invalidation) tightens correctness and shouldn't affect a correctly-configured deployment, but is worth noting for non-standard IdP/token setups.
  • Legacy integration routes now 301-redirect into the /integrations hub (#1716). Old standalone paths (e.g. /integrations/psa, /security, /huntress, /monitoring) redirect to the corresponding hub tab (/integrations#psa, etc.). Bookmarks keep working; no action needed.
  • Email-to-ticket customer routing is opt-in and configured in-app (#1715). Sender-domain→org mappings and the optional triage-org fallback are set in the app (no env var); inbound mail is still gated by the existing DMARC/senderAuth.verified check. Behavior is unchanged until you add a mapping or enable triage.

Notes

  • Migrations are auto-applied; to apply them manually against a managed Postgres before the API boots, set AUTO_MIGRATE=false and run them yourself.
  • This release pins zod to v4 internally — no operator action, relevant only if you maintain local patches.
  • New infra: the portal container (built & published by the release pipeline to ghcr.io/lanternops/breeze/portal; required by the v0.82.0 compose — see the action-required note above) and the per-partner Stripe API-key billing model (partners paste their own restricted Stripe secret key in-app; no platform-level Stripe Connect client setup needed anymore).

Full changelog: v0.81.0...v0.82.0

What's Changed

Full Changelog: v0.81.0...v0.82.0

Don't miss a new breeze release

NewReleases is sending notifications on new releases.