mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-10-19 10:33:29 +00:00
docs: publish security review evidence
This commit is contained in:
parent
effcf2d50c
commit
787a191a5e
12 changed files with 458 additions and 26 deletions
|
|
@ -175,3 +175,11 @@ and measure their own workload.
|
|||
Pulse is intended to be the operational monitoring layer for the platforms it
|
||||
supports. It is not a SIEM, a general log-ingestion platform, or a substitute
|
||||
for an organization's incident escalation and change-control process.
|
||||
|
||||
## Independent review
|
||||
|
||||
Pulse does not currently claim an independent security certification. The
|
||||
[Independent Security Review Scope](SECURITY_REVIEW.md) maps the main trust
|
||||
boundaries to source files, tests, reproducible baseline commands, and the
|
||||
private disclosure channel so external reviewers can evaluate concrete
|
||||
behavior rather than marketing claims.
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ Pulse Pro capabilities.
|
|||
## Security, privacy, and access
|
||||
|
||||
- [Production deployment and security](PRODUCTION_SECURITY.md)
|
||||
- [Independent security review scope](SECURITY_REVIEW.md)
|
||||
- [Security guide](../SECURITY.md)
|
||||
- [Privacy and telemetry disclosure](PRIVACY.md)
|
||||
- [OIDC and SSO](OIDC.md)
|
||||
|
|
|
|||
160
docs/SECURITY_REVIEW.md
Normal file
160
docs/SECURITY_REVIEW.md
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
# Independent Security Review Scope
|
||||
|
||||
Pulse does not currently claim an independent security certification or a
|
||||
third-party penetration-test attestation. This page gives reviewers a concrete,
|
||||
reproducible starting point and makes the intended trust boundaries explicit.
|
||||
|
||||
Before reviewing the code, read:
|
||||
|
||||
- [Production Deployment and Security](PRODUCTION_SECURITY.md) for the
|
||||
least-privilege deployment model and operational checklist;
|
||||
- the canonical [Security Policy](../SECURITY.md) for reporting and hardening;
|
||||
- [Agent Security](AGENT_SECURITY.md) for root privilege, command execution,
|
||||
guest access, and update verification;
|
||||
- [Installation](INSTALL.md) for the signed, version-pinned server installer.
|
||||
|
||||
## Suggested review boundaries
|
||||
|
||||
### 1. Authentication, authorization, and tenant isolation
|
||||
|
||||
Review browser sessions, API-token scopes, organization binding, proxy
|
||||
authentication, and denial behavior. Confirm that a credential valid for one
|
||||
route or organization cannot acquire management, agent, or cross-tenant
|
||||
authority elsewhere.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `internal/api/auth.go`
|
||||
- `internal/api/authorization.go`
|
||||
- `internal/api/middleware.go`
|
||||
- `internal/api/api_token_scope_transport_integration_test.go`
|
||||
- `internal/api/middleware_tenant_authorization_test.go`
|
||||
- `pkg/auth/`
|
||||
|
||||
### 2. Credential storage and configuration transfer
|
||||
|
||||
Review encryption-key creation and permissions, AES-GCM use, encrypted
|
||||
configuration persistence, backup/restore behavior, and export/import
|
||||
authorization. Confirm that missing or unsafe key material fails closed rather
|
||||
than silently replacing a key and orphaning encrypted data.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `internal/crypto/crypto.go`
|
||||
- `internal/crypto/crypto_test.go`
|
||||
- `internal/config/persistence.go`
|
||||
- `internal/config/persistence_fail_test.go`
|
||||
- `internal/api/config_transfer_authorization.go`
|
||||
- `internal/api/config_transfer_authorization_test.go`
|
||||
|
||||
### 3. Agent privilege and command authority
|
||||
|
||||
Review the Linux agent's default root profile as a privileged monitoring
|
||||
boundary. Confirm that command execution remains disabled by default, enabling
|
||||
it does not bypass policy and approval, report-only credentials cannot acquire
|
||||
execution authority, and agent health endpoints remain loopback-bound unless
|
||||
explicitly changed.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `cmd/pulse-agent/main.go`
|
||||
- `internal/agentexec/`
|
||||
- `internal/api/agent_command_authorization.go`
|
||||
- `internal/api/agent_command_authorization_test.go`
|
||||
- `scripts/install.sh`
|
||||
- `docs/AGENT_SECURITY.md`
|
||||
|
||||
### 4. Installer and update supply chain
|
||||
|
||||
Review the server installer's release pinning and Ed25519 verification, agent
|
||||
checksum and signature enforcement, executable validation, self-test, and
|
||||
atomic replacement behavior. Include the documented first automatic v5-to-v6
|
||||
agent update limitation in the threat model.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `install.sh`
|
||||
- `docs/INSTALL.md`
|
||||
- `internal/agentupdate/update.go`
|
||||
- `internal/agentupdate/update_http_test.go`
|
||||
- `.github/workflows/create-release.yml`
|
||||
- `docs/CODE_SIGNING_POLICY.md`
|
||||
|
||||
### 5. Discovery and outbound network boundaries
|
||||
|
||||
Confirm that network discovery is disabled by default, probes only the
|
||||
documented Proxmox ports, honors subnet allowlists and blocklists, and applies
|
||||
host, concurrency, and timeout bounds. Review outbound URL validation and SSRF
|
||||
protections for integrations and probes.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `internal/config/config.go`
|
||||
- `internal/discovery/`
|
||||
- `pkg/discovery/`
|
||||
- `internal/securityutil/outbound_http.go`
|
||||
- `pkg/securityutil/outbound_http.go`
|
||||
|
||||
### 6. Container and host separation
|
||||
|
||||
Review the block on storing host SSH private keys inside Pulse containers,
|
||||
Docker/Podman socket handling, Proxmox guest inventory opt-ins, and data-volume
|
||||
permissions. Confirm that API-only Proxmox monitoring does not require Pulse
|
||||
software on the hypervisor.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `SECURITY.md`
|
||||
- `docs/AGENT_SECURITY.md`
|
||||
- `internal/hostagent/proxmox_lxc_filesystems.go`
|
||||
- `internal/monitoring/docker_detection.go`
|
||||
- `internal/api/contract_test.go`
|
||||
- `internal/dockeragent/`
|
||||
|
||||
### 7. Production-scale failure behavior
|
||||
|
||||
Review behavior under concurrent reads and writes, stale data, partial platform
|
||||
responses, retention, and large resource sets. Pulse includes simulated
|
||||
500-node API and metrics-store regression coverage; treat that as reproducible
|
||||
engineering evidence, not as a production certification.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `internal/api/load_test.go`
|
||||
- `pkg/metrics/store_loadtest_test.go`
|
||||
- `pkg/metrics/store_slo_test.go`
|
||||
|
||||
## Reproducible baseline
|
||||
|
||||
From a clean checkout with the documented Go and Node versions installed:
|
||||
|
||||
```bash
|
||||
go test ./internal/crypto ./pkg/auth ./internal/agentupdate \
|
||||
./internal/agentexec ./internal/discovery ./pkg/discovery \
|
||||
./internal/securityutil ./pkg/securityutil
|
||||
|
||||
go test ./internal/api \
|
||||
-run '^TestLoad_500Node_(ConcurrentResources|ConcurrentMetricsHistory|MixedEndpoints)$' \
|
||||
-count=1
|
||||
|
||||
go test ./pkg/metrics \
|
||||
-run '^TestLoadTest500Nodes_WriteAndQueryIntegration$' \
|
||||
-count=1
|
||||
|
||||
python3 scripts/check_public_docs.py
|
||||
```
|
||||
|
||||
These commands are a baseline, not a substitute for manual review, dependency
|
||||
analysis, fuzzing, deployment-specific testing, or an independent threat model.
|
||||
|
||||
## Reporting findings
|
||||
|
||||
Please report suspected vulnerabilities privately to
|
||||
<security@pulseapp.io>. Include the affected version or commit, deployment
|
||||
model, required privileges, reproduction steps, expected impact, and any
|
||||
suggested containment. Do not include live credentials or customer data.
|
||||
|
||||
General defects and hardening suggestions that do not disclose an exploitable
|
||||
weakness can use the public [issue tracker](https://github.com/rcourtman/Pulse/issues).
|
||||
The canonical disclosure contact and current security guidance remain in the
|
||||
[Security Policy](../SECURITY.md).
|
||||
|
|
@ -6165,6 +6165,25 @@ it is read from the purchase-start query, validated, and passed to the
|
|||
license-server portal handoff. No agent enrollment, report, ack, or update
|
||||
route reads or emits it, and the agent-facing payload shapes are unchanged.
|
||||
|
||||
### Generic host onboarding preserves API-first Proxmox setup
|
||||
|
||||
`frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx`
|
||||
now makes the least-privilege Proxmox choice visible before an operator copies
|
||||
a host-agent command. The generic host installer remains canonical for
|
||||
host-local, Docker, and Kubernetes telemetry, but it routes PVE and PBS users
|
||||
to the existing platform-connection flows first and states that normal
|
||||
Proxmox inventory and metrics do not require a root agent. The root agent stays
|
||||
an explicit augmentation for SMART, temperatures, and host-local storage
|
||||
detail. `ConnectionEditor` also reconciles its selected credential slot when a
|
||||
direct onboarding route changes in place, so following the PVE or PBS link from
|
||||
the already-mounted agent dialog replaces the agent installer with the matching
|
||||
API credential form instead of changing only the dialog title. This adds no
|
||||
enrollment, token, command, report, discovery, or update authority and does not
|
||||
replace the existing PVE or PBS setup handlers. Source guards in
|
||||
`InfrastructureOperationsModel.test.tsx` and `ConnectionEditor.test.tsx` pin
|
||||
the API-first copy, both canonical onboarding routes, and the reactive
|
||||
credential-slot handoff.
|
||||
|
||||
### Platform connection panel state waits on the infrastructure capability
|
||||
|
||||
`Settings.tsx` constructs `useInfrastructureSettingsState` for every settings
|
||||
|
|
|
|||
|
|
@ -1,18 +1,19 @@
|
|||
{
|
||||
"version": 1,
|
||||
"base_sha": "d3a345bd66d635b59427cdfb06bd030a053daded",
|
||||
"verified_at": "2026-08-15T09:17:52Z",
|
||||
"base_sha": "effcf2d50c076310c36aba0876a69b3178587e10",
|
||||
"verified_at": "2026-08-16T09:16:52Z",
|
||||
"result": "passed",
|
||||
"changed_paths": [
|
||||
"frontend-modern/src/api/patrolAttention.ts",
|
||||
"frontend-modern/src/features/patrol/PatrolRecentWorkPanel.tsx"
|
||||
"frontend-modern/src/components/Settings/ConnectionEditor/ConnectionEditor.tsx",
|
||||
"frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx"
|
||||
],
|
||||
"content_sha256": {
|
||||
"frontend-modern/src/api/patrolAttention.ts": "035e201a4c9a67c230f67004113b632c8e9ee82edf36bea0acaf86d5b9725b0e",
|
||||
"frontend-modern/src/features/patrol/PatrolRecentWorkPanel.tsx": "b62d2cd4ccd5c2da4442a54d04863047f667fa5f076975046d3c2a0dc15e560e"
|
||||
"frontend-modern/src/components/Settings/ConnectionEditor/ConnectionEditor.tsx": "1c6289caaad0230b2a1e3301235c701c760182f203dc0af7170972b8a11768e8",
|
||||
"frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx": "8007a0da1ef3140cc32174dea3bf52857aa351441d0011f862c3fd27b83649a2"
|
||||
},
|
||||
"routes": [
|
||||
"/patrol"
|
||||
"/settings/infrastructure?add=agent",
|
||||
"/settings/infrastructure?add=pve"
|
||||
],
|
||||
"viewports": [
|
||||
{
|
||||
|
|
@ -25,19 +26,16 @@
|
|||
}
|
||||
],
|
||||
"states": [
|
||||
"Recently handled populated with six newest server-filtered verified Patrol receipts in calm operator language",
|
||||
"Raw executor lifecycle telemetry and full opaque resource ids are absent from the compact receipt list",
|
||||
"Executing-agent and independent-observer trust labels render from the canonical evidence class",
|
||||
"Refresh failure keeps the last truthful receipts visible with an explicit unavailable message",
|
||||
"Refresh recovery clears the error and reloads the same six verified receipts",
|
||||
"Activity history handoff remains adjacent to verified receipts",
|
||||
"Phone-width receipt list stays within the 390-pixel document width"
|
||||
"Agent installer explains that Proxmox inventory and metrics start with a narrowly scoped API token and do not require a root agent",
|
||||
"API-first guidance links to PVE, PBS, and the production security model before the install-token step",
|
||||
"PVE route displays the API credential form with API Token selected and the least-privilege API inventory explanation",
|
||||
"Desktop dialogs remain within the 1280-pixel document width",
|
||||
"Phone-width agent and PVE dialogs remain within the 390-pixel document width"
|
||||
],
|
||||
"interactions": [
|
||||
"refreshed the populated Recently handled list and confirmed compact action, trust, and resource presentation",
|
||||
"stopped the disposable server and refreshed to exercise the error state",
|
||||
"confirmed six existing receipts remained visible during the refresh error",
|
||||
"restored the healthy server and refreshed to clear the error",
|
||||
"resized to 390 by 844 and confirmed document width stayed at 390"
|
||||
"opened the generic Pulse Agent onboarding route and inspected the API-first guidance",
|
||||
"followed Connect Proxmox VE through the API and confirmed the mounted dialog retargeted from the agent installer to the PVE credential form",
|
||||
"repeated the agent-to-PVE handoff at 390 by 844 and confirmed the API inventory and root-boundary copy remained visible",
|
||||
"confirmed document and dialog widths at desktop and phone viewports without horizontal overflow"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,3 +175,11 @@ and measure their own workload.
|
|||
Pulse is intended to be the operational monitoring layer for the platforms it
|
||||
supports. It is not a SIEM, a general log-ingestion platform, or a substitute
|
||||
for an organization's incident escalation and change-control process.
|
||||
|
||||
## Independent review
|
||||
|
||||
Pulse does not currently claim an independent security certification. The
|
||||
[Independent Security Review Scope](SECURITY_REVIEW.md) maps the main trust
|
||||
boundaries to source files, tests, reproducible baseline commands, and the
|
||||
private disclosure channel so external reviewers can evaluate concrete
|
||||
behavior rather than marketing claims.
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ Pulse Pro capabilities.
|
|||
## Security, privacy, and access
|
||||
|
||||
- [Production deployment and security](PRODUCTION_SECURITY.md)
|
||||
- [Independent security review scope](SECURITY_REVIEW.md)
|
||||
- [Security guide](../SECURITY.md)
|
||||
- [Privacy and telemetry disclosure](PRIVACY.md)
|
||||
- [OIDC and SSO](OIDC.md)
|
||||
|
|
|
|||
160
frontend-modern/public/docs/SECURITY_REVIEW.md
Normal file
160
frontend-modern/public/docs/SECURITY_REVIEW.md
Normal file
|
|
@ -0,0 +1,160 @@
|
|||
# Independent Security Review Scope
|
||||
|
||||
Pulse does not currently claim an independent security certification or a
|
||||
third-party penetration-test attestation. This page gives reviewers a concrete,
|
||||
reproducible starting point and makes the intended trust boundaries explicit.
|
||||
|
||||
Before reviewing the code, read:
|
||||
|
||||
- [Production Deployment and Security](PRODUCTION_SECURITY.md) for the
|
||||
least-privilege deployment model and operational checklist;
|
||||
- the canonical [Security Policy](../SECURITY.md) for reporting and hardening;
|
||||
- [Agent Security](AGENT_SECURITY.md) for root privilege, command execution,
|
||||
guest access, and update verification;
|
||||
- [Installation](INSTALL.md) for the signed, version-pinned server installer.
|
||||
|
||||
## Suggested review boundaries
|
||||
|
||||
### 1. Authentication, authorization, and tenant isolation
|
||||
|
||||
Review browser sessions, API-token scopes, organization binding, proxy
|
||||
authentication, and denial behavior. Confirm that a credential valid for one
|
||||
route or organization cannot acquire management, agent, or cross-tenant
|
||||
authority elsewhere.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `internal/api/auth.go`
|
||||
- `internal/api/authorization.go`
|
||||
- `internal/api/middleware.go`
|
||||
- `internal/api/api_token_scope_transport_integration_test.go`
|
||||
- `internal/api/middleware_tenant_authorization_test.go`
|
||||
- `pkg/auth/`
|
||||
|
||||
### 2. Credential storage and configuration transfer
|
||||
|
||||
Review encryption-key creation and permissions, AES-GCM use, encrypted
|
||||
configuration persistence, backup/restore behavior, and export/import
|
||||
authorization. Confirm that missing or unsafe key material fails closed rather
|
||||
than silently replacing a key and orphaning encrypted data.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `internal/crypto/crypto.go`
|
||||
- `internal/crypto/crypto_test.go`
|
||||
- `internal/config/persistence.go`
|
||||
- `internal/config/persistence_fail_test.go`
|
||||
- `internal/api/config_transfer_authorization.go`
|
||||
- `internal/api/config_transfer_authorization_test.go`
|
||||
|
||||
### 3. Agent privilege and command authority
|
||||
|
||||
Review the Linux agent's default root profile as a privileged monitoring
|
||||
boundary. Confirm that command execution remains disabled by default, enabling
|
||||
it does not bypass policy and approval, report-only credentials cannot acquire
|
||||
execution authority, and agent health endpoints remain loopback-bound unless
|
||||
explicitly changed.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `cmd/pulse-agent/main.go`
|
||||
- `internal/agentexec/`
|
||||
- `internal/api/agent_command_authorization.go`
|
||||
- `internal/api/agent_command_authorization_test.go`
|
||||
- `scripts/install.sh`
|
||||
- `docs/AGENT_SECURITY.md`
|
||||
|
||||
### 4. Installer and update supply chain
|
||||
|
||||
Review the server installer's release pinning and Ed25519 verification, agent
|
||||
checksum and signature enforcement, executable validation, self-test, and
|
||||
atomic replacement behavior. Include the documented first automatic v5-to-v6
|
||||
agent update limitation in the threat model.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `install.sh`
|
||||
- `docs/INSTALL.md`
|
||||
- `internal/agentupdate/update.go`
|
||||
- `internal/agentupdate/update_http_test.go`
|
||||
- `.github/workflows/create-release.yml`
|
||||
- `docs/CODE_SIGNING_POLICY.md`
|
||||
|
||||
### 5. Discovery and outbound network boundaries
|
||||
|
||||
Confirm that network discovery is disabled by default, probes only the
|
||||
documented Proxmox ports, honors subnet allowlists and blocklists, and applies
|
||||
host, concurrency, and timeout bounds. Review outbound URL validation and SSRF
|
||||
protections for integrations and probes.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `internal/config/config.go`
|
||||
- `internal/discovery/`
|
||||
- `pkg/discovery/`
|
||||
- `internal/securityutil/outbound_http.go`
|
||||
- `pkg/securityutil/outbound_http.go`
|
||||
|
||||
### 6. Container and host separation
|
||||
|
||||
Review the block on storing host SSH private keys inside Pulse containers,
|
||||
Docker/Podman socket handling, Proxmox guest inventory opt-ins, and data-volume
|
||||
permissions. Confirm that API-only Proxmox monitoring does not require Pulse
|
||||
software on the hypervisor.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `SECURITY.md`
|
||||
- `docs/AGENT_SECURITY.md`
|
||||
- `internal/hostagent/proxmox_lxc_filesystems.go`
|
||||
- `internal/monitoring/docker_detection.go`
|
||||
- `internal/api/contract_test.go`
|
||||
- `internal/dockeragent/`
|
||||
|
||||
### 7. Production-scale failure behavior
|
||||
|
||||
Review behavior under concurrent reads and writes, stale data, partial platform
|
||||
responses, retention, and large resource sets. Pulse includes simulated
|
||||
500-node API and metrics-store regression coverage; treat that as reproducible
|
||||
engineering evidence, not as a production certification.
|
||||
|
||||
Starting points:
|
||||
|
||||
- `internal/api/load_test.go`
|
||||
- `pkg/metrics/store_loadtest_test.go`
|
||||
- `pkg/metrics/store_slo_test.go`
|
||||
|
||||
## Reproducible baseline
|
||||
|
||||
From a clean checkout with the documented Go and Node versions installed:
|
||||
|
||||
```bash
|
||||
go test ./internal/crypto ./pkg/auth ./internal/agentupdate \
|
||||
./internal/agentexec ./internal/discovery ./pkg/discovery \
|
||||
./internal/securityutil ./pkg/securityutil
|
||||
|
||||
go test ./internal/api \
|
||||
-run '^TestLoad_500Node_(ConcurrentResources|ConcurrentMetricsHistory|MixedEndpoints)$' \
|
||||
-count=1
|
||||
|
||||
go test ./pkg/metrics \
|
||||
-run '^TestLoadTest500Nodes_WriteAndQueryIntegration$' \
|
||||
-count=1
|
||||
|
||||
python3 scripts/check_public_docs.py
|
||||
```
|
||||
|
||||
These commands are a baseline, not a substitute for manual review, dependency
|
||||
analysis, fuzzing, deployment-specific testing, or an independent threat model.
|
||||
|
||||
## Reporting findings
|
||||
|
||||
Please report suspected vulnerabilities privately to
|
||||
<security@pulseapp.io>. Include the affected version or commit, deployment
|
||||
model, required privileges, reproduction steps, expected impact, and any
|
||||
suggested containment. Do not include live credentials or customer data.
|
||||
|
||||
General defects and hardening suggestions that do not disclose an exploitable
|
||||
weakness can use the public [issue tracker](https://github.com/rcourtman/Pulse/issues).
|
||||
The canonical disclosure contact and current security guidance remain in the
|
||||
[Security Policy](../SECURITY.md).
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
import { Component, For, type JSX, Show, createMemo, createSignal } from 'solid-js';
|
||||
import { Component, For, type JSX, Show, createEffect, createMemo, createSignal } from 'solid-js';
|
||||
import type { ConnectionType, ProbeCandidate } from '@/api/connections';
|
||||
import { AddressProbeStep } from './AddressProbeStep';
|
||||
import {
|
||||
|
|
@ -54,6 +54,13 @@ export const ConnectionEditor: Component<ConnectionEditorProps> = (props) => {
|
|||
const showCredentialSlot = () => activeType() !== null;
|
||||
const autoDetectLabels = createMemo(() => getInfrastructureAutoDetectLabels());
|
||||
|
||||
createEffect(() => {
|
||||
const routeType = props.initialType ?? null;
|
||||
const routeCandidate = props.initialCandidate ?? null;
|
||||
setSelectedType(routeType);
|
||||
setSelectedCandidate(routeCandidate);
|
||||
});
|
||||
|
||||
const chooseCandidate = (candidate: ProbeCandidate) => {
|
||||
if (props.onSelectCandidate) {
|
||||
props.onSelectCandidate(candidate);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import { beforeEach, describe, expect, it, vi } from 'vitest';
|
||||
import { fireEvent, render, screen, waitFor } from '@solidjs/testing-library';
|
||||
import { ConnectionsAPI, type ProbeResponse } from '@/api/connections';
|
||||
import { createSignal } from 'solid-js';
|
||||
import { ConnectionsAPI, type ConnectionType, type ProbeResponse } from '@/api/connections';
|
||||
import { ConnectionEditor } from '../ConnectionEditor';
|
||||
|
||||
const connectionsApiMock = vi.hoisted(() => ({
|
||||
|
|
@ -174,6 +175,23 @@ describe('ConnectionEditor', () => {
|
|||
expect(screen.queryByRole('button', { name: /probe api endpoint/i })).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('retargets the credential slot when a direct route changes type', async () => {
|
||||
const [initialType, setInitialType] = createSignal<ConnectionType>('agent');
|
||||
const renderSlot = vi.fn((props) => <div data-testid="slot">slot:{props.type}</div>);
|
||||
|
||||
render(() => (
|
||||
<ConnectionEditor
|
||||
initialType={initialType()}
|
||||
renderCredentialSlot={renderSlot}
|
||||
onClose={() => {}}
|
||||
/>
|
||||
));
|
||||
|
||||
expect(screen.getByTestId('slot').textContent).toBe('slot:agent');
|
||||
setInitialType('pve');
|
||||
await waitFor(() => expect(screen.getByTestId('slot').textContent).toBe('slot:pve'));
|
||||
});
|
||||
|
||||
it('skips probe setup when an initialType is supplied in edit mode', () => {
|
||||
const renderSlot = vi.fn((props) => <div data-testid="slot">slot:{props.type}</div>);
|
||||
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ import {
|
|||
type InfrastructureCommandSection,
|
||||
type InstallProfile,
|
||||
} from './infrastructureOperationsModel';
|
||||
import { buildInfrastructureOnboardingPath } from './infrastructureWorkspaceModel';
|
||||
import { useInfrastructureOperationsContext } from './useInfrastructureOperationsState';
|
||||
|
||||
export type InfrastructureInstallerFocus =
|
||||
|
|
@ -48,10 +49,10 @@ const INSTALLER_FOCUS_PRESENTATION: Record<
|
|||
agent: {
|
||||
title: 'Install on a host',
|
||||
description:
|
||||
'Start here to add the first system you want Pulse to monitor, then expand into Docker, Kubernetes, Proxmox, and related infrastructure.',
|
||||
'Install the agent for host-local, Docker, or Kubernetes telemetry. API-backed platforms such as Proxmox start under Platform connections.',
|
||||
recommendationTitle: 'Recommended install model',
|
||||
recommendationDetail:
|
||||
'Pulse Agent is a low-overhead background service. Machines in Pulse are systems with the agent installed and reporting full node-local telemetry such as CPU, memory, disks, network I/O, temperatures, SMART disk health, services, Docker, or Kubernetes coverage. Use Availability checks for ping-only or agentless device monitoring. For Proxmox clusters, keep the cluster API connection for platform inventory and add the agent to each node for host-level augmentation.',
|
||||
'Pulse Agent is a low-overhead background service. It collects node-local telemetry such as CPU, memory, disks, network I/O, temperatures, SMART disk health, services, Docker, and Kubernetes. For Proxmox, start with a dedicated read-only or narrowly scoped API token; no root agent is required for normal platform inventory and metrics. Add the agent only to nodes that need host-local augmentation. Use Availability checks for ping-only or agentless device monitoring.',
|
||||
preferredProfile: 'auto',
|
||||
platforms: ALL_AGENT_PLATFORMS,
|
||||
},
|
||||
|
|
@ -247,6 +248,41 @@ export const InfrastructureInstallerSection: Component<InfrastructureInstallerSe
|
|||
</p>
|
||||
</div>
|
||||
|
||||
<Show when={focus() === 'agent'}>
|
||||
<div
|
||||
data-testid="proxmox-api-first-guidance"
|
||||
class="rounded-md border border-blue-200 bg-blue-50 px-4 py-3 text-sm text-blue-950 dark:border-blue-700 dark:bg-blue-900 dark:text-blue-50"
|
||||
>
|
||||
<p class="font-semibold">Adding Proxmox? Start with the API connection.</p>
|
||||
<p class="mt-1 text-xs text-blue-800 dark:text-blue-200">
|
||||
Pulse can monitor normal PVE and PBS inventory, guests, storage, utilization, and
|
||||
status without installing software as root on the Proxmox host. Add a host agent later
|
||||
only for telemetry the API cannot provide, such as SMART, temperatures, and host-local
|
||||
storage detail.
|
||||
</p>
|
||||
<div class="mt-2 flex flex-wrap gap-x-4 gap-y-2 text-xs font-medium">
|
||||
<a
|
||||
href={buildInfrastructureOnboardingPath('pve')}
|
||||
class="text-blue-700 underline decoration-blue-300 underline-offset-2 hover:text-blue-900 dark:text-blue-200 dark:hover:text-white"
|
||||
>
|
||||
Connect Proxmox VE through the API
|
||||
</a>
|
||||
<a
|
||||
href={buildInfrastructureOnboardingPath('pbs')}
|
||||
class="text-blue-700 underline decoration-blue-300 underline-offset-2 hover:text-blue-900 dark:text-blue-200 dark:hover:text-white"
|
||||
>
|
||||
Connect PBS through the API
|
||||
</a>
|
||||
<a
|
||||
href="/docs/PRODUCTION_SECURITY"
|
||||
class="text-blue-700 underline decoration-blue-300 underline-offset-2 hover:text-blue-900 dark:text-blue-200 dark:hover:text-white"
|
||||
>
|
||||
Review the production security model
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</Show>
|
||||
|
||||
<Show when={focus() === 'docker'}>
|
||||
<div class="rounded-md border border-blue-200 bg-blue-50 px-4 py-3 text-sm text-blue-950 dark:border-blue-700 dark:bg-blue-900 dark:text-blue-50">
|
||||
<p class="font-semibold">Docker inside Proxmox LXCs</p>
|
||||
|
|
|
|||
|
|
@ -206,6 +206,22 @@ describe('infrastructure operations model', () => {
|
|||
expect(autoProfile?.description).toContain('every detected PVE / PBS service');
|
||||
});
|
||||
|
||||
it('keeps generic host onboarding explicit about the API-first Proxmox path', () => {
|
||||
expect(infrastructureInstallerSectionSource).toContain(
|
||||
'Adding Proxmox? Start with the API connection.',
|
||||
);
|
||||
expect(infrastructureInstallerSectionSource).toContain(
|
||||
'no root agent is required for normal platform inventory and metrics',
|
||||
);
|
||||
expect(infrastructureInstallerSectionSource).toContain(
|
||||
"buildInfrastructureOnboardingPath('pve')",
|
||||
);
|
||||
expect(infrastructureInstallerSectionSource).toContain(
|
||||
"buildInfrastructureOnboardingPath('pbs')",
|
||||
);
|
||||
expect(infrastructureInstallerSectionSource).toContain('/docs/PRODUCTION_SECURITY');
|
||||
});
|
||||
|
||||
it('keeps the Docker install profile aligned with the shared Docker and Podman label', () => {
|
||||
const dockerProfile = INSTALL_PROFILE_OPTIONS.find((option) => option.value === 'docker');
|
||||
|
||||
|
|
@ -252,7 +268,7 @@ describe('infrastructure operations model', () => {
|
|||
'Pulse Agent is a low-overhead background service.',
|
||||
);
|
||||
expect(infrastructureInstallerSectionSource).toContain(
|
||||
'Machines in Pulse are systems with the agent installed',
|
||||
'API-backed platforms such as Proxmox start under Platform connections.',
|
||||
);
|
||||
expect(infrastructureInstallerSectionSource).toContain(
|
||||
'Use Availability checks for ping-only or agentless device monitoring.',
|
||||
|
|
@ -262,9 +278,9 @@ describe('infrastructure operations model', () => {
|
|||
'before asking for administrator privileges',
|
||||
);
|
||||
expect(infrastructureInstallerSectionSource).toContain(
|
||||
'For Proxmox clusters, keep the cluster API',
|
||||
'For Proxmox, start with a dedicated read-only or narrowly scoped API token',
|
||||
);
|
||||
expect(infrastructureInstallerSectionSource).toContain('host-level');
|
||||
expect(infrastructureInstallerSectionSource).toContain('host-local');
|
||||
expect(infrastructureInstallerSectionSource).toContain('augmentation.');
|
||||
expect(infrastructureInstallerSectionSource).toContain('Installation commands');
|
||||
expect(infrastructureInstallerSectionSource).toContain(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue