Skip to content

v0.99.0

Choose a tag to compare

@github-actions github-actions released this 22 Jul 15:26
· 3859 commits to main since this release
67d4833

Breeze RMM v0.99.0 — a rebuilt home dashboard, a much better quote editor, working approver-device registration, and a large security-review remediation.

Summary

  • Home dashboard rebuilt — six KPI tiles, a triage-first alerts feed, fleet-status bar, and posture cards, with exact server-side counts replacing client-side counts that were wrong past 500 devices (#2719).
  • Quote editor overhaul — collapsible cost bands, drag-to-reorder, bulk edit, undo delete, per-block subtotals, and a portal proposal that finally renders line images and descriptions; plus a data repair for historical quotes with orphaned lines or missing quote numbers (#2711).
  • Approver-device registration fixed — mobile authenticator registration was broken in both clients; it now works via single-use re-auth grants (passkey / TOTP / password) (#2710).
  • Security-review remediation — all 29 findings from the 2026-07-20 internal review closed: partner-wide authorization, org/site isolation, portal flows, SSRF defenses, RLS coverage (#2679).

Added

  • Home dashboard (#2719) — six KPI tiles, alerts triage feed, fleet-status bar, and posture cards (security score with 30-day sparkline, patch compliance, vulnerabilities). All widgets are org-selector-aware and permission-gated; unknown counts render "—" instead of a fake 0, and a failed widget shows a visible degraded state instead of pretending to be healthy.
  • Quote editor overhaul (#2711) — collapsible per-line cost bands, formatted money inputs, actionable margin warnings, a sticky contents outline, drag-to-reorder, a bulk edit bar, undo delete, per-block subtotals, and AI-assisted line descriptions. The customer portal proposal now renders line images, names, and blurbs it previously dropped, and the accept checkbox is visible.
  • Grant-based approver-device registration (#2710) — registering a mobile authenticator now runs through single-use re-auth grants minted by passkey, TOTP, or password (weakest factor refused when a stronger one is enrolled). This repairs a flow that failed with HTTP 400 in both clients — hard-blocking approvals for require_enrollment partners and silently downgrading everyone else's approvals to L1. Update the mobile app; old builds now get a clean 403 on the legacy path and self-heal on next login after updating.
  • Admin MFA reset (#2696) — admins can reset another user's MFA for lost-authenticator recovery (Settings → Users → "Reset MFA"): clears the factor, revokes live sessions and refresh tokens, forces re-enrollment at next login. Requires the acting admin's own session to have satisfied MFA; self-reset refused; audited.
  • Touch ID / Windows Hello self-approve for Tier-3 AI actions (#2691) — when the requester is the only eligible approver, the AI chat approval card offers "Verify & Approve" backed by a WebAuthn platform-authenticator ceremony. The genuine four-eyes case (another approver exists) intentionally keeps the buttonless waiting state.
  • M365 reset-password one-time credential reveal (#2693) — temporary passwords from headless M365 password resets are sealed with AES-256-GCM and revealed exactly once to the requesting tech (7-day window, then reaped), never appearing in logs or audit rows. Off by default behind M365_GRAPH_ACTIONS_TOOLS_ENABLED — see upgrade notes before enabling.

Improved

  • Vulnerabilities page honors the org selector (#2715) — all five fleet endpoints now narrow to the selected organization instead of always showing every accessible org. Per-device routes deliberately ignore the selector so a stale selection can't blank a device's findings tab.
  • Posture report stops scoring stale readings (#2706) — firewall/encryption readings older than 30 days (configurable 1–365 via maxSecurityStatusAgeDays) now count as "unknown" instead of current pass/fail, with new unknown-count summary fields. Compliance percentages may shift after upgrade — that's the report getting honest, not a regression.
  • Quote PDFs keep section headers with their first row (#2664) — no more section label stranded alone at the bottom of a page.

Fixed

  • Huntress built-in package deployable (#2705) — the Versions tab was blank and deploy grayed out because two catalog routes filtered out partner-scoped built-in packages.
  • Partner API exports stop withholding records over benign strings (#2695) — the entropy-based secret detector flagged machine strings like default Ubuntu LVM paths; replaced with a segment-aware structural detector scoped to customer-authored fields. Real secrets still block.
  • Backup S3 endpoints normalized (#2668) — scheme-less endpoints (minio.local:9000) previously passed the connectivity test but failed every actual device backup; they're now normalized to https:// and persisted, and silent Object Lock downgrades now log loudly.
  • Grid-view device cards gate actions by status (#2630) — no more Run Script on decommissioned devices; queued commands now say "will run when hostname reconnects" instead of a false "Command Sent".
  • Claude Code CLI can connect to the Breeze MCP server (#2709) — dynamic client registration now accepts http://localhost:<port>/callback redirect URIs (loopback matching stays exact — localhost.evil.com is still rejected).
  • Mobile (#2688, #2682, #2683) — the iOS build works again (dependency breakage), and approver-registration failures show a visible banner instead of silently recording every approval at L1.
  • Historical quote repair (#2711) — a migration reattaches orphaned quote lines (invisible and uneditable in the editor while still counting in totals) and allocates numbers for pre-v0.92 drafts stuck with none.

Security

  • 2026-07-20 security review fully remediated (#2679) — 29 findings closed: partner-wide authorization hardening (integrations, billing, patch approvals, roles, tickets), org/site isolation (groups, discovery, alerts, reports, search, policies), portal quote/invoice/password-reset/CSRF flows, RLS coverage for new tables, UniFi SSRF defenses, agent telemetry-role enforcement.
  • Portal quote accept/decline is now recipient-gated (#2679) — the authenticated customer portal only lets the emails a quote was actually sent to accept or decline it. Quotes sent before this release have no recipient rows and fail closed — re-send an open quote if the customer still needs to act on it.
  • Sole-operator approvals re-verified at decide time (#2690) — an intent created while you were the only eligible approver can no longer be self-approved after the org gains a second approver; the decide now fails closed with "another approver is required".
  • AI action tier recalibration (#2691) — file_operations:list, patch scans, and ticket timers drop from Tier 3 (approval required) to Tier 2 (auto-execute + audit). File reads and all file mutations remain Tier 3.
  • Agent event-log messages capped server-side (#2722) — the event-log ingest path now rejects oversized message values instead of trusting agent-side truncation, closing an index-bloat vector from compromised or outdated agents.
  • Dependency CVE patches (#2699, #2694, #2714) — pnpm 10.34.5 (clears 6 HIGH advisories incl. two arbitrary-code-execution CVEs), adm-zip, brace-expansion, shell-quote, fast-uri, fast-xml-parser, sharp/libvips, grpc-go.

Self-hosters are encouraged to upgrade.

Self-Hosting / Upgrade Notes

Upgrade. Bump BREEZE_VERSION to 0.99.0, then:

docker compose pull api web portal && docker compose up -d

(If you build from source, run pnpm install first.)

Database — 3 migrations, applied automatically. They auto-apply on API boot via autoMigrate (unless you set AUTO_MIGRATE=false) and are idempotent. No large-table rewrites: two are instant DDL/policy changes (the quote_recipients table and an RLS policy fix), and the quote backfill (#2711) touches only rows with a NULL block_id or NULL quote_number — self-limiting, and it reports repaired-row counts as WARNINGs in the Postgres log (zero rows on most deployments). Expect a fast boot.

No new required environment variables. Nothing here will refuse to boot.

  • Conditional: if you enable M365_GRAPH_ACTIONS_TOOLS_ENABLED (default off) for the M365 credential reveal (#2693), you must first set APP_ENCRYPTION_KEY_ID alongside your existing APP_ENCRYPTION_KEY — in .env and mapped in the api service's environment: block. Without it the seal guard fails closed and every reveal fails.
  • Recommended: pull the updated docker-compose.yml (#2712). It now threads 36 documented .env variables into the API container that were previously silently inert — Twilio SMS-MFA, Mailgun, SMTP_FROM/SMTP_SECURE, ENABLE_2FA, BREEZE_PLATFORM_ADMINS, IP-allowlist mode, MCP OAuth flags, JWT key rotation, remote-session caps, M365 toggles, BILLING_URL, and more. Old compose files keep working, but setting those vars in .env does nothing until the mapping exists (compose only interpolates vars listed in the environment: block). A CI parity test now guards this class permanently. Four vestigial vars were removed from .env.example (RATE_LIMIT_WINDOW_MS, RATE_LIMIT_MAX_REQUESTS, SESSION_MAX_AGE, ENABLE_API_DOCS — they were dead in code).

Behavior changes & feature flags.

  • Portal quotes fail closed until re-sent (#2679) — quotes sent before v0.99.0 cannot be accepted/declined through the authenticated portal until re-sent (recipient authorization is new and old quotes have no recipient rows).
  • AI tier recalibration (#2691) — three action groups (file_operations:list, patch scans, ticket timers) no longer require approval; they auto-execute with audit.
  • Sole-operator self-approve (#2690) — refused if a second eligible approver was added after the intent was created.
  • Posture report (#2706) — stale (>30 days) firewall/encryption readings score as "unknown", so compliance percentages may shift.
  • Mobile app (#2710) — update to the current build for approver-device registration; old builds get 403 on the legacy path.
  • M365_GRAPH_ACTIONS_TOOLS_ENABLED remains off by default; no other flag defaults changed.

No breaking changes for a standard upgrade — the items above are behavior tightenings with the actions listed.

Full Changelog: v0.98.1...v0.99.0


What's Changed

  • fix(api): extension loader test writes temp dirs to tmpdir, not the repo by @ToddHebebrand in #2654
  • docs(changelog): record namespace reservation + rotation deploy notes by @ToddHebebrand in #2659
  • fix(quotes): keep the PDF section label + column header with their first row by @ToddHebebrand in #2664
  • docs(release): include portal in the standard deploy line by @ToddHebebrand in #2667
  • fix(api): close two Sentry regressions — contextless device_commands writes (#1375) and unnormalized S3 endpoints by @ToddHebebrand in #2668
  • chore(deps): bump the expo-sdk group with 3 updates by @dependabot[bot] in #2669
  • fix(agent): de-flake backup DurationMs assertion, add real timing teeth by @ToddHebebrand in #2681
  • chore(deps): bump the react-native-animation group across 1 directory with 2 updates by @dependabot[bot] in #2670
  • chore(deps): bump react-native-screens from 4.26.1 to 4.26.2 in the mobile group across 1 directory by @dependabot[bot] in #2671
  • chore(deps): bump @types/office-js from 1.0.599 to 1.0.600 in the typescript-tooling group across 1 directory by @dependabot[bot] in #2672
  • chore(deps): bump astro from 7.0.9 to 7.1.2 in the astro group across 1 directory by @dependabot[bot] in #2674
  • chore(deps): bump hono from 4.12.30 to 4.12.31 in the hono group across 1 directory by @dependabot[bot] in #2677
  • chore(deps): bump react-i18next from 17.0.9 to 17.0.10 by @dependabot[bot] in #2678
  • chore(deps): bump @anthropic-ai/sdk from 0.111.0 to 0.112.3 in /e2e-tests by @dependabot[bot] in #2673
  • chore(deps): bump @tanstack/react-query from 5.101.2 to 5.101.3 in the tanstack group across 1 directory by @dependabot[bot] in #2675
  • chore(deps): bump the tailwind group across 1 directory with 3 updates by @dependabot[bot] in #2676
  • fix(deps): bound the @xmldom/xmldom security override to 0.8.x — it was breaking expo prebuild by @ToddHebebrand in #2682
  • fix(mobile): surface approver-registration failure instead of silently capping approvals at L1 by @ToddHebebrand in #2683
  • fix(mobile): declare babel-preset-expo and pin @expo/dom-webview to the SDK 57 range — unblocks the iOS build by @ToddHebebrand in #2688
  • fix(ci): guard Dockerfile workspace-manifest copy scope (#2661) by @ToddHebebrand in #2689
  • test(ai): bind tierConfig.ts + docs to the real guardrail tier tables (#2686) by @ToddHebebrand in #2692
  • feat(ai): inline Touch ID self-approve for Tier-3 AI actions + tier recalibration by @ToddHebebrand in #2691
  • fix(security): remediate 2026-07-20 security review by @ToddHebebrand in #2679
  • fix(approvals): re-derive sole-operator status at decide time (#2685) by @ToddHebebrand in #2690
  • fix(web): gate DeviceCard (grid view) menu actions (#2488) by @bdunncompany in #2630
  • fix(deps): clear main Trivy red — bump brace-expansion + shell-quote past their CVEs by @ToddHebebrand in #2694
  • fix(security): patch pnpm CVEs (10.34.5) + adm-zip HIGH, clear Trivy image scan by @ToddHebebrand in #2699
  • chore(deps): bump cloud.google.com/go/storage from 1.63.1 to 1.64.0 in /agent by @dependabot[bot] in #2704
  • chore(deps): bump github.com/pion/webrtc/v4 from 4.2.16 to 4.2.17 in /agent by @dependabot[bot] in #2703
  • chore(deps): bump github.com/gosnmp/gosnmp from 1.43.2 to 1.44.0 in /agent by @dependabot[bot] in #2702
  • chore(deps): bump google.golang.org/api from 0.288.0 to 0.289.0 in /agent by @dependabot[bot] in #2701
  • chore(deps): bump the aws-sdk group in /agent with 2 updates by @dependabot[bot] in #2700
  • feat: one-time reveal of M365 reset-password temporary credential by @ToddHebebrand in #2693
  • fix(partner-api): segment-aware export secret detector (stop withholding inventory records) by @ToddHebebrand in #2695
  • feat(auth): admin MFA reset for lost-authenticator recovery by @ToddHebebrand in #2696
  • chore(deps): bump recharts from 2.15.4 to 3.9.2 by @dependabot[bot] in #2580
  • fix(software): deploy built-in Huntress package (partner-scoped catalog reads) by @ToddHebebrand in #2705
  • fix(reports): don't score stale firewall/encryption as current in Security & Compliance Posture by @ToddHebebrand in #2706
  • docs: reorganize plans/specs/docs into domain folders + contributor workflow by @ToddHebebrand in #2708
  • fix(mcp-oauth): accept http://localhost redirect_uri so Claude Code CLI can register by @ToddHebebrand in #2709
  • feat(auth): grant-based approver-device registration (#2707) by @ToddHebebrand in #2710
  • fix(security): clear Trivy HIGH findings from CVE DB refresh by @ToddHebebrand in #2714
  • fix(db): restore shipped migration bytes edited by the docs reorg (release blocker) by @ToddHebebrand in #2717
  • ci: enforce shipped-migration immutability against the latest release tag by @ToddHebebrand in #2718
  • fix(deploy): thread documented .env vars into api container + add parity guard by @ToddHebebrand in #2712
  • feat(quotes): editor UX overhaul + orphan-line fix (backfill, clone re-parent, unassigned-lines surface) by @ToddHebebrand in #2711
  • feat(dashboard): rebuild home dashboard — accurate counts, posture cards, honest failure states by @ToddHebebrand in #2719
  • fix(vulnerabilities): honor the org selector on fleet endpoints by @ToddHebebrand in #2715
  • fix(api): cap agent event-log message length server-side (#2642) by @bdunncompany in #2722

Full Changelog: v0.98.1...v0.99.0