Commit graph

427 commits

Author SHA1 Message Date
rcourtman
eb59faaa4a fix: cluster-aware guest deduplication and multi-agent token binding
- Add cluster-aware guest ID generation (clusterName-VMID instead of instanceName-VMID)
  to prevent duplicate VMs/containers when multiple cluster nodes are monitored

- Add cluster deduplication at registration time - when a node is added that belongs
  to an already-configured cluster, merge as endpoint instead of creating duplicate

- Add startup consolidation to automatically merge duplicate cluster instances

- Change host agent token binding from agent GUID to hostname, allowing:
  - Multiple host agents to share a token (each bound by hostname)
  - Agent reinstalls on same host without token conflicts

- Remove 12-character password minimum requirement

- Remove emoji from auto-registration success message

- Fix grouped view node lookup to support both cluster-aware node IDs
  (clusterName-nodeName) and legacy guest grouping keys (instance-nodeName)

Fixes duplicate guests appearing when agents are installed on multiple
cluster nodes. Also improves multi-agent UX by allowing shared tokens.
2025-12-14 10:16:17 +00:00
rcourtman
1b8a310f2e feat: display linked host agent badge on PVE nodes
- NodeGroupHeader shows '+ Host Agent' badge when node has linked agent
- NodeSummaryTable shows '+Agent' badge in the node row
- Filter out linked hosts from Managed Agents list (prevents duplication)

This provides visual feedback when a PVE node has enhanced monitoring
via an installed host agent.
2025-12-13 23:18:31 +00:00
rcourtman
db8afeea18 feat: frontend support for linked host agents and PVE nodes
- Added linkedHostAgentId to Node interface
- Added linkedNodeId/linkedVmId/linkedContainerId to Host interface
- Filter out linked hosts from 'Managed Agents' list (they show merged with nodes)

Next: Update Dashboard to display linked entity badges
2025-12-13 23:16:48 +00:00
rcourtman
cc5586c5c0 feat: auto-generate new token after each install command copy
Users no longer need to manually click 'New Token' - a fresh token is
automatically generated after each copy. The command shown is always
ready for the next host.
2025-12-13 23:00:58 +00:00
rcourtman
893d3d5c79 fix: clarify one-token-per-host requirement and improve stale agent cleanup
- Setup wizard now clearly states 'Use a different token for each host'
- New Token button is always visible and more prominent (blue styling)
- WebSocket store now clears stale agents (>60s since lastSeen) immediately
  when receiving empty host arrays, instead of waiting for 3 consecutive updates
2025-12-13 22:57:00 +00:00
rcourtman
68456763f9 fix: apply empty agent updates immediately when existing agents are stale
The anti-flapping logic previously required 3 consecutive empty updates
before clearing stale agents from the UI. Now if all existing hosts/dockerHosts
have lastSeen > 60 seconds ago, empty updates are applied immediately.

This fixes the issue where removed agents stayed visible for too long.
2025-12-13 22:41:15 +00:00
rcourtman
122bd49700 fix: clarify that one token works on multiple hosts
Changed misleading 'Each copy uses a unique token' to 'Use the same
command on multiple servers'. Also toned down the 'Different Token'
button since it's rarely needed.
2025-12-13 22:22:25 +00:00
rcourtman
9aa1000bdb feat: make uninstall command always visible in Agents settings
Previously the uninstall command was hidden behind the token generation step.
Now it's always visible at the bottom of the 'Add a unified agent' card.
2025-12-13 21:41:27 +00:00
rcourtman
1a9973461e chore: update lockfiles 2025-12-13 21:30:57 +00:00
rcourtman
7891027d55 style: replace emojis with text indicators in UI components
- SecurityWarning: replace emoji icons with text-based indicators
- NodeModal: minor formatting cleanup
2025-12-13 21:30:44 +00:00
rcourtman
7eb6d33dad fix: add null safety checks for resources() in useResourcesAsLegacy
Prevents errors when resources array is undefined during initial load.
2025-12-13 21:30:36 +00:00
rcourtman
4ad8235f7a feat: add API token to WebSocket URL for authentication
WebSocket connections can't send custom headers, so the token is passed
as a query parameter. Works with the backend change to support ?token= auth.
2025-12-13 21:30:27 +00:00
rcourtman
a5893bba21 perf: debounce search and optimize filter parsing in Backups and Storage
- UnifiedBackups: memoize parsed search filters, debounce search input
- Storage: debounce search input to prevent jank during rapid typing
2025-12-13 21:29:45 +00:00
rcourtman
d5638c7c14 perf: debounce search input in Kubernetes clusters view
Prevents UI jank during rapid typing by using a 200ms debounced search term.
2025-12-13 21:28:19 +00:00
rcourtman
8abcc93aac perf: optimize Dashboard guest sorting and parent node lookups
- Pre-compute guest-to-parent-node mapping to avoid repeated lookups during render
- Memoize sort comparator to avoid duplicating sorting logic
- Reduces computational overhead when rendering large guest lists
2025-12-13 21:27:50 +00:00
rcourtman
8ed0851fb9 feat: simplify setup wizard to 3 steps (welcome, security, complete)
Removed Connect and Features steps that were adding friction without much value.
The wizard now focuses on:
1. Welcome - introduction and bootstrap token entry
2. Security - credential setup
3. Complete - shows install command and connected agents

Agent polling now happens in CompleteStep instead of relying on WebSockets
which aren't available during the pre-login setup phase.
2025-12-13 21:27:21 +00:00
rcourtman
7ae0b5cafd fix: Hide AI sidebar button when AI is disabled
The button was showing when aiChatStore.enabled was undefined.
Changed condition from 'enabled !== false' to 'enabled === true'
to only show when AI is explicitly enabled.
2025-12-13 16:13:25 +00:00
rcourtman
ae3e3a64f0 fix: Make OIDC toggle auto-save when disabling
- Disabling OIDC now saves immediately (safe operation)
- Enabling requires Save button press (prevents lockout without config)
- Shows helpful hint when enabling: configure first, then save
2025-12-13 16:09:48 +00:00
rcourtman
e4fa231ad3 fix: Make AI Assistant toggle auto-save immediately
The toggle was only updating local state without persisting.
Now it saves and shows confirmation feedback on toggle.
2025-12-13 16:01:03 +00:00
rcourtman
5a52913a90 fix: Resolve TypeScript errors and add ARIA accessibility
- Fixed type mismatches in ProxmoxAgentNodesPanel (prop signatures)
- Fixed temperatureTransports type (array vs single object)
- Added ARIA attributes to SetupWizard for screen reader support
- All tsc --noEmit checks pass
2025-12-13 15:49:37 +00:00
rcourtman
414574739b chore: Use proper logger in WelcomeStep instead of console.error 2025-12-13 15:43:13 +00:00
rcourtman
c1d9c1bb95 fix: Correct NodeConfig import path in ProxmoxAgentNodesPanel 2025-12-13 15:39:28 +00:00
rcourtman
e470fbec83 chore: Fix lint warnings in SetupWizard and add AI API docs
- Fixed unused variables in wizard components
- Fixed invalid aiEnabled field in FeaturesStep (AI uses separate API)
- Added AI endpoints section to API.md
2025-12-13 15:36:40 +00:00
rcourtman
e27b6f2657 Merge main into ai-features: incorporate latest bugfixes
Resolved conflicts:
- pkg/fsfilters/filters.go: Keep both TrueNAS and EnhanceCP filter fixes
- DockerUnifiedTable.tsx: Use main's resource column overlap fix
2025-12-13 15:18:51 +00:00
rcourtman
cb06077fab feat: Add multi-step Setup Wizard for Pulse 5.0 onboarding
- New SetupWizard component with 5-step flow:
  1. Welcome: Bootstrap token unlock, platform showcase
  2. Security: Admin account + API token creation
  3. Connect: Multi-platform infrastructure (Proxmox, Docker, K8s)
  4. Features: AI and auto-updates toggles
  5. Complete: Credentials display with copy/download

- Replaced FirstRunSetup with SetupWizard in Login.tsx
- Added Install Update button to UpdatesSettingsPanel
- Enhanced UpdatesSettingsPanel with update plan integration
- Added UpdateConfirmationModal to Settings for inline updates

Positions Pulse as a unified infrastructure monitoring platform,
not just a Proxmox-specific tool.
2025-12-13 15:08:47 +00:00
rcourtman
dbac8632b7 feat: add persistent metrics history API endpoint
- Add GET /api/metrics-store/history endpoint for querying SQLite-backed metrics
- Support flexible time ranges: 1h, 6h, 12h, 24h, 7d, 30d, 90d
- Return aggregated data with min/max values for longer time ranges
- Add TypeScript types and ChartsAPI.getMetricsHistory() client method

This enables frontend charts to visualize long-term trends using the
tiered retention system (raw → minute → hourly → daily averages).
2025-12-13 14:18:16 +00:00
rcourtman
17aaf6d603 Enhance settings panels with improved UI/UX
General Settings:
- Add animated sun/moon icon to dark mode toggle with gradient backgrounds
- Dynamic label showing current theme state (Light mode/Dark mode)
- Smooth CSS transitions for icon rotation and scaling

Updates Settings:
- Redesign version display with visual card layout
- Add build type badges (Development, Docker, Source) as colorful pills
- Show 3-column layout with arrow indicator when updates available
- Move Check Now button to footer with refresh icon
- Display auto-check status indicator

Security Overview:
- Add loading skeleton during data fetch
- Enhance proxy auth notice with gradient header and admin badge
- Style logout/guide links as proper buttons
- Add Security Best Practices tips card with recommendations
2025-12-13 13:41:43 +00:00
rcourtman
c5ac33e8c6 feat(backups): Add time format toggle to BackupsFilter
- Added toggle button to switch between relative and absolute time display
- Time preference is persisted to localStorage
- Toggle shows clock icon with 'Relative' or 'Absolute' label
- Implements the TODO from UnifiedBackups.tsx
2025-12-13 13:17:35 +00:00
rcourtman
75874687fb chore: Fix all remaining lint warnings
- Prefix unused catch error variables with underscore in AIChat.tsx and Alerts.tsx
- Reduced lint warnings from 8 to 0
- Clean lint output with no warnings or errors
2025-12-13 11:05:08 +00:00
rcourtman
3c0f4aa576 chore(settings): Remove unused diagnostics code and cleanup
- Removed unused helper functions (formatIsoDateTime, formatIsoRelativeTime, etc.)
- Removed unused handler functions (handleRegisterProxyNodes, handleDockerPrepareToken, handleCopy)
- Removed unused type interfaces (ProxyRegisterNode, DockerMigrationResult)
- Removed unused imports (copyToClipboard, showTokenReveal, APITokenRecord)
- Removed unused state signals for diagnostics actions
- Reduced lint warnings from 26 to 8
- Settings.tsx reduced from 5955 to 5740 lines
2025-12-13 10:53:18 +00:00
rcourtman
529daf58f8 chore(settings): Prefix unused variables to suppress lint warnings
- Prefix unused destructured variables with underscore
- Reduces lint warnings from 26 to 18
- Remaining warnings are for legacy helper functions
2025-12-13 08:02:24 +00:00
rcourtman
065cbe46cf chore(settings): Clean up unused imports and optimize polling
- Removed unused getPulsePort/getPulseWebSocketUrl imports
- Optimized polling to only run on proxmox tab (DiagnosticsPanel handles its own fetching)
- Remaining lint warnings are for legacy code that may need future refactoring
2025-12-13 07:59:52 +00:00
rcourtman
de2f6e0edb enhance(settings): Improve SecurityPostureSummary with score indicator
- Added dynamic security score calculation (0-100%)
- Added gradient header that changes color based on score:
  - Green (>=80%): Strong security
  - Amber (50-79%): Moderate security
  - Red (<50%): Weak security
- Improved visual hierarchy with color-coded status cards
- Added 'Critical' labels for important missing features
- Changed icons to lucide-solid for consistency
2025-12-13 07:54:09 +00:00
rcourtman
6a3c143740 refactor(settings): Extract DiagnosticsPanel and improve AI Settings UX
- Created standalone DiagnosticsPanel component with modern visual design
  - Gradient header with system health indicator
  - Card-based layout for System Runtime, PVE Nodes, PBS, Discovery
  - Status badges and improved visual hierarchy
  - Export functionality (full and GitHub-sanitized)

- Reduced Settings.tsx from 8,035 to 5,956 lines (26% reduction)
  - Removed ~2,079 lines of inline diagnostics code
  - Improved maintainability by encapsulating diagnostics logic

- Improved AI Settings UX:
  - Cost Controls: Gradient design, RECOMMENDED badge, $ prefix
  - Shows daily/weekly budget equivalents when value is entered
  - Auto-Fix: Streamlined acknowledgment with clear button instead of checkbox
  - Better visual hierarchy throughout
2025-12-13 07:51:49 +00:00
rcourtman
0074e49792 fix(frontend): hide unconfigured navigation tabs 2025-12-13 00:21:00 +00:00
rcourtman
0ddc30c1e1 Redesign Ceph, Replication, and Mail Gateway pages for UI consistency
- Ceph: Complete rework with summary cards (storage, clusters, services, pools),
  search with type-to-search, proper loading/disconnected/empty states, cluster
  overview table, pools table with filtering, health badges with tooltips

- Replication: Add summary cards (total/healthy/issues/next sync), status filter
  buttons (All/Healthy/Warning/Error), search with type-to-search, countdown timers
  for next sync with overdue/imminent highlighting, row highlighting for problem jobs,
  error tooltips, loading state

- Mail Gateway: Add aggregate summary cards across all instances (mail/spam/virus/
  quarantine/queue), visual threat rate progress bars, status badges with health
  indicators, queue depth tooltips with breakdown, streamlined stats grid with
  color-coded threat categories, improved cluster nodes table

All three pages now follow the same design patterns as Dashboard, Hosts, Docker,
and Storage using Card, EmptyState, and consistent styling.
2025-12-13 00:08:29 +00:00
rcourtman
c48c5b8861 fix(hosts): Merge filter sections into single row 2025-12-12 23:43:13 +00:00
rcourtman
ca8cd0e3b4 style(hosts,docker): Move search bar to its own row above filters
- Consistent with Kubernetes page layout
- Search bar now takes full width on top row
- Filter toggles on second row below search
2025-12-12 23:41:37 +00:00
rcourtman
fa5fde56e6 style(kubernetes): Move search bar to its own row above filters 2025-12-12 23:37:49 +00:00
rcourtman
9725849d77 feat(kubernetes): Add keyboard focus for search input
- Typing anywhere on the page auto-focuses the search input
- Escape key clears search and blurs input
- Matches Dashboard behavior for consistent UX
- Fixed missing createEffect import
2025-12-12 23:36:31 +00:00
rcourtman
91f8b81547 feat(kubernetes): Add column picker and sorting for all views
- Add sortable headers to Clusters and Nodes views
- Add ColumnPicker dropdown for Pods view (toggle Namespace, Cluster, Ready, Restarts, Image, Age columns)
- Column visibility persists to localStorage
- Sorting persists across sessions for all views
2025-12-12 23:31:46 +00:00
rcourtman
987f7a3822 feat(kubernetes): Add sorting and namespace filter to K8s UI
- Add sortable table headers for Pod and Deployment views
- Click column headers to toggle sort direction
- Sort state persists across sessions
- Add namespace dropdown filter for Pods/Deployments views
- Auto-populates from available namespaces
- Include namespace filter in reset and active filters check
2025-12-12 23:24:04 +00:00
rcourtman
0cd16b29cc feat(kubernetes): Add Kubernetes mock data and UI
Backend:
- Add K8s cluster, node, pod, deployment mock data generation
- Configurable via PULSE_MOCK_K8S_CLUSTERS, PULSE_MOCK_K8S_NODES,
  PULSE_MOCK_K8S_PODS, PULSE_MOCK_K8S_DEPLOYMENTS env vars
- Generate realistic cluster data with versions, namespaces, pod phases
- Add dynamic metric updates for K8s resources
- Deep copy K8s data in cloneState to prevent race conditions

Frontend:
- Add KubernetesClusters component with 4 view modes:
  Clusters, Nodes, Pods, Deployments
- Filter bar with search, status filter, show hidden toggle
- Nodes view: status, roles, CPU/memory/pod capacity, kubelet version
- Pods view: namespace, status, ready containers, restarts, image, age
- Deployments view: replicas, ready/up-to-date status
- Matches Docker/Dashboard table styling patterns
2025-12-12 23:13:40 +00:00
rcourtman
d96942596f feat: add Kubernetes platform support 2025-12-12 21:31:11 +00:00
rcourtman
bf43d448cf fix: Robust OCI container detection with state persistence
Backend:
- Seed OCI classification from previous state so containers never
  'downgrade' to LXC if config fetching intermittently fails
- Prevent type regression in recordGuestSnapshot when OCI was previously detected
- Move metrics zeroing before snapshot recording for cleaner flow

Frontend:
- Add isOCIContainer() memo that checks both type and isOci flag
- Use isOCI helper in Dashboard.tsx for AI context building
- Include oci-container type in useResources container conversion
- Preserve isOci and osTemplate fields through legacy conversion

This ensures OCI containers retain their classification even when
Proxmox API permissions or transient errors prevent config reads.
2025-12-12 20:06:39 +00:00
rcourtman
a20760f527 fix: Preserve OCI container type through unified resource conversion
The useResources.ts hook was hardcoding type: 'lxc' when converting
unified resources to legacy container format, causing OCI containers
to intermittently display as LXC when WebSocket updates occurred.

Now preserves the actual type from platformData (oci/lxc).
2025-12-12 19:18:36 +00:00
rcourtman
e82cf7eaaf feat: Enhance OCI container display and AI context
- Frontend: Add ociImage memo to extract clean image name from osTemplate
- Frontend: Show OCI image name in type badge tooltip
- Frontend: Display OCI image in OS column when no guest agent info available
- Frontend: Include ociImage in AI context data for selected OCI containers
- Backend: Differentiate OCI containers as 'oci_container' type in AI context
- Backend: Add Metadata field to ResourceContext for extensibility
- Backend: Include oci_image in container metadata for AI analysis
- Backend: Update section heading to 'LXC/OCI Containers' in AI context

This follows Docker container patterns to avoid duplicating work.
2025-12-12 18:00:09 +00:00
rcourtman
dfb5d50f73 feat: Add Proxmox 9.1+ OCI container support
- Backend: Add IsOCI and OSTemplate fields to Container model
- Backend: Add extractContainerOSTemplate() and isOCITemplate() detection functions
- Backend: Detect OCI containers via ostemplate config and set type to 'oci'
- Frontend: Add isOci and osTemplate to Container interface
- Frontend: Add 'oci-container' to ResourceType with distinct purple badge
- Frontend: Update Dashboard filters to include OCI containers with LXC
- Tests: Add comprehensive unit tests for OCI detection logic

OCI containers are detected by checking the ostemplate for patterns like:
- oci: prefix (e.g., oci:docker.io/library/alpine:latest)
- docker: prefix (e.g., docker:nginx:latest)
- Known registry URLs (docker.io, ghcr.io, gcr.io, quay.io, etc.)
- Local templates with oci- or oci_ filename patterns
2025-12-12 17:51:43 +00:00
rcourtman
7f057432ed feat: AI security and policy improvements for 5.0
- Add DOMPurify sanitization for AI chat markdown rendering (XSS fix)
- Configure DOMPurify to add target=_blank and rel=noopener to links
- Update system prompt to align with command approval policy
- Clarify safe vs destructive commands in prompt
- Improve patrol auto-fix mode guidance with safe operation list
- Add verification requirements for auto-fix actions
- Update observe-only mode to be clearer about read-only restrictions
2025-12-12 17:38:55 +00:00
rcourtman
2381631df0 fix(ui): Move Auto-Fix Model selector next to Auto-Fix toggle
UX improvement: The Auto-Fix Model dropdown was too far from the
Patrol Auto-Fix toggle, making it hard to find.

Now the flow is:
1. Scroll to 'AI Patrol Behavior' section
2. Check the acknowledgement checkbox
3. Enable 'Patrol Auto-Fix' toggle
4. Model selector appears RIGHT BELOW the toggle

The model dropdown only appears when auto-fix is enabled (since
it's irrelevant otherwise).
2025-12-12 15:17:44 +00:00