1416 Commits

Author SHA1 Message Date
rcourtman 6f582671b0 Fix Proxmox live chart CPU fallback
Refs #1525
2026-07-06 15:05:18 +01:00
rcourtman caa9b41834 Fix OIDC provider detail persistence
Refs #1521
2026-07-06 11:18:18 +01:00
rcourtman c9c5f34eb4 Fix host metric percent normalization
Apply token-gated command policy when deriving connection fleet state.
2026-07-06 10:08:36 +01:00
rcourtman 04a9e6ad3e Fix Proxmox agent install token isolation
Keep Proxmox setup tokens node-scoped so cluster installs do not rotate one shared Pulse API token.

Suppress command-enable config for tokens that cannot register command channels and keep reusable installer tokens out of agent:exec.
2026-07-05 17:21:34 +01:00
rcourtman c384d5e0c8 Prepare v6.0.3 patch release 2026-07-05 11:07:27 +01:00
rcourtman d029e4dc42 Fix demo fixture entitlement recovery
Seed the hidden demo fixture entitlement during stable demo updates so release builds can enable governed mock resources after runtime configuration is restored.

Keep the deployment contract and release policy checks aligned with the release-build entitlement gate.
2026-07-04 22:44:43 +01:00
rcourtman 313648b2f1 feat(mcp): add additive fleet-context filtering
get_fleet_context returned the whole registry with no way to narrow it,
so a large fleet produced a payload that exceeded the agent harness's
50KB cap and forced agents to receive or page through healthy resources
that are pure noise from a triage standpoint.

Add optional additive query-param filters — hasFindings, severity,
technology, resourceType — that compose by intersection. All optional
(omitting every filter returns the full fleet, backward compatible);
unknown/unmatched values return 200 with resources: [] (a valid triage
answer, not an error). The hasFindings=true filter is the headline
triage case: show me only what needs attention.

The MCP adapter layer had no GET query-param transport — ProjectCapabilityCall
short-circuited GET after path substitution and dropped all other args.
Close that gap generically: ProjectedCall gains a Query url.Values field
populated from leftover non-path public args for GET/DELETE, and
BuildCapabilityHTTPRequest encodes it onto the request URL. Benefits any
future GET capability with filter args, not just fleet-context. The
resources/list adapter calls fleet-context with empty args and continues
to receive the unfiltered fleet.

The manifest now declares the filters via inputSchema so they are
discoverable through the capability surface the same way add_node's
params are.

- ProjectedCall.Query + GET query-param forwarding (projection.go, http.go)
- fleetContextFilter parsing/matching in HandleFleetContext
- fleetContextInputSchema + InputSchema on the capability
- Regenerated cmd/pulse-mcp/README.md via generate-pulse-intelligence-docs
- Contract updates: api-contracts, ai-runtime, agent-lifecycle, storage-recovery
- Tests: adapter query-forwarding unit tests, 7 filter handler tests
  (hasFindings/severity/technology/resourceType/no-filter/unknown/compose),
  contract pinning inputSchema + end-to-end query forwarding
2026-07-03 18:01:05 +01:00
rcourtman 20c2f27057 feat(mcp): add list_resource_capabilities tool
Agents had no way to discover which governed capabilities a resource
advertises before calling plan_action. The data existed (Resource.Capabilities
with full param schemas) but was only surfaced as count-limited prose
facts inside get_resource_context, which deliberately omits parameter
schemas. This forced agents to guess capabilityName and params.

Add a dedicated structured surface: GET /api/agent/resource-capabilities/{id}
returns the canonical ResourceCapability list (name, type, approval level,
platform, full parameter schemas) for a single resource. A resource with
no advertised capabilities returns 200 with an empty array, the signal
to skip plan_action.

Internal plumbing already existed (registry.Get + Resource.Capabilities,
the same path plan_action validates against); this is the wiring work at
the canonical agent-surface layer. The tools/call dispatch is fully
generic so no mcp.go changes were needed.

Companion to get_resource_context: that tool remains the human-readable
prose summary; this is the structured schema surface for action planning.

- Manifest capability, name/path constants, output schema helper
- Handler mirroring HandleResourceContext error/scope patterns
- Route registration behind monitoring:read
- Activity telemetry mapping to resource_context class
- Regenerated cmd/pulse-mcp/README.md via generate-pulse-intelligence-docs
- Contract updates: api-contracts, ai-runtime, agent-lifecycle, storage-recovery
- Tests: manifest ownership/addressing/table-test, handler happy/empty/404/405,
  contract pinning capability presence/scope/wire-shape
2026-07-03 17:07:41 +01:00
rcourtman b1fdefdd50 Normalize Docker container CPU capacity
Refs #1293
2026-07-03 11:51:08 +01:00
rcourtman 875e414b4b Align resource staleness with poll cadence
Refs #1468
2026-07-03 09:05:12 +01:00
rcourtman dcf541784d Bound server state broadcast memory
Refs #1442
2026-07-02 23:27:49 +01:00
rcourtman dd357c1ef3 Fix hosted relay onboarding test setup
- seed connected relay status before building mobile onboarding payloads
2026-07-02 22:34:37 +01:00
rcourtman 97b9369333 Guard infrastructure import plan approvals
- add candidate import approval and preview gate for node onboarding
- document metrics, availability, and proxy role behavior
- lock config auth reads and preserve storage metrics fallback
2026-07-02 21:59:26 +01:00
rcourtman 6c9b4f8e8d Harden GA telemetry disclosure 2026-07-02 11:50:03 +01:00
rcourtman df67c01a64 Fix mobile relay runtime startup 2026-07-01 10:38:57 +01:00
rcourtman c0ac0762da Fix security scan findings
Harden proxy-auth admin role checks, metrics listener exposure, Teams webhook escaping, and dependency lockfiles.
2026-07-01 09:55:35 +01:00
rcourtman c759c9a77a Gate mobile pairing codes on relay readiness 2026-06-30 17:12:55 +01:00
rcourtman 229867636d Add resource priority to Patrol queue 2026-06-30 10:37:54 +01:00
rcourtman 4eac3b535c Accept ping alias for availability targets 2026-06-29 22:43:13 +01:00
rcourtman 597c369a63 Add alert delivery diagnosis endpoint 2026-06-29 22:27:01 +01:00
rcourtman 6b7d0b45f9 Add agent fleet diagnostics endpoint 2026-06-29 18:03:46 +01:00
rcourtman 73208a2863 Document state summary integration contract 2026-06-29 17:39:11 +01:00
rcourtman d6a21eba98 Add update funnel telemetry
Record anonymous 30-day update attempts, successes, failures, and coarse failure categories from local update history.
2026-06-28 15:19:39 +01:00
rcourtman 125959e4e0 fix(dev): login endpoint respects admin bypass mode
handleLogin rejected all credentials when ALLOW_ADMIN_BYPASS=1 because
it validated against config AuthUser/AuthPass directly without checking
the bypass flag. This made dev-mode browser testing impossible after a
backend restart with bypass env vars — the API middleware accepted all
requests but the login page could never obtain a session cookie.

When bypass is enabled, accept any credentials and create a session as
'admin'.
2026-06-27 16:09:23 +01:00
rcourtman 63d7640a06 Fix missing impact text and incomplete alert type coverage in unified findings
1. Add Impact field to findingView struct — was completely missing from
   the unified findings API response serialization.
2. Expand generateImpact() to cover all ~25 alert types the system
   produces. Previously only 7 had curated impact text.
3. Fix naming mismatches: poweredOff/nodeOffline never matched actual
   alert types powered-off/host-offline.
4. Expand TypeCategoryMap with all missing alert types.
2026-06-27 14:43:09 +01:00
rcourtman ad3b90e605 fix: ensure availability probes report at least 1ms latency on success
TCP probes to fast local-network services can complete in under 1ms,
causing latency.Milliseconds() to return 0. Combined with omitempty on
the poller status struct, this made some probes show 'Online' with no
latency in the settings panel. Now successful probes always report at
least 1ms.
2026-06-26 22:52:28 +01:00
rcourtman 06ea25e5ce Fix webhook private CIDR allowlist lost after monitor reload (#1507)
When a monitor reload was triggered by node auto-registration, the
reloadFunc in server.go recreated the monitor (and its notification
manager) but never re-applied system settings. The new notification
manager started with an empty webhook private CIDR allowlist, causing
webhook notifications to private IPs to fail until the allowlist was
manually re-saved in Settings.

Fix: call router.ReloadSystemSettings() at the end of reloadFunc,
after the new monitor references are set. This re-applies all
persisted system settings — including the webhook CIDR allowlist —
to the freshly created notification manager.

Refs #1507
2026-06-26 22:15:48 +01:00
rcourtman f5adf39c99 fix: stop reporting scheduler unhealthy when individual tasks are dead-lettered
The /api/health endpoint gated scheduler health on
DeadLetterCount()==0, causing a 503 whenever any single monitored
node became unreachable. Dead-lettered tasks are the scheduler
working as designed — after repeated failures the task is moved to
the dead-letter queue to prevent infinite retries.

In the live lab this manifested as a persistent 503 on /api/health
because the Pi node (192.168.0.2) times out on every poll cycle,
dead-lettering its task while the other 20+ tasks continue normally.

The scheduler is healthy when the monitor is running. Dead-letter
counts remain available as diagnostic info via the
/api/monitoring/scheduler/health endpoint.
2026-06-26 14:03:47 +01:00
rcourtman 9bcff2983d Clarify missing license public key activation error 2026-06-26 13:00:42 +01:00
rcourtman 62c2b765d0 feat: attach availability checks as facet on known resource row
Agentless availability checks (ICMP/TCP/HTTP) were always minting
standalone network-endpoint resources, leaving them disconnected from
the known Proxmox/Docker guest they actually monitor. This made
availability evidence invisible on the platform resource row where the
user expects it, per the performance-and-scalability bounded-row
contract.

Backend (unified-resources ingest):
- Add LinkedResourceID field to AvailabilityData and AvailabilityTarget
- resolveAvailabilityLink: explicit link first, then exact-IP unambiguous
  correlation; skip hostname-only (lossy); guard against overwriting a
  different target's facet
- Unlinked/unmatched probes still mint network-endpoint (fallback)

Frontend:
- Relax getAvailabilityProbePresentation for any resource with availability
- Add compact protocol badge to UnifiedResourceHostTableCard name cell
- Add optional 'Link to resource' field to availability target form
- Add linkedResourceId to frontend types

Contracts: api-contracts, unified-resources, monitoring,
performance-and-scalability, storage-recovery.

Governance: coverage_gap + candidate_lane in status.json.
2026-06-26 12:16:11 +01:00
rcourtman a4c5cfd26d Fix encoded resource type filters
Treat browser-encoded comma-separated resource type lists the same as literal comma filters so Docker and platform pages keep canonical inventory rows.
2026-06-25 20:20:35 +01:00
rcourtman 6dce36fbab Clarify Patrol current-work copy 2026-06-25 14:37:04 +01:00
rcourtman dd2f4c07fe alerts: offer manual targeted Patrol check from the alert AI button
The alert AI button now offers a manual targeted Patrol check alongside the
existing context-only Pulse Assistant handoff, so the take-the-lead intent routes
to Patrol (the investigator) instead of overloading Assistant (the explainer).

POST /api/ai/patrol/run (HandleForcePatrol) accepts an optional scope body and
routes through the same TriggerScopedPatrol engine and scoped run record as
automatic alert-triggered work, not a new trigger route; empty body keeps the
legacy fleet-wide run. Scoped runs honour Patrol readiness but bypass the
full-run cadence gate, consistent with the existing scoped-cadence rule, and
carry resource identity only (no command or remediation payload).

Frontend: triggerPatrolRun(scope?) and a split AI button (patrolOption) on the
alert overview card whose menu runs the scoped check; icon/history rows stay
single-purpose. Contract updates land in the touched/dependent subsystem docs
(ai-runtime, api-contracts, agent-lifecycle, storage-recovery, frontend-primitives,
security-privacy, patrol-intelligence, alerts); subsystem_lookup_test line
expectation refreshed for the api-contracts shift.
2026-06-25 08:49:29 +01:00
rcourtman c47560ad69 Fix websocket state broadcast retention
Refs #1442
2026-06-24 11:16:27 +01:00
rcourtman 1f6fe16e49 Make Z.ai provider base URL user-overridable
Z.ai keys on the coding subscription get 429 'Insufficient balance' on the standard /api/paas/v4 endpoint. Add a per-provider BaseURLField to the Z.ai registry entry, a ZaiBaseURL override on AIConfig (returned by GetBaseURLForProvider when set, else the standard default), the handler request/response/apply plumbing, and a 'Custom Base URL' field on the Z.ai provider card so operators can point at /api/coding/paas/v4. Mirrors the existing OpenAI custom-base-URL override; the standard endpoint remains the default for pay-as-you-go users. Adds config/handler/frontend proofs and updates the ai-runtime, api-contracts, frontend-primitives, agent-lifecycle, and storage-recovery contracts.
2026-06-23 22:49:55 +01:00
rcourtman 09fc029bd6 Canonicalize assistant provider registry
Add a registry-backed provider model for runtime metadata and chat-compatible transports.

Support Z.ai, Groq, Mistral, Cerebras, Together, and Fireworks through the shared chat-compatible client path while keeping native providers on their existing adapters. Expose provider metadata through settings and render the expanded provider set in the frontend.
2026-06-23 19:38:22 +01:00
rcourtman ee8a24e14a backend and governance: MCP contract, agent capabilities, API, and release-control
Manifest-backed MCP tools, prompts, and resources with surface affordance contracts; agent capability manifest and governance projection; API contract tests and capability route projection; operations-loop and intelligence-funnel telemetry; release-control subsystem documentation, registry, and tooling; licensing and configuration.
2026-06-23 17:26:15 +01:00
rcourtman 7235dcf504 Clarify Patrol event trigger runtime state
Expose runtime-blocked event triggers in Patrol status and surface the user-facing reason in the Patrol UI.
2026-06-15 10:08:54 +01:00
rcourtman cf7524d06a Fix Proxmox SMART disk temperature collection
Refs #1471
2026-06-14 10:57:46 +01:00
rcourtman 6c2a085bb8 Stabilize action plan drift hashing 2026-06-13 20:49:27 +01:00
rcourtman 11e0347991 Add governed Proxmox guest lifecycle actions 2026-06-13 14:11:32 +01:00
rcourtman ccfd6ee7b7 Fix Docker lifecycle command-agent dispatch 2026-06-13 11:50:09 +01:00
rcourtman 2a33c3a09a Add Docker action readiness reasons
Refs #1034
2026-06-12 23:58:24 +01:00
rcourtman 53a05ccb7c Fail closed Docker and Podman actions without agents
Refs #1034
2026-06-12 22:42:16 +01:00
rcourtman 6725d6a784 Add governed Docker and Podman lifecycle actions
Refs #1034
2026-06-12 21:17:58 +01:00
rcourtman b179b1782c Stabilize Proxmox guest Docker inventory 2026-06-12 12:10:54 +01:00
rcourtman eab067171c Clarify Proxmox Docker LXC host setup 2026-06-12 10:46:38 +01:00
rcourtman 55db13fc06 Fix CI test drift and SSE idle race
Refs Build and Test failures on pulse/v6-release.
2026-06-11 15:48:00 +01:00
rcourtman b1114f4986 Keep /api/health off the monitor write lock; tolerate load stalls in the dev watchdog
The liveness handler called SchedulerHealth(), which refreshes provider
instance caches under the monitor's write lock and snapshots queues and
breakers on every probe — it only needed the dead-letter count. Add
Monitor.DeadLetterCount() (queue-local mutex only) and use it.

The hot-dev watchdog killed the backend after 2 missed 3s probes; on a
dev box running race-detector test suites and builds that is routine
CPU starvation, and each kill destroyed any in-flight Assistant chat
stream (observed repeatedly during the chat-feel audit). Default the
miss threshold to 4 (~20s) — genuine wedges still die quickly.
2026-06-11 15:24:00 +01:00
rcourtman 201819f8f8 test(go): skip perf-budget overruns on contended local hosts, enforce in CI
A full local go test run on 2026-06-11 failed pkg/metrics while vite
builds were saturating the machine. Reproduced under synthetic 8-core
load: only the TestSLO_* wall-clock p95 assertions failed, never the
functional tests. A latency budget measured on a shared dev machine
cannot distinguish host contention from a code regression; load storms
inflated medians up to ~4x with no code change, so no absolute
threshold separates the two.

Route the latency SLO assertions (pkg/metrics, internal/api,
internal/monitoring) and the load/stress perf assertions (internal/api)
through helpers that keep strict enforcement on GitHub Actions runners
(controlled environment, existing hosted-runner envelopes unchanged)
and skip locally on overrun, printing the full p50/p95/p99
distribution in the skip message. A local pass still means the budget
was genuinely met. Error-response and correctness checks remain hard
failures. CI -race runs are unaffected: these tests already skip under
the race detector.

Verified: pkg/metrics, internal/api, and internal/monitoring all pass
with 8 CPU burners saturating the host, the scenario that previously
turned TestSLO_RollupTierBatchedFleet and four other budget tests red.
2026-06-11 13:12:59 +01:00