Commit graph

4826 commits

Author SHA1 Message Date
rcourtman
94259a45da Add Windows service support to unified agent
Port Windows SCM integration from pulse-host-agent to pulse-agent,
enabling the unified agent to run as a Windows service with proper
start/stop handling and event logging.

Related to #766
2025-11-27 17:00:03 +00:00
rcourtman
a92a53fb98 fix: correct show_local URL path and hide subtitle when local login hidden
- Update OIDC.md docs to show correct URL path (/?show_local=true, not /login)
- Hide "Enter your credentials" subtitle when local login is hidden

Related to #750
2025-11-27 16:23:44 +00:00
rcourtman
1b5528356b fix: clear stale errors after successful cluster operations
Previously, errors stored in ClusterClient.lastError were only cleared
during initial health checks or when recovering unhealthy nodes. This
caused stale error messages to persist in the UI even after the
underlying issues were resolved.

The fix clears cached errors in two places:
1. After passing connectivity test in getHealthyClient()
2. After successful operation in executeWithFailover()

This ensures that once an endpoint starts working again, any previous
error messages are cleared from the UI without requiring a restart.

Related to #659, #754
2025-11-27 16:22:16 +00:00
rcourtman
d425bc3df4 fix: multiple agent installation and update issues
- Default enableDocker to false in UI to prevent unintended Docker
  agent activation on host-only installs (Related to #766)
- Deploy agent scripts and binaries during web UI upgrades, not just
  the main binary (Related to #760)
- Apply symlink resolution fix to standalone docker agent self-update
  to prevent cross-device rename failures (Related to #737)
2025-11-27 15:49:03 +00:00
rcourtman
584bdc88ff fix: add hash check to polling fallback and persist sidebar state
- Add content hash check to config watcher polling path to match fsnotify
  behavior, preventing unnecessary restarts when .env is touched but
  content unchanged (Related to #748)
- Change settings sidebar to expanded by default and persist user
  preference using usePersistentSignal (Related to #764)
2025-11-27 15:24:23 +00:00
rcourtman
dbd741f9c4 fix: remove unused samplerInterval variable 2025-11-27 13:20:58 +00:00
rcourtman
6a8258be14 chore: remove dead code and unused exports
Remove ~900 lines of unused code identified by static analysis:

Go:
- internal/logging: Remove 10 unused functions (InitFromConfig, New,
  FromContext, WithLogger, etc.) that were built but never integrated
- cmd/pulse-sensor-proxy: Remove 7 dead validation functions for a
  removed command execution feature
- internal/metrics: Remove 8 unused notification metric functions and
  10 Prometheus metrics that were never wired up

Frontend:
- Delete ActivationBanner.tsx stub component
- Remove unused exports: stopMetricsSampler, getSamplerStatus,
  formatSpeedCompact, parseMetricKey, getResourceAlerts
2025-11-27 13:17:39 +00:00
rcourtman
c4f3095de2 refactor(ui): improve table column sizing and progress bar constraints
- Cap progress bars at 140px max-width for better readability
- Constrain shell layout to 1400px max-width, centered
- Fix metric columns (CPU, Memory, Disk) at 156px
- Give name/resource columns extra space via flex
- Remove Docker Disk column (data rarely available from API)
- Remove fixed percentage widths from backups table for auto-sizing
- Improve text contrast in progress bar labels
2025-11-27 12:09:12 +00:00
rcourtman
4e5977f5d9 fix(dev): export auth env vars in hot-dev script
Use load_env_file for /etc/pulse/.env to properly export
PULSE_AUTH_USER and PULSE_AUTH_PASS to the backend process.
2025-11-27 11:14:27 +00:00
rcourtman
5bc86a4cb1 fix(mock): adjust backup time distribution for more realistic data
Reduce never-backed-up guests from 10% to 5% so most mock guests
show backup status rather than grey shields.
2025-11-27 11:04:20 +00:00
courtmanr@gmail.com
c86ce1629d fix(tests): resolve flaky ID generation and symlink resolution on macOS 2025-11-27 10:50:13 +00:00
courtmanr@gmail.com
135d6c3858 feat(ui): apply glassmorphism and staggered animations to tables 2025-11-27 10:44:36 +00:00
rcourtman
2ff0a0988f refactor: remove unnecessary type conversions
Remove redundant type conversions identified by unconvert linter:
- Remove int() conversions for already-int VMID fields
- Remove int64() conversions for already-int64 arithmetic results
- Remove uint64() conversions for already-uint64 Disk/MaxDisk fields
- Remove int() on syscall.Stdin (already int constant)
2025-11-27 10:33:35 +00:00
rcourtman
fdb2f86d90 style: fix revive linter warnings
- Mark unused stub parameters with underscore
- Rename 'copy' variable to avoid shadowing builtin
- Remove unnecessary else blocks after return statements
2025-11-27 10:26:26 +00:00
rcourtman
bd2635cabe chore: remove deprecated build tags and use strings.ReplaceAll
- Remove redundant // +build directives (go:build is sufficient in Go 1.17+)
- Replace strings.Replace(..., -1) with strings.ReplaceAll
2025-11-27 10:16:08 +00:00
rcourtman
8152197207 fix: mark unused parameters to satisfy unparam linter
Mark intentionally unused parameters with underscore to:
- Silence unparam warnings for legitimate unused parameters
- Keep function signatures intact for API compatibility
- Remove unused req from serveChecksum helper
2025-11-27 10:12:48 +00:00
rcourtman
8f6a481cd2 refactor: use builtin max() and fix unused parameter
- Replace custom maxInt64 helper with Go 1.21+ builtin max()
- Mark unused cfg parameter in newAdaptiveIntervalSelector
- Remove test for deleted helper function
2025-11-27 10:08:37 +00:00
rcourtman
e1b9c133c3 fix: remove ineffectual assignments
- Fix loop variable reassignment in config_handlers.go
- Remove redundant boolean assignments in swarm.go
2025-11-27 09:48:29 +00:00
rcourtman
f76c1fb43b chore: update to non-deprecated Docker SDK types
- Use container.Summary instead of types.Container
- Use swarmtypes.ServiceListOptions instead of types.ServiceListOptions
- Use swarmtypes.TaskListOptions instead of types.TaskListOptions

These types were deprecated in favor of package-specific types.
2025-11-27 09:36:05 +00:00
rcourtman
7abdb18b99 style: use direct type conversions in model converters
Replace struct literal copies with direct type conversions where
the source and destination types have identical field layouts.
2025-11-27 09:24:39 +00:00
rcourtman
69051d5fe1 refactor: replace deprecated strings.Title with custom titleCase
Add simple titleCase functions that handle ASCII strings without
the Unicode punctuation issues of strings.Title.
2025-11-27 09:22:52 +00:00
rcourtman
611740087c style: fix additional staticcheck warnings
- Lowercase error messages (ST1005)
- Use context.Background() instead of nil (SA1012)
- Fix rand.Intn(1) which always returns 0 (SA4030)
- Remove unnecessary nil check before len() (S1009)
2025-11-27 09:21:11 +00:00
rcourtman
ad998a1e2f style: fix staticcheck style warnings
- Merge variable declaration with assignment (S1021)
- Use unconditional strings.TrimPrefix (S1017)
- Remove unnecessary nil checks around range (S1031)
- Remove unnecessary fmt.Sprintf (S1039)
- Use copy() instead of manual loop (S1001)
- Use time.Until instead of t.Sub(time.Now()) (S1024)
- Use buf.String() instead of string(buf.Bytes()) (S1030)
2025-11-27 09:19:33 +00:00
rcourtman
6ff345fb6b chore: fix staticcheck SA warnings
- Fix SA4006 unused value issues in ssh.go, validation.go, generator.go
- Replace deprecated ioutil with io/os in config.go
- Replace deprecated tar.TypeRegA with tar.TypeReg
- Remove deprecated rand.Seed calls (auto-seeded in Go 1.20+)
- Fix always-true nil check in main.go
- Fix impossible nil comparison in tempproxy/client.go
- Add nil check for config in monitor.New()
2025-11-27 09:16:53 +00:00
rcourtman
bc9e89696b chore: fix staticcheck U1000 unused code warnings
- Remove unused ipv6Regex from validation.go
- Suppress unused recordAlertFired/recordAlertResolved hooks (kept for future use)
- Remove unused apiLimiter rate limiter
- Remove unused stopOnce fields from csrf_store.go and session_store.go
- Remove unused lastBroadcast field from hub.go
- Remove unused lastUsedIndex field from cluster_client.go
2025-11-27 09:12:17 +00:00
rcourtman
8276ae837e chore: cleanup proxmox IsAuthError and remove stray comment
- Make IsAuthError unexported (isAuthError) since it's only used internally
- Remove stray '// test comment' from docker_metadata.go
2025-11-27 08:59:01 +00:00
rcourtman
3045aa16fb chore: remove unused phaseError type from discovery 2025-11-27 08:47:13 +00:00
rcourtman
2fccd575b2 chore: remove unused ClusterHealth types
Remove internal/models/cluster.go containing ClusterHealth and
ClusterNodeStatus types that were never used in the codebase.
2025-11-27 08:45:50 +00:00
rcourtman
3fce14469c chore: remove legacy proxy handlers and unused functions
Remove legacy V1 handlers replaced by V2 versions:
- sendError (replaced by sendErrorV2)
- handleGetStatus (replaced by handleGetStatusV2)
- handleEnsureClusterKeys (replaced by handleEnsureClusterKeysV2)
- handleRegisterNodes (replaced by handleRegisterNodesV2)
- handleGetTemperature (replaced by handleGetTemperatureV2)

Also remove related unused functions:
- getPublicKey wrapper (only getPublicKeyFrom is used)
- pushSSHKey wrapper (only pushSSHKeyFrom is used)
- nodeValidator.ipAllowed method (standalone ipAllowed is used)
- validateConfigFile (never called)
- runServiceDebug (Windows debug mode, never called)
2025-11-27 08:41:28 +00:00
rcourtman
2a5520ef25 chore: remove unused API response types
Remove ChartData, Dataset, ConfigImportResponse, ConfigExportResponse,
InstallScriptResponse, ErrorResponse, and SuccessResponse types that
were defined but never used in the codebase.
2025-11-27 08:37:22 +00:00
rcourtman
b341ce42fb style: fix whitespace in middleware.go 2025-11-27 08:34:31 +00:00
rcourtman
861bff123d chore: remove unused store methods
Remove 121 lines of unused store methods:
- CSRFTokenStore: Stop, ExtendCSRFToken
- SessionStore: Stop, ExtendSession, GetSession
- RecoveryTokenStore: Stop, save, GetActiveTokenCount, ValidateRecoveryToken

These methods were part of a standard store pattern but never wired up
to the application lifecycle. The constant-time validation variant is
used instead of the timing-vulnerable ValidateRecoveryToken.
2025-11-27 08:31:50 +00:00
rcourtman
907989d9b1 chore: remove unused DockerMetadataHandler.Reload method 2025-11-27 05:14:56 +00:00
rcourtman
c439a83fba chore: remove additional dead code
Remove 241 lines of unreachable code across internal and pkg:
- internal/crypto/crypto.go: unused NewCryptoManager wrapper
- internal/monitoring/scheduler.go: unused fixedIntervalSelector type
- internal/ssh/knownhosts/manager.go: unused hostKeyExists function
- internal/updates/manager.go: unused getLatestRelease wrapper
- internal/updates/updater.go: unused GetAll method
- pkg/discovery/discovery.go: unused scanWorker and runPhase (legacy compat)
- pkg/proxmox/client.go: unused post, getTaskStatus, waitForTaskCompletion, getTaskLog
- pkg/proxmox/cluster_client.go: unused markUnhealthy wrapper
2025-11-27 05:13:26 +00:00
rcourtman
b370799988 chore: remove more dead code
Remove 330 lines of unreachable code:
- internal/monitoring/temperature_service.go: unused temperature service abstraction
- internal/monitoring/temperature.go: unused NewTemperatureCollector wrapper
- internal/mock/generator.go: unused GenerateAlerts function
- internal/mock/integration.go: unused ToggleMockMode wrapper
- internal/notifications/notifications.go: unused sendEmailWithContent,
  generatePayloadFromTemplate, isPrivateRange172, groupAlerts
- internal/notifications/email_providers.go: unused GetProviderDefaults
2025-11-27 00:10:55 +00:00
rcourtman
0dc0235f77 chore: remove dead code and unused files
Remove 604 lines of unreachable code identified by deadcode analysis:
- internal/config/credentials.go: unused credential resolver
- internal/config/registration.go: unused registration config
- internal/monitoring/poller.go: unused channel-based polling (keep types)
- internal/api/middleware.go: unused TimeoutHandler, JSONHandler, NewAPIError, ValidationError
- internal/api/security.go: unused IsLockedOut, SecurityHeaders
- internal/api/auth.go: unused min helper
- internal/config/config.go: unused SaveConfig
- internal/config/client_helpers.go: unused CreatePBSConfigFromFields
- internal/logging/logging.go: unused NewRequestID
2025-11-27 00:05:04 +00:00
rcourtman
798c40a801 chore: remove unused API types
Remove 261 lines of unused type definitions from types.go:
- NodeRequest, SettingsRequest (unused, actual impl in config_handlers.go)
- ConfigResponse, NodeConfig, SettingsConfig (unused)
- BackupResponse, BackupInfo, MetricsResponse, MetricData (unused)
- StorageResponse, StorageInfo, StorageTotals (unused)
- DiagnosticsResponse and related types (unused)
- SecurityStatusResponse, ExportRequest, ImportRequest (unused)
- NotificationTestRequest, UpdateCheckResponse (unused)
- WebSocketMessage, LoginRequest, LoginResponse (unused)
- TestConnectionResponse, NodeConnectionResponse (unused)
- DiscoveryResponse, DiscoveredServer (pkg/discovery has own types)
- AutoRegisterResponse (unused)
2025-11-26 23:51:41 +00:00
rcourtman
01f7d81d38 style: fix gofmt formatting inconsistencies
Run gofmt -w to fix tab/space inconsistencies across 33 files.
2025-11-26 23:44:36 +00:00
rcourtman
e6adffb2ff fix: prevent context leak in temperature collection
- Use defer for tempCancel() to ensure context is always cancelled
- Remove redundant shouldCollect variable that was always true
- Fix indentation after removing the unnecessary conditional block
2025-11-26 23:43:18 +00:00
rcourtman
901318f395 chore: clean up stale .gitignore entries
Remove references to files that no longer exist:
- Legacy mock mode files (mock_integration.go, mock_stub.go, etc.)
- Duplicate entries (CLAUDE.md, /pulse-sensor-proxy)
- Experimental/abandoned feature paths
2025-11-26 23:39:46 +00:00
rcourtman
9cca0f75d6 fix: set make_latest=true when publishing releases
Without this flag, releases published from draft state don't
automatically become the 'latest' release on GitHub, causing
users to download outdated installer scripts.
2025-11-26 22:41:18 +00:00
rcourtman
da31905c79 fix: auto-publish release instead of leaving as draft
The release pipeline now publishes the release automatically after
uploading all assets. This ensures downstream workflows (Docker publish,
Helm chart, demo server update) see the correct "latest" release and
don't skip due to the race condition where the draft wasn't published yet.
2025-11-26 21:54:37 +00:00
rcourtman
4163c02315 feat: add backup status indicator to guest table
Shows shield icon next to guest name when backup is stale or missing:
- Yellow shield: backup 24-72 hours old
- Red shield: backup older than 72 hours
- Gray shield: no backup found

Fresh backups (<24h) show no indicator to keep the UI clean.
Templates are excluded from backup status display.
2025-11-26 21:30:41 +00:00
rcourtman
fe2a815d89 Bump version to 4.33.1 2025-11-26 20:38:31 +00:00
rcourtman
c6167f08e6 fix: deploy unified agent scripts and binaries during installation
The installer was missing:
1. copy_unified_agent_binaries_from_dir() to extract pulse-agent-* binaries
   from the release tarball to /opt/pulse/bin/
2. install.sh and install.ps1 in the deploy_agent_scripts() array

This caused /install.sh and /download/pulse-agent to return 404 on fresh
installations and upgrades from pre-4.33.0 versions.

Related to #760, #751
2025-11-26 20:35:52 +00:00
rcourtman
7a1a5408e2 fix: resolve symlinks for agent self-update to avoid cross-device rename
When the agent binary is symlinked (e.g., from /opt/pulse/bin to
/usr/local/bin), the self-update would fail with "invalid cross-device
link" because os.Rename() doesn't work across filesystems.

Now resolves symlinks before update and creates the temp file in the
same directory as the real binary.

Related to #737
2025-11-26 20:16:09 +00:00
courtmanr@gmail.com
41b7c25889 Enhance table responsiveness across multiple components 2025-11-26 17:57:09 +00:00
rcourtman
14e67df535 fix: create tag before draft release (GitHub API limitation)
Draft releases cannot create tags via the GitHub API, resulting in
'untagged-xxx' releases. Fixed by creating the tag first, then
creating the draft release pointing to it.

See: https://github.com/cli/cli/issues/11589
2025-11-26 15:48:56 +00:00
rcourtman
7eff58dc1a refactor: build Docker images once, retag on publish
- Preflight builds multi-arch images to staging tags on GHCR
- Publish workflow just retags staging → final (no rebuild)
- Reduces publish time from ~10min to ~1min
2025-11-26 15:35:34 +00:00
rcourtman
35313e298d refactor: split Docker publish into separate workflow
Docker images now build only after release is published, not during
the draft creation phase. This prevents users from getting updates
before the release is reviewed and approved.
2025-11-26 15:28:11 +00:00