From 3df9963df1e6469c30356f959e3e575fd7f1b028 Mon Sep 17 00:00:00 2001
From: rcourtman
Date: Fri, 27 Mar 2026 09:34:11 +0000
Subject: [PATCH] Unify first-run onboarding handoff
---
.../v6/internal/subsystems/agent-lifecycle.md | 10 +++++
.../subsystems/frontend-primitives.md | 16 +++----
.../internal/subsystems/unified-resources.md | 6 +++
.../InfrastructureInstallerSection.tsx | 24 +++++-----
...nfrastructureOperationsController.test.tsx | 2 +-
.../SetupWizard/SetupCompletionPanel.tsx | 45 ++++++++++---------
.../components/SetupWizard/SetupWizard.tsx | 26 +++++++----
.../SetupCompletionPanel.guardrails.test.ts | 12 ++---
.../__tests__/SetupCompletionPanel.test.tsx | 8 ++--
.../__tests__/SetupWizard.test.tsx | 23 ++++++++--
.../SetupWizard/steps/SecurityStep.tsx | 5 ++-
.../SetupWizard/steps/WelcomeStep.tsx | 7 ++-
.../InfrastructurePageSurface.tsx | 3 +-
.../Infrastructure.empty-state.test.tsx | 12 ++---
...frastructureEmptyStatePresentation.test.ts | 4 +-
.../infrastructureEmptyStatePresentation.ts | 4 +-
16 files changed, 127 insertions(+), 80 deletions(-)
diff --git a/docs/release-control/v6/internal/subsystems/agent-lifecycle.md b/docs/release-control/v6/internal/subsystems/agent-lifecycle.md
index b2b017a256..fd4c619c3b 100644
--- a/docs/release-control/v6/internal/subsystems/agent-lifecycle.md
+++ b/docs/release-control/v6/internal/subsystems/agent-lifecycle.md
@@ -137,6 +137,16 @@ management, and fleet control surfaces.
2. Keep shared API proof routing aligned whenever install, register, or profile payloads change.
3. Update runtime and settings tests in the same slice when lifecycle behavior changes.
4. Preserve canonical /api/auto-register node identity continuity when canonical hosts shift between hostname and IP forms for the same node.
+5. Keep first-session lifecycle handoff explicit: the live setup completion
+ surface in `frontend-modern/src/components/SetupWizard/SetupCompletionPanel.tsx`
+ must route the primary CTA into `/settings/infrastructure/install`, frame
+ that route as the first-host install step, and present Direct Proxmox as
+ the named alternative rather than leaving post-setup next actions implicit.
+6. Keep `frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx`
+ oriented around the first monitored host. Install-token generation,
+ governed command copy, and install instructions belong to the canonical
+ lifecycle path; transport details and adjacent alternatives must remain
+ secondary to that first-host onboarding narrative.
## Current State
diff --git a/docs/release-control/v6/internal/subsystems/frontend-primitives.md b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
index 316aab60ea..15011a9a3c 100644
--- a/docs/release-control/v6/internal/subsystems/frontend-primitives.md
+++ b/docs/release-control/v6/internal/subsystems/frontend-primitives.md
@@ -165,6 +165,12 @@ work extends shared components instead of creating new local variants.
`frontend-modern/src/utils/dashboardEmptyStatePresentation.ts`, and make
infrastructure setup guidance name the canonical destination explicitly
instead of falling back to generic settings CTA labels.
+7. Keep the live first-session wizard on the canonical three-step runtime
+ shape in `frontend-modern/src/components/SetupWizard/SetupWizard.tsx`
+ (`Welcome`, `Security`, then `Install`), and keep the step indicator plus
+ completion CTA language aligned with the governed infrastructure install
+ workspace instead of regressing to a route jump that leaves the next action
+ implicit.
## Current State
@@ -1311,16 +1317,6 @@ badge label, title, and lock-button copy, and
the settings-shell consumer for environment-variable-locked container-update
controls. Future environment-lock UX should extend those owners instead of
reintroducing panel-local lock labels, badge styling, or title copy.
-First-session runtime framing is now part of that same owned primitive story.
-`frontend-modern/src/components/SetupWizard/SetupWizard.tsx` must stay on the
-real two-step runtime shape (`Welcome`, then `Security`) and hand successful
-setup directly into the canonical Infrastructure Operations install route
-instead of regrowing a second setup-only completion step. The standalone
-preview surface in
-`frontend-modern/src/components/SetupWizard/SetupCompletionPreview.tsx` may
-still exist for guarded preview coverage, but it must remain explicitly
-separate from the runtime wizard so first-session UX does not split into two
-competing product flows again.
The release-ready shell proof now also includes a representative desktop
Playwright rehearsal in
`tests/integration/tests/15-settings-shell-consistency.spec.ts` so general,
diff --git a/docs/release-control/v6/internal/subsystems/unified-resources.md b/docs/release-control/v6/internal/subsystems/unified-resources.md
index 9f21bd5013..2b301e1a7c 100644
--- a/docs/release-control/v6/internal/subsystems/unified-resources.md
+++ b/docs/release-control/v6/internal/subsystems/unified-resources.md
@@ -145,6 +145,12 @@ assembly branch.
2. Update contract and guardrail tests when a new resource type is added
3. Route runtime changes through the explicit unified-resource proof policies in `registry.json`; default fallback proof routing is not allowed
4. Tighten banned-path tests when a compatibility bridge is removed
+5. Keep the infrastructure landing empty state on canonical first-run routing:
+ when inventory is empty, `frontend-modern/src/features/infrastructure/InfrastructurePageSurface.tsx`
+ and `frontend-modern/src/utils/infrastructureEmptyStatePresentation.ts`
+ must send operators directly to `/settings/infrastructure/install`, name
+ first-host install as the default next step, and keep Direct Proxmox as the
+ explicit alternative instead of regressing to generic settings-root CTAs.
## Current State
diff --git a/frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx b/frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx
index 557d792aa5..9a0aeeea36 100644
--- a/frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx
+++ b/frontend-modern/src/components/Settings/InfrastructureInstallerSection.tsx
@@ -28,8 +28,8 @@ export const InfrastructureInstallerSection: Component = () => {
title={state.isEmbedded() ? 'Install on a host' : 'Infrastructure'}
description={
state.isEmbedded()
- ? 'Use the unified agent as the default path for hosts, Docker, Kubernetes, and agent-managed Proxmox.'
- : 'Primary setup hub for unified agents across systems, Docker, Kubernetes, Proxmox, and related infrastructure.'
+ ? 'Start here to add the first system you want Pulse to monitor, then expand into Docker, Kubernetes, Proxmox, and related infrastructure.'
+ : 'Primary setup hub for installing Pulse on the first host you want to monitor, then expanding into Docker, Kubernetes, Proxmox, and related infrastructure.'
}
icon={}
bodyClass="space-y-5"
@@ -112,10 +112,10 @@ export const InfrastructureInstallerSection: Component = () => {
-
Unified Agent is the default monitoring gateway.
+
Start with the first host you want Pulse to monitor.
- Install it on each system you want Pulse to monitor. The installer auto-detects
- available platforms on that machine and enables the right integrations.
+ Install the Pulse agent on that system first. Once it connects, Pulse can keep using this
+ workspace to add more hosts and layered platform integrations.
{state.requiresToken()
- ? 'Create a fresh token scoped for Agent, Docker, and Kubernetes monitoring.'
+ ? 'Create a fresh token for the generated install commands and host reporting.'
: 'Tokens are optional on this Pulse instance. Generate one if you want copied commands to preserve explicit credentialed transport.'}
@@ -190,8 +190,8 @@ export const InfrastructureInstallerSection: Component = () => {
- Token {state.latestRecord()?.name} created. Commands below now
- include this credential.
+ Install token {state.latestRecord()?.name} created. Commands below
+ now include this credential.
@@ -229,7 +229,7 @@ export const InfrastructureInstallerSection: Component = () => {
Installation commands
- Generate a token above to unlock installation commands.
+ Generate an install token above to unlock the commands for your first host.
Click "Generate token" above to see installation commands
+
+ Click "Generate token" above to see the install commands for your first host.
+
diff --git a/frontend-modern/src/components/Settings/__tests__/InfrastructureOperationsController.test.tsx b/frontend-modern/src/components/Settings/__tests__/InfrastructureOperationsController.test.tsx
index 9de2970895..f34986bb57 100644
--- a/frontend-modern/src/components/Settings/__tests__/InfrastructureOperationsController.test.tsx
+++ b/frontend-modern/src/components/Settings/__tests__/InfrastructureOperationsController.test.tsx
@@ -605,7 +605,7 @@ describe('InfrastructureOperationsController token generation', () => {
setupComponent();
await waitFor(() => {
- expect(screen.getByText('Generate API token')).toBeInTheDocument();
+ expect(screen.getByText('Generate install token')).toBeInTheDocument();
});
expect(screen.getByRole('button', { name: /Generate token/i })).toBeInTheDocument();
});
diff --git a/frontend-modern/src/components/SetupWizard/SetupCompletionPanel.tsx b/frontend-modern/src/components/SetupWizard/SetupCompletionPanel.tsx
index e69c87f2f4..1bec4a8e82 100644
--- a/frontend-modern/src/components/SetupWizard/SetupCompletionPanel.tsx
+++ b/frontend-modern/src/components/SetupWizard/SetupCompletionPanel.tsx
@@ -40,30 +40,30 @@ interface CompleteStepProps {
}
const UNIFIED_RESOURCE_GUIDANCE = {
- title: 'Unified Resource Inventory',
+ title: 'What happens next',
description:
- 'Pulse v6 starts with the Unified Agent. Install it on a system, let Pulse create one monitored system in inventory, then enrich that same inventory with workloads and linked platforms.',
+ 'Pulse is now secured. Your next step is to install the Pulse agent on the first system you want to monitor, then let Pulse discover and enrich that system over time.',
steps: [
- {
- title: 'Secure Pulse',
- description:
- 'Finish first-run setup so your admin account and API access are ready for real monitoring.',
- },
{
title: 'Open Infrastructure Install',
description:
- 'Use the canonical install workspace to generate the right Unified Agent commands for Linux, macOS, Windows, and related platforms.',
+ 'Use the canonical install workspace to generate the right install token and connection settings.',
},
{
- title: 'Bring Systems Into Pulse',
+ title: 'Copy the command for your target system',
description:
- 'Each install creates one monitored system in Pulse, then Docker, Kubernetes, Proxmox, and other context can attach to that same system.',
+ 'Choose Linux, macOS, Windows, or another supported target and copy the matching command.',
+ },
+ {
+ title: 'Run it on the first host you want to monitor',
+ description:
+ 'When the agent connects, Pulse creates your first monitored system and you can add more infrastructure from there.',
},
],
inventoryFacts: [
- 'One install becomes one monitored system in Pulse.',
- 'Infrastructure Operations owns token generation, connection URL, TLS/CA, and platform-specific install commands.',
- 'Settings no longer splits install across a separate setup-only command surface.',
+ 'Start with one host, then add more systems later from the same install workspace.',
+ 'Infrastructure Install owns the token, connection URL, TLS/CA settings, and platform-specific commands.',
+ 'Direct Proxmox stays available as an alternative path when you need it.',
],
} as const;
@@ -334,10 +334,11 @@ Keep these credentials secure!
- Security Configured
+ Install your first monitored host
- Open Infrastructure Install to bring your first monitored system into Pulse.
+ Your admin account is ready. Next, open Infrastructure Install and run the generated
+ command on the first system you want Pulse to monitor.
@@ -417,10 +418,10 @@ Keep these credentials secure!
The canonical install flow now lives in Infrastructure Operations. Open that
- workspace to generate tokens, set the agent connection URL, configure TLS or custom
- CA options, and copy the correct install commands for Linux, macOS, Windows, and
- related platforms.
+ workspace to generate an install token, set the agent connection URL, configure TLS
+ or custom CA options, and copy the correct command for the first system you want
+ Pulse to monitor.
+ You are about to do three things: unlock setup on this Pulse server, create your admin
+ account, and install the first system you want Pulse to monitor.
+
- Run the following command on your machine to retrieve the secure bootstrap token:
+ Run the following command on the machine where Pulse is installed to retrieve the
+ secure bootstrap token:
diff --git a/frontend-modern/src/features/infrastructure/InfrastructurePageSurface.tsx b/frontend-modern/src/features/infrastructure/InfrastructurePageSurface.tsx
index d94091c9bd..185be1a8a5 100644
--- a/frontend-modern/src/features/infrastructure/InfrastructurePageSurface.tsx
+++ b/frontend-modern/src/features/infrastructure/InfrastructurePageSurface.tsx
@@ -1,5 +1,6 @@
import { For, Show } from 'solid-js';
import { useNavigate } from '@solidjs/router';
+import { buildInfrastructureWorkspacePath } from '@/components/Settings/infrastructureWorkspaceModel';
import { EmptyState } from '@/components/shared/EmptyState';
import { Card } from '@/components/shared/Card';
import { FilterSegmentedControl, LabeledFilterSelect } from '@/components/shared/FilterToolbar';
@@ -119,7 +120,7 @@ export function InfrastructurePageSurface() {
actions={