github LanternOps/breeze v0.116.0

3 hours ago

Breeze RMM v0.116.0 — accept quotes on a customer's behalf, a partner-scope foundation for business reports, network topology becomes an opt-in partner module, and a broad fix + security-hardening sweep across billing, AI sessions, and disk cleanup.

Summary

A tech can now accept a quote for a customer over the phone or in person — record the method and signer, attach evidence, and the invoice issues automatically — closing a workflow gap that previously required the customer to click through the portal (#6596, #6657, #6659, #6660, #6663). Business Reports gets its W01 partner-scope foundation: reports can now be owned by a partner instead of only an organization, laying the groundwork for partner-wide reporting; generating a partner-owned report still refuses until W02 ships (#6673). Network Topology (shipped v0.115.0 but unreachable) is now a real Partner Settings → Modules toggle instead of a permanently-off developer code (#6540). AI sessions get two enforcement fixes — a configured max-turns budget now actually applies (#6562), and the /workspace AI Assistant page is now hidden and blocked for roles without ai_sessions:use, matching the API gate added in v0.115.0 (#6559). Retired labour-pricing fields are now rejected outright instead of silently dropped (#6477). Disk Cleanup v2's OS-native cleaners now require an agent on 0.116.0, not just 0.115.0, after lab-found hang/miscount fixes (#6643). A wide fix sweep covers billing/time-entry edge cases, backup verification, monitor previews, and stale-write races, plus a five-item security-hardening pass.

Added

  • Upgrade preflight + version history — on boot the API logs which deprecations and removals this upgrade crosses (from a shipped breaking-change manifest) and records each version it runs in breeze_version_history. It reports only and never blocks boot; an operator CLI with --strict (or BREEZE_UPGRADE_PREFLIGHT_STRICT=true) exits non-zero when a removal is crossed (#6714).
  • Accept a quote on behalf of a customer (#6596): from the quote detail page, record a verbal/in-person acceptance (method + signer), and the invoice is issued immediately — gated on a new quotes:accept permission, back-filled to every role that already had "send" (#6596). Optional customer-notice auto-email on acceptance, configurable in Partner Billing Settings (#6657). Evidence file can be attached to the acceptance record (#6663). A matching "Decline on behalf" action records a customer decline with an optional reason (#6659).
  • Business Reports partner-scope foundation, W01 (#6673, feature #3198): the reports table can now be owned by a partner (org_id XOR partner_id), with dual-axis RLS and no partner-wide read branch — a partner-owned report is private to that partner. No new user-visible report type is generatable yet; creating one returns unsupported_report_scope until W02.
  • Business Reports, W02 (#6739, feature #3198): three new report types — SLA attainment, time & billability, and AR aging — generate at org scope or partner-wide (suspended orgs excluded), on demand or on a schedule, as PDF or CSV. Billable value is priced per row in its own currency, never summed across currencies. Report-list labels and editing for these types follow in W03.
  • Network Topology partner module toggle: Settings ▸ Partner ▸ Modules now has a real "Network Topology (Beta)" switch (plus physical/interface-health/diagnostics/AI sub-toggles); the device Topology tab shows a proper empty state with a link to enable it instead of a raw materialization_disabled code (#6540).

Improved

  • Metric anomaly detection groups repeated anomalies into episodes that auto-resolve when the metric clears, with baselines protected from anomalous data. Still behind ml.anomalies.enabled (default off); with it off, open episodes close as detection_off (#6702, #6708). The anomaly evaluation endpoint now excludes cleared anomalies and reports episode-level figures (#6726).
  • Ticket Time & Billing entries with no configured hourly rate now show a clear "no rate" badge instead of inflating billable hours, and the billables list and invoice assembly agree on what counts as missing (#6581, #6583).
  • Invoice line descriptions no longer bake in a "(billed X of Y worked)" note (#6587); invoice delete-preview totals round correctly at the currency's minor unit (#6612).
  • DR plan editor and Backup config forms auto-scroll to the first invalid field on a failed save (#6578); DR plan save and BMR-token creation now surface success/error toasts instead of failing silently (#6580).
  • Devices list correctly reflects "Offline" immediately on a WebSocket close/error instead of getting stuck "Online" (#6566).
  • Configuration Policies ▸ Monitors: monitor preview works again (#6615), deleting a monitor with existing alert history no longer fails (#6556), a deleted monitor no longer reappears after reopening the policy (#6564), and a new HTTP-check expecting a 3xx status defaults "follow redirects" off (#6558).
  • MCP tenant clients now see an accurate, shorter tool list instead of tools that tools/call always denies (#6479).

Fixed

  • Ticketing: an inbound customer reply now reopens a resolved ticket through the normal status-change path (#6711), and resolve/reopen emit ML feedback events (#6715). M365 mailbox tickets take their full text from the HTML body instead of the 255-char preview (#6703) and import email attachments onto the ticket (#6709).
  • Agent reliability scoring no longer counts non-hardware log lines as memory/disk signals (#6713).
  • Agent disconnects no longer publish device.offline twice, so webhooks and offline automations fire once (#6722).
  • DNS security: content-policy blocks (streaming, social media, gambling, adult content, unknown) no longer raise a high-severity "DNS threat blocked" alert per device every hour — only real threat categories alert (#6704). Provider labels like "Adult Themes", "Trading" or "Download" are no longer misfiled as adware (#6706).
  • Windows event logs: System-log errors are now classified as hardware (disk, NTFS, storage, WHEA, thermal) or system instead of one bucket (#6705).
  • Several stale-write races in billing now refuse instead of silently succeeding: editing/deleting an already-changed time entry, ticket part, or time-entry row now errors instead of reporting a false success (#6567, #6588, #6613, #6617).
  • Ticket time entries hitting the billable_minutes database constraint now show a friendly refusal instead of a 500 (#6616).
  • Backup verification tab shows the agent's actual failure reason instead of a generic message (#6618).
  • /devices/network no longer renders a broken device-detail shell when navigated to directly (#6560).
  • Bare-metal BMR token minting is refused up front when the source snapshot isn't restorable, instead of minting a token that fails later (#6548).
  • SSO login failures now return a proper "Invalid credentials" error instead of a generic 500 (#6623).
  • Microsoft mailbox "Connect" no longer 500s on an admin-consent denial; shows a friendly error instead (#6553). Inbound email-to-ticket gains flood backpressure (global rate ceiling, default 20 jobs/sec), loop/bounce suppression, and an opt-in full-message-reply mode (#6534).
  • AI-session turn limits configured in Settings ▸ AI Usage now actually end a session at the configured max, instead of every session silently defaulting to 50 turns regardless of configuration (#6562).
  • Retired labour-pricing fields (defaultHourlyRate, defaultBillable, rateCurrency) are now rejected with a 400 naming the field and its billing-profile replacement, instead of being silently accepted and dropped (#6477).
  • Disk Cleanup: freed-space totals are now correct on lazy-reclaim filesystems (#6546) and on btrfs hosts with bind mounts (#6545); the retired Windows cleanmgr sub-ID is reachable again in selection (#6606); cleanup run history renders correctly (#6602).

Security

  • /workspace (AI Assistant full-page chat) and its sidebar nav entry are now gated on ai_sessions:use, closing a gap where a role without the permission could open the composer and only discover it was denied on send (#6559).
  • IP allowlist is now checked before a request transaction opens, avoiding unnecessary DB work on a request that will be denied (#6532).
  • A failed passkey verification no longer echoes the expected WebAuthn origin string in the error response (#6565).
  • Tier-2 AI-tool release authority, admin-history bounds, and contract-tool/line-materialization caller-authority checks are tightened so an over-privileged AI session or contract action is denied at the authority boundary rather than allowed through (#5570).

Self-Hosting / Upgrade Notes

Upgrade: bump BREEZE_VERSION in .env, then docker compose pull api web portal && docker compose up -d (or pnpm install when running from source).

Migrations: 22 new migration files, all idempotent and auto-applying on boot via autoMigrate. Read through them; none does a large-table rewrite or backfill against existing hot data — they add new tables/columns for quote acceptances, backup-provider integration, AI Operator task graph, caller verification, metric anomaly episodes (plus an episode feedback source type), the reports partner-ownership shape, and breeze_version_history (the app role gets SELECT only). No action required beyond the normal upgrade.

No new required environment variables. New optional env vars, both defaulted/off:

  • INBOUND_QUEUE_MAX_PER_SEC (default 20) — global inbound-email-to-ticket processing rate ceiling; jobs are delayed, never dropped, when over the ceiling.
  • CALLER_VERIFICATION_ENABLED — must be the exact literal true to enable; default false/unset keeps every /caller-verification route 404. Backend-only in this release, no reachable UI.

Behavior changes & flags:

  • Disk Cleanup v2's OS-native cleaners now require agent 0.116.0, not 0.115.0 — an agent still on 0.115.x gets a clear "update the agent" refusal instead of running the pre-fix cleaners that could hang or misreport (#6643).
  • quotes:accept is a new permission, back-filled onto every role that could already send a quote, gating the new accept/decline-on-behalf actions (#6596).
  • Retired labour-pricing fields (defaultHourlyRate, defaultBillable, rateCurrency) now return a 400 instead of a silent 200 no-op — this is the release where the rejection actually takes effect; v0.115.0 still accepted and silently discarded these writes (#6477, #6639).
  • Confirming an account's email now requires clicking "Confirm my email" on the verify-email page instead of auto-verifying on page load (#6579).
  • /workspace and the "AI Assistant" nav item are now hidden/blocked for any role lacking ai_sessions:use (#6559); AI session turn limits are now actually enforced at the configured value (#6562).
  • Network Topology is now a real Partner Settings ▸ Modules toggle (settings.topologyFeatureFlags) — still defaults off; existing partners see no change until they opt in (#6540).

No breaking changes.

Known gaps in this release:

  • Customer portal invoice view (logged in) shows invoice lines grouped by ticket but without the ticket category label; the web invoice, the PDF and the public invoice link are correct (#6674).
  • Windows System-log hardware/system classification (#6705) passed its collector test suite natively on Windows Server 2022, but live event-log collection was not exercised end to end before release.

What's Changed

New Contributors

Full Changelog: v0.115.0...v0.116.0

Don't miss a new breeze release

NewReleases is sending notifications on new releases.