diff --git a/docs/images/web-flow-01-login-first-run.png b/docs/images/web-flow-01-login-first-run.png
new file mode 100644
index 00000000..21f362a3
Binary files /dev/null and b/docs/images/web-flow-01-login-first-run.png differ
diff --git a/docs/images/web-flow-02-chat.png b/docs/images/web-flow-02-chat.png
new file mode 100644
index 00000000..f081a3a7
Binary files /dev/null and b/docs/images/web-flow-02-chat.png differ
diff --git a/docs/images/web-flow-03-dashboard.png b/docs/images/web-flow-03-dashboard.png
new file mode 100644
index 00000000..36b63e66
Binary files /dev/null and b/docs/images/web-flow-03-dashboard.png differ
diff --git a/docs/images/web-flow-04-memory.png b/docs/images/web-flow-04-memory.png
new file mode 100644
index 00000000..796b517a
Binary files /dev/null and b/docs/images/web-flow-04-memory.png differ
diff --git a/docs/images/web-flow-05-documents.png b/docs/images/web-flow-05-documents.png
new file mode 100644
index 00000000..60fe46da
Binary files /dev/null and b/docs/images/web-flow-05-documents.png differ
diff --git a/docs/images/web-flow-06-document-templates.png b/docs/images/web-flow-06-document-templates.png
new file mode 100644
index 00000000..6283e55d
Binary files /dev/null and b/docs/images/web-flow-06-document-templates.png differ
diff --git a/docs/images/web-flow-07-artifacts.png b/docs/images/web-flow-07-artifacts.png
new file mode 100644
index 00000000..5115929e
Binary files /dev/null and b/docs/images/web-flow-07-artifacts.png differ
diff --git a/docs/images/web-flow-08-guidelines.png b/docs/images/web-flow-08-guidelines.png
new file mode 100644
index 00000000..a1391e95
Binary files /dev/null and b/docs/images/web-flow-08-guidelines.png differ
diff --git a/docs/images/web-flow-09-agents.png b/docs/images/web-flow-09-agents.png
new file mode 100644
index 00000000..483f309a
Binary files /dev/null and b/docs/images/web-flow-09-agents.png differ
diff --git a/docs/images/web-flow-10-skills.png b/docs/images/web-flow-10-skills.png
new file mode 100644
index 00000000..d389c8be
Binary files /dev/null and b/docs/images/web-flow-10-skills.png differ
diff --git a/docs/images/web-flow-11-tools.png b/docs/images/web-flow-11-tools.png
new file mode 100644
index 00000000..a941e574
Binary files /dev/null and b/docs/images/web-flow-11-tools.png differ
diff --git a/docs/images/web-flow-12-tool-templates.png b/docs/images/web-flow-12-tool-templates.png
new file mode 100644
index 00000000..f0ff29e6
Binary files /dev/null and b/docs/images/web-flow-12-tool-templates.png differ
diff --git a/docs/images/web-flow-13-orchestration.png b/docs/images/web-flow-13-orchestration.png
new file mode 100644
index 00000000..70c3d950
Binary files /dev/null and b/docs/images/web-flow-13-orchestration.png differ
diff --git a/docs/images/web-flow-14-projects.png b/docs/images/web-flow-14-projects.png
new file mode 100644
index 00000000..91dc0a7d
Binary files /dev/null and b/docs/images/web-flow-14-projects.png differ
diff --git a/docs/images/web-flow-15-workspaces.png b/docs/images/web-flow-15-workspaces.png
new file mode 100644
index 00000000..e2ee0e7a
Binary files /dev/null and b/docs/images/web-flow-15-workspaces.png differ
diff --git a/docs/images/web-flow-16-code.png b/docs/images/web-flow-16-code.png
new file mode 100644
index 00000000..8b56b1b0
Binary files /dev/null and b/docs/images/web-flow-16-code.png differ
diff --git a/docs/images/web-flow-17-settings.png b/docs/images/web-flow-17-settings.png
new file mode 100644
index 00000000..7071d02a
Binary files /dev/null and b/docs/images/web-flow-17-settings.png differ
diff --git a/docs/images/web-flow-18-provider-setup.png b/docs/images/web-flow-18-provider-setup.png
new file mode 100644
index 00000000..8048d5d2
Binary files /dev/null and b/docs/images/web-flow-18-provider-setup.png differ
diff --git a/docs/images/web-flow-19-command-center.png b/docs/images/web-flow-19-command-center.png
new file mode 100644
index 00000000..0838c8ca
Binary files /dev/null and b/docs/images/web-flow-19-command-center.png differ
diff --git a/docs/images/web-flow-20-admin.png b/docs/images/web-flow-20-admin.png
new file mode 100644
index 00000000..d329242f
Binary files /dev/null and b/docs/images/web-flow-20-admin.png differ
diff --git a/docs/images/web-flow-21-admin-providers.png b/docs/images/web-flow-21-admin-providers.png
new file mode 100644
index 00000000..91038d1f
Binary files /dev/null and b/docs/images/web-flow-21-admin-providers.png differ
diff --git a/docs/images/web-flow-22-admin-integrations.png b/docs/images/web-flow-22-admin-integrations.png
new file mode 100644
index 00000000..4ab52873
Binary files /dev/null and b/docs/images/web-flow-22-admin-integrations.png differ
diff --git a/docs/images/web-flow-23-admin-system-integrations.png b/docs/images/web-flow-23-admin-system-integrations.png
new file mode 100644
index 00000000..7b1e2442
Binary files /dev/null and b/docs/images/web-flow-23-admin-system-integrations.png differ
diff --git a/docs/images/web-flow-24-admin-workspaces.png b/docs/images/web-flow-24-admin-workspaces.png
new file mode 100644
index 00000000..56a30ba6
Binary files /dev/null and b/docs/images/web-flow-24-admin-workspaces.png differ
diff --git a/docs/images/web-flow-25-governance.png b/docs/images/web-flow-25-governance.png
new file mode 100644
index 00000000..77fb3c07
Binary files /dev/null and b/docs/images/web-flow-25-governance.png differ
diff --git a/docs/images/web-flow-26-diagnostics.png b/docs/images/web-flow-26-diagnostics.png
new file mode 100644
index 00000000..0ed4a722
Binary files /dev/null and b/docs/images/web-flow-26-diagnostics.png differ
diff --git a/docs/images/web-flow-27-trust-boundary.png b/docs/images/web-flow-27-trust-boundary.png
new file mode 100644
index 00000000..7771d64b
Binary files /dev/null and b/docs/images/web-flow-27-trust-boundary.png differ
diff --git a/docs/userflow.md b/docs/userflow.md
new file mode 100644
index 00000000..7d192b85
--- /dev/null
+++ b/docs/userflow.md
@@ -0,0 +1,239 @@
+# Web App User Flow
+
+A screen-by-screen walkthrough of the Sovrant Web app (Blazor Server, `http://localhost:5100`), captured from a live run of version 1.4.0 in embedded mode with a fresh database. Every screenshot lives in [`docs/images/`](images/) with the `web-flow-` prefix.
+
+The flow follows the order a new user encounters the product: first-run setup → chat home → the rail-nav sections (Dashboard, Knowledge, Agents, Projects) → settings and provider setup → the admin surfaces.
+
+---
+
+## 1. First-run: create the administrator account
+
+**Route:** `/login`
+
+On a fresh install no accounts exist, so the login page switches to first-time setup. The first account created becomes the administrator with full control over registration, approvals, and server settings. On subsequent visits this page shows the normal sign-in form (plus self-registration, if the admin has enabled it).
+
+
+
+## 2. Chat (home)
+
+**Route:** `/`
+
+After registering, the user lands on Chat — the home screen. The empty state asks "What are you working on?" and offers starter prompts (create a custom agent, build a team, set up a mission, connect an MCP server). The left sidebar holds **+ New Chat** and conversation search; the top context bar exposes the model picker ("No model" until a provider is configured), workspace selector, project selector, and integrations menu. The composer includes a per-record **Private** toggle and a **+ Remember** control.
+
+
+
+## 3. User Dashboard
+
+**Route:** `/dashboard` (rail nav: chart icon)
+
+Cross-workspace activity for the signed-in user: missions, team runs, agent runs, sessions, shared items, and Claws, with quick actions to start a chat or run an agent.
+
+
+
+## Knowledge section
+
+### 4. Memory
+
+**Route:** `/memory`
+
+Per-user memory entries the agents can recall across sessions, with privacy scoping.
+
+
+
+### 5. Documents
+
+**Route:** `/documents`
+
+Document library for the current workspace — files agents can read, produce, and update.
+
+
+
+### 6. Document Templates
+
+**Route:** `/documents/templates`
+
+Reusable document templates users can instantiate.
+
+
+
+### 7. Artifacts
+
+**Route:** `/artifacts`
+
+Artifacts produced by agent runs (reports, files, outputs), browsable per workspace.
+
+
+
+### 8. Guidelines
+
+**Route:** `/guidelines`
+
+Behavioral guidelines that steer agents (the CLAUDE.md-style instruction layer).
+
+
+
+## Agents section
+
+### 9. Agents
+
+**Route:** `/agents`
+
+The 25 built-in agent templates (architect, coder, code-reviewer, data-analyst, …) in a master–detail layout showing each template's role, effort level, and tool grants, plus a **+ New** button for custom agents and a recent-runs strip.
+
+
+
+### 10. Skills
+
+**Route:** `/skills`
+
+The 32 built-in skills agents can invoke, with search and detail view.
+
+
+
+### 11. Tools
+
+**Route:** `/tools`
+
+The 58 tools available to agents (file I/O, shell, web search, delegation, …), including enablement and permission info.
+
+
+
+### 12. Tool Templates
+
+**Route:** `/tools/templates`
+
+User-defined tool templates.
+
+
+
+### 13. Orchestration
+
+**Route:** `/orchestration`
+
+Teams, swarms, and missions — the multi-agent orchestration surfaces with per-team run profiles.
+
+
+
+## Projects section
+
+### 14. Projects
+
+**Route:** `/projects`
+
+Projects within the current workspace; conversations and runs can be filed under a project via the top context bar.
+
+
+
+### 15. Workspaces
+
+**Route:** `/workspaces`
+
+The user's workspaces (a personal workspace is seeded on first login) and membership management.
+
+
+
+### 16. Code
+
+**Route:** `/code`
+
+Code-focused view for repository-oriented sessions.
+
+
+
+## Settings & provider setup
+
+### 17. Settings
+
+**Route:** `/settings`
+
+Per-user preferences: appearance, defaults, and account controls (including sign-out).
+
+
+
+### 18. Provider Setup
+
+**Route:** `/setup`
+
+Connect an LLM provider (API key + model) so chats and agent runs have a model to route to. Reachable from the "Set up →" link in the model picker; models can be switched anytime from the sidebar.
+
+
+
+## Admin section (admin role only)
+
+### 19. Command Center
+
+**Route:** `/command`
+
+The live cockpit: missions, team runs, agent runs, sessions, and Claws currently in flight, auto-refreshing while runs are active.
+
+
+
+### 20. Admin — Users
+
+**Route:** `/admin`
+
+User management with tabs for Users, Registration (open/closed, approval required), and Password Reset. The first-run admin account appears as active with the admin role.
+
+
+
+### 21. Admin — Providers
+
+**Route:** `/admin/providers`
+
+Server-wide LLM provider configuration.
+
+
+
+### 22. Admin — Integrations
+
+**Route:** `/admin/integrations`
+
+Webhook/chat integrations (Slack, Teams, Discord, custom).
+
+
+
+### 23. Admin — System Integrations
+
+**Route:** `/admin/system-integrations`
+
+System-level integrations such as MCP servers and Claw runtimes.
+
+
+
+### 24. Admin — Workspaces
+
+**Route:** `/admin/workspaces`
+
+Administration across all workspaces on the server.
+
+
+
+### 25. Governance
+
+**Route:** `/governance`
+
+Governance controls: policies and limits that bound what agents may do.
+
+
+
+### 26. Diagnostics
+
+**Route:** `/diagnostics`
+
+Runtime diagnostics: health, logs, and environment information.
+
+
+
+### 27. Trust Boundary
+
+**Route:** `/trust-boundary`
+
+The trust-boundary view — what data and capabilities are exposed where, in line with the security architecture (see [security-architecture.md](security-architecture.md)).
+
+
+
+---
+
+## How these were captured
+
+Screenshots were taken with Playwright/Chromium at 1440×900 against a debug build (`dotnet run --project src/Sovrant.Web`) with a fresh SQLite database: the script registers the first-run admin account through the real login form, then visits each route as that user. Re-running the capture on an existing database signs in instead of registering.
diff --git a/src/Sovrant.Desktop/ViewModels/LoginViewModel.cs b/src/Sovrant.Desktop/ViewModels/LoginViewModel.cs
index 29f46200..4bf369e7 100644
--- a/src/Sovrant.Desktop/ViewModels/LoginViewModel.cs
+++ b/src/Sovrant.Desktop/ViewModels/LoginViewModel.cs
@@ -17,8 +17,18 @@ public partial class LoginViewModel : ObservableObject
[ObservableProperty] private string _email = string.Empty;
[ObservableProperty] private string _password = string.Empty;
[ObservableProperty] private string _errorMessage = string.Empty;
+ [ObservableProperty] private string _infoMessage = string.Empty;
[ObservableProperty] private bool _isBusy;
+ [ObservableProperty] private string _busyLabel = string.Empty;
[ObservableProperty] private bool _isRegistrationOpen;
+ [ObservableProperty] private bool _isFirstRun;
+ [ObservableProperty] private bool _isApprovalRequired;
+
+ /// Registration section is only offered once an admin exists and registration is open.
+ public bool ShowRegistrationSection => !IsFirstRun && IsRegistrationOpen;
+
+ partial void OnIsFirstRunChanged(bool value) => OnPropertyChanged(nameof(ShowRegistrationSection));
+ partial void OnIsRegistrationOpenChanged(bool value) => OnPropertyChanged(nameof(ShowRegistrationSection));
public event Action? LoginSucceeded; // (userId, role, email)
@@ -31,20 +41,31 @@ public LoginViewModel(IIdentityService identity, ITokenService tokens, ICredenti
public async Task InitializeAsync()
{
+ IsFirstRun = await _identity.IsFirstRunAsync().ConfigureAwait(true);
IsRegistrationOpen = await _identity.IsRegistrationOpenAsync().ConfigureAwait(true);
+ IsApprovalRequired = !IsFirstRun && IsRegistrationOpen
+ && await _identity.IsApprovalRequiredAsync().ConfigureAwait(true);
}
- [RelayCommand]
- private async Task LoginAsync()
+ private bool ValidateInput()
{
ErrorMessage = string.Empty;
+ InfoMessage = string.Empty;
if (string.IsNullOrWhiteSpace(Email) || string.IsNullOrWhiteSpace(Password))
{
ErrorMessage = "Email and password are required.";
- return;
+ return false;
}
+ return true;
+ }
+
+ [RelayCommand]
+ private async Task LoginAsync()
+ {
+ if (!ValidateInput()) return;
IsBusy = true;
+ BusyLabel = "Signing you in…";
try
{
var result = await _identity.LoginAsync(Email, Password).ConfigureAwait(true);
@@ -66,14 +87,10 @@ private async Task LoginAsync()
[RelayCommand]
private async Task RegisterAsync()
{
- ErrorMessage = string.Empty;
- if (string.IsNullOrWhiteSpace(Email) || string.IsNullOrWhiteSpace(Password))
- {
- ErrorMessage = "Email and password are required.";
- return;
- }
+ if (!ValidateInput()) return;
IsBusy = true;
+ BusyLabel = IsFirstRun ? "Creating your administrator account…" : "Creating your account…";
try
{
var result = await _identity.RegisterAsync(Email, Password).ConfigureAwait(true);
@@ -85,7 +102,7 @@ private async Task RegisterAsync()
if (result.IsPendingApproval)
{
- ErrorMessage = "Account created. An administrator must approve it before you can sign in.";
+ InfoMessage = "Account created. An administrator must approve it before you can sign in.";
return;
}
diff --git a/src/Sovrant.Desktop/Views/LoginWindow.axaml b/src/Sovrant.Desktop/Views/LoginWindow.axaml
index d1e23c0c..1727589e 100644
--- a/src/Sovrant.Desktop/Views/LoginWindow.axaml
+++ b/src/Sovrant.Desktop/Views/LoginWindow.axaml
@@ -4,7 +4,7 @@
x:Class="Sovrant.Desktop.Views.LoginWindow"
x:DataType="vm:LoginViewModel"
Title="Sovrant — Sign in"
- Width="420" Height="460"
+ Width="420" SizeToContent="Height"
CanResize="False"
WindowStartupLocation="CenterScreen">
@@ -17,7 +17,22 @@
+ Margin="0,0,0,4"
+ IsVisible="{Binding !IsFirstRun}"/>
+
+
+
+
+
+
+
@@ -42,15 +57,31 @@
TextWrapping="Wrap"
IsVisible="{Binding ErrorMessage, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
+
+
+
+
+
+
-
-
+
+
@@ -60,9 +91,16 @@
Command="{Binding RegisterCommand}"
IsEnabled="{Binding !IsBusy}"
Padding="0,8"/>
+
+
diff --git a/src/Sovrant.Web/Components/Layout/Sidebar.razor b/src/Sovrant.Web/Components/Layout/Sidebar.razor
index f3d83941..8733ecc0 100644
--- a/src/Sovrant.Web/Components/Layout/Sidebar.razor
+++ b/src/Sovrant.Web/Components/Layout/Sidebar.razor
@@ -5,6 +5,9 @@