Commit graph

233 commits

Author SHA1 Message Date
rcourtman
bbbb417b01 Prevent token manager auth swap and fix docker agent perms (Related to #740) 2025-11-22 07:18:42 +00:00
rcourtman
91c51689c9 Guard host-agent installs on noexec filesystems (Related to #718) 2025-11-21 23:00:47 +00:00
rcourtman
4e68675e0b Add recovery notifications and grouping controls 2025-11-21 22:07:00 +00:00
rcourtman
30a069dfa6 Add TrueNAS SCALE persistence for host agent (Related to #718) 2025-11-21 10:07:14 +00:00
rcourtman
0adc4e7838 Initialize ObservedValues in Windows installer 2025-11-20 21:01:44 +00:00
rcourtman
516097990a Add sorting controls to Docker resources table
Related to #730
2025-11-20 17:58:19 +00:00
rcourtman
d779328878 Add Apprise test support for notifications
Related to #584
2025-11-20 17:54:20 +00:00
courtmanr@gmail.com
1e229d5f38 Improve login page UI and fix hot-dev script for macOS 2025-11-20 12:21:49 +00:00
courtmanr@gmail.com
1626b0e3ae Fix 'Remember me' label toggle behavior 2025-11-20 11:58:42 +00:00
rcourtman
64c654b330 Fix NodeModal authType typing for type-check 2025-11-20 10:07:22 +00:00
rcourtman
bdcde70b81 Handle host agent overrides in thresholds
Related to #722
2025-11-20 10:02:19 +00:00
rcourtman
f4e2cbca48 Improve token collision handling and installer subnet support 2025-11-20 09:45:36 +00:00
rcourtman
4067b0717a Improve Windows installer arch detection (related to #723) 2025-11-20 09:37:45 +00:00
courtmanr@gmail.com
a39fdc9e99 fix: local dev setup, encryption key generation, and pnpm lockfile 2025-11-19 14:48:09 +00:00
rcourtman
c5ef7684a7 fix: update js-yaml to address CVE-2025-64718 prototype pollution vulnerability 2025-11-18 22:50:07 +00:00
rcourtman
74c2dbfa15 Fix node modal form reset when toggling temperature (#713) 2025-11-18 22:28:49 +00:00
rcourtman
3f46d35a81 feat: make PVE polling interval configurable (related to #467) 2025-11-18 21:30:04 +00:00
rcourtman
2c3f197f63 Gate backups spinner on initial payload only 2025-11-18 16:43:02 +00:00
rcourtman
1d214a1c61 Stop showing indefinite backup spinner with no data 2025-11-18 16:37:10 +00:00
rcourtman
a46ca5052b Fix proxy UI type errors 2025-11-17 14:35:32 +00:00
rcourtman
a479040651 Improve temperature proxy workflow 2025-11-17 14:25:46 +00:00
rcourtman
aa7b7b0922 Set initialDataReceived on first websocket payload 2025-11-16 00:03:04 +00:00
rcourtman
26442beca1 Tie backup loading state to initial data flag 2025-11-15 23:46:20 +00:00
rcourtman
4e9572d5e3 Gate backups spinner on websocket connection 2025-11-15 23:41:38 +00:00
rcourtman
3c1f4c20ae Stop backup page spinner after first state update 2025-11-15 23:31:36 +00:00
rcourtman
e375a21d4b Fix backup UX and proxy config dedupe 2025-11-15 23:26:44 +00:00
rcourtman
de5b314842 Improve temperature proxy control-plane flow 2025-11-15 21:49:51 +00:00
rcourtman
b577a3d464 Fix incorrect upgrade instructions for systemd/bare metal installs
The Settings page was telling systemd/bare metal users to run install.sh
for upgrades, which is wrong - install.sh is for fresh installations only
and does nothing if Pulse is already installed.

Changes:
- Updated upgrade instructions to mention built-in "Install Update" button
- Added correct manual upgrade steps (download tarball, stop service, extract, start)
- Removed misleading "run install.sh" instruction

This fixes a critical UX issue where users would run install.sh and think
nothing happened, when they should either:
1. Use the built-in automatic update feature (Install Update button)
2. Manually download and extract the new binary

Related files:
- frontend-modern/src/components/Settings/Settings.tsx:4052-4072
2025-11-15 13:39:12 +00:00
rcourtman
068c17aad9 Change 'SSH Fallback' to 'Proxy (SSH)' in Capabilities column
The "SSH Fallback" label was confusing to users. Changed to "Proxy (SSH)"
to make it clearer that the proxy is using SSH to collect temperature data
from cluster nodes.

This appears in the Capabilities column on Settings → Nodes when:
- Temperature monitoring is enabled
- Socket proxy is not available/healthy
- HTTPS proxy is not available/reachable
2025-11-15 10:50:48 +00:00
rcourtman
639635a84b Add Docker container name auto-detection to bootstrap UI
- Added DetectDockerContainerName() to detect container name from hostname
- Extended /api/security/status to expose dockerContainerName field
- Updated FirstRunSetup to show actual container name when detected:
  * Before: 'docker exec <container-name> cat /data/.bootstrap_token'
  * After: 'docker exec pulse cat /data/.bootstrap_token'

This reduces friction for users - no need to look up the container name.
Works when Docker container is named (--name flag), falls back to
placeholder for auto-generated container IDs.
2025-11-15 10:45:00 +00:00
rcourtman
ae0481c982 Improve bootstrap token UX with smart environment detection
- Added DetectLXCCTID() to internal/system/container.go to detect Proxmox container ID
- Extended /api/security/status to expose inContainer and lxcCtid fields
- Updated FirstRunSetup to show most relevant command based on detected environment:
  * LXC with CTID: Shows 'pct exec 171 -- cat /etc/pulse/.bootstrap_token'
  * Docker: Shows 'docker exec <container-name> cat /data/.bootstrap_token'
  * Bare metal: Shows 'cat /etc/pulse/.bootstrap_token'
- Collapsed alternative methods behind 'Show other retrieval methods' button

This addresses user feedback that showing all options was overwhelming.
Now users see the command most likely to work for their setup first,
with alternatives hidden but still accessible.
2025-11-15 10:18:59 +00:00
rcourtman
f64344d1da Add Proxmox LXC instructions to bootstrap token screen
When Pulse runs in Docker inside a Proxmox LXC container, users need
specific instructions to retrieve the bootstrap token. Added pct exec
and pct enter commands to the Docker instructions section.

Now shows three scenarios:
1. Direct Docker host: docker exec
2. Kubernetes: kubectl exec
3. Proxmox LXC with Docker: pct exec / pct enter

This makes first-time setup easier for users deploying Pulse in LXC
containers on Proxmox.
2025-11-15 09:56:27 +00:00
rcourtman
20194d9bb7 Add CI build workflow and tighten proxy diagnostics 2025-11-14 13:32:29 +00:00
rcourtman
65fbd72b15 feat: add shared status indicators
Related to #677
2025-11-14 12:42:08 +00:00
rcourtman
1d0d23d237 Related to #710: harden Windows installer arch detection 2025-11-14 10:50:56 +00:00
rcourtman
4f8b807f0c Refine Windows host installer logging (related to #709) 2025-11-13 23:09:22 +00:00
rcourtman
70673c1fdc Improve temperature proxy diagnostics and tests 2025-11-13 22:31:53 +00:00
rcourtman
22f092f941 Add HTTP mode to pulse-sensor-proxy for multi-instance temperature monitoring
This implements HTTP/HTTPS support for pulse-sensor-proxy to enable
temperature monitoring across multiple separate Proxmox instances.

Architecture changes:
- Dual-mode operation: Unix socket (local) + HTTPS (remote)
- Unix socket remains default for security/performance (no breaking change)
- HTTP mode enables temps from external PVE hosts

Backend implementation:
- Add HTTPS server with TLS + Bearer token authentication to sensor-proxy
- Add TemperatureProxyURL and TemperatureProxyToken fields to PVEInstance
- Add HTTP client (internal/tempproxy/http_client.go) for remote proxy calls
- Update temperature collector to prefer HTTP proxy when configured
- Fallback logic: HTTP proxy → Unix socket → direct SSH (if not containerized)

Configuration:
- pulse-sensor-proxy config: http_enabled, http_listen_addr, http_tls_cert/key, http_auth_token
- PVEInstance config: temperature_proxy_url, temperature_proxy_token
- Environment variables: PULSE_SENSOR_PROXY_HTTP_* for all HTTP settings

Security:
- TLS 1.2+ with modern cipher suites
- Constant-time token comparison (timing attack prevention)
- Rate limiting applied to HTTP requests (shared with socket mode)
- Audit logging for all HTTP requests

Next steps:
- Update installer script to support HTTP mode + auto-registration
- Add Pulse API endpoint for proxy registration
- Generate TLS certificates during installation
- Test multi-instance temperature collection

Related to #571 (multi-instance architecture)
2025-11-13 16:13:53 +00:00
rcourtman
c1d076db0c Simplify Remember Me label text
Remove '30 days' from label - most apps just say 'Remember me' without
specifying the duration.
2025-11-13 10:40:53 +00:00
rcourtman
56a7579c99 Add Remember Me feature with sliding session expiration (Related to #707)
Implements a "Remember Me" option that allows users to stay logged in
for 30 days instead of the default 24 hours. This addresses the pain
point of frequent re-authentication in LAN-only environments while
maintaining authentication security.

Backend changes:
- Add rememberMe field to login request handling
- Support variable session durations (24h default, 30d with Remember Me)
- Implement sliding session expiration that extends sessions on each
  authenticated request using the original duration
- Store OriginalDuration in session data for proper sliding window
- Update session cookie MaxAge to match session duration

Frontend changes:
- Add "Remember Me for 30 days" checkbox to login form
- Pass rememberMe flag in login request
- Improve UI with clear duration indication

Key features:
- Sessions extend automatically on each request (sliding window)
- Original duration preserved across session extension
- Backward compatible with existing sessions (legacy sessions work)
- Sessions persist across server restarts

This provides a better user experience for LAN deployments without
compromising security by completely disabling authentication.
2025-11-13 10:37:08 +00:00
rcourtman
bb55144637 Improve update integration diagnostics 2025-11-12 22:27:05 +00:00
rcourtman
88d0aeebdf Ensure alert cooldown persists reliably
Related to #706
2025-11-12 21:52:24 +00:00
rcourtman
3fa7356ff3 Improve auth timeout handling (related to #705) 2025-11-12 21:50:53 +00:00
rcourtman
3b079eeddb Add release dry run workflow and API update integration test 2025-11-12 21:02:52 +00:00
rcourtman
7815b45483 Fix CSRF token validation failure in Settings diagnostics endpoints (related to #600)
The "Check Proxy Nodes" button in Settings > Diagnostics was returning
403 Forbidden due to missing CSRF token. The frontend was using native
fetch() instead of apiFetch() which automatically includes CSRF tokens
for POST requests.

Fixed three endpoints in Settings.tsx:
- /api/diagnostics (GET) - for consistency
- /api/diagnostics/temperature-proxy/register-nodes (POST) - reported issue
- /api/diagnostics/docker/prepare-token (POST) - same bug

Note: Export/import config endpoints intentionally continue using native
fetch() because they need custom 401/403 handling to show the API token
modal instead of redirecting to login.
2025-11-12 00:00:55 +00:00
rcourtman
ea6cad10ce Release workflow guardrails (related to #695) 2025-11-11 22:34:00 +00:00
rcourtman
b2d441852d Merge update service refactor with SSE and job queue
- Add job queue system to ensure only one update runs at a time
- Add Server-Sent Events (SSE) for real-time push updates
- Increase rate limit from 20/min to 60/min for update endpoints
- Add unit tests for queue and SSE functionality
- Frontend: Update modal now uses SSE with polling fallback

Eliminates: 429 rate limit errors, duplicate modals, race conditions
Related to #671
2025-11-11 10:06:16 +00:00
Claude
cc46e3c6f0
Refactor update service to eliminate polling and race conditions
This commit implements a comprehensive refactoring of the update system
to address race conditions, redundant polling, and rate limiting issues.

Backend changes:
- Add job queue system to ensure only ONE update runs at a time
- Implement Server-Sent Events (SSE) for real-time update progress
- Add rate limiting to /api/updates/status (5-second minimum per client)
- Create SSE broadcaster for push-based status updates
- Integrate job queue with update manager for atomic operations
- Add comprehensive unit tests for queue and SSE components

Frontend changes:
- Update UpdateProgressModal to use SSE as primary mechanism
- Implement automatic fallback to polling when SSE unavailable
- Maintain backward compatibility with existing update flow
- Clean up SSE connections on component unmount

API changes:
- Add new endpoint: GET /api/updates/stream (SSE)
- Enhance /api/updates/status with client-based rate limiting
- Return cached status with appropriate headers when rate limited

Benefits:
- Eliminates 429 rate limit errors during updates
- Only one update job can run at a time (prevents race conditions)
- Real-time updates via SSE reduce unnecessary polling
- Graceful degradation to polling when SSE unavailable
- Better resource utilization and reduced server load

Testing:
- All existing tests pass
- New unit tests for queue and SSE functionality
- Integration tests verify complete update flow
2025-11-11 09:33:05 +00:00
rcourtman
e894bc7b1d Fix recurring update issues (related to #671)
This commit addresses three recurring issues with the update system:

1. **Checksum mismatches (v4.27.0, v4.28.0):**
   - Root cause: Release process uploads checksums.txt first, but if artifacts
     are rebuilt after that upload, checksums become stale
   - Fix: Update RELEASE_CHECKLIST.md to REQUIRE running validate-release.sh
     before publishing (step 9, non-negotiable)
   - The validation script exists and catches these errors, but wasn't being
     enforced in the release process

2. **Duplicate error modals:**
   - Root cause: UpdateProgressModal rendered in both App.tsx
     (GlobalUpdateProgressWatcher) and UpdateBanner.tsx
   - Fix: Remove UpdateProgressModal from UpdateBanner.tsx
   - GlobalUpdateProgressWatcher automatically shows the modal when updates
     start, so the banner's modal is redundant

3. **Rate limiting too strict:**
   - Root cause: UpdateProgressModal polls /api/updates/status every 2 seconds
     (30 req/min), but rate limit was 20/min
   - Fix: Increase UpdateEndpoints rate limit from 20/min to 60/min
   - Allows modal to poll without hitting rate limits during updates

These were all manual process errors and configuration issues, not code bugs.
The validation script enforcement prevents future checksum mismatches.
2025-11-11 09:09:30 +00:00
rcourtman
bb6ea3b23c Fix offline alert state not displaying in thresholds UI (related to #683)
When disabling offline alerts for VMs/containers, the setting was being persisted
correctly and honored by the alert system, but the UI always showed "Warn" instead
of the actual saved state.

Root cause: When reconstructing the overrides list from backend config, the guest
override mapping was copying poweredOffSeverity but omitting disableConnectivity,
causing ResourceTable to fall back to global defaults.

Fix: Add disableConnectivity field to guest override reconstruction in Alerts.tsx
(line 676), matching the pattern already used for Docker containers.
2025-11-10 20:32:04 +00:00