- Fix frontend update functionality with proper channel switching
- Add channel-aware version detection in footer
- Implement proper development build versioning using git describe
- Fix footer spacing issue with update indicators
- Add quick channel switch buttons with immediate updates
- Prevent update notifications for development builds ahead of releases
- Fix release URL linking to correct channel-specific releases
- Improve error handling and rate limiting for GitHub API calls
The update system now properly:
- Detects development builds vs release builds
- Shows channel-appropriate updates only
- Handles stable/RC channel switching seamlessly
- Provides proper version semantics for development environments
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add support for ?channel=stable or ?channel=rc query parameter to /api/version
- This enables frontend channel switching preview functionality
- Aligns /api/version behavior with /api/updates/check endpoint
- Fixes issue where channel switching in settings UI didn't work properly
- Fix missing analysis property in versionUtils error fallbacks
- Improve tarball creation to always include install-pulse.sh
- Add verification step to ensure install script is included in releases
- This resolves the issue where releases were missing the installer script
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Only show RC updates when the latest RC version is actually newer than
the current version, not just when they are different. This prevents
showing 'update available' when current RC (e.g., rc3) is newer than
the latest GitHub RC (e.g., rc1).
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add stable-release.yml GitHub Action workflow
- Enhance versionUtils.js with semantic commit analysis
- Update RELEASE_GUIDE.md with automated workflow documentation
- Support automatic version bumping and release creation
- Include multi-arch Docker builds and changelog generation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Handle 403 rate limit errors without throwing 500 server errors
- Return informative response when rate limited instead of crashing
- Fix variable scope issue in error handling
- Prevent Settings modal from breaking when GitHub API is unavailable
- Add specific error messages for rate limits, 404s, and network issues
This resolves the Settings modal 500 errors when GitHub API rate limits
are exceeded, providing a better user experience.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Create versionUtils.js for unified version logic across components
- Update UpdateManager to use centralized getCurrentVersion()
- Update /api/version endpoint to use centralized logic
- Ensures consistent version calculation between update checks and version display
- Prevents version fragmentation between different system components
This resolves the issue where Settings modal showed inconsistent RC versions
by ensuring both the current version display and update checking use the
same dynamic git-based calculation.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Remove escalation functionality from alert management system including:
- Remove escalationTime configuration from alert rules
- Remove escalation checking and processing logic
- Remove escalation UI indicators and notifications
- Clean up escalation-related state management
- Remove escalation socket events and handlers
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add robust error handling to version API endpoint with fallback responses
- Fix duplicate event listeners on notification toggles by cloning elements
- Update toggle configuration keys to GLOBAL_EMAIL_ENABLED/GLOBAL_WEBHOOK_ENABLED
- Add debug toggles for troubleshooting notification components
- Remove visual feedback animations to prevent UI flashing
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Eliminate redundant acknowledgements.json file by storing acknowledgement data in active-alerts.json
- Update alert manager to load acknowledgements from active alerts on startup
- Remove acknowledgements.json from hot reload ignore patterns
- Reduce file I/O operations and eliminate data duplication in alert system
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add master enable/disable toggle for entire alert system
- Update config API to support ALERTS_ENABLED setting
- Enhance settings UI with alert system configuration section
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add missing createSafeRuleCopy method to prevent circular references in alert serialization
- Add acknowledgment events to alert history for visibility in recent activity
- Enhance email configuration loading and alert system reliability
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Eliminate all severity classifications (warning, critical, info) to create a simpler, more focused alert system where alerts are treated uniformly.
Changes:
- Remove severity-based logic from server-side alert processing
- Simplify email and webhook notifications to use consistent styling
- Remove severity dropdowns and badges from UI components
- Update alert display to use unified red styling for all alerts
- Eliminate severity-based filtering and escalation logic
- Simplify custom threshold system to single threshold values
- Remove severity validation and defaults from rule creation
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Simplified alert rules: removed warning/critical levels, now one rule per metric type
- Unified alert editing: all rules (built-in and custom) use same modal template
- Enhanced UI: show actual thresholds/conditions in rules list without clicking edit
- Fixed Create Rule button: changed from event listener to direct onclick approach
- Fixed disabled rules visibility: disabled rules now stay in list with toggle off
- Removed redundant labels: eliminated "Enabled/Disabled" badges (toggle shows state)
- Updated alert summary cards: replaced Critical/Warning/Info with Active/Acknowledged/Rules/Status
- Improved UX: consistent editing experience across all alert types
- Cleaned up duplicate code: removed separate modal templates for system vs custom alerts
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed circular reference errors preventing WebSocket communication
- Added alert count badges to all alert rules (system and custom)
- Made global email/webhook toggles act as true master switches
- Fixed email toggle not saving to .env file
- Added proper notification channel indicators for both system and custom alerts
- Fixed system alert enable/disable functionality with correct ID mapping
- Improved alert display clarity:
- Shows actual rule names for custom alerts
- Displays rule conditions to identify which rule triggered
- Removed redundant details button and popup
- Added triggered time and escalation status directly to cards
- Fixed email configuration not displaying in UI
- Made notification checkboxes disable when global settings are off
- Improved UI text clarity (removed confusing 'optional overrides' language)
- Enhanced auto-refresh for real-time alert updates
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed undefined guest.type errors in generateAlertMessage by adding proper null checks
- Separated notification status from alert objects to prevent circular references during serialization
- Added comprehensive error handling with fallback data when alert serialization fails
- Improved alert state management to track notification status separately
- Fixed alert display issues in UI by ensuring proper data structure
- Added debugging helpers for troubleshooting serialization issues
- Cleaned up console logging and removed development artifacts
These changes resolve the "Converting circular structure to JSON" errors that were
preventing alerts from being properly displayed and managed in the UI.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add auto-resolve checkbox option in custom alert creation/editing with clear description
- Remove "Additional Email Recipients" section to simplify email configuration
- Enhance email provider selection with better error handling and password preservation
- Add provider-specific SMTP guidance (Gmail STARTTLS, custom placeholders)
- Improve password field UX with context-aware placeholders based on provider
- Fix WebSocket connectivity by binding server to all interfaces (0.0.0.0)
- Add visual feedback for email save/test operations
Users can now choose between auto-resolving alerts (default) or keeping them active
for manual acknowledgment, providing better control over alert accountability.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Major enhancements to backup monitoring accuracy and user experience:
## Core Fixes
- **Fix timestamp precision loss**: PVE/PBS age filtering now shows correct times (17h vs incorrect 36h)
- **Server-side deduplication**: Shared storage backups no longer counted multiple times
- **Client-side deduplication**: Calendar drill-down shows each guest only once per date
- **Clean UI**: Removed redundant backup count numbers when type badges are shown
## Technical Implementation
- Added `latestTimes` object with type-specific timestamps to guest data structure
- Implemented `deduplicateStorageBackups()` function using volid-based deduplication
- Enhanced calendar-heatmap processing to merge duplicate guest entries by vmid
- Updated backup detail card to use direct timestamp lookup instead of date aggregation
## Files Modified
- `server/dataFetcher.js`: Added shared storage deduplication logic
- `src/public/js/ui/backups.js`: Enhanced guest data with type-specific latest times
- `src/public/js/ui/backup-detail-card.js`: Fixed age calculation and removed redundant counts
- `src/public/js/ui/calendar-heatmap.js`: Implemented client-side guest deduplication
- `docs/BACKUP_ARCHITECTURE.md`: Documented pragmatic solution approach
## Result
- Accurate backup ages when filtering by PVE/PBS/Snapshots
- No more duplicate counting from shared storage (NFS, Ceph, etc.)
- Clean calendar view with single guest entries per date
- Foundation for future backup system enhancements
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Major Development Environment Improvements
### Integrated Development Mode
- Modified systemd service to use 'npm run dev' for complete development stack
- Concurrently runs both development server and Tailwind CSS watcher
- Automatic CSS rebuilding when Tailwind classes change
- Seamless hot reload for frontend, backend, and CSS changes
### Hot Reload Enhancements
- Always attempt to load chokidar for development convenience
- Enhanced file watcher initialization with better error messaging
- Added debug logging for NODE_ENV detection and chokidar availability
- Improved development experience with real-time change detection
### Development vs Production Distinction
- Development: systemd runs 'npm run dev' with NODE_ENV=development
- Production: installer creates service running 'node server/index.js' with NODE_ENV=production
- Clear separation between development and production environments
- Updated CLAUDE.md with integrated development mode documentation
### UI and Configuration Updates
- Removed DEV branding from title and header (development-specific cleanup)
- Added CLAUDE.md to .gitignore (development reference file)
- Restored proper RC branding for release candidate version
### Development Workflow Optimization
- No more manual 'npm run build:css' commands needed
- Complete hot reload: frontend JS → browser reload, CSS changes → auto-rebuild → browser reload
- Production-ready systemd service management with PolicyKit
- Optimal development experience with automatic toolchain management
This creates a seamless development environment where any change to Tailwind classes
automatically rebuilds CSS and triggers browser reload, while maintaining proper
production deployment through the existing install script.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Update PBS connectivity check endpoint for better compatibility
- Make alert checking asynchronous to prevent blocking
- Update test expectations for webhook error messages with retry counts
- Enhance alerts handler with better event listeners and error handling
- Improve PBS UI by replacing symbols with clearer text labels
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Major Improvements
### Alert Threshold Calculation Fix
- Fixed compound threshold rules to properly calculate disk usage percentages
- Resolved issue where raw bytes were compared against percentage thresholds
- Consistent behavior between single-metric and compound threshold rules
### Enhanced Debugging & Error Handling
- Added environment-controlled debug logging with ALERT_DEBUG=true
- Comprehensive error messages with specific property validation context
- New /api/alerts/debug endpoint for threshold evaluation testing
- Clear feedback on missing/invalid threshold properties
### Alert Management UI Fixes
- Fixed alert editing to properly pre-populate form values
- Support for both old (type/value) and new (metric/threshold) property formats
- Unified threshold population logic for dashboard presets and existing alerts
- Clean alert message display with correct percentage values
### Hot Reload Improvements
- Excluded runtime data files (alert-rules.json, acknowledgements.json) from hot reload
- Prevents page refreshes when creating/deleting alerts
- Better development experience with targeted file watching
### Code Quality & Maintainability
- Consistent property naming throughout (metric/condition/threshold)
- Input validation with descriptive error messages
- Backward compatibility maintained for existing alerts
- Production-ready with clean, optimized code
## Technical Changes
- Server: Enhanced AlertManager validation and evaluation logic
- Client: Fixed threshold population and property mapping
- Debug: Environment-based logging and API endpoints
- DevEx: Improved hot reload exclusions
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fixed evaluateThresholdCondition() to calculate disk percentage using (disk / maxdisk) * 100
- Fixed getThresholdCurrentValue() to display disk percentage correctly in alerts
- Updated formatCompoundThresholdMessage() to pass guest parameter for accurate calculations
- Now compound threshold rules properly compare percentage values against percentage thresholds
- Resolves issue where 78% disk threshold wasn't triggering due to comparing raw bytes vs percentage
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Implement resilient DNS resolution for API calls with fallback mechanisms
- Add compound threshold alert rules with multi-metric evaluation
- Enable immediate alert evaluation when rules are enabled
- Add alert rules file watching for dynamic configuration updates
- Improve alert state management with proper resolution handling
- Include comprehensive testing and documentation for DNS features
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Enhanced refreshRules() to trigger immediate evaluation of current state
- Added evaluateCurrentState() method to check existing conditions without duration delays
- Added API endpoints for alert evaluation and rule reloading
- Improved alert management modal with better status loading and configuration
- Fixed async handling in config API for rule refreshing
- Added immediate alert creation for down alerts when re-enabling rules
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
The smart cluster handling prevented endpoint duplication but individual
node resource fetching was still sequential and blocking. This adds:
- Promise.allSettled for parallel node resource fetching
- 8-second timeouts on individual resource requests
- Proper error handling for failed resources
This should completely eliminate dashboard freezes when nodes go offline.
Addresses issue #104 follow-up
- Add visual threshold-to-alert conversion feature in dashboard filtering UI
- Implement compound threshold rules that support multiple metrics with AND logic
- Enhance existing AlertManager to handle both single-metric and compound threshold rules
- Add dynamic alert rule creation modal with step-by-step configuration
- Implement comprehensive rule management (view, enable/disable, delete)
- Add real-time evaluation of compound threshold rules in main metrics processing loop
- Create compound rule API endpoints integrated with existing alerts system
- Add smart threshold summary display and button state management
- Support email/webhook notifications for compound threshold rule violations
- Maintain backward compatibility with existing single-metric alert rules
This bridges the gap between visual filtering and automated alerting, allowing users to
convert their threshold filtering criteria into persistent monitoring rules with a
seamless user experience.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add step-by-step email configuration with provider presets (Gmail, Outlook, Yahoo)
- Implement auto-detection of email providers based on email domain
- Provide provider-specific setup instructions and App Password guidance
- Add collapsible advanced settings to hide technical SMTP details
- Fix SSL/TLS configuration for Gmail (use STARTTLS instead of SSL)
- Improve SMTP transporter configuration with requireTLS and better error handling
- Add comprehensive provider help sections with clear instructions
- Fix configuration persistence by properly including SMTP settings in config API
- Enhance security by not exposing passwords in API responses
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix host/port field confusion with clear guidance text
- Implement form data preservation between PVE and PBS tab switches
- Add smart URL parsing to extract hostnames from full URLs
- Ensure save button captures configuration from all tabs
- Improve configuration loading to handle both structured and flat formats
- Fix Docker config directory detection logic
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add cluster membership detection to identify same-cluster endpoints
- Implement endpoint prioritization with failover support
- Eliminate data duplication by using only one endpoint per cluster
- Maintain backward compatibility with existing configurations
- Add caching for cluster membership detection (5min TTL)
This resolves the core issue where users configure multiple endpoints
for the same cluster, causing blocking timeouts and data duplication.
Now only the primary endpoint is used, with automatic failover to
backup endpoints when needed.
Addresses issue #104
- Updated /api/version endpoint to use UpdateManager instead of hardcoded stable-only checks
- Removed obsolete checkLatestVersion() function that only checked stable releases
- Footer now correctly shows updates only for user's selected channel (stable or RC)
- Eliminates false "update available" notifications when RC versions exist but user is on stable channel
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Removed UPDATE_CHANNEL from main .env file to eliminate conflicts with frontend settings management
- Updated configLoader.js to read UPDATE_CHANNEL from config/.env (where frontend saves settings) instead of main .env
- Now defaults to 'stable' channel when no frontend setting is configured
- Frontend can fully manage update channel preference without .env conflicts
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add polkit rule for sudoless service management
- Improve update manager with multi-strategy restart approach
- Fix npm dependency conflicts in update process
- Add comprehensive test suite for update system
- Enhance frontend update progress tracking
- Update install script with automatic polkit setup
- Skip npm install since release tarballs already include node_modules
- Better validation of update package structure
- Improved error handling and logging
- Use Node.js fs operations instead of shell commands for better cross-platform support
This should eliminate npm errors during auto-update process.
- Changed Promise.all to Promise.allSettled to prevent one offline endpoint from blocking all others
- Added intelligent node deduplication that prefers online nodes with fresh data
- Implemented 5-second timeout for discovery calls to fail fast
- Added 1-minute cache to preserve node state during brief outages
- Fixed transition states to avoid "red dot with online status" issue
This addresses issue #104 where:
- Dashboard would freeze when primary node went offline
- Nodes were duplicated when multiple endpoints pointed to same cluster
- Dashboard stopped updating during node reboots
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add webhook configuration to structured config response in configApi
- Update settings UI to properly display webhook enabled state
- Fix Discord webhook 400 errors by sending platform-specific payloads
- Detect webhook type (Discord/Slack) and send appropriate format
- Preserve webhook settings when saving configuration
- Update both test webhook and alert webhook sending logic
Fixes#119🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Fixes two webhook-related problems reported in issue #119:
- Webhook checkbox not persisting after save due to config not being included in API response
- 400 errors during webhook testing due to incorrect form data binding
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Add robust timestamp validation with getValidTimestamp() method
- Handle invalid timestamp values gracefully with fallback to current time
- Prevent RangeError when Date constructor receives invalid values
- Add comprehensive AlertManager test suite with 12 test cases
- Test webhook payload structure, timestamp handling, and error scenarios
- Verify Discord/Slack compatibility and email notification fixes
- Increase AlertManager test coverage from 0% to 40.11%
Fixes#114 completely with bulletproof timestamp handling
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
- Fix RangeError in AlertManager by using correct timestamp fields (triggeredAt/lastUpdate) instead of non-existent alert.timestamp
- Replace Promise.resolve() with requestAnimationFrame() for better scroll position restoration timing
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
Enhanced backup health status calculations with more accurate age-based
categorization and improved UI filtering. Added comprehensive backup data
validation test suite and ground truth testing framework.
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>
## Test Coverage Achievements
- **apiClients.js**: 100% statement coverage ✅
- **configLoader.js**: 100% statement coverage ✅
- **pbsUtils.js**: 100% statement coverage ✅
- **Overall coverage**: 77.97% (up from 77.83%)
- **All tests passing**: 116/116 ✅
## Key Improvements
### Jest Configuration
- Fix Jest configuration to use V8 coverage provider instead of Babel
- Resolve Babel/Istanbul errors that were preventing tests from running
- Add `testEnvironment: "node"` and `coverageProvider: "v8"` settings
### Test Coverage Enhancements
- **pbsUtils.js**: Export and test `categorizeAndCountTasks` function for complete coverage
- **configLoader.js**: Add test for config directory loading path
- **dataFetcher.js**: Add defensive null checking for API clients and comprehensive test fixes
- **All test files**: Update test expectations to match current application behavior
### Test Reliability
- Fix config tests to match new setup mode behavior instead of error throwing
- Update dataFetcher tests for correct API call sequences and error messages
- Add proper mock data for backup functionality testing
- Resolve test flakiness with proper async handling
### Code Quality
- Add null safety check in dataFetcher for missing API client endpoints
- Export previously internal function for better testability
- Maintain backward compatibility while improving robustness
## Files Changed
- `package.json`: Update Jest configuration
- `server/pbsUtils.js`: Export categorizeAndCountTasks function
- `server/dataFetcher.js`: Add null client validation
- `server/tests/*.test.js`: Comprehensive test updates and additions
🤖 Generated with [Claude Code](https://claude.ai/code)
Co-Authored-By: Claude <noreply@anthropic.com>