Commit Graph

641 Commits

Author SHA1 Message Date
rcourtman 7ec012a2e1 feat(pro): expose update_alerts feature and add AI-powered update risk assessment
- Expose FeatureUpdateAlerts in /api/license/features endpoint (was hidden)
- Add 'Update Alerts' label to frontend Pro License panel
- Add AI-powered update risk assessment for Docker container updates
  - Classifies containers by type (auth, web server, database, etc.)
  - Provides context-aware recommendations for update timing
  - Time-based urgency escalation (warning >7d, critical >14d)
- Handle edge cases: nil alerts, empty metadata, float64 pendingHours
- Fix switch case ordering to properly route docker-container-update alerts
- Add comprehensive tests for update analysis (15 new test functions)
2026-01-02 19:21:17 +00:00
rcourtman c577a7d142 chore: update logo to vector SVG 2026-01-02 18:06:27 +00:00
rcourtman 3637184c63 fix(alerts): decouple PBS custom threshold detection from Node defaults. Related to #1017 2026-01-02 17:46:01 +00:00
rcourtman b94b6f89d4 Fix ThresholdsTable tests: correct mocking and assertions for resource rendering and filtering 2026-01-02 17:40:23 +00:00
rcourtman 9f0a5d54aa fix(alerts): prevent PBS thresholds from falling back to Node defaults. Related to #1017 2026-01-02 17:04:15 +00:00
rcourtman 9bdbf2616c chore(tests): remove unused test code and redundant test cases
- 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)
2026-01-02 16:11:09 +00:00
rcourtman 0b0b503919 feat: Enable update checks for Docker environments. Related to #1016 2026-01-02 14:22:40 +00:00
rcourtman 3e6ebd593c fix(alerts): resolve mapping and formatting issues for disk temperature thresholds (#1013) 2026-01-02 11:27:48 +00:00
rcourtman 60220ee161 feat: Add server-wide control to disable Docker update actions
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
2026-01-02 10:29:43 +00:00
rcourtman df1ff42280 fix: Add backup freshness thresholds to UI. Related to #839 2026-01-01 23:06:34 +00:00
rcourtman cb99673b7c Improve devcontainer configuration
- 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>
2026-01-01 19:42:01 +00:00
rcourtman 9abe9c47a2 feat(alerts): add disk temperature alerts for host agents
- 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
2026-01-01 16:31:34 +00:00
rcourtman ee45323312 feat: Allow configuring physical disk polling interval in UI (Related to #1007) 2026-01-01 16:00:28 +00:00
rcourtman 7d12c4a23b fix: Host view temperature color now respects configured thresholds. Related to #984 2026-01-01 15:32:42 +00:00
rcourtman 491f6d13c7 fix: OIDC login now uses server-side redirect for same-window navigation
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
2026-01-01 14:45:23 +00:00
rcourtman f130d6fc60 legal: add terms of service and safety disclaimers for AI features 2026-01-01 12:15:58 +00:00
rcourtman 3a7e26f42f fix: Temperature text color now respects configured thresholds. Related to #984
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
2025-12-31 23:00:36 +00:00
rcourtman dc65b96e6d fix: Improve light theme contrast for low I/O values. Related to #976
Changed text-gray-300 to text-gray-500 for I/O values under 1 MB/s in light mode.
The previous color was barely visible against the white background.
2025-12-30 22:35:39 +00:00
rcourtman 421ddf027a Fix guest URL editing inconsistencies: unify icons and use Portal for popover 2025-12-30 20:09:58 +00:00
rcourtman 0caf39456d fix: Show copy buttons always visible in Updates settings. Fixes #960. Changed from opacity-0 (hover to show) to opacity-60 (always visible, brighten on hover) for better discoverability. 2025-12-30 12:41:24 +00:00
rcourtman d744b6f495 fix: Show unsaved changes warning immediately when typing in Network settings. Fixes #959. Changed Public URL and CORS fields to use onInput instead of onChange for immediate feedback. 2025-12-30 12:36:51 +00:00
rcourtman f855625f65 feat: Add full-width mode toggle for wider views on large monitors. Related to #974 2025-12-30 12:20:44 +00:00
rcourtman a62d7dc78d fix: Improve host agent matching for temperature transport badge. Related to #971
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.
2025-12-30 09:50:40 +00:00
rcourtman 1cbe0691e3 feat(ui): implement alert overrides for backups/snapshots and add unsaved changes warning (fixes #961, fixes #959) 2025-12-30 08:46:48 +00:00
rcourtman b17891fd02 feat(ui): add 'Checking updates...' indicator for Docker hosts 2025-12-30 00:28:10 +00:00
rcourtman 4225f905b0 feat: Add manual Docker update check button. Related to #955 2025-12-29 23:37:05 +00:00
rcourtman 060334375f Fix docker hosts toast usage 2025-12-29 17:26:47 +00:00
rcourtman d07b471e40 Refactor Docker agent: metrics collection, security checks, and batch updates
- 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
2025-12-29 17:20:18 +00:00
rcourtman d38a37fe3d fix: Improve useResourcesAsLegacy reactivity with array spreading
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
2025-12-29 16:27:58 +00:00
rcourtman 0c3ebef312 feat: Add Fahrenheit temperature unit option. Related to #957
- 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
2025-12-29 16:16:30 +00:00
rcourtman d377a5c464 fix: Pass SMART disk temperatures to frontend. Related to #941
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
2025-12-29 15:27:46 +00:00
rcourtman a4611739a9 fix: Hosts page not updating in real-time (SolidJS reactivity bug)
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
2025-12-29 11:45:45 +00:00
rcourtman 545990e48f feat: Allow reverting dismissed AI alerts from suppression rules
- 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
2025-12-29 09:44:36 +00:00
rcourtman 6f794753ee fix: Add Public URL setting for email notifications
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
2025-12-28 16:08:22 +00:00
rcourtman 9f3367da36 fix: Include GuestURL in NodeFrontend for cluster node navigation
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
2025-12-28 14:49:49 +00:00
rcourtman 282b7a73cb fix: Allow deleting all digits in SMTP port field
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
2025-12-28 10:30:56 +00:00
rcourtman ac1cc1e0a9 fix: Change email TLS/STARTTLS to mutually exclusive dropdown
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
2025-12-28 10:28:43 +00:00
rcourtman cf44b0cca6 polish: Improve update detection edge cases and UX
- 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
2025-12-27 18:14:27 +00:00
rcourtman b50872b686 feat: Implement unified update detection system (Phase 1)
Docker container image update detection with full stack implementation:

Backend:
- Add internal/updatedetection package with types, store, registry checker, manager
- Add registry checking to Docker agent (internal/dockeragent/registry.go)
- Add ImageDigest and UpdateStatus fields to container reports
- Add /api/infra-updates API endpoints for querying updates
- Integrate with alert system - fires after 24h of pending updates

Frontend:
- Add UpdateBadge and UpdateIcon components for update indicators
- Add updateStatus to DockerContainer TypeScript interface
- Display blue update badges in Docker unified table image column
- Add 'has:update' search filter support

Features:
- Registry digest comparison for Docker Hub, GHCR, private registries
- Auth token handling for Docker Hub public images
- Caching with 6h TTL (15min for errors)
- Configurable alert delay via UpdateAlertDelayHours (default: 24h)
- Alert metadata includes digests, pending time, image info
2025-12-27 17:58:38 +00:00
rcourtman fc6d6d22d3 ui: enhance Docker update documentation in Settings
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.
2025-12-27 11:13:36 +00:00
rcourtman b27b76ae46 feat: implement agent self-unregistration and UI improvements
- 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
2025-12-26 23:20:55 +00:00
rcourtman 8c440b6f54 feat: notify server during agent uninstallation
- 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.
2025-12-26 22:38:46 +00:00
rcourtman 2dc144f8dd feat: Add kiosk mode for clean dashboard display
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
2025-12-26 18:06:28 +00:00
rcourtman 03d680365c feat(ui): optimize mobile view for Alerts, Storage, and Navigation
- 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
2025-12-26 13:26:21 +00:00
rcourtman 3eedbff6e6 fix(storage): correct column priority types and setup pre-push hook
- 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
2025-12-26 12:21:37 +00:00
rcourtman beb33883b8 fix(storage): add toggleable flag to column definitions
The columns weren't appearing in the ColumnPicker because they
were missing the 'toggleable: true' property.
2025-12-26 11:57:29 +00:00
rcourtman f94c11ca34 fix: Allow clearing AI findings when AI is disabled
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
2025-12-26 11:43:34 +00:00
rcourtman 4d03319566 ci: add pre-push hook to prevent TypeScript CI failures
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
2025-12-26 11:37:37 +00:00
rcourtman c1393fbaa7 refactor(dashboard): merge Needs Backup into Problems filter
- 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
2025-12-26 11:13:41 +00:00
rcourtman 83790a4bfc fix(frontend): resolve TypeScript errors causing CI failures
- 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)
2025-12-26 11:06:42 +00:00