Commit graph

884 commits

Author SHA1 Message Date
rcourtman
a4571f580b fix(monitoring): harden VM memory selection and flag repeated VM usage 2026-03-03 16:19:17 +00:00
rcourtman
768b6d8b7a fix(frontend): resolve npm audit advisories in lockfile 2026-03-02 23:59:34 +00:00
rcourtman
d43dfbc490 feat(ui): add host removal action to hosts table
Add an actions menu to the hosts overview with a "Remove host from
Pulse" button. Includes permission checks (requires settings:write
scope), confirmation handling, and a security regression test for
the delete endpoint scope enforcement.
2026-03-01 23:28:33 +00:00
rcourtman
b1ff7e006f fix(ui): show PULSE_PUBLIC_URL value in settings and expand node tables to full width (#1305, #1304)
Expose PublicURL from runtime config in the system settings API response
so the frontend displays the actual value instead of the placeholder when
the env var is set.

Add w-full to PVE, PBS, and PMG node tables so they expand to fill the
container in full-width mode.
2026-03-01 14:42:30 +00:00
rcourtman
9aee8fa293 fix(ui): add Pro badge to Reporting tab and reduce patrol trigger log noise (#1285, #1258)
Show "Pro" badge on the Reporting settings tab so users know upfront
that advanced reporting requires a Pro license, rather than discovering
it after filling out the form.

Downgrade patrol trigger queue-full and rejection messages from Warn to
Debug — these are normal rate-limiting behavior, not actionable warnings.
2026-02-26 21:09:13 +00:00
rcourtman
af712006c9 fix(ai): allow Gemini and other models via OpenRouter without false provider warning (#1296)
Model name detection used substring matching (.includes('gemini')) which
falsely required Gemini provider config for OpenRouter model IDs like
"google/gemini-2.5-flash". Now only known provider prefixes are treated
as explicit delimiters, slash-containing names route to OpenAI (OpenRouter
convention), and colons in model names (e.g. "llama3.2:latest") are no
longer misinterpreted as provider prefixes.
2026-02-26 20:49:10 +00:00
rcourtman
6221be7311 fix(docker): serialize batch container updates per host (#1289)
The backend only allows one command per host at a time. The "Update All"
button was firing requests in parallel chunks, causing the second
container per host to fail with 400. Group targets by host and process
them sequentially within each host while still updating different hosts
in parallel.
2026-02-24 23:16:22 +00:00
rcourtman
ffc14c7507 fix(docker): stop CPU bars flickering for idle containers (#1288)
The isRunning prop used a `cpuPercent > 0` gate that treated idle
containers (0% CPU) as not-running, causing the bar to flip between
a percentage and an em-dash on every poll cycle. Remove the value
guard so visibility depends only on container running state, matching
how memory, disk, and restart columns already behave.
2026-02-23 22:05:18 +00:00
rcourtman
cac5be2ca1 chore(frontend-modern): remove stale pnpm lockfile 2026-02-23 11:15:37 +00:00
rcourtman
5457b04608 fix(ai): deduplicate Docker host 3-way chain in mention picker (#1252)
Replace first-match-only logic in upsertMentionResource with a
union-merge algorithm that collects all matching keys, merges losers
into a canonical winner, and re-points aliases. This fixes the case
where a host agent bridges a VM and a DockerHost but only the first
alias match was merged, leaving a duplicate entry in the picker.
2026-02-22 15:15:14 +00:00
rcourtman
f9654f5b7a
Merge pull request #1279 from muratoda/feature/use-locale-aware-time-format
Change last refresh time display format to system locale
2026-02-21 23:11:48 +00:00
rcourtman
1170da6a57 fix(ai): serialize linkedVmId/linkedContainerId and harden mention status (#1252)
HostFrontend was missing LinkedVmId and LinkedContainerId fields, so the
frontend dedup aliases for VM/container agents resolved to undefined and
never matched. Also add .trim() to getStatusColor and default host agent
status to 'online' to fix grey status dots.
2026-02-21 22:00:43 +00:00
rcourtman
50e476c942 fix(ai): fix mention status colors and dedup for docker/VM/LXC agents (#1252)
Three fixes for remaining mention autocomplete issues:

- Status dots now correctly show green/red/yellow for online/offline/
  degraded statuses (previously only handled running/stopped/paused)
- Docker hosts merge with their host agent via agentId cross-reference
- VMs and LXC containers merge with host agents running inside them
  via linkedVmId/linkedContainerId backend ID aliases
2026-02-20 22:53:52 +00:00
rcourtman
3da224877c feat(agent): add --env flag for custom environment variables in service files (#1277)
Users can now pass --env KEY=VALUE (repeatable) to the install script to
inject custom environment variables into the agent's service file. Useful
for KUBECONFIG and similar paths not auto-detected by the installer.

The Settings UI adds a textarea for entering env vars that get appended
to the generated install command. Both frontend and script validate key
format and reject unsafe value characters.
2026-02-20 20:15:29 +00:00
rcourtman
3efb3fc1da fix(ai): deduplicate PVE node and host agent in AI mention autocomplete (#1252)
When a PVE node has a linked host agent (or vice versa), they now merge
into a single mention resource instead of appearing as duplicate entries.
Uses alias cross-referencing via both linkedHostAgentId and linkedNodeId
(node-backend-id) to handle one-way and two-way links.
2026-02-20 19:59:29 +00:00
rcourtman
78c815915d feat(ui): add URL edit column to hosts and docker table views (#1276)
Add pencil icon + link column to the hosts overview table and the
docker unified table (containers and services), matching the existing
VM/guest URL column pattern. Uses the shared UrlEditPopover component
and existing metadata APIs. No backend changes needed.
2026-02-20 19:24:47 +00:00
rcourtman
6c78d78fc7 fix(webhooks): test button in edit form sends redacted headers (#1273)
When editing an existing webhook, header values are masked as
***REDACTED*** for security. The "Test" button in the edit form
sent these redacted values to the webhook endpoint, causing auth
failures (HTTP 403) on services like ntfy.sh that require tokens.

The test button outside the edit form worked because it used the
server-side saved config with real header values.

Fix: frontend now includes the webhook ID in test payloads for
existing webhooks, and the backend TestWebhook handler merges
redacted values with the saved originals before sending the test
(same logic already used by UpdateWebhook).
2026-02-20 13:31:52 +00:00
rcourtman
fe2916ad4f fix(hosts): add URL field to host drawer overview tab (#1197)
The inline URL edit was removed from the hosts table in 5.1.2 and
the only way to set a host URL was buried in the Discovery tab
(which requires AI features and a successful discovery scan).

Adds a Web Interface URL field directly in the System card of the
host drawer's Overview tab - always accessible without AI/Pro.
Users can add, edit, and remove URLs with inline editing.

Also fixes the Discovery tab using GuestMetadataAPI instead of
HostMetadataAPI for host URLs, which caused saved URLs to not
appear in the hosts table.
2026-02-20 13:31:52 +00:00
muratoda
b730b8be35
Change last refresh time display format to system locale 2026-02-19 23:33:18 +03:00
rcourtman
62cd4e03db fix(docker): add container custom URL editing UI in agent settings (#1054)
Add per-container custom URL inputs to the expanded Docker agent row in
Settings → Agents. URLs are stored via DockerMetadataAPI with the key
format {hostId}:container:{containerId}, matching the backend migration
that preserves URLs across container image updates.

(cherry picked from commit 0babb2e546a0a1edaf3210073e3d5b6b7655239b)
2026-02-18 12:57:12 +00:00
rcourtman
7efcec3120 fix(agents,ai): host URL field, AI Docker routing, Proxmox registration logging (#1197, #1210, #1267)
#1197: Add Custom URL input to the expanded host row in Settings → Agents.
Loads existing URL via HostMetadataAPI on row expand; saves on button click.
Only shown for host-type agent rows.

#1210: Fix agent_connected always false for Docker hosts on Proxmox VMs.
connectedAgentHostnames now also marks Docker host hostnames reachable when
their matching VM/LXC has a node with a connected Proxmox agent, mirroring
the routing logic already used in the control path.

#1267/#1269: Improve Proxmox auto-registration failure logging. Response body
is now included in the error message, and the warning directs users to delete
the state file to force re-registration rather than claiming the node exists.

(cherry picked from commit 305f6d3c94f0da4fc970450a6304da57d6d7fe80)
2026-02-18 12:57:09 +00:00
rcourtman
a69a2061cb fix(ui,disk): remove double 'ago' suffix and allow /var/lib/docker block devices (#1266, #1143)
#1266: ageFormatted already includes 'ago' from formatTimeDiff(); remove the
duplicate literal suffix from the backup age tooltip in GuestRow.tsx.

#1143: Remove /var/lib/docker from specialMountPrefixes so real block devices
mounted there are visible in disk usage. Container overlay layers (fstype=overlay)
are already filtered by virtualFSTypes and are unaffected.

(cherry picked from commit 5acef3405d4288f627788675123e266d661c2fe3)
2026-02-18 12:56:58 +00:00
rcourtman
e5a95a0da1 fix(frontend): full-width setting sync and webhook auth header preservation
Full-width setting resets (#1130): loadFromServer() was skipping the
server sync when localStorage already had a value. Server is now always
the source of truth on session load, so the saved preference propagates
across browsers and after reinstalls.

Webhook test 403 after save (#1273): selectService() was unconditionally
resetting headerInputs to the service template defaults, stripping any
user-added auth headers (e.g. Authorization: Bearer for ntfy.sh) when
editing an existing webhook. Now only resets headers when creating a new
webhook (when !editingId()).

Fixes #1130
Fixes #1273

(cherry picked from commit f9b62f0ae726785ef3134c24bc24d99e71d11d7e)
2026-02-18 12:56:50 +00:00
rcourtman
ad97f19cbf fix: add trailing slash to profile API URLs to prevent POST→GET redirect (#1212)
Go's ServeMux 301-redirects /api/admin/profiles to /api/admin/profiles/
when the pattern is registered with a trailing slash. The fetch() API
follows 301 by changing POST to GET (per HTTP spec), so the create
request silently became a list request — returning 200 OK without
actually creating anything.
2026-02-10 21:32:34 +00:00
rcourtman
a6bc55428c fix: load system settings for proxy auth and OIDC users with local theme (#1219)
The proxy auth and OIDC initialization paths skipped loading system
settings when the user had a local theme preference in localStorage.
This meant shouldHideDockerUpdateActions() always returned false,
so the "Update All" button showed even when disabled server-side.

Add the same else branch that the standard login path already has,
which loads system settings asynchronously regardless of theme pref.
2026-02-10 21:20:17 +00:00
rcourtman
c3c7bdf4a4 fix(ui): wrap NodeSummaryTable and HostsOverview with ScrollableTable for mobile (#1196)
NodeSummaryTable and HostsOverview used raw overflow-x-auto divs with
min-width: 800px, causing column overlap on narrow screens. Wrap both
with ScrollableTable and bump min-width to 1000px to match actual
column totals. Also bump DockerHostSummaryTable min-width from 800px
to 920px to match its column widths.
2026-02-10 19:24:03 +00:00
rcourtman
dea68a7521 fix(ui): change memory balloon segment color from yellow to blue (#1193)
Cherry-pick c2daf4b1 from main. Yellow was confusing users as it
matched the warning threshold color.
2026-02-10 12:57:30 +00:00
rcourtman
72ccd2f839 fix(ui): prevent Docker host summary column overlap on mobile (#1223, #1196)
The host summary table used minWidth='100%' on mobile, forcing 8 columns
into ~375px with table-layout:fixed. This made HOST and Uptime headers
overlap into "HOSTIIME". Set mobileMinWidth to 800px so the table scrolls
horizontally instead of crushing columns.
2026-02-09 23:30:04 +00:00
rcourtman
97f844e19e fix(ui): make Show All columns actually show all including IP/OS (#1222)
resetToDefaults() was restoring defaultHidden (which includes os, ip)
instead of clearing the hidden list. The button says "Show all" so it
should set hiddenColumns to [] rather than reverting to defaults.
2026-02-09 22:35:11 +00:00
rcourtman
e06ebb1bb7 fix(ui): set versionInfo on cached update path so agent badges work (#1228)
When checkForUpdates used cached data, it returned without setting
updateStore.versionInfo. This caused getServerVersion() to return
empty, making checkAgentVersion() skip the comparison and report all
agents as up-to-date (green) regardless of their actual version.
2026-02-09 22:33:56 +00:00
rcourtman
79016ec1b0 fix(ui): add missing v prefix to release download URLs (#1232)
UpdateBanner release-tag links were already fixed; this also fixes
the manual download commands in UpdatesSettingsPanel which were
generating 404 URLs (missing v in both the tag path and asset filename).
2026-02-09 22:23:38 +00:00
rcourtman
c92ccc122e fix(state): deduplicate PVE nodes and AI mention resources (#1217, #1214)
Backend: nodes with the same logical identity (cluster+name) are merged
using a health-weighted preference, preserving host-agent links across
node-ID churn.

Frontend: extract buildMentionResources() with alias-based dedup so
docker hosts and standalone host agents sharing an ID/hostname appear
once in the @ mention autocomplete.
2026-02-09 22:19:55 +00:00
rcourtman
2d78cf4e84 fix(dashboard): restore guest URL add/edit controls in table rows (#1221) 2026-02-09 14:00:15 +00:00
rcourtman
8a48acef1d fix: hotfix 5.1.5 — node duplication, alert scrambling, ntfy resolved formatting
- fix(models): filter nodes by instance in UpdateNodesForInstance to prevent
  PVE node duplication across poll cycles (#1214, #1192, #1217)
- fix(alerts): sort GetActiveAlerts output for stable ordering, preventing
  hostname scrambling in frontend (#1218)
- fix(notifications): add ntfy-specific resolved webhook formatting with
  plain-text body and proper headers (#1213)
- fix(frontend): respect "hide Docker update actions" setting in
  DockerFilter Update All button (#1219)
- fix(frontend): add missing v prefix to GitHub release tag URLs (#1195)
- fix(monitoring): reduce disk detection warning from Warn to Debug to
  eliminate log spam for pass-through disks (#1216)
- chore: bump VERSION to 5.1.5
2026-02-08 11:48:22 +00:00
rcourtman
d1e61d8a8a fix: ship alerting hotfixes and prepare 5.1.4 2026-02-07 22:05:55 +00:00
rcourtman
3d6488d159 fix: add agent:exec to API scope options in token creation UI
Users couldn't manually select agent:exec when creating tokens
via Settings → Security → API Tokens because it wasn't listed
in the scope options.
2026-02-04 22:42:48 +00:00
rcourtman
f6338f34fa fix: add agent:exec scope to generated agent tokens
Agent tokens created from the Settings UI and the backend install
command handler were missing the agent:exec scope, which was added
as a security requirement in 60f9e6f0. This caused all newly
installed agents to fail registration with "Agent exec token missing
required scope: agent:exec".

Fixes #1191
2026-02-04 22:33:01 +00:00
rcourtman
ee0e89871d fix: reduce metrics memory 86x by reverting buffer and adding LTTB downsampling
The in-memory metrics buffer was changed from 1000 to 86400 points per
metric to support 30-day sparklines, but this pre-allocated ~18 MB per
guest (7 slices × 86400 × 32 bytes). With 50 guests that's 920 MB —
explaining why users needed to double their LXC memory after upgrading
to 5.1.0.

- Revert in-memory buffer to 1000 points / 24h retention
- Remove eager slice pre-allocation (use append growth instead)
- Add LTTB (Largest Triangle Three Buckets) downsampling algorithm
- Chart endpoints now use a two-tier strategy: in-memory for ranges
  ≤ 2h, SQLite persistent store + LTTB for longer ranges
- Reduce frontend ring buffer from 86400 to 2000 points

Related to #1190
2026-02-04 19:49:52 +00:00
rcourtman
b3fa409b74 Allow SMTP auth over unencrypted connections, fix rate limit persistence, sanitize diagnostics export
- Replace Go stdlib smtp.PlainAuth (which refuses credentials without TLS)
  with a custom plainAuth that respects the user's explicit transport choice
- Remove TLS guard from LoginAuth for the same reason
- Add RateLimit field to EmailConfig so the user's configured value is
  persisted instead of being silently overwritten with 60
- Implement actual sanitization in the "Export for GitHub" diagnostics
  button (was previously ignored — both exports produced identical data)

Related to #1189
2026-02-04 15:42:47 +00:00
rcourtman
bd3d3e13ea Show history chart min/max persistently in header instead of flickering tooltip
The per-point min/max in the tooltip would appear and disappear while
scrubbing because some aggregated points happened to have min equal to
value. Replaced with overall dataset min/max displayed right-aligned in
the chart header, color-coded blue (min) and red (max).
2026-02-04 14:38:01 +00:00
rcourtman
05266d9062 Show node display name in alerts instead of raw Proxmox node name
Alerts previously showed the raw Proxmox node name (e.g., "on pve") even
when users configured a display name (e.g., "SPACEX") via Settings or the
host agent --hostname flag. This affected the alert UI, email notifications,
and webhook payloads.

Add NodeDisplayName field to the alert chain: cache display names in the
alert Manager (populated by CheckNode/CheckHost on every poll), resolve
them at alert creation via preserveAlertState, refresh on metric updates,
and enrich at read time in GetActiveAlerts. Update models.Alert, the
syncAlertsToState conversion, email templates, Apprise body text, webhook
payloads, and all frontend rendering paths.

Related to #1188
2026-02-04 14:26:44 +00:00
rcourtman
2d29b3dcd7 Unify Proxmox discovery and integrate PMG Patrol
- Unified Proxmox VE discovery by redirecting Node requests to linked Host Agents.
- Added smart deduplication and legacy fallback for Proxmox discovery results.
- Integrated Proxmox Mail Gateway (PMG) into AI Patrol system.
- Added comprehensive tests for discovery redirection and deduplication.
2026-02-04 13:52:36 +00:00
rcourtman
f4f8134f59 Align disk detail time range selector with other drawers 2026-02-04 13:43:28 +00:00
rcourtman
5c18748742 Add SMART disk lifecycle monitoring with historical charts
Expand the smartctl collector to capture detailed SMART attributes (SATA
and NVMe), propagate them through the full data pipeline, persist them
as time-series metrics, and display them in an interactive disk detail
drawer with historical sparkline charts.

Backend: add SMARTAttributes struct, writeSMARTMetrics for persistent
storage, "disk" resource type in metrics API with live fallback.
Frontend: enhanced DiskList with Power-On column and SMART warnings,
new DiskDetail drawer matching NodeDrawer styling patterns, generic
HistoryChart metric support with proper tooltip formatting.
2026-02-04 13:35:40 +00:00
rcourtman
95d178b881 Add missing pmg_checked field to live patrol run record
The PatrolRunRecord interface requires pmg_checked but the live
run placeholder in AIIntelligence.tsx was missing it, causing a
type error that blocked pushes.
2026-02-04 13:15:33 +00:00
rcourtman
f15a47c513 Fix stale kiosk mode test assertion
setKioskMode(false) stores 'false' explicitly rather than removing
the key, to distinguish disabled from unset. The test expectation
was outdated.
2026-02-04 13:14:50 +00:00
rcourtman
5ccf8ac7bc Fix UnifiedAgents test missing Router wrapper
UnifiedAgents calls useNavigate() which requires a Router context.
The test was rendering the component without one, breaking CI.
2026-02-04 12:49:40 +00:00
rcourtman
fd108faa7d feat(profiles): de-emphasize AI suggestions and fix multi-tenant support
UI/UX Improvements for AI-skeptical users:
- Only show 'Ideas' button if AI is enabled AND configured
- Renamed 'Suggest Profile' to 'Ideas' with lightbulb icon
- Moved 'New Profile' button to primary position
- Changed AI button styling from prominent purple to subtle gray
- Updated modal title to 'Profile Ideas' with neutral language

Multi-tenant bug fix:
- ProfileSuggestionHandler now uses MultiTenantPersistence
- Properly resolves tenant-specific persistence from request context
- Fixes potential nil pointer panic in multi-tenant deployments
- Existing profiles are now correctly loaded per-tenant for AI context

Tests updated to use MultiTenantPersistence with org context injection.
2026-02-04 11:39:50 +00:00
rcourtman
1af342da2d fix: add 7-day snooze cooldown to GitHub star modal
"Maybe later" previously only hid the modal for the current session,
causing it to reappear on every subsequent visit. Now it snoozes the
modal for 7 days before showing again.
2026-02-04 11:04:52 +00:00
rcourtman
5c1487e406 feat: add resource picker and multi-resource report generation
Replace manual resource ID entry with a searchable, filterable resource
picker that uses live WebSocket state. Support selecting multiple
resources (up to 50) for combined fleet reports.

Multi-resource PDFs include a cover page, fleet summary table with
aggregate health status, and condensed per-resource detail pages with
overlaid CPU/memory charts. Multi-resource CSVs include a summary
section followed by interleaved time-series data with resource columns.

New POST /api/admin/reports/generate-multi endpoint handles multi-resource
requests while the existing single-resource GET endpoint remains unchanged.

Also fixes resource ID validation regex to allow colons used in
VM/container IDs (e.g., "instance:node:vmid").
2026-02-04 10:24:23 +00:00