Skip to content

fix: OS updates UX improvements — merged packages view, hold/unhold, modal accessibility - #25

Merged
sarg3nt merged 12 commits into
mainfrom
fix/os-updates-bugs
Mar 9, 2026
Merged

fix: OS updates UX improvements — merged packages view, hold/unhold, modal accessibility#25
sarg3nt merged 12 commits into
mainfrom
fix/os-updates-bugs

Conversation

@sarg3nt

@sarg3nt sarg3nt commented Mar 8, 2026

Copy link
Copy Markdown
Owner

Summary

  • Merged OS Packages view: Combined Available Updates and Installed Packages into a single section with an Updates/All Packages filter dropdown. Page load fetches only the upgradable list (fast); full installed list is lazy-loaded on demand.
  • Hold/Unhold packages: Added held badge in the grid, Unhold action button, and full hold/unhold API support across agent and dashboard.
  • Available Version column: Shows current version in muted text when up to date; green when an update exists.
  • Removed Revert feature: Removed Revert button and all related code — older versions are not reliably available in standard apt repos. Use snapshots instead.
  • Modal accessibility: Added Escape key handler for all modals app-wide (OS updates + HAProxy editor). Primary action/close button is focused when a modal opens. Enter key submits confirm modals.

Test Plan

  • OS Packages defaults to Updates view on page load (fast — only upgradable packages fetched)
  • Switching to All Packages lazy-loads full list (spinner visible briefly)
  • Switching back to Updates uses cached upgradable list (no re-fetch)
  • Available Version shows green version when update exists; muted current version otherwise
  • Hold a package — held badge appears, Unhold button replaces Remove in actions
  • Unhold a package — badge disappears, normal state restored
  • Press Escape to close any open modal
  • Tab to buttons in modals; primary button is pre-focused; Enter activates it
  • HAProxy editor: Escape closes backups, validation, marker-error, save-reason, and snippets modals

Closes #18

🤖 Generated with Claude Code

sarg3nt and others added 4 commits March 2, 2026 09:59
- Implemented a new JavaScript utility to enforce character limits on input fields and textareas.
- Added visual feedback with a character counter that changes color based on proximity to the limit.
- Integrated the utility to initialize on DOMContentLoaded.

refactor: overhaul toast notification system

- Enhanced the toast notification system with new features including dismissible toasts, custom buttons, and progress bars.
- Introduced a more flexible API for showing toasts with options for duration and persistence.
- Improved styling and structure for better user experience and maintainability.
- Added drag-to-dismiss functionality and ensured unique IDs for each toast.
- Implemented comprehensive tests for the toast library to ensure reliability.

test: add unit tests for toast library functionality

- Created a test suite for the toast library covering various scenarios including creation, dismissal, and custom button functionality.
- Ensured that the toast system behaves correctly under different conditions and configurations.
… add reboot state management and polling; enhance package upgrade/uninstall functionality for pip and pipx; implement live PyPI package lookup; improve UI feedback during operations.
…modal accessibility, and cleanup

- Merge Available Updates and Installed Packages into single OS Packages section with
  Updates/All Packages filter dropdown; lazy-load full package list only when needed
- Add hold/unhold package support with held badge in grid and Unhold action button
- Remove Revert package feature (older versions not reliably available in apt repos)
- Available Version column shows current version in muted text when up to date,
  green when an update exists
- Normalize upgradable package shape for grid so Updates view loads fast (small list)
- Add PageURL to upgradable packages endpoint
- Add Escape key handler for all modals app-wide (OS updates + HAProxy editor)
- Focus primary action/close button when modals open for keyboard navigation
- Enter key submits confirm modal when input field is shown
- Add hold/unhold API routes and handlers (agent + dashboard)
- Remove GetPackageVersions from PackageManager interface and all implementations

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 8, 2026 06:43
Comment thread gearbox-agent/internal/gears/updates/apt_runner.go Fixed
Comment thread gearbox-agent/internal/gears/updates/apt_runner.go Fixed
Comment thread gearbox-agent/internal/gears/updates/pm_apt.go Fixed
Comment thread gearbox-agent/internal/gears/updates/pm_apt.go Fixed
Comment thread gearbox-agent/internal/gears/updates/updates.go Fixed
Comment thread gearbox-agent/internal/gears/updates/updates.go Fixed
Comment thread gearbox-agent/internal/gears/updates/updates.go Fixed
Comment thread gearbox-agent/internal/gears/updates/updates.go Fixed
Comment thread gearbox-agent/internal/gears/updates/updates.go Fixed
Comment thread gearbox-agent/internal/gears/updates/updates.go Fixed

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the OS Updates gear UX and expands underlying package-management capabilities across the dashboard and agent, including new hold/unhold actions, Python tools status, modal accessibility improvements, and richer agent-side operations/logging.

Changes:

  • Reworked toast utilities (new dismissal APIs, options, progress/drag behavior) and added a character-limit helper used across multiple templates.
  • Expanded OS updates + package management APIs/models (installed packages listing, hold/unhold, snapshot preview/restore streaming, persisted update logs; broader distro/package-manager support on the agent).
  • Tightened input length validation across several handlers/templates and adjusted agent operational settings (systemd unit + deploy process).

Reviewed changes

Copilot reviewed 46 out of 46 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
gearbox/static/js/utils/toast.test.html Adds a browser-based test page for the toast utility.
gearbox/static/js/utils/toast.js Rewrites toast system with options, timers/progress bar, drag-to-dismiss, and new public APIs.
gearbox/static/js/utils/char-limit.js Adds a generic char-limit counter utility driven by data-charlimit.
gearbox/static/js/haproxy_config/editor.js Improves modal focus management and adds Escape-to-close for multiple modals.
gearbox/internal/gears/os_updates/handlers.go Updates OS updates page data wiring (Python tools status field).
gearbox/internal/framework/templates/pages/login.templ Adds maxlength constraints to login inputs.
gearbox/internal/framework/templates/pages/haproxy_settings.templ Adds maxlength/data-charlimit constraints to HAProxy server form fields.
gearbox/internal/framework/templates/pages/haproxy_config/modals.templ Adds maxlength/data-charlimit constraints for modal inputs.
gearbox/internal/framework/templates/pages/gears.templ Renames Pipx setting UI to “Python tools” and updates config accessor.
gearbox/internal/framework/templates/pages/alerts.templ Adds maxlength/data-charlimit to action note textareas.
gearbox/internal/framework/templates/pages/alert_rules.templ Adds maxlength/data-charlimit to rule name/description inputs.
gearbox/internal/framework/templates/layouts/base.templ Adjusts Tabulator header filter styling; loads char-limit.js.
gearbox/internal/framework/templates/components/table.templ Adds maxlength to table search input.
gearbox/internal/framework/handler/users.go Adds server-side max-length validation for multiple user/account forms.
gearbox/internal/framework/handler/os_updates_error_test.go Adds tests to prevent duplicated “Failed to …” error prefixes with JS error handling.
gearbox/internal/framework/handler/login.go Adds server-side max-length validation for login credentials.
gearbox/internal/framework/handler/haproxy_config.go Adds server-side max-length validation for HAProxy box create/update.
gearbox/internal/framework/handler/gears.go Updates OS updates config parsing to use ShowPythonTools.
gearbox/internal/framework/database/gears.go Renames config field to ShowPythonTools (keeps json:"show_pipx" for compatibility) and updates defaults.
gearbox/internal/framework/agent/models.go Extends agent API models (installed packages metadata, holds, snapshot preview, update logs, pip status, combined python tools).
gearbox/internal/framework/agent/client_test.go Adds tests for update logs endpoints and improved plain-text HTTP error propagation.
gearbox/internal/framework/agent/client.go Improves error parsing; adds long-running request path; adds multiple OS updates/package mgmt client methods and route updates.
gearbox/cmd/server/main.go Registers new dashboard routes for OS updates (preview, installed packages, hold/unhold, logs, operation status, pip/pypi endpoints).
gearbox-agent/internal/gears/updates/updates_test.go Adds tests for parsing update history logs and command error output preservation.
gearbox-agent/internal/gears/updates/pm_zypper.go Adds zypper package manager implementation.
gearbox-agent/internal/gears/updates/pm_yum.go Adds yum package manager implementation.
gearbox-agent/internal/gears/updates/pm_pacman.go Adds pacman package manager implementation.
gearbox-agent/internal/gears/updates/pm_interface.go Introduces a common PackageManager interface.
gearbox-agent/internal/gears/updates/pm_dnf.go Adds dnf package manager implementation.
gearbox-agent/internal/gears/updates/pm_apt.go Adds apt package manager implementation (history parsing, holds, installed/search, snapshots).
gearbox-agent/internal/gears/updates/pm_apk.go Adds apk package manager implementation.
gearbox-agent/internal/gears/updates/detector.go Detects and caches appropriate package manager based on OS/distro info.
gearbox-agent/internal/gears/updates/apt_runner_test.go Adds tests around streaming runner behavior and log serialization.
gearbox-agent/internal/gears/updates/apt_runner.go Adds persistent update logs + streaming restore support and log capture.
gearbox-agent/internal/gears/security/plugin.go Adds length validation to security gear request fields.
gearbox-agent/internal/framework/events/bus.go Clarifies apt event semantics as “package manager” events (keeps names for compatibility).
gearbox-agent/deploy/gearbox-agent.service Changes runtime environment and relaxes hardening to allow broader system operations.
gearbox-agent/Makefile Deploy now ships the systemd service file and reloads daemon on target host.

Comment thread gearbox/static/js/utils/toast.js
Comment thread gearbox-agent/internal/gears/updates/apt_runner.go
Comment thread gearbox/static/js/utils/toast.test.html Outdated
Comment thread gearbox-agent/deploy/gearbox-agent.service Outdated
sarg3nt and others added 2 commits March 8, 2026 13:03
- toast.js: fix enforceMaxToasts() infinite loop by splicing the toast from
  activeToasts synchronously before calling dismiss(), so the array length
  decreases each iteration
- apt_runner.go: guard GetUpdateLog against panic when id < 8 chars; return
  an error instead of slicing out of bounds
- Remove toast.test.html from static/ (publicly served); test harness should
  not ship in production builds
- Add validateSnapshotID() to reject snapshot IDs containing path separators
  or other unsafe characters, preventing path traversal in updates.go,
  apt_runner.go, and pm_apt.go
- Restore systemd hardening: add ProtectHome=read-only, PrivateTmp=true, and
  ProtectKernelTunables=true while keeping NoNewPrivileges=false and omitting
  ProtectSystem=strict (agent needs write access to /etc and /var)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Remove hardcoded API key from functional_test.go comment; replace
  with <YOUR_API_KEY> placeholder that matches gitleaks allowlist pattern
- Fix runCommandWithOutput to return errors.New(errDetail) instead of
  wrapping the raw exit error — prevents bare "exit status N" suffix
  in user-facing messages and avoids including "Failed to" prefixes
  from systemctl/shutdown output in error responses
- Apply same fix to runPipxCommandWithOutput and runPipCommandWithOutput
- Add "Failed to" prefix exclusion in extractErrorLines fallback path

Fixes TestHandleScheduleReboot, TestHandleConfigureUnattended,
TestAllEndpointsNoFailedToPrefix, TestTriggerUpdateCheck_ErrorIncludesAptOutput,
and TestFullErrorChain_CheckForUpdates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 8, 2026 23:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 45 out of 45 changed files in this pull request and generated 2 comments.

Comment thread gearbox-agent/internal/gears/updates/pm_apt.go
Comment thread gearbox-agent/internal/gears/updates/detector.go Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 45 out of 45 changed files in this pull request and generated 1 comment.

Comment thread gearbox-agent/internal/gears/updates/apt_runner.go
Copilot AI review requested due to automatic review settings March 9, 2026 00:37

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 48 out of 48 changed files in this pull request and generated 1 comment.

Comment thread gearbox/static/js/utils/char-limit.js Outdated
sarg3nt and others added 2 commits March 8, 2026 17:44
- Add isValidPackageName() validation to HoldPackage and UnholdPackage
  in pm_apt.go, consistent with InstallPackage and RemovePackage
- Fix unsupportedPM.ListHeldPackages() to return errNotSupported instead
  of (nil, nil), making it consistent with all other unsupportedPM stubs
- Log a warning instead of silently ignoring MkdirAll error in NewAptRunner
- Guard initCharLimit against elements not yet in the DOM (no parentElement)
  by returning early if parentElement is nil

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 9, 2026 00:53
Commit 2fdb5ba introduced functional_test.go with an example API key
value in a doc comment (for illustrating how to run the test). It was
not a real credential and has since been replaced with <YOUR_API_KEY>
placeholder, but gitleaks scans the full commit history so the original
commit still triggers the rule. Allowlist the commit SHA explicitly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 50 out of 50 changed files in this pull request and generated 1 comment.

Comment thread gearbox/static/js/utils/char-limit.js
Moving el._charLimitInit = true to after the parentElement guard
prevents elements called before DOM insertion from being permanently
marked as initialized. Now callers can safely retry initCharLimit()
after inserting the element into the DOM.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@sarg3nt
sarg3nt merged commit 0a31b56 into main Mar 9, 2026
21 checks passed
@sarg3nt
sarg3nt deleted the fix/os-updates-bugs branch May 10, 2026 08:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

OS Updates Gear: Bug Fixes, UX Improvements, and Comprehensive Test Suite

3 participants