- Remove unused findAlertByID helper and its min dependency from update_alerts_test.go
- Remove redundant negative zero test case from utility_test.go (-0.0 == 0.0 in Go)
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
- 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
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
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
The findMatchingHostAgent function now uses the proper linkedHostAgentId
relationship from the backend state, falling back to hostname matching only
if no linked agent is found. This fixes the 'Agent required' badge showing
incorrectly when agents are running and collecting data.
- Separated metrics collection into internal/dockeragent/collect.go
- Added agent self-update pre-flight check (--self-test)
- Implemented signed binary verification with key rotation for updates
- Added batch update support to frontend with parallel processing
- Cleaned up agent.go and added startup cleanup for backup containers
- Updated documentation for Docker features and agent security
When returning legacy arrays directly from store state, the createMemo
wouldn't notify dependents because the same array reference was returned
even when its contents changed (via reconcile). The spread operator
creates a new array reference each time, ensuring downstream memos
like sortedHosts() properly re-run.
This is a defense-in-depth fix complementing commit f5c0af77 which
fixed HostRow destructuring. Together these ensure reliable real-time
updates on the Hosts page.
Related to #949
- Add temperature unit preference in Settings > General
- Store preference in localStorage (temperatureUnit: 'celsius' | 'fahrenheit')
- Create formatTemperature() utility that respects the preference
- Update all temperature displays across the UI:
- TemperatureGauge component
- HostsOverview page (sensors, disk temps)
- DiskList (SMART temperatures)
- ThresholdSlider
- ThresholdBadge
- ThresholdsTable
- ProxmoxNodesSection
- NodeSummaryTable tooltips
- Alert formatters
The SMART disk temperature data was being collected by the agent but not
passed through to the frontend. Fixed by:
1. Added SMART field to HostSensorSummaryFrontend and created
HostDiskSMARTFrontend type in models_frontend.go
2. Updated hostSensorSummaryToFrontend() in converters.go to include
SMART data conversion
3. Added HostDiskSMART interface to frontend TypeScript types
4. Updated HostTemperatureCell to display disk temperatures in tooltip
with a 'Disk Temperatures' section and fallback to SMART temps when
no CPU/sensor temps are available
Fixed a critical reactivity bug in HostsOverview.tsx where the HostRow
component was destructuring props.host in the function body. In SolidJS,
this breaks reactivity because the destructured value is a static snapshot
captured at component creation time.
Changes:
- Removed 'const { host } = props' destructuring in HostRow
- Changed all 'host.' references to 'props.host.' to maintain reactivity
- Converted cpuPercent and diskStats to reactive getters (functions)
- Added documentation comment explaining why destructuring breaks reactivity
This fixes Issue #949 where CPU, memory, and disk values on the Hosts
page would stay stale until manual page refresh.
Related to #949
- Add Undismiss() method to FindingsStore to revert dismissed findings
- Include all dismissed findings in GetSuppressionRules() (not just suppressed)
- Add DismissedReason field to SuppressionRule struct
- Update DeleteSuppressionRule to handle dismissed (non-suppressed) findings
- Update frontend to show dismissal type badges (Suppressed/Expected/Noted)
- Change 'Delete' button to 'Reactivate' for dismissed findings
Related to #950
Docker deployments with custom port mappings would show incorrect URLs
in email alerts because the auto-detection couldn't determine the
external port.
Added a "Public URL" setting in Settings > Network that allows users
to configure the dashboard URL used in email notifications.
- Added publicURL field to SystemSettings (persistence.go)
- Load/save publicURL in system settings handler
- Apply publicURL to notification manager on change
- Added UI input in NetworkSettingsPanel
- Shows env override warning if PULSE_PUBLIC_URL is set
Related to #944
The GuestURL field was missing from NodeFrontend and its converter,
causing configured Guest URLs to be ignored when clicking on cluster
node names. The frontend would fall back to the auto-detected IP
instead of using the user-configured Guest URL.
Related to #940
The port field would immediately jump back to 587 when trying to clear
it because parseInt("") returns NaN, and NaN || 587 becomes 587.
Now the field allows empty values while typing, and only applies the
default (587) when the field loses focus with an invalid value.
Related to #935
TLS and STARTTLS are mutually exclusive encryption methods:
- TLS (port 465): Implicit encryption from connection start
- STARTTLS (port 587): Starts unencrypted, upgrades to TLS
- None (port 25): No encryption
Having both as independent checkboxes allowed invalid configurations.
Now uses a single dropdown with the three options.
Related to #936
- Add GHCR (GitHub Container Registry) token support for public images
- Clean up dockerUpdateFirstSeen tracking when containers are removed
- Improve UpdateIcon tooltip to show digest info
- Add cursor-help to indicate hoverable tooltip
Show the actual update commands with copy buttons for Docker installations,
making it easier for Docker users to update. Includes both docker run and
docker-compose variants.
This addresses audit finding that Docker updates need better documentation
since they can't auto-update like LXC/systemd deployments.
- Add DELETE /api/agents/unregister endpoint for agent self-unregistration
- Agent now unregisters itself from Pulse server when uninstalled
- Add clarifying note in UnifiedAgents explaining linked agents behavior
- Linked agents are managed via their PVE node but this is now explained in UI
- Add LastSeen field to HostAgent model for better agent status tracking
- Add /api/agents/host/uninstall endpoint for agent self-unregistration
- Update install.sh to notify server during --uninstall (reads agent ID from disk)
- Update install.ps1 with same logic for Windows
- Update frontend uninstall command to include URL/token flags
This ensures that when an agent is uninstalled, the host record is
immediately removed from Pulse and any linked PVE nodes have their
+Agent badge cleared.
Add ?kiosk=1 URL parameter to hide the filter panel and section nav
for a cleaner dashboard view. Useful for dedicated LCD displays or
wallboard setups.
Related to #917
- Implement compact mobile navigation with label truncation on xs screens
- Optimize Alerts Overview with tighter spacing and better description truncation
- Enhance Storage table mobile view: consolidate Shared column, use StatusDots, and increase bar thickness
- Increase Node Summary table row height and column min-widths for readability
- Add xs (400px) breakpoint for granular mobile styling
- Fix Storage.tsx using number priorities instead of string literals
- Move husky configuration to repository root for proper git hook support
- Add package.json/lock.json to root (un-ignore in .gitignore)
- Configure pre-push hook to run type-check before push
Users who accumulated AI findings before the patrol-without-AI bug was
fixed (24c4bb0b) could not dismiss them because the AI Insights tab
and Clear All button were only visible when patrol was enabled.
Now the AI Insights tab and Clear All button are visible whenever there
are findings to clear, even if AI/patrol is not enabled.
Related to #885
Adds husky with a pre-push hook that runs type-check before allowing
pushes. This catches the TypeScript errors locally that were causing
repeated CI failures and email spam.
Skip with: git push --no-verify
- Removed redundant 'Needs Backup' toggle from filter bar
- Problems filter already includes backup issues (stale, critical, never)
- Reduces UI clutter while preserving functionality
- Also includes user's lint fixes for Backups tests
- Remove unused setUseRelativeTime in UnifiedBackups.tsx (TS6133)
- Remove unused testing-library imports in PBSEnhancementBanner.test.ts (TS6133)
- Fix type comparison in test by using union type instead of 'as const' (TS2367)