- KnowledgeStore: use atomic write (temp+rename) to prevent file
corruption from concurrent async saves
- Change password tests: add auth headers since endpoint now requires
authentication
- ClearSession test: expect 2 cookies (pulse_session + pulse_csrf)
matching updated clearSession behavior
- API token test: update to match current behavior where query-string
tokens are accepted (needed for WebSocket connections)
- Host agent config: allow ScopeHostManage to resolve any host, not
just token-bound hosts
Backend:
- Add HostData field to ChartResponse struct in types.go
- Add host data processing in /api/charts endpoint using 'host:' prefix key
- Include hosts count in debug logging for chart responses
Frontend:
- Add 'host' to MetricResourceKind type in metricsKeys.ts
- Add hostData field to ChartsResponse interface in charts.ts
- Process hostData in seedFromBackend() in metricsHistory.ts
- Pass resourceId to EnhancedCPUBar and StackedMemoryBar in HostsOverview.tsx
- Add '7d' and '30d' to TIME_RANGE_OPTIONS in metricsViewMode.ts
This enables sparkline trend visualization for unified host agents,
consistent with Proxmox guests. Data accumulates over time at 30s intervals.
1. Enforce monitoring:read scope on WebSocket upgrades
- Prevents low-privilege tokens (e.g. host-agent:report) from accessing
full infra state via requestData on the main WebSocket.
2. Enforce agent token binding to prevent impersonation
- Added Metadata field to APITokenRecord to support bound_agent_id
- Updated agentexec server to validate token-to-agent binding if present
- Prevents agent:exec tokens from registering as arbitrary agent IDs
1. Host agent link/unlink/delete now require settings:write scope
- Prevents compromised host-agent:manage tokens from manipulating
or deleting unrelated hosts
- Host tokens scoped to one host can no longer affect other hosts
2. AI investigation endpoints now require ai:execute scope
- /api/ai/findings/* was only protected by RequireAuth
- Low-privilege tokens could read investigation details and chat logs
3. Notification DLQ endpoints now require settings:read/write scope
- DLQ entries contain notification configs (webhooks, SMTP, etc.)
- Prevents monitoring:read tokens from reading credential data
- DLQ retry/delete operations require settings:write
CRITICAL FIX: This endpoint previously allowed unauthenticated users to
trigger service restarts, which is a denial-of-service vulnerability.
Now requires:
- Authentication (CheckAuth) when auth is configured
- Admin role for proxy auth users
- settings:write scope for API tokens
Initial setup (no auth configured yet) remains accessible to allow
first-time security configuration to trigger restart.
- AI Intelligence endpoints (/api/ai/intelligence/*, /api/ai/forecast/*,
/api/ai/unified/findings, etc.) now require ai:execute scope to prevent
low-privilege tokens from reading sensitive intelligence data
- AI Knowledge endpoints (/api/ai/knowledge/*) now require ai:chat scope
to prevent arbitrary guest data access across the fleet
- AI Debug Context (/api/ai/debug/context) now requires settings:read scope
to prevent system prompt and infrastructure details leakage
- WebSocket origin check now validates peer IP is private when allowing
private network origins, mitigating CSWSH attacks where a malicious page
on the same LAN tries to hijack connections using victim's session cookie
- OAuth endpoints now require settings:write scope (not just admin)
- Approval endpoints now require ai:execute scope
- Added CommandHash to approvals for replay protection
- Approvals are now single-use (consumed on first use)
- consumeApprovalWithValidation validates command matches approval
- Add professional cover page with branding and report period
- Add Executive Summary page with health status banner (HEALTHY/WARNING/CRITICAL)
- Add Quick Stats section with color-coded metrics and trend indicators
- Add Key Observations with automated analysis of CPU, memory, disk, and disk wear
- Add Recommended Actions section with prioritized, actionable items
- Add Resource Details page with hardware info, storage pools, physical disks
- Add color-coded tables for alerts, storage, and disk health
- Add performance charts with area fills and proper scaling
- Improve overall visual design with consistent color scheme
- Fix SAML session invalidation to use correct SessionStore method
SSE Broadcaster:
- Add per-client mutex to prevent concurrent writes to ResponseWriter
- Fix data race in cleanupLoop reading LastActive without synchronization
- Update LastActive in SendHeartbeat so clients aren't incorrectly pruned
after 5 minutes of idle heartbeat traffic
Alert Acknowledgements:
- Extract authenticated user from X-Authenticated-User header instead of
hardcoding 'admin' or trusting request body's User field
- Prevents audit log spoofing and ensures accurate user attribution
Security Status Endpoint:
- Remove ?token= query param validation from public /api/security/status
- Prevents endpoint from acting as a token validity oracle for attackers
- Authentication still works via session cookies and X-API-Token header
Security fixes:
- Auto-register now requires settings:write scope for API tokens
- X-Forwarded-For in auto-register only trusted from verified proxies
- Public URL capture requires authentication (no loopback bypass)
- Lockout reset now uses RequireAdmin for session users
Reliability fixes:
- Docker stop command expiration clears PendingUninstall flag
- Cancelled notifications get completed_at set and are cleaned up
- Fix SSRF and rate limit bypass in SendEnhancedWebhook by validating the rendered URL.
- Fix rate limit spoofing in updates API by using secure IP extraction (trusted proxies).
- Fix memory leak in metrics history by correctly clearing fully stale data series.
- Fix public URL poisoning by preventing overwrites when explicitly configured.
- Fix data race in webhook notifications by removing shared state
- Fix duplicate monitors on config reload by stopping old instances
- Prevent metrics ID deletion on transient startup errors
- Support Bearer auth header for config export/import endpoints
- Fix API-only mode to accept Bearer tokens and query params
- Fix data race in API token validation using fine-grained locking
- Fix unified agent download serving wrong binary for invalid arch
- Fix AI infra discovery running when AI disabled and missing stop mechanism
- Add AI provider indicator showing local (Ollama) vs cloud (Anthropic/OpenAI) analysis
- Add "What Discovery Does" explanation section before first scan
- Show commands preview before scan so users know what will run
- Add scan details section showing raw command outputs for admins
- Filter sensitive Docker labels (passwords, secrets, tokens) before AI analysis
- Add comprehensive tests for label filtering
This improves sysadmin confidence by making discovery transparent about
what it does, what data it collects, and where that data goes.
- Fix routing for POST/PUT/DELETE on /api/discovery/host/ endpoints
(Go's http.ServeMux was matching the longer prefix before method-specific routes)
- Add HOST-specific AI prompt that focuses on identifying the host OS
rather than services/containers running on it
- Add success message UI after discovery completes
- Fix timing so success appears after data is visible (not during refetch)
- Add error handling and display for failed discoveries
Some local LLM servers (LM Studio, llama.cpp) expose OpenAI-compatible
APIs but don't support function calling. When tools are sent to these
models, they output raw control tokens instead of proper responses.
This change adds:
- openai_tools_disabled config field in AIConfig
- AreToolsDisabledForProvider() method to check at runtime
- API support to get/set the new setting
- Tests for the new functionality
When enabled and using a custom OpenAI base URL, the chat service will
skip sending tools to the model, allowing basic chat functionality to
work even with models that don't support function calling.
Fixes#1154
- Remove standalone pulse-assistant architecture doc (content lives in CLAUDE.md)
- Add CountdownTimer component for patrol schedule display
- Rewrite patrol handler test to focus on interval persistence
- Extract MockStateProvider to shared test file
Refactor Router to allow HTTP client injection for install script proxying. Add tests for unified agent install mechanism and additional metrics store coverage.
- Sync UserNote, AcknowledgedAt, SnoozedUntil, DismissedReason, Suppressed,
and TimesRaised from ai.Finding to unified store in both callback and
startup sync paths. Mirror note writes to unified store immediately.
- Dim acknowledged findings (opacity-60), add "Acknowledged" badge, hide
acknowledge button once acknowledged, sort below unacknowledged in
severity mode.
- Pass finding_id through frontend chat API → backend ChatRequest →
ExecuteRequest. Look up full finding from unified store (mutex-guarded)
and prepend structured context to the prompt.
- Add comprehensive tests for discovery_handlers.go (~75% coverage)
- Add tests for chat_service_adapter.go (previously 0% coverage)
- Fix missing API key issues in chat adapter tests by using ollama model configuration
Simplify server config by consolidating BackendHost and BackendPort into
a single BindAddress field. The port is now solely controlled by FrontendPort.
Changes:
- Replace BackendHost/BackendPort with BindAddress in Config struct
- Add deprecation warning for BACKEND_HOST env var (use BIND_ADDRESS)
- Update connection timeout default from 45s to 60s
- Remove backendPort from SystemSettings and frontend types
- Update server.go to use cfg.BindAddress
- Update all tests to use new config field names
- Update license_required error to mention 'Auto-fix' instead of
'Assisted and Full autonomy' for clearer user messaging
- Update full_mode_locked error to reference the UI toggle label
'Auto-fix critical issues' instead of internal field name