Breeze RMM v0.94.0 — customer portal onboarding, partner policy libraries, and sharper vulnerability correlation.
Summary
- Customer Portal onboarding — invite, resend, bulk-invite, disable, and delete portal (customer) users from Org Settings; invited users accept via a tokenized link and set their own password (#2283, #2299).
- Partner policy libraries — partner-owned configuration policies are now a reusable library you can assign to a chosen subset of orgs, not all-or-nothing (#2280/#2285).
- Tickets from AI conversations — turn an AI chat into a ticket in one step (#2287).
- Better vulnerability correlation — a deterministic DisplayName→CPE resolver plus case-insensitive catalog matching, so installed software maps to CVEs more reliably (#2290/#2292/#2294).
- Self-hosted internal OIDC SSO — self-hosters can opt into SSO against internal/private-network OIDC issuers (#2295/#2296).
Added
- Portal Users management — a new panel in Org Settings to invite/resend/bulk-invite/disable/delete customer-portal users; disable is terminal (a disabled user can't be resurrected by invite/resend/accept). Invite acceptance is a tokenized link → set password → activate (#2283).
- Assign partner policies to specific orgs — a master "All organizations" toggle plus a searchable org checklist on partner-owned config policies. New partner-owned policies are now created empty (reach 0 devices until assigned); site/group/device precision stays in the Assignments tab (#2280/#2285).
- Create a ticket from an AI conversation — one-step ticket creation off an AI chat thread (#2287).
- Quote line-item images from a URL — add an image to a quote line item by URL, matching the existing image-block behavior (#2279).
Improved
- Vulnerability correlation accuracy — deterministic DisplayName→CPE resolution with a global resolution cache/unmatched-name log, and case-insensitive catalog product matching (#2290/#2292/#2294).
- Quotes billing — the org bill-to address is now frozen onto a quote when it's sent, and a billing-contact setting was added (#2284).
- Web QA papercuts — remove-user confirmation, email-field guards, and hardening of token-refresh 5xx handling (#2299).
Fixed
- MCP bootstrap —
tools/listnow loads correctly by using Zod 4's nativetoJSONSchema(#2289). - Software catalog delete scoping — deleting a catalog package is now scoped to the item's own org, preventing cross-org deletes (#2281).
Security
- Software catalog delete now enforces org scope (#2281) — closes a tenant-scope gap on catalog package deletion.
- Self-hosted internal-OIDC SSO is opt-in and fail-closed (#2295/#2296) — private-network OIDC targets are reachable only when a deployment affirmatively declares self-hosting; loopback, link-local, cloud-metadata, and CGNAT addresses stay blocked in both modes.
- Recovery-key escrow documented (#2278).
- Self-hosters are encouraged to upgrade.
Self-Hosting / Upgrade Notes
Upgrade command — bump BREEZE_VERSION=0.94.0 in /opt/breeze/.env, then:
docker compose pull api web && docker compose up -d(If you build from source, run pnpm install first.)
-
Database — 2 idempotent migrations, no rewrites. They auto-apply on API boot via
autoMigrate(unlessAUTO_MIGRATE=false):2026-07-07-portal-user-invites.sql— adds two nullable columns (invited_by,invited_at) toportal_users. Instant metadata-only change.2026-07-08-vuln-product-resolutions.sql— creates a new (empty)software_product_resolutionstable with system-scoped RLS and adds a nullablematch_confidencecolumn todevice_vulnerabilities. Instant; no backfill.- No large-table rewrites or backfills — this is a fast, in-place upgrade.
-
No new required environment variables. The config validator boots with the same required set as v0.93.0.
-
Behavior change — internal-OIDC SSO opt-in. SSO can now reach OIDC issuers on private networks (RFC1918/ULA, and plain-HTTP), but only when
IS_HOSTEDis affirmatively set to a recognized self-host value (i.e.IS_HOSTED=false). Unset/empty/garbage/hosted stays strict and fail-closed — no change for hosted deployments, and no change for self-hosters who don't set it. Loopback, link-local, cloud-metadata, and CGNAT targets remain blocked in every mode. This reuses the existingIS_HOSTEDvar; there is nothing new to add. -
Behavior change — partner-owned config policies are created empty. New partner-owned (all-orgs) policies now reach 0 devices until you assign them to orgs (previously they auto-seeded an all-orgs assignment on create). Existing partner-owned policies are untouched — they keep their current assignment. No migration, no backfill.
No breaking changes.
What's Changed
- docs(security): document recovery-key escrow + bump docs-review tracker to v0.93.0 by @ToddHebebrand in #2278
- feat(quotes): add a line-item image from a URL (parity with image blocks) by @ToddHebebrand in #2279
- fix(software): scope catalog package delete to the item's own org by @ToddHebebrand in #2281
- chore(deps): bump the github-actions group with 5 updates by @dependabot[bot] in #2282
- fix(quotes): freeze org bill-to address on send + add billing-contact settings by @ToddHebebrand in #2284
- feat(portal): customer portal onboarding + invite flow + Portal Users management UI by @ToddHebebrand in #2283
- chore(deps): bump the expo-sdk group across 1 directory with 10 updates by @dependabot[bot] in #2235
- feat(ticketing): create a ticket from an AI conversation by @ToddHebebrand in #2287
- fix(mcp): use zod 4 native toJSONSchema so bootstrap tools/list loads by @bdunncompany in #2289
- fix(vuln): match catalog products case-insensitively in correlation by @ToddHebebrand in #2292
- fix(sso): allow self-hosted internal OIDC issuers via IS_HOSTED-gated private-network opt-in by @ToddHebebrand in #2295
- feat(config-policy): partner-owned policies as reusable library — assign to a selectable subset of orgs (#2280) by @ToddHebebrand in #2285
- fix(sso): PR-review follow-ups for OIDC private-network opt-in (#2295) by @ToddHebebrand in #2296
- fix(vuln): deterministic DisplayName→CPE resolver for correlation (#2290) by @ToddHebebrand in #2294
- fix(web): QA papercuts — remove-user confirm, email guards, refresh 5xx hardening by @ToddHebebrand in #2299
Full Changelog: v0.93.0...v0.94.0