Phase 9 Stabilization — Release Notes
What changed in v2.1.0.0. Phase 9 is a polish-and-fix release that follows the Phase 8 (v2.0.0.0) Foundation Features drop — no new endpoints, no schema migrations, focused on UX, a high-impact bug fix, and bundle / test-coverage cleanups.
What's new in v2.1.0.0
- Scrollable nav and action bars — the top main menu, Settings tabs, and the Hosts-page action bar now pan with prev/next arrows when the viewport is too narrow to show every item, and labels like OS Upgrades never break across two lines.
- Report branding fix — Phase 8.7 introduced org branding for generated reports, but the OSS report endpoint was constructing the Pro+ generators without the ORM models reference, which silently disabled the branding lookup at render time. Reports now carry the configured logo, company name, and header text as designed.
- Frontend bundle split — the Vite build now splits vendor code into discrete chunks (React, MUI core, MUI DataGrid, MUI Charts, MUI Icons, i18next, axios, react-icons, Emotion). The main app chunk dropped from roughly 829 KB to 571 KB, and the build no longer trips the 700 KB chunk-size warning.
- Test-coverage push — 83 new endpoint-coverage tests added for previously thin areas (diagnostics, host account management, antivirus status / defaults, firewall status, third-party repos, user preferences, reports, secrets, Graylog integration, scripts, host monitoring, OpenTelemetry, packages-operations, queue, host hostname, host Graylog).
- Lint / scan clean — Pylint 10.00/10, ESLint 0 errors, SonarQube scan passes. No skipped tests in the suite.
UI: Scrollable Navigation
Three places previously wrapped or hid items when the viewport got narrow:
- Top main menu (Dashboard / Hosts / Updates / OS Upgrades / ...) — items used to wrap mid-label (e.g. OS Upgrades would split across two lines). The menu is now wrapped in a
ScrollableNavListthat keeps every label on one line and exposes left/right scroll arrows when overflow occurs. - Settings tabs (Integrations / Access Groups / Update Profiles / ...) — the MUI Tabs component is now configured with
variant="scrollable" scrollButtons="auto" allowScrollButtonsMobile, matching the in-app HostDetail tab strip. - Hosts-page action bar (Approve Selected / Reboot / Update Agent / ...) — the bottom button row now uses
ScrollableButtonBar, which forceswhite-space: nowrapon everyMuiButtonchild and shows MUI-styled scroll arrows on overflow.
Behavior is identical across desktop and mobile: arrows hide when the row fits, appear with a fade when it doesn't, and the focus order skips hidden arrows so keyboard navigation stays clean.
Bug fix: Report branding now appears on generated reports
If you uploaded a logo or saved a company name under Settings → Report Branding after Phase 8.7 shipped and didn't see it on subsequent reports, this is the fix. Background:
- Phase 8.7's Pro+
reporting_enginelooks up theReportBrandingsingleton via the ORM at render time, which requires it to receive themodelsmodule from the OSS endpoint code that constructs the generators. - The OSS endpoint code (
backend/api/reports/endpoints.py) was instantiatingHtmlReportGeneratorImpl,HostsReportGeneratorImpl, andUsersReportGeneratorImplwithout passingmodels=, so the engine's branding lookup silently no-op'd. - v2.1.0.0 passes
models=modelsto all three generator constructors. Both the/view/...(HTML) and/generate/...(PDF) endpoints now render with branding when a row exists inreport_branding.
No action required for upgraders. Existing branding rows render automatically after upgrade. If you previously worked around the issue by re-uploading the logo, you can remove the duplicate row with the existing Delete Logo action.
Bug fix: Audit-log report used the wrong generator
A latent bug in the same endpoint module routed GET /api/reports/generate/audit-log to HostsReportGeneratorImpl.generate_audit_log_report, which doesn't exist. The route now correctly calls UsersReportGeneratorImpl.generate_audit_log_report. The HTML /view/audit-log path was unaffected.
Performance: Frontend bundle
The Vite config (frontend/vite.config.ts) now uses an id-based manualChunks function that aggressively splits anything in node_modules into discrete vendor buckets:
vendor-react— React, ReactDOM, React Routervendor-mui-data-grid— MUI X DataGridvendor-mui-charts— MUI X Chartsvendor-mui-icons— Material-UI iconsvendor-mui— MUI core (material, system, styled-engine, lab, utils, private-theming)vendor-i18n— i18next + react-i18nextvendor-axios,vendor-icons,vendor-emotionvendor— everything else fromnode_modules
Result: the main index-*.js chunk is now ~571 KB (down from ~829 KB), and re-deploys don't bust caches for unchanged vendor code. The 700 KB chunk-size warning no longer trips during build.
Quality: Lint, tests, SonarQube
The Phase 9 closeout enforces a "100% clean" bar:
- Pylint — 10.00/10 across the whole backend and agent codebase.
- ESLint — 0 errors, 0 warnings on the frontend (
--max-warnings 0). - Backend tests — 4441 pytest cases, all passing. Coverage 76% (the 80% target was aspirational; SonarQube has no hard coverage gate, and the residual gap is concentrated in startup-lifecycle and Graylog/Grafana integration paths that need a live external service to exercise meaningfully).
- Agent tests — 93% coverage, exceeds the 80% Phase 9 target.
- Frontend tests — Vitest passes with the new
ResizeObserverpolyfill insetupTests.ts(jsdom doesn't ship one and the newScrollableNavList/ScrollableButtonBarcomponents instantiate one insideuseEffect). - SonarQube —
make sonarqube-scanreports EXECUTION SUCCESS. No new issues introduced.
Migration notes
None. v2.1.0.0 ships zero schema changes: no new tables, no new columns, no Alembic migrations. The upgrade is a drop-in replacement of the server binaries and frontend bundle. Agents do not need to be re-deployed.
If you are upgrading from a release older than v2.0.0.0, follow the Phase 8 operator guide first to understand the Foundation Features and any Phase 8 schema migrations they introduced.
Troubleshooting
"My report still doesn't show branding after upgrading"
- Verify a branding row exists: Settings → Report Branding should show your logo / company name. If the form is empty, the singleton was never persisted — fill it in and save.
- Confirm the Pro+
reporting_enginemodule loaded successfully. Without it, OSS deployments return402from/api/reports/generate/...and/api/reports/view/...; the branding lookup is a Pro+ codepath. - Hard-refresh your browser cache on the report-viewer page — the in-page
iframecan serve a cached pre-fix HTML. - Re-generate one report and inspect the
audit_logrow: a successful render writes an entry whosedetailsJSON includes{"branding_applied": true}.
"My nav arrows don't appear even though items are clipped"
- The arrows only render when the inner scroller's
scrollWidthexceeds itsclientWidth. If the nav is fitting via word-wrap (older versions), browser zoom can mask overflow — set zoom to 100% and confirm. - Verify your browser supports
ResizeObserver(every supported browser does — IE11 isn't a target). - If the arrows render but never become enabled, check the browser console for CSS errors against
scrollnav/ScrollableButtonBarrules.
"Frontend bundle build is slow / fails"
- The new
manualChunksonly runs at build time and adds <1 s to the Vite build — if it fails, the most common cause is a stalenode_modules;rm -rf frontend/node_modules && npm install. - The chunk-size warning threshold is now 700 KB; any chunk above that warrants investigation but no longer fails the build.
i18n / l10n
All Phase 8 strings remain translated in the 14 supported locales (ar, de, en, es, fr, hi, it, ja, ko, nl, pt, ru, zh_CN, zh_TW). Phase 9 introduced no new operator-visible strings — every change is structural (CSS, scrollable wrappers, bundle config) or under-the-hood (test fixtures, generator constructors).
Deferred to Phase 10
- External penetration test — vendor engagement; carried over from Phase 7 / Phase 8 as a budget item, not a missed deliverable.
- Backend coverage from 76% → 80% — the residual gap is concentrated in startup lifecycle and Graylog / Grafana integration code that needs a live external service in CI to exercise; addressing that requires the integration-tests harness work tracked under Phase 10 stabilization.
- Pro+ Enterprise-tier modules (virtualization_engine, fleet provisioning) — Phase 10 scope.