- Add missing KubernetesChecked field to persistence (data was being lost)
- Fix Duration field to properly convert between ms and nanoseconds
- Add automatic cleanup of stale stream subscribers (memory leak fix)
- Add error tracking for findings persistence with callback support
- Add GetPersistenceStatus() and SetOnSaveError() methods
- Add tests for new error tracking functionality
- Add to DOCKER.md configuration table and new 'Disabling Update Features' section
- Add to CONFIGURATION.md monitoring overrides table
- Clarify difference between disabling update detection vs hiding buttons
Implements PULSE_DISABLE_DOCKER_UPDATE_ACTIONS environment variable and
Settings UI toggle to hide Docker container update buttons while still
allowing update detection. This addresses requests for a 'read-only' mode
in production environments.
Backend:
- Add DisableDockerUpdateActions to SystemSettings and Config structs
- Add environment variable parsing with EnvOverrides tracking
- Expose setting in GET/POST /api/config/system endpoints
- Block update API with 403 when disabled (defense-in-depth)
Frontend:
- Add disableDockerUpdateActions to SystemConfig type
- Create systemSettings store for reactive access to server config
- Add Docker Settings card in Settings → Agents tab with toggle
- Show env lock badge when set via environment variable
UpdateButton improvements:
- Properly handle loading state (disabled + visual indicator)
- Use Solid.js Show components for proper reactivity
- Show read-only UpdateBadge when updates disabled
- Show interactive button when updates enabled
Closes discussion #982
This resolves issues where snapshots/backups persist after deletion if the
Instance field didn't match the ID prefix (due to case changes, name changes, etc).
Now consistent with how VMs, Containers, Storage, etc. are filtered.
Also adds Instance field to BackupTask model for completeness.
Addresses #1009 (refs #991)
This update integrates learned baselines into the heuristic analysis to detect abnormal behavior and records significant events (migrations, restarts, spikes) for correlation analysis. Also fixed syntax errors in Ollama integration tests.
This update integrates learned baselines into the heuristic analysis to detect abnormal behavior and records significant events (migrations, restarts, spikes) for correlation analysis.
- Add persistent volume mounts for Go/npm caches (faster rebuilds)
- Add shell config with helpful aliases and custom prompt
- Add comprehensive devcontainer documentation
- Add pre-commit hooks for Go formatting and linting
- Use go-version-file in CI workflows instead of hardcoded versions
- Simplify docker compose commands with --wait flag
- Add gitignore entries for devcontainer auth files
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Simplify Dockerfile: use golang:1.24 base, install Node via features
- Add proper port forwarding for Pulse (7655 frontend, 7656 API)
- Add Vue Volar extension for frontend development
- Add start-pulse-dev.sh helper script for auto-starting dev server
- Add FRONTEND_DEV_HOST to containerEnv for proper binding
- Add .env.devcontainer to .gitignore (local override file)
- Update frontend dependencies
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add DiskTemperature threshold to ThresholdConfig (default: 55°C trigger, 50°C clear)
- Process host SMART sensor data in CheckHost to generate disk_temperature alerts
- Add 'Disk Temp °C' column to Host Agents thresholds table in UI
- Make temperature tooltip interactive and scrollable to fix overflow issues
- Update AlertThresholds type to include diskTemperature field
Closes: #941
On errors, redirect back to login page with error params instead of
showing plain text error pages. This ensures users see friendly error
messages in the UI.
Related to #1006
Changed OIDC login flow from fetch+JavaScript redirect to direct GET
navigation with server-side HTTP redirect. This guarantees same-window
navigation in all browsers, including Arc which was opening new windows
for JavaScript-driven navigations.
Backend: /api/oidc/login now supports both GET (redirect) and POST (JSON)
Frontend: Simplified to use window.location.href to GET endpoint
Related to #1006
pollGuestSnapshots was reading m.state.VMs and m.state.Containers while
only holding the Monitor's mutex (m.mu), not the State's internal mutex.
This caused a data race where VMs/containers could be modified by another
goroutine while being read, leading to stale or missing snapshot data.
Symptoms: Deleted snapshots persisting in UI, new snapshots not appearing,
only fixable by service restart.
Fix: Use GetSnapshot() which properly acquires State's mutex and returns
a consistent copy of the data.
Related to #991
On systems where Docker compatibility layer obscures Podman (like CoreOS),
the auto-detection can fail. Users can now force the runtime:
--docker-runtime podman
PULSE_DOCKER_RUNTIME=podman
Valid values: auto (default), docker, podman
Related to Discussion #958
Add PULSE_DISABLE_DOCKER_UPDATE_CHECKS environment variable and
--disable-docker-update-checks flag to disable Docker image update
detection. This is useful for:
- Avoiding Docker Hub rate limits
- Users who don't want update notifications in their dashboard
Related to Discussion #982
The /cluster/replication endpoint only returns job configuration (guest,
schedule, source, target), not status data (last_sync, next_sync,
duration, fail_count, state).
This fix enriches each replication job with status from the per-node
endpoint /nodes/{node}/replication/{id}/status to get timing and state
data needed for proper UI display.
Added integration tests to verify:
- Status endpoint is called and data is merged correctly
- Graceful handling when status endpoint fails
Fixes#992
On SELinux-enforcing systems (Fedora, RHEL, CentOS), binaries installed to
non-standard locations need proper security contexts for systemd to execute
them. Without this, systemd fails with 'Permission denied' even when the
binary has correct Unix permissions.
Changes:
- Add restore_selinux_contexts() function to both install scripts
- Uses restorecon (preferred) or chcon (fallback) to set bin_t context
- Only runs when SELinux is detected and enforcing
- Called after binary installation, before systemd service start
Previously, the PULSE_DISK_EXCLUDE environment variable and --disk-exclude
flag only filtered mount points in the hostmetrics collector. This change
extends the exclusion to SMART data collection.
Changes:
- Updated smartctl.CollectLocal() to accept diskExclude patterns
- Added matchesDeviceExclude() for block device pattern matching
- Patterns support: exact match (sda), prefix (nvme*), contains (*cache*)
- Updated hostagent to pass DiskExclude to SMART collector
- Added comprehensive tests for pattern matching
- Updated documentation
Previously, the TemperatureGauge component used hardcoded thresholds
(critical: 80°C, warning: 70°C) for text coloring. Now it uses the
user-configured temperature threshold from alert settings.
Changes:
- Add getTemperatureThreshold() helper to alertsActivation store
- Pass critical/warning props to TemperatureGauge in NodeSummaryTable
- Warning is set to (threshold - 5°C) matching the hysteresis pattern
When running as a unified agent (pulse-agent with --enable-docker), the
Docker module was using a different fallback chain for agent ID than the
host module. In unified mode with empty machineID, the Docker module fell
back to daemonID while the host module fell back to hostname. This caused
the server to reject Docker reports with 'token already in use by agent'
errors because the same API token was bound to different agent IDs.
The fix ensures that in unified mode, the Docker module uses the exact
same fallback chain as the host module: machineID -> hostname. The daemonID
fallback is only used in standalone mode for backward compatibility.
Fixes#985, #986
The runtime stage was copying both amd64 and arm64 pulse binaries to /tmp/,
then selecting one based on TARGETARCH and deleting the rest. Due to Docker's
immutable layers, the deleted binaries were still counted toward image size.
Changed to copy directly using TARGETARCH variable substitution, which only
copies the needed binary for the target architecture.
This saves ~34MB per architecture in the final image.
Note: The agent_runtime stage and /opt/pulse/bin/ download binaries still have
room for optimization, but require more complex changes.
Related to #981
When a powered-off VM is backed up by Proxmox, the alert briefly disappears
as the VM status changes. The previous fix (3830e701) preserved ackState when
alerts were removed, but the cleanup TTL was measured from the acknowledgement
time. For alerts acknowledged > 1 hour ago (common for intentionally powered-off
VMs), the ackState was immediately considered stale and deleted when cleanup ran.
The fix adds an inactiveAt timestamp to track when an alert was removed, and
uses this time for the cleanup TTL instead of the acknowledgement time. This
ensures acknowledgement state is preserved for at least 1 hour after the alert
disappears, regardless of when it was originally acknowledged.
Related to #980
- RAID tests now use /dev/md2 since md0/md1 are skipped for Synology compatibility
- AI handler tests now expect 'AI is not enabled' message after AI gating change
dispatchAlert() now checks if an alert is already acknowledged before sending
notifications. Previously, acknowledged alerts (especially backup-age alerts)
would continue to dispatch notifications every poll cycle because the
acknowledgement check was missing from the dispatch path.
The fix adds an early return in dispatchAlert() when alert.Acknowledged is true,
matching the existing checks for flapping, activation state, and quiet hours.