Commit Graph

2428 Commits

Author SHA1 Message Date
rcourtman 253bc56c19 Align storage recovery registry with Proxmox backup surface
Remove ownership and proof-policy references to Proxmox backup presentation files that were retired by the guest-centric backup surface, keeping the storage-recovery contract aligned with tracked runtime paths.
2026-06-01 00:22:27 +01:00
rcourtman a3e36d787f Remove the /install.sh GitHub proxy fallback; serve bundled agent installer or fail closed (#1470)
Root fix for the recurring class behind issue #1470. The served /install.sh and
/install.ps1 endpoints existed to hand out the unified AGENT installer, but their
GitHub fallback fetched the top-level install.sh release asset, which since
49412357a is the SERVER installer. Prior commits made that fallback unreachable
in normal deployments (deploy the sidecars; serve the local script even when
unsigned), but the endpoint was still structurally capable of serving the wrong
script in the no-local-bundle case.

The agent installer is a per-build artifact bundled into every release tarball and
Docker image, not a release asset, so the endpoint has no business proxying a
release asset at all. Remove proxyInstallScriptFromGitHub and its
installScriptReleaseAssetURL wrapper. handleDownloadInstallScriptCommon now serves
the locally bundled agent installer (signed when sidecars are present, unsigned
otherwise) or fails closed with 503 when no bundled script exists. Serving the
SERVER installer at this endpoint is now structurally impossible, not merely
unreachable.

The shared version-pinning (releaseAssetTag/releaseAssetURL) and installScriptClient
remain for the agent-BINARY download proxy, which legitimately fetches published
release assets; its version-pinning stays covered by the agentBinaryReleaseAssetURL
contract tests.

Replace the obsolete install-script proxy tests with fail-closed assertions
(including a guard that the endpoint makes no outbound call), drop the four
installScriptReleaseAssetURL contract tests, and revise the four subsystem
contracts that pinned the install-script fallback transport (api-contracts items
8 and 27, agent-lifecycle item 14, storage-recovery item 14, plus the
deployment-installability note) to state that install scripts are served local or
fail closed with no GitHub fallback.
2026-05-29 14:51:18 +01:00
rcourtman 191ddfdfc8 Never serve the server installer at /install.sh; serve local agent installer (#1470)
The "Install on Linux/Windows" wizard does `curl -fsSL <server>/install.sh |
bash -s -- --url ...` and never verifies the response signature headers (curl|bash
discards them). But for published releases handleDownloadInstallScriptCommon
proxied the top-level GitHub install.sh asset whenever the local agent installer
lacked its .sig/.sshsig sidecars, and since 49412357a that asset is the SERVER
installer, which rejects --url. Every install missing the sidecars served the
wrong script. The companion deploy_agent_scripts fix deploys the sidecars for new
installs, but existing boxes stay broken until they redeploy.

Serve the locally bundled agent installer when its signatures are absent instead
of proxying. An unsigned-but-correct local script beats a signed-but-wrong proxied
one when nothing verifies the headers, and this retroactively fixes already-deployed
boxes the moment they get the new binary. The proxy now runs only when no local
installer is bundled at all, so the endpoint can no longer hand the agent wizard a
server installer in any reachable deployment state. New installs still ship the
sidecars and are served signed.

Revise the install-script signature/fallback contract this changes, across the
three subsystems that pin it (api-contracts item 8, agent-lifecycle item 14,
storage-recovery item 14) plus the deployment-installability note, to state that
the served endpoint serves the agent installer with correctness outranking
signature presence. Add a handler guard asserting a published-release server with
a present-but-unsigned local installer serves it locally and does not proxy.
2026-05-29 14:19:04 +01:00
rcourtman 7b2cac08bd Fix /install.sh agent wizard on LXC/systemd installs (issue #1470)
The running server serves the unified AGENT installer at its /install.sh
endpoint, which the "Install on Linux" wizard fetches with --url/--token-file.
For published releases handleDownloadInstallScriptCommon only serves the local
/opt/pulse/scripts/install.sh when its .sig and .sshsig sidecars sit next to it;
otherwise it proxies the top-level GitHub install.sh asset. Since 49412357a that
asset is the SERVER installer (LXC/systemd quickstart, --version), so the proxy
now hands the agent wizard a server installer that rejects --url with
"Unknown option".

deploy_agent_scripts copied only the .sh/.ps1 files, never the sidecars, so every
published-release LXC/systemd install always hit the proxy and served the wrong
script. The Docker image already deploys both sidecars (Dockerfile); LXC/systemd
did not. This was latent across rc.1-rc.5 (the proxied asset was the agent
installer then) and surfaced in rc.6 once the asset flipped to the server
installer.

Deploy the .sig/.sshsig sidecars alongside each script so the endpoint serves
the local agent installer and never falls back to the server-installer asset.
Add a behavioral guard that runs deploy_agent_scripts and asserts the sidecars
land next to the served script, and document the served-endpoint sidecar
requirement in the deployment-installability contract.
2026-05-29 13:49:14 +01:00
rcourtman 8177ee1788 Fix Proxmox guest memory fallback
Prefer QEMU guest-agent MemAvailable when Proxmox reports saturated VM memory without guest free fields.

Add regression coverage for the issue #1319 Windows fsinfo volume payload so usable C/E/F volumes remain counted while System Reserved partitions are skipped.

Refs #1319
2026-05-29 11:44:29 +01:00
rcourtman a631381abb fix(patrol): disambiguate alert-driven AI toggles in config panel
Rename the Pro-gated "Alert-Triggered Analysis" toggle to "Container
Update Risk" with container-update-scoped copy. The enterprise
AlertTriggeredAnalyzer only assesses docker-container-update alerts and
returns nil for all other types, so the old general name was misleading
and collided with the genuinely general "Alert-Triggered Patrols"
control. Reorder the panel so the explanatory box leads, followed by
Alert-Triggered Patrols plus its severity selector, Anomaly-Triggered
Patrols, Container Update Risk, then Autonomous critical remediation.

The rename is presentation-only: persisted settings keys
(alert_triggered_analysis, patrol_alert_triggers_enabled,
patrol_alert_trigger_min_severity) are unchanged.
2026-05-28 23:11:54 +01:00
rcourtman 9be163324d Add optional dedicated agent-ingest listener (PULSE_AGENT_INGEST_PORT)
Operators can set PULSE_AGENT_INGEST_PORT to serve agent report and
management traffic (/api/agents/*) on a second listener, so that surface
can be placed on its own network or firewall boundary without exposing
the web UI or the rest of the REST API on that port. The dedicated port
serves only the /api/agents/* prefix and 404s everything else.

The option is additive and fail-closed: it is disabled at 0, the main
listener keeps serving agent ingest so existing single-port deployments
and agents are unaffected, and validation rejects out-of-range ports or
collisions with the frontend or HTTP redirect ports.
2026-05-28 22:55:38 +01:00
rcourtman 2f0a5a818f Make alert-triggered Patrol investigate the specific breach
Previously an alert that triggered Patrol ran a broad health check that
explicitly ignored the threshold breach. Now an alert carries its real
payload (metric type, value, threshold, identifier, level, message) into
the patrol scope, and the alert_fired run is framed around root-causing
that specific breach instead of a general assessment.

Three coordinated changes:

- Carry the alert payload into PatrolScope.AlertContext through the alert
  bridge (PatrolTriggerEvent), so the patrol prompt sees the breach
  specifics rather than just an alert-type string.
- Frame alert_fired patrol runs around the breach: replace the
  "ignore threshold breaches" instruction with a root-cause directive
  targeting the alert's metric and threshold.
- Add per-rule control via AIConfig.AlertTriggersInvestigation: a master
  enable, a minimum-severity floor (patrol_alert_trigger_min_severity,
  default critical-only), and an optional alert-type allowlist
  (patrol_alert_trigger_types). The router's bridge callback consults the
  policy and drops non-qualifying alert_fired events before queuing a
  scoped patrol. A config-panel selector persists the severity floor.

Adds config, handler, and frontend proof tests, and updates the affected
subsystem contracts.
2026-05-28 22:42:32 +01:00
rcourtman 87604edb21 Add hosted MSP signup front door to the cloud control plane
Adds public self-serve signup for the hosted MSP offering alongside the
existing individual Cloud signup page. New handlers serve /cloud/msp/signup,
/cloud/msp/signup/complete, and /api/public/msp/signup, gated behind the same
PublicCloudSignupEnabled flag. Per-tier Stripe prices
(CP_MSP_STARTER_PRICE_ID, CP_MSP_GROWTH_PRICE_ID, CP_MSP_SCALE_PRICE_ID) are
validated against the canonical msp_starter/growth/scale plan versions; the
page renders an explicit "not open yet" notice when no MSP price is
configured. Checkout sessions carry account_kind=msp metadata so the
provisioner seeds an isolated operator workspace. The cloud and MSP JSON
signup endpoints now share one checkout skeleton parameterized per path.
2026-05-28 22:38:15 +01:00
rcourtman 05abf07219 Add Kubernetes, TrueNAS, and vSphere alert targets 2026-05-28 18:23:14 +01:00
rcourtman 75d1a0477b Enforce upgrade readiness before v6 updates
Refs #1476
2026-05-28 17:22:01 +01:00
rcourtman e1d1ec1d7c Add update readiness checks for v6 upgrades
Surface server upgrade readiness on update plans so v5 agent continuity and agent token scope issues are checked before install.
2026-05-28 16:47:49 +01:00
rcourtman 94992685d1 Capture continuous discovery reconciliation 2026-05-28 16:42:01 +01:00
rcourtman aa4a5fa631 Add agent provisioning capabilities 2026-05-28 16:31:19 +01:00
rcourtman f7a40f3a22 Add Proxmox setup doctor repair flow 2026-05-28 15:51:31 +01:00
rcourtman 7297aae4af Fix late issue triage regressions
Refs #1341

Refs #1429

Refs #1469

Refs #1472

Refs #1476

Refs #1481
2026-05-28 14:49:20 +01:00
rcourtman 47e9eb9aea Reconcile Ceph pool alert identity
Refs #1341
2026-05-28 14:42:43 +01:00
rcourtman 5a22b04c4c Harden audit log store failures
Refs #1464
2026-05-28 13:44:20 +01:00
rcourtman c05eed4306 Fix TrueNAS unavailable SMART disk health
Refs #1474

Separate TrueNAS native disk state from SMART health so null or unavailable smart_status projects as UNKNOWN without replacement risk, while explicit SMART failure and native failure states still alert.

Proof:

- go test ./internal/truenas ./internal/unifiedresources ./internal/storagehealth

- npm --prefix frontend-modern test -- src/features/storageBackups/__tests__/diskPresentation.test.ts
2026-05-28 12:53:46 +01:00
rcourtman a84867c044 Expand anonymous telemetry adoption coverage 2026-05-28 11:39:30 +01:00
rcourtman b0a1937106 Rename Docker runtime navigation label 2026-05-27 21:02:19 +01:00
rcourtman 8769f07eea Land SMART/SSH temperature feature, rc.6 finalization, and post-IA-revert governance reconciliation 2026-05-27 15:27:25 +01:00
rcourtman 84c43ad3e1 Fix Windows agent installer readiness path 2026-05-26 10:19:56 +01:00
rcourtman 6f4a9ca88b Show backup age in workload rows 2026-05-26 10:05:40 +01:00
rcourtman d6f2ec202d Simplify Proxmox backup recovery navigation 2026-05-26 09:45:05 +01:00
rcourtman c1a4f4579e Align Windows agent onboarding with seamless install flow 2026-05-26 09:29:03 +01:00
rcourtman a0b75792a4 Add Proxmox backup recovery coverage views 2026-05-26 09:19:45 +01:00
rcourtman d5589cc8ca Make agent machine onboarding seamless 2026-05-26 09:07:59 +01:00
rcourtman 1e16cf34f5 Keep Machines limited to Pulse Agent resources 2026-05-26 07:45:16 +01:00
rcourtman 3561803d76 Add pingable machine availability preset 2026-05-26 07:37:49 +01:00
rcourtman 95500b0376 Clarify availability check add flows 2026-05-26 06:14:06 +01:00
rcourtman 7cf0a474ee Rename Standalone surface to Machines 2026-05-25 21:51:31 +01:00
rcourtman 7470b62a01 Fix Proxmox PBS backup artifact surface 2026-05-25 21:47:12 +01:00
rcourtman bfafe559f6 Classify agentless machine availability targets 2026-05-25 21:38:43 +01:00
rcourtman 4721f3d1c0 Fix resolved notifications after direct alert dispatch
Refs #1350
2026-05-25 20:18:52 +01:00
rcourtman f2e3169b12 Rename Standalone default tab to Machines 2026-05-25 18:07:55 +01:00
rcourtman ed67706824 Keep Standalone availability checks in focused tab 2026-05-25 17:51:09 +01:00
rcourtman 697634da76 Consolidate Standalone IA governance 2026-05-25 17:28:22 +01:00
rcourtman ce37d78772 Normalize Standalone landing decision 2026-05-25 17:19:46 +01:00
rcourtman ed1770c4f4 Rename Agents surface to Standalone 2026-05-25 17:15:31 +01:00
rcourtman d6f60963a1 Show availability checks on Agents page 2026-05-25 16:44:16 +01:00
rcourtman 322457c03b Move availability checks to monitoring settings 2026-05-25 16:08:47 +01:00
rcourtman bfc79ff06d Retire remaining settings route aliases 2026-05-25 15:10:33 +01:00
rcourtman cfb16e6da1 Retire legacy settings infrastructure aliases 2026-05-25 14:07:17 +01:00
rcourtman 3c0bd12fc6 Retire aggregate route-state path builders 2026-05-25 13:42:26 +01:00
rcourtman 3f9c8168fb Retire legacy top-level browser aliases 2026-05-25 13:16:42 +01:00
rcourtman 8b0b1b0c6e Retire aggregate top-level workspace routes 2026-05-25 12:34:57 +01:00
rcourtman c9be4c86f2 Clarify aggregate workspace routes 2026-05-25 11:43:35 +01:00
rcourtman e38f0b8e1f Remove legacy infrastructure route 2026-05-25 11:04:38 +01:00
rcourtman 052e344e1b Add Kubernetes RBAC inventory to the agent + canonical + UI
Closes the only API-coverage gap from the Docker / Kubernetes IA
maturity review: Roles, ClusterRoles, RoleBindings, and
ClusterRoleBindings now flow from the Kubernetes agent through the
canonical resource registry into the Kubernetes platform-page
Configuration tab.

Agent: pkg/agents/kubernetes/report.go gains four new report struct
types that carry summary counts plus subject-kind sets; individual
subject names and full PolicyRule contents are deliberately omitted
so Pulse stays a "what permissions exist where" surface, not an RBAC
enumeration tool. internal/kubernetesagent/agent.go gains four
collectors that call rbacv1.RoleList/ClusterRoleList/etc. through the
existing runKubernetesCallWithRetry wrapper, matching the
ServiceAccount collector's RBAC-forbidden retry pattern.

Canonical: internal/models mirrors with NormalizeCollections coverage;
convert* funcs in internal/monitoring/kubernetes_agents.go translate
agent report -> model; ResourceTypeK8sRole / K8sClusterRole /
K8sRoleBinding / K8sClusterRoleBinding join the canonical type set;
registry ingest* + adapter resourceFrom* functions emit one Resource
per RBAC object with ruleCount / roleKind / roleName / subjectCount /
subjectKinds / aggregationLabels on the K8s meta; search mapping in
internal/api/resources.go and the privacy allow-list in
internal/api/org_handlers.go pick up the four new type tokens; the
K8s privacy category in unifiedresources/policy_metadata.go classifies
them like the rest of K8s.

Frontend: ResourceType union + ResourceKubernetesMeta carry the new
kinds and RBAC summary fields; KubernetesPageSurface query asks for
them; the page model buckets them into the Configuration group;
KubernetesConfigTable renders Role / ClusterRole rule counts and the
aggregated flag, plus RoleBinding / ClusterRoleBinding role refs and
"N subjects · Kind1, Kind2 +overflow" subject summaries.

Curated demo seeds per-namespace Roles + RoleBindings plus an
aggregated ClusterRole + ClusterRoleBinding for pulse-demo-monitoring
in each cluster so the Configuration tab renders 18 RBAC rows across
the three demo clusters.

Contracts updated for the canonical-shape guard: monitoring,
api-contracts, unified-resources, frontend-primitives,
organization-settings (canonical) plus agent-lifecycle and
storage-recovery (dependent via Extension Points). Verification
proofs extended: kubernetes_registry_test.go, kubernetes_agents_test.go,
agent_inventory_test.go (new TestCollectRBACInventoryReportsSummaryCountsOnly
that pins the subject-name-omission contract), demo_scenarios_test.go,
adapter_coverage_test.go, contract_test.go, org_handlers_test.go,
resourceIdentity.test.ts, reportingResourceTypes.test.ts,
KubernetesConfigTable.test.tsx, and the
subsystem_lookup_test.py line-anchor bumps that the contract edits
shifted (api-contracts 246 -> 253, organization-settings 92 -> 93).

Verified:
- go build ./internal/... ./cmd/... clean
- go test ./internal/unifiedresources/..., ./internal/mock/...,
  ./internal/kubernetesagent/..., ./internal/api/...,
  the K8s subset of ./internal/monitoring/... all clean (three
  pre-existing unrelated monitoring failures noted earlier remain
  unchanged by this commit)
- npm run type-check, lint:eslint, lint:theme,
  lint:canonical-platforms clean
- vitest: 70 K8s frontend tests pass including the new RBAC render
  coverage in KubernetesConfigTable.test.tsx
- browser proof on /kubernetes/configuration: 36 config rows
  including 18 RBAC rows across three clusters; ClusterRole
  "pulse-demo-monitoring" shows "12 rules · Aggregated";
  ClusterRoleBinding shows "3 subjects · Group, ServiceAccount +1"
2026-05-25 09:25:03 +01:00