docs: Update documentation for 145 files

Generated by AurionDocs
Job ID: c99fff50-67a3-4294-b4df-3e73f4f12de9
Source commit: 4dcb480
This commit is contained in:
Hue
2026-07-23 08:10:35 +02:00
parent 4dcb480d1d
commit f8f4e03ddd
145 changed files with 22779 additions and 0 deletions
+147
View File
@@ -0,0 +1,147 @@
# Architecture — HueByte/EchoHub
> *Auto-synthesized from 598 documented symbols across 128 files on `master`.*
## Topic Guides
Deep-dives into cross-cutting concerns synthesized from the per-symbol corpus.
- [API client and authentication](api-client-authentication.md) — How the EchoHub client authenticates with the server, handles tokens, and defines authentication DTOs.
- [Theming and UI color management](ui-theming.md) — Representing themes, color palettes, and runtime theme application.
- [Real-time connection management](real-time-connection.md) — Managing the SignalR hub connection lifecycle and connection state.
- [Encryption and room key management](encryption-roomkeys.md) — End-to-end encryption plumbing and secure handling of per-channel room keys.
- [Command handling](command-handling.md) — Slash-command parsing and dispatching command actions from UI and orchestrator.
- [Attachments and file transfers](attachments-transfer.md) — Staging and sending attachments in chat messages and coordinating outbound attachments.
- [Clipboard utilities](clipboard-tools.md) — Helpers for clipboard interactions: files and images.
- [Update management](update-management.md) — Data and update flow: backup prior to updates and update checks.
## Architecture Diagram
```mermaid
%%{init: {'theme':'base','themeVariables':{'background':'#faf7ef','primaryColor':'#f0e2c2','primaryTextColor':'#1f2840','primaryBorderColor':'#8a7548','secondaryColor':'#d9efec','secondaryBorderColor':'#1d8a80','secondaryTextColor':'#1f2840','tertiaryColor':'#f2ebd8','tertiaryBorderColor':'#8a7548','tertiaryTextColor':'#1f2840','lineColor':'#1d8a80','titleColor':'#1f2840','fontSize':'14px','edgeLabelBackground':'#faf7ef','clusterBkg':'#f2ebd8','clusterBorder':'#8a7548','actorBkg':'#f0e2c2','actorBorder':'#8a7548','actorTextColor':'#1f2840','actorLineColor':'#8a7548','signalColor':'#1d8a80','signalTextColor':'#1f2840','activationBkgColor':'#d9efec','activationBorderColor':'#1d8a80','noteBkgColor':'#f2ebd8','noteBorderColor':'#8a7548','noteTextColor':'#1f2840','labelBoxBkgColor':'#f0e2c2','labelBoxBorderColor':'#8a7548','labelTextColor':'#1f2840','transitionColor':'#1d8a80','transitionLabelColor':'#1f2840','stateLabelColor':'#1f2840','altBackground':'#f2ebd8'}}}%%
flowchart TB
n0["src/EchoHub.Core/DTOs · ChatService (11 files)"]
n1["src/EchoHub.Client/Services · AppOrchestrator (14 files)"]
n2["src/EchoHub.Client/UI · MainWindow (18 files)"]
n3["src/EchoHub.Core/DTOs · ApiClient (10 files)"]
n4["src/EchoHub.Server · User (12 files)"]
n5["src/EchoHub.Core/DTOs · ChannelService (7 files)"]
n6["src/EchoHub.Server · Program (12 files)"]
n7["src/EchoHub.Client/Config (5 files)"]
n8["src/EchoHub.Client/UI · Channel (4 files)"]
n9["src/EchoHub.Core/DTOs · ChannelsController (2 files)"]
n10["src/EchoHub.Core/Models (5 files)"]
n0 -->|5| n10
n0 -->|6| n4
n0 -->|7| n6
n0 -->|4| n7
n0 -->|6| n8
n1 -->|14| n0
n1 -->|5| n2
n1 -->|4| n3
n1 -->|6| n4
n1 -->|8| n7
n1 -->|5| n8
n2 -->|8| n0
n2 -->|4| n4
n3 -->|6| n0
n3 -->|8| n4
n3 -->|4| n9
n4 -->|9| n3
n5 -->|7| n0
n5 -->|4| n4
n5 -->|5| n8
n6 -->|6| n0
n6 -->|7| n4
n9 -->|4| n4
n9 -->|4| n5
```
## System Overview
EchoHub is a client/server chat system that exposes an HTTP API implemented by multiple controllers and a realtime messaging surface via a hub (ChatHub), with client-side components for connecting and playback. The server hosts application services and background workers (e.g. file cleanup, data migrations) that implement business logic and maintenance tasks. Persistent state is stored in the Entity Framework DbContext (EchoHubDbContext) which is used by controllers and services. Clients interact with the server through the ApiClient and implement messaging callbacks against the IEchoHubClient contract.
## Key Components
**Controllers** — HTTP API surface for client and administrative actions. Implemented by [`AuthController`](../Code/src/EchoHub.Server/Controllers/AuthController.cs.md), [`ChannelsController`](../Code/src/EchoHub.Server/Controllers/ChannelsController.cs.md), [`FilesController`](../Code/src/EchoHub.Server/Controllers/FilesController.cs.md), [`InvitesController`](../Code/src/EchoHub.Server/Controllers/InvitesController.cs.md), [`ModerationController`](../Code/src/EchoHub.Server/Controllers/ModerationController.cs.md), [`ServerController`](../Code/src/EchoHub.Server/Controllers/ServerController.cs.md), [`UsersController`](../Code/src/EchoHub.Server/Controllers/UsersController.cs.md).
**Services** — Application services implement business logic, file handling, background tasks, and utilities used by controllers and hubs. Implemented by [`ChannelService`](../Code/src/EchoHub.Server/Services/ChannelService.cs.md), [`ChatService`](../Code/src/EchoHub.Server/Services/ChatService.cs.md), [`FileStorageService`](../Code/src/EchoHub.Server/Services/FileStorageService.cs.md), [`FileCleanupService`](../Code/src/EchoHub.Server/Services/FileCleanupService.cs.md), and supporting utilities such as [`AsciiBannerService`](../Code/src/EchoHub.Core/Services/AsciiBannerService.cs.md), [`AudioPlaybackService`](../Code/src/EchoHub.Client/Services/AudioPlaybackService.cs.md), [`ClientEncryptionService`](../Code/src/EchoHub.Client/Services/ClientEncryptionService.cs.md), and [`DataMigrationService`](../Code/src/EchoHub.Server/Setup/DataMigrationService.cs.md).
**Workers / Hubs** — Real-time messaging and hosted work are provided by SignalR-style hubs and background services; the primary realtime hub is implemented by [`ChatHub`](../Code/src/EchoHub.Server/Hubs/ChatHub.cs.md).
**Data Access** — Persistent application state is managed via the Entity Framework DbContext used across services and controllers: [`EchoHubDbContext`](../Code/src/EchoHub.Server/Data/EchoHubDbContext.cs.md).
**External Clients** — Client-side communication with the server is encapsulated by an HTTP/real-time client and the client contract. Implemented by [`ApiClient`](../Code/src/EchoHub.Client/Services/ApiClient.cs.md) and the client interface [`IEchoHubClient`](../Code/src/EchoHub.Core/Contracts/IEchoHubClient.cs.md).
**Configuration** — Server runtime options and feature flags are defined in option classes used by services and integrations. Implemented by [`IrcOptions`](../Code/src/EchoHub.Server.Irc/IrcOptions.cs.md), [`ServerLogsOptions`](../Code/src/EchoHub.Server/Config/ServerLogsOptions.cs.md), [`SpamOptions`](../Code/src/EchoHub.Server/Config/SpamOptions.cs.md), [`StatsOptions`](../Code/src/EchoHub.Server/Config/StatsOptions.cs.md).
**IRC integration** — IRC-related command handling and service wiring are provided by IRC support classes and extensions. Implemented by [`IrcServiceExtensions`](../Code/src/EchoHub.Server.Irc/IrcServiceExtensions.cs.md) and [`IrcCommandHandler`](../Code/src/EchoHub.Server.Irc/IrcCommandHandler.cs.md).
**Core Contracts** — Domain and integration interfaces that define service boundaries and encryption abstractions. Implemented by [`IChannelService`](../Code/src/EchoHub.Core/Contracts/IChannelService.cs.md), [`IChatService`](../Code/src/EchoHub.Core/Contracts/IChatService.cs.md), [`IMessageEncryptionService`](../Code/src/EchoHub.Core/Contracts/IMessageEncryptionService.cs.md), and [`IUserService`](../Code/src/EchoHub.Core/Contracts/IUserService.cs.md).
## Component Map
*Subsystems below are structural clusters detected from the dependency graph — groups of symbols more densely wired to each other than to the rest of the codebase.*
- **src/EchoHub.Client/UI · MainWindow** — 18 documented files
- **src/EchoHub.Client/Services · AppOrchestrator** — 14 documented files
- **src/EchoHub.Server · Program** — 12 documented files
- **src/EchoHub.Server · User** — 12 documented files
- **src/EchoHub.Core/DTOs · ChatService** — 11 documented files
- **src/EchoHub.Core/DTOs · ApiClient** — 10 documented files
- **src/EchoHub.Core/DTOs · ChannelService** — 7 documented files
- **src/EchoHub.Client/Config** — 5 documented files
- **src/EchoHub.Core/Models** — 5 documented files
- **src/EchoHub.Client/Themes** — 4 documented files
- **src/EchoHub.Client/UI · Channel** — 4 documented files
- **src/EchoHub.Server · ServerLogsStreamService** — 4 documented files
- *…and 11 more subsystem folders*
### Components by Role
**Configuration**
- `IrcOptions``src/EchoHub.Server.Irc/IrcOptions.cs`
- `ServerLogsOptions``src/EchoHub.Server/Config/ServerLogsOptions.cs`
- `SpamOptions``src/EchoHub.Server/Config/SpamOptions.cs`
- `StatsOptions``src/EchoHub.Server/Config/StatsOptions.cs`
**Controllers**
- `AuthController``src/EchoHub.Server/Controllers/AuthController.cs`
- `ChannelsController``src/EchoHub.Server/Controllers/ChannelsController.cs`
- `FilesController``src/EchoHub.Server/Controllers/FilesController.cs`
- `InvitesController``src/EchoHub.Server/Controllers/InvitesController.cs`
- `ModerationController``src/EchoHub.Server/Controllers/ModerationController.cs`
- `ServerController``src/EchoHub.Server/Controllers/ServerController.cs`
- `UsersController``src/EchoHub.Server/Controllers/UsersController.cs`
**Data Access**
- `EchoHubDbContext``src/EchoHub.Server/Data/EchoHubDbContext.cs`
**Extensions**
- `IrcServiceExtensions``src/EchoHub.Server.Irc/IrcServiceExtensions.cs`
**External Clients**
- `ApiClient``src/EchoHub.Client/Services/ApiClient.cs`
- `IEchoHubClient``src/EchoHub.Core/Contracts/IEchoHubClient.cs`
**Handlers**
- `CommandHandler``src/EchoHub.Client/Commands/CommandHandler.cs`
- `IrcCommandHandler``src/EchoHub.Server.Irc/IrcCommandHandler.cs`
**Realtime Hubs**
- `ChatHub``src/EchoHub.Server/Hubs/ChatHub.cs`
**Services**
- `AsciiBannerService``src/EchoHub.Core/Services/AsciiBannerService.cs`
- `AudioPlaybackService``src/EchoHub.Client/Services/AudioPlaybackService.cs`
- `ChannelService``src/EchoHub.Server/Services/ChannelService.cs`
- `ChatService``src/EchoHub.Server/Services/ChatService.cs`
- `ClientEncryptionService``src/EchoHub.Client/Services/ClientEncryptionService.cs`
- `DataMigrationService``src/EchoHub.Server/Setup/DataMigrationService.cs`
- `FileCleanupService``src/EchoHub.Server/Services/FileCleanupService.cs`
- `FileStorageService``src/EchoHub.Server/Services/FileStorageService.cs`
- `IChannelService``src/EchoHub.Core/Contracts/IChannelService.cs`
- `IChatService``src/EchoHub.Core/Contracts/IChatService.cs`
- `IMessageEncryptionService``src/EchoHub.Core/Contracts/IMessageEncryptionService.cs`
- `IUserService``src/EchoHub.Core/Contracts/IUserService.cs`
---
*Generated by Aurion on 2026-07-23 05:56:01 UTC*
+29
View File
@@ -0,0 +1,29 @@
# Onboarding — HueByte/EchoHub
> *A curated reading path through this codebase for new contributors. Work through the stops in order.*
This reading path gets a new team member from zero to a place where they can run the app and make a small contribution. Read the short architecture overview first to understand the system's collaboration pattern, then inspect the entry points to see how the pieces are wired; from there follow a single request through the ingress layer into the services and state so you can start making safe, focused changes.
## Stop 1: What this project is
At this stop skim the auto-generated system description to learn the overall collaboration pattern and where state is owned; the document also highlights the main components and their responsibilities. Start by opening [Architecture](Architecture.md) to pick up the big-picture boundaries and the primary data stores so later code-level reads map to that conceptual model.
## Stop 2: Where execution starts
Read the two Program entry points to see how the client and server are bootstrapped, which early runtime concerns are wired, and what cross-cutting services are registered. Inspect the client [Program.cs](../Code/src/EchoHub.Client/Program.cs.md) to see startup tasks like rollback handling, permission checks, configuration provisioning, logging setup, and PATH preparation; then open the server [Program.cs](../Code/src/EchoHub.Server/Program.cs.md) to see how configuration, logging, data access, authentication, service registrations and the ASP.NET Core pipeline are arranged.
## Stop 3: Where requests come in
Trace a single end-to-end interaction by following the client command entry, the server HTTP controller, and the real-time hub used for chat. Read the client [CommandHandler.cs](../Code/src/EchoHub.Client/Commands/CommandHandler.cs.md) to learn how user commands are emitted, then the server [UsersController.cs](../Code/src/EchoHub.Server/Controllers/UsersController.cs.md) to see the API surface that handles user-related requests, and finally the SignalR [ChatHub.cs](../Code/src/EchoHub.Server/Hubs/ChatHub.cs.md) to understand real-time message routing and authorization checks.
## Stop 4: Where the business logic lives
Drill into the substantive services that perform work for the client: network calls, audio, encryption, and backup orchestration. Read the client [ApiClient.cs](../Code/src/EchoHub.Client/Services/ApiClient.cs.md) that manages HTTP requests and disposal, the [AudioPlaybackService.cs](../Code/src/EchoHub.Client/Services/AudioPlaybackService.cs.md) that handles playback concerns, the [ClientEncryptionService.cs](../Code/src/EchoHub.Client/Services/ClientEncryptionService.cs.md) which implements IMessageEncryptionService for message protection, the [NotificationSoundService.cs](../Code/src/EchoHub.Client/Services/NotificationSoundService.cs.md) for user-facing alerts, and the [UpdateBackupService.cs](../Code/src/EchoHub.Client/Services/UpdateBackupService.cs.md) which is involved in BackupInfo serialization and backup flows.
## Stop 5: Where state lives
Look at the code that owns connection state, persisted backups, and the commands that drive application state changes. Revisit [CommandHandler.cs](../Code/src/EchoHub.Client/Commands/CommandHandler.cs.md) to understand the commands that mutate client state, inspect [ConnectionManager.cs](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) for the lifecycle and disposal of live connections, open [UpdateBackupService.cs](../Code/src/EchoHub.Client/Services/UpdateBackupService.cs.md) to see how BackupInfo is serialized for persistence, and check the UI [ConnectDialog.cs](../Code/src/EchoHub.Client/UI/Dialogs/ConnectDialog.cs.md) to learn where connection information is captured and handed off to the connection manager.
## Stop 6: Where to put new code
Use the conventional places represented by controllers, server services, and hubs when deciding where to add features or fixes. For HTTP and auth-related endpoints add or update controllers like [AuthController.cs](../Code/src/EchoHub.Server/Controllers/AuthController.cs.md); server-side domain operations belong in services such as [ChannelService.cs](../Code/src/EchoHub.Server/Services/ChannelService.cs.md) (which implements IChannelService); and real-time or cross-connection behavior belongs in the SignalR hub [ChatHub.cs](../Code/src/EchoHub.Server/Hubs/ChatHub.cs.md).
## Next steps
Run the app locally: read the two [Program.cs](../Code/src/EchoHub.Server/Program.cs.md) and [Program.cs](../Code/src/EchoHub.Client/Program.cs.md) files to learn how to start the server and client, then launch both projects and use the Connect dialog to exercise the [ChatHub](../Code/src/EchoHub.Server/Hubs/ChatHub.cs.md) path.
---
*Synthesised by Aurion on 2026-07-23 05:54:49 UTC*
@@ -0,0 +1,89 @@
# Adding a new controller
> *Workflow template auto-derived from 7 existing exemplar(s).*
This template describes how to add a new HTTP controller to the server: reach for this pattern when you need a new API surface implemented as an [ApiController] class that exposes routes and actions. Use the reference controller below as the concrete shape to copy (attributes, base class, constructor injection, and action patterns), and consult the existing examples to match naming and placement.
## Reference implementation
```csharp
[ApiController]
[Route("api/files")]
[Authorize]
[EnableRateLimiting("general")]
public class FilesController : ControllerBase
{
private readonly FileStorageService _fileStorage;
public FilesController(FileStorageService fileStorage)
{
_fileStorage = fileStorage;
}
/// <summary>
/// Serves an uploaded file. Anonymous by design: the unguessable GUID in the URL is the
/// access token (Discord-CDN-style capability URL), so attachment links can be opened
/// directly in a browser and shared to IRC clients. E2E-encrypted room blobs are
/// ciphertext at rest, so anonymous access reveals nothing for those channels.
/// </summary>
[HttpGet("{fileId}")]
[AllowAnonymous]
public IActionResult GetFile(string fileId)
{
if (!Guid.TryParse(fileId, out _))
return BadRequest(new ErrorResponse("Invalid file identifier."));
var filePath = _fileStorage.GetFilePath(fileId);
if (filePath is null)
return NotFound(new ErrorResponse("File not found."));
var contentType = Path.GetExtension(filePath).ToLowerInvariant() switch
{
".jpg" or ".jpeg" => "image/jpeg",
".png" => "image/png",
".gif" => "image/gif",
".webp" => "image/webp",
".mp3" => "audio/mpeg",
".wav" => "audio/wav",
".ogg" => "audio/ogg",
".flac" => "audio/flac",
".aac" => "audio/aac",
".m4a" => "audio/mp4",
".wma" => "audio/x-ms-wma",
".pdf" => "application/pdf",
".txt" => "text/plain",
_ => "application/octet-stream"
};
// Images and audio render inline so a browser displays them instead of
// downloading; everything else keeps the attachment disposition.
if (contentType.StartsWith("image/") || contentType.StartsWith("audio/"))
return PhysicalFile(filePath, contentType);
var fileName = Path.GetFileName(filePath);
return PhysicalFile(filePath, contentType, fileName);
}
}
```
## Where it lives
Controllers in this codebase are placed under src/EchoHub.Server/Controllers, and exemplar files use names such as AuthController.cs, ChannelsController.cs, FilesController.cs, InvitesController.cs, ModerationController.cs, ServerController.cs, and UsersController.cs with corresponding public classes named AuthController, ChannelsController, FilesController, InvitesController, ModerationController, ServerController, and UsersController. Use that same folder and naming pattern when adding a new controller file.
## Wiring
A specific registration site for controllers was not detected in the symbol graph provided. Inspect the existing controllers listed below to see how they are referenced in the project and to follow the same runtime usage patterns used by the application.
## Existing examples
- [`AuthController`](../../Code/src/EchoHub.Server/Controllers/AuthController.cs.md)
- [`ChannelsController`](../../Code/src/EchoHub.Server/Controllers/ChannelsController.cs.md)
- [`FilesController`](../../Code/src/EchoHub.Server/Controllers/FilesController.cs.md)
- [`InvitesController`](../../Code/src/EchoHub.Server/Controllers/InvitesController.cs.md)
- [`ModerationController`](../../Code/src/EchoHub.Server/Controllers/ModerationController.cs.md)
- [`ServerController`](../../Code/src/EchoHub.Server/Controllers/ServerController.cs.md)
- [`UsersController`](../../Code/src/EchoHub.Server/Controllers/UsersController.cs.md)
---
*Synthesised by Aurion on 2026-07-23 05:55:15 UTC*
@@ -0,0 +1,94 @@
# Adding a new service
> *Workflow template auto-derived from 8 existing exemplar(s).*
Adding a new service
When you need to encapsulate a piece of server functionality—either a long-lived background job or an application service consumed by controllers and other services—you add a new service type in this codebase. Use the existing service types in src/EchoHub.Server/Services as your models: pick a clear name that ends with "Service", place the source alongside the other services, and wire it up where services are registered.
## Reference implementation
Real code from `src/EchoHub.Server/Services/MuteExpirationService.cs` that a new instance can be modelled on:
```csharp
/// <summary>
/// Background service that periodically unmutes users whose timed mute has expired.
/// </summary>
public sealed class MuteExpirationService : BackgroundService
{
private static readonly TimeSpan CheckInterval = TimeSpan.FromSeconds(15);
private readonly IServiceScopeFactory _scopeFactory;
private readonly ILogger<MuteExpirationService> _logger;
public MuteExpirationService(IServiceScopeFactory scopeFactory, ILogger<MuteExpirationService> logger)
{
_scopeFactory = scopeFactory;
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
await Task.Yield();
while (!stoppingToken.IsCancellationRequested)
{
try
{
await UnmuteExpiredUsersAsync(stoppingToken);
}
catch (Exception ex) when (ex is not OperationCanceledException)
{
_logger.LogWarning(ex, "Error checking mute expirations");
}
await Task.Delay(CheckInterval, stoppingToken);
}
}
private async Task UnmuteExpiredUsersAsync(CancellationToken ct)
{
using var scope = _scopeFactory.CreateScope();
var db = scope.ServiceProvider.GetRequiredService<EchoHubDbContext>();
var now = DateTimeOffset.UtcNow;
var expired = await db.Users
.Where(u => u.IsMuted && u.MutedUntil.HasValue && u.MutedUntil.Value <= now)
.ToListAsync(ct);
if (expired.Count == 0)
return;
foreach (var user in expired)
{
user.IsMuted = false;
user.MutedUntil = null;
_logger.LogInformation("Auto-unmuted user {Username} (timed mute expired)", user.Username);
}
await db.SaveChangesAsync(ct);
}
}
```
## Where it lives
Service source files are placed in src/EchoHub.Server/Services. Existing service types include names such as ChannelService, ChatService, FileCleanupService, FileStorageService, LinkEmbedService, MessageEncryptionService, MuteExpirationService, and ServerDirectoryService; each service file in that folder defines the corresponding type (for example, public class ChannelService : IChannelService and public sealed class FileCleanupService : BackgroundService). Follow the same placement and name your new type with a Service suffix so it sits alongside these exemplars.
## Wiring
Detected registration/composition site: src/EchoHub.Server/Program.cs. Inspect that file to see how services from src/EchoHub.Server/Services are registered and how hosted/background services are added to the application; new service types should be wired there consistent with the existing registrations.
## Existing examples
- [`ChannelService`](../../Code/src/EchoHub.Server/Services/ChannelService.cs.md)
- [`ChatService`](../../Code/src/EchoHub.Server/Services/ChatService.cs.md)
- [`FileCleanupService`](../../Code/src/EchoHub.Server/Services/FileCleanupService.cs.md)
- [`FileStorageService`](../../Code/src/EchoHub.Server/Services/FileStorageService.cs.md)
- [`LinkEmbedService`](../../Code/src/EchoHub.Server/Services/LinkEmbedService.cs.md)
- [`MessageEncryptionService`](../../Code/src/EchoHub.Server/Services/MessageEncryptionService.cs.md)
- [`MuteExpirationService`](../../Code/src/EchoHub.Server/Services/MuteExpirationService.cs.md)
- [`ServerDirectoryService`](../../Code/src/EchoHub.Server/Services/ServerDirectoryService.cs.md)
---
*Synthesised by Aurion on 2026-07-23 05:55:34 UTC*
@@ -0,0 +1,54 @@
# API client and authentication
> How the EchoHub client authenticates with the server, handles tokens, and defines authentication DTOs.
This guide explains how the EchoHub client performs HTTP operations and manages authentication tokens, and it documents the DTOs the client uses when talking to the server. It focuses on the client-side [ApiClient](../Code/src/EchoHub.Client/Services/ApiClient.cs.md) as the central point for login/refresh/logout and common API operations, and the small set of DTOs and client callback interface the ApiClient consumes and produces. Read this when you need to understand which types carry credentials and tokens, how attachments and avatar uploads are represented, and where server-initiated events are delivered on the client.
## ApiClient.cs
Implements token management and API calls to the EchoHub server.
The [ApiClient](../Code/src/EchoHub.Client/Services/ApiClient.cs.md) class is a high-level HTTP client that centralizes authentication lifecycle (LoginAsync, LoginWithRefreshTokenAsync, RefreshTokenAsync, LogoutAsync, SetTokens) and exposes token state via properties like Token, RefreshToken, and ExpiresAt. It provides helper methods for authenticated requests (AuthenticatedRequestAsync, AuthenticatedGetAsync, EnsureAuthenticated, GetValidTokenAsync) and common server operations surfaced to callers: channel and message management (CreateChannelAsync, DeleteChannelAsync, SendMessageWithAttachmentsAsync, DeleteMessageAsync, RekeyChannelAsync, NukeChannelAsync), moderation actions (AssignRoleAsync, BanUserAsync, KickUserAsync, MuteUserAsync, UnbanUserAsync, UnmuteUserAsync), profile and upload flows (UploadAvatarAsync, DownloadFileToTempAsync, UpdateProfileAsync, ExportMyDataAsync, DeleteMyAccountAsync), and utilities for handling file content types (GetContentType). The ApiClient implements IDisposable (Dispose) and contains response handling helpers (EnsureSuccessAsync) so callers get a single, managed surface for HTTP/authorization concerns. According to its relationships it depends on the DTO definitions in [AuthDtos](../Code/src/EchoHub.Core/DTOs/AuthDtos.cs.md), [ChatDtos](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md), [ModerationDtos](../Code/src/EchoHub.Core/DTOs/ModerationDtos.cs.md), and [ProfileDtos](../Code/src/EchoHub.Core/DTOs/ProfileDtos.cs.md); in practice the ApiClient serializes and deserializes instances of those DTOs when calling corresponding endpoints and when returning structured results to its callers.
## AuthDtos.cs
Defines login request data structure used to authenticate.
The [AuthDtos](../Code/src/EchoHub.Core/DTOs/AuthDtos.cs.md) file defines the transport types used by the authentication endpoints: the immutable positional [LoginRequest](../Code/src/EchoHub.Core/DTOs/AuthDtos.cs.md) record carrying Username and Password, the [LoginResponse](../Code/src/EchoHub.Core/DTOs/AuthDtos.cs.md) record that bundles Token, RefreshToken, ExpiresAt and basic user identity fields, plus a [RefreshRequest](../Code/src/EchoHub.Core/DTOs/AuthDtos.cs.md) and [RegisterRequest](../Code/src/EchoHub.Core/DTOs/AuthDtos.cs.md). These DTOs are pure data containers (no business logic) intended to be serialized over HTTP; the documentation calls out that Password is sensitive and that LoginResponse is what clients consume to establish an authenticated session. The ApiClient uses these DTOs when performing login and token-refresh flows (see relationships: used by ApiClient.cs).
## AuthDtos.cs (LoginResponse)
Represents server response after authentication including tokens.
The [LoginResponse](../Code/src/EchoHub.Core/DTOs/AuthDtos.cs.md) record is the structured server reply to a successful authentication, containing the short-lived Token, the RefreshToken, an ExpiresAt timestamp, and identifying fields like Username with optional display personalization. Clients (like the [ApiClient](../Code/src/EchoHub.Client/Services/ApiClient.cs.md)) consume LoginResponse to populate their in-memory token state and to drive expiration/refresh logic; because it contains the expiry moment, consumers can decide when to call RefreshTokenAsync or LoginWithRefreshTokenAsync instead of issuing unauthenticated requests.
## AuthDtos.cs (RefreshRequest)
Represents refresh token request for renewing authentication.
The [RefreshRequest](../Code/src/EchoHub.Core/DTOs/AuthDtos.cs.md) is the DTO used to request new authentication tokens from the server using a refresh token. It is the lightweight, immutable payload the ApiClient will serialize when it invokes its refresh endpoint (RefreshTokenAsync / LoginWithRefreshTokenAsync) so the server can validate the refresh token and return a new [LoginResponse](../Code/src/EchoHub.Core/DTOs/AuthDtos.cs.md).
## IEchoHubClient.cs
Interface for EchoHub client surface used by ApiClient to perform operations.
The [IEchoHubClient](../Code/src/EchoHub.Core/Contracts/IEchoHubClient.cs.md) interface defines the callback surface that a client implementing the real-time hub must provide: methods such as ReceiveMessage(MessageDto), UserJoined(channelName, username, UserPresenceDto?), UserLeft, ChannelUpdated(ChannelDto), UserStatusChanged, UserKicked, UserBanned, MessageDeleted, ChannelDeleted, ChannelNuked, ForceDisconnect, and Error. The doc shows example minimal implementations that log or handle these events quickly and non-blockingly. While the ApiClient handles HTTP and token management, this interface is the typed contract used by any hub/transport layer to deliver server-initiated events to client code; the relationship shows IEchoHubClient depends on DTO types like those in [ChatDtos](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) and [ProfileDtos](../Code/src/EchoHub.Core/DTOs/ProfileDtos.cs.md), which are delivered through these callbacks.
## ChatDtos.cs
`AttachmentDto` collaborates directly with `ApiClient` and other members of this topic (10 dependency links).
The [ChatDtos](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) file defines message and channel payloads used across both HTTP API and hub callbacks. In particular, the [AttachmentDto](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) record carries Kind (AttachmentKind), Url, FileName, FileSize, and an optional AsciiPreview; it represents a message attachment's metadata and is the shape ApiClient sends or receives when uploading, downloading, or rendering attachments. Other DTOs in the same file (MessageDto, ChannelDto, ChannelMetaDto, SendMessageRequest, SendUrlRequest, ReplyRefDto, etc.) are the structured inputs and outputs ApiClient uses for channel operations and that appear on the [IEchoHubClient](../Code/src/EchoHub.Core/Contracts/IEchoHubClient.cs.md) callbacks. The docs note an important detail: in end-to-end encrypted channels the content behind the Url (and previews) may be ciphertext opaque to the server, which affects how clients process the Url returned in AttachmentDto.
## ModerationDtos.cs
`AssignRoleRequest` collaborates directly with `ApiClient` and other members of this topic (4 dependency links).
The [ModerationDtos](../Code/src/EchoHub.Core/DTOs/ModerationDtos.cs.md) file provides small, immutable payloads for moderation actions; the [AssignRoleRequest](../Code/src/EchoHub.Core/DTOs/ModerationDtos.cs.md) record carries a Username and a ServerRole value and is intended to be sent to moderation endpoints to request a role change. The file also contains BanRequest, KickRequest, and MuteRequest records used for banning, kicking, and muting operations. The ApiClient serializes these DTOs when invoking its moderation methods (AssignRoleAsync, BanUserAsync, KickUserAsync, MuteUserAsync), so moderation actions are expressed as data objects across the HTTP boundary.
## ProfileDtos.cs
`AvatarUploadResponse` collaborates directly with `ApiClient` and other members of this topic (4 dependency links).
The [ProfileDtos](../Code/src/EchoHub.Core/DTOs/ProfileDtos.cs.md) file defines small user-profile payloads used by profile/update and avatar upload endpoints. The [AvatarUploadResponse](../Code/src/EchoHub.Core/DTOs/ProfileDtos.cs.md) record holds AvatarAscii, the ASCII-art representation returned after an avatar upload; ApiClient's UploadAvatarAsync returns or deserializes this DTO so callers can display or store the ASCII preview. UpdateProfileRequest and UpdateStatusRequest are optional-field records used for partial profile updates and are the payloads ApiClient will send via UpdateProfileAsync.
How the pieces fit
The ApiClient is the HTTP façade: it consumes and produces the DTOs in AuthDtos, ChatDtos, ModerationDtos, and ProfileDtos when calling server endpoints and populating client state. Authentication flows center on the LoginRequest/LoginResponse/RefreshRequest DTOs and ApiClient methods that set and refresh Token/RefreshToken and expose helpers like GetValidTokenAsync and EnsureAuthenticated. Separately, real-time server-to-client events are delivered through the [IEchoHubClient](../Code/src/EchoHub.Core/Contracts/IEchoHubClient.cs.md) callback interface using the same Chat and Profile DTOs, keeping transport and event handling decoupled while the ApiClient handles request/response semantics and token lifecycle.
---
*Covers 8 of 8 source files identified for this topic.*
*Synthesised by Aurion on 2026-07-23 05:50:51 UTC*
@@ -0,0 +1,41 @@
# Attachments and file transfers
> Staging and sending attachments in chat messages and coordinating outbound attachments.
Outgoing attachments are staged in the UI, packaged as transport objects, and then coordinated through the app orchestrator into the live connection for transmission. This topic shows the small set of types and methods that carry file streams and metadata from the MainWindow staging UI through AppOrchestrator into the connection layer so they can be uploaded (optionally encrypted) and surfaced as attachment DTOs in messages.
## OutgoingAttachment.cs
Represents an attachment queued for sending to a channel or user.
The [OutgoingAttachment](../Code/src/EchoHub.Client/Services/OutgoingAttachment.cs.md) record is the in-process transport object used to carry a single file stream and its filename through the sending pipeline. It declares four properties: the raw Stream and FileName (required), and two optional strings DeclaredKind and EncryptedPreview which are intended for end-to-end encrypted scenarios. As a record it provides value-based equality for tracking/deduplication but notably does not manage the Stream lifetime — callers open and dispose streams around instances of this type. In this topic it is produced/consumed by the orchestrator layer (see [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md)).
## MainWindow.cs
Provides UI hooks for staging attachments and displaying progress.
The [MainWindow](../Code/src/EchoHub.Client/UI/MainWindow.cs.md) component exposes the user-facing hooks that allow files to be staged and progress or status to be shown. Among its many members are StageFiles (to accept user-selected files) and SetStagedAttachments (to update the UI with the current list of staged items), plus UI update methods such as UpdateSpinner/UpdateInputTitle to reflect in-progress operations. MainWindow depends on the message/attachment DTO types in [ChatDtos.cs](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) for rendering metadata and is called by [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md) when orchestrated work (prepare/send/clear attachments) must update the UI.
## AppOrchestrator.cs
Builds outbound attachments and coordinates sending operations.
The [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md) owns the high-level send flow: it implements BuildOutgoingAttachmentAsync to assemble outbound attachment payloads (creating [OutgoingAttachment](../Code/src/EchoHub.Client/Services/OutgoingAttachment.cs.md) instances), provides cleanup helpers such as CleanupPastedTempFiles, and contains command handlers like HandleCmdSendFile and HandleCmdClearAttachments that respond to user actions. It depends on the DTO types in [ChatDtos.cs](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) when preparing message payloads and coordinates with the UI by reading staged files from and writing status back to [MainWindow](../Code/src/EchoHub.Client/UI/MainWindow.cs.md). For transmission the orchestrator delegates connection and delivery responsibilities to the connection layer ([ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md)).
## ConnectionManager.cs
`ConnectionManager` collaborates directly with `AppOrchestrator` and other members of this topic (4 dependency links).
The [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) encapsulates the live chat connection lifecycle: authentication, optional end-to-end key fetching, and instantiation/wiring of the SignalR hub connection. It exposes a thin event surface so UI code (principally [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md)) can subscribe to SignalR events without dealing with SignalR details, and it implements IAsyncDisposable so the orchestrator can tear down network resources cleanly. ConnectAsync (documented in the file) reports progress via a provided onStatus callback, treats failure to obtain an E2E key as non-fatal, and returns compound results (the internal [ConnectResult](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) record) that include login, channel list, and histories for the orchestrator to use.
## ChatDtos.cs
`AttachmentDto` collaborates directly with `AppOrchestrator` and other members of this topic (4 dependency links).
The [AttachmentDto](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) is the immutable transport representation of an attachment that travels with messages: it records the attachment Kind, a Url where the resource can be retrieved, FileName, FileSize, and an optional AsciiPreview used for character-art rendering. The DTO is the canonical metadata shape used across UI, API, and connection boundaries; the orchestrator uses these DTO types when composing or processing message payloads, and the MainWindow reads them to render attachments in the UI. In end-to-end encrypted channels the DTOs Url and AsciiPreview may represent ciphertext that the server cannot interpret.
How the pieces fit
- UI staging: users pick files via [MainWindow](../Code/src/EchoHub.Client/UI/MainWindow.cs.md). MainWindow.StageFiles and SetStagedAttachments hold the files and show progress to the user while AppOrchestrator drives the workflow.
- Packaging: [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md) constructs [OutgoingAttachment](../Code/src/EchoHub.Client/Services/OutgoingAttachment.cs.md) records (via BuildOutgoingAttachmentAsync), cleans up temp files, and maps to the DTO shapes from [ChatDtos.cs](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) when preparing messages.
- Delivery: the orchestrator delegates network work to [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md), which manages connection/auth/E2E keys and forwards events so the UI and orchestrator can report progress and completion.
---
*Covers 5 of 5 source files identified for this topic.*
*Synthesised by Aurion on 2026-07-23 05:53:19 UTC*
@@ -0,0 +1,31 @@
# Clipboard utilities
> Helpers for clipboard interactions: files and images.
This guide describes the clipboard-focused utilities in the client: one helper that exposes file-list clipboard contents, another that normalizes image clipboard data into PNG bytes, and the UI entry points that call those helpers to stage attachments or consume images.
## ClipboardFiles.cs
Clipboard file utilities for handling file lists.
The [ClipboardFiles](../Code/src/EchoHub.Client/Services/ClipboardFiles.cs.md) static class provides a single, platform-aware API (exposed via TryGetFiles) to read file paths when the OS clipboard contains a file-list. It hides OS-specific handling—on Windows it reads CF_HDROP with a short retry loop to tolerate clipboard contention, on Linux it uses text/uri-list through wl-paste or xclip—and it performs existence checks and filters out non-file entries so callers receive only existing paths. TryGetFiles returns true only when at least one valid file path is found, otherwise false, allowing callers to fall back if no usable file-list is present; this class is consumed by the UI layer ([MainWindow](../Code/src/EchoHub.Client/UI/MainWindow.cs.md)).
## ClipboardImage.cs
Clipboard image utilities for copying images to the clipboard.
The [ClipboardImage](../Code/src/EchoHub.Client/Services/ClipboardImage.cs.md) static class exposes TryGetPng to extract whatever image is currently on the OS clipboard and return it as PNG-encoded bytes suitable for saving, embedding, or transmitting. It normalizes multiple clipboard image formats: it prefers a native PNG clipboard format to preserve alpha, and falls back to platform bitmaps (CF_DIB on Windows) by wrapping DIB bytes in a minimal BMP header and decoding/re-encoding to PNG via DibToPng; malformed DIB input yields null and TryGetPng surfaces that as a failure (false). TryGetPng routes to OS-specific helpers, logs errors rather than throwing, and returns false on unsupported platforms or on failure; [MainWindow](../Code/src/EchoHub.Client/UI/MainWindow.cs.md) depends on this helper to obtain clipboard image bytes.
## MainWindow.cs
`MainWindow` collaborates directly with `ClipboardFiles` and other members of this topic (2 dependency links).
The [MainWindow](../Code/src/EchoHub.Client/UI/MainWindow.cs.md) UI class defines a large set of interactive behaviors and a handful of members that interact with the clipboard: notably methods named StageFiles, SetStagedAttachments and GuardedClipboardAction appear in its surface. Per the documented relationships, MainWindow delegates platform specifics to the clipboard helpers: it invokes [ClipboardFiles](../Code/src/EchoHub.Client/Services/ClipboardFiles.cs.md).TryGetFiles to obtain file paths copied by the user and then uses its own staging APIs (SetStagedAttachments/StageFiles) to prepare those paths for attachment. Likewise, MainWindow can call [ClipboardImage](../Code/src/EchoHub.Client/Services/ClipboardImage.cs.md).TryGetPng to obtain a normalized PNG byte array when the user has copied an image, allowing the UI to save, embed, or attach that image without per-OS handling. GuardedClipboardAction provides a place to centralize error handling and UI feedback around those clipboard calls so failures from the helpers (they return false rather than throwing) can be handled gracefully.
How the pieces fit
- The two service classes encapsulate platform-specific clipboard concerns: [ClipboardFiles] returns a filtered list of existing file paths or false; [ClipboardImage] returns a PNG byte array or false.
- [MainWindow] orchestrates user-facing clipboard flows: it calls those helpers from StageFiles/SetStagedAttachments and related clipboard actions, then integrates the results into the message-composition and attachment UI.
- The helpers favor returning a simple success/failure result (and normalized data) so the UI can decide whether to stage attachments, embed image bytes, or fall back to alternative input methods.
---
*Covers 3 of 3 source files identified for this topic.*
*Synthesised by Aurion on 2026-07-23 05:53:51 UTC*
@@ -0,0 +1,46 @@
# Command handling
> Slash-command parsing and dispatching command actions from UI and orchestrator.
*Figure: How Command handling works.*
```mermaid
%%{init: {'theme':'base','themeVariables':{'background':'#faf7ef','primaryColor':'#f0e2c2','primaryTextColor':'#1f2840','primaryBorderColor':'#8a7548','secondaryColor':'#d9efec','secondaryBorderColor':'#1d8a80','secondaryTextColor':'#1f2840','tertiaryColor':'#f2ebd8','tertiaryBorderColor':'#8a7548','tertiaryTextColor':'#1f2840','lineColor':'#1d8a80','titleColor':'#1f2840','fontSize':'14px','edgeLabelBackground':'#faf7ef','clusterBkg':'#f2ebd8','clusterBorder':'#8a7548','actorBkg':'#f0e2c2','actorBorder':'#8a7548','actorTextColor':'#1f2840','actorLineColor':'#8a7548','signalColor':'#1d8a80','signalTextColor':'#1f2840','activationBkgColor':'#d9efec','activationBorderColor':'#1d8a80','noteBkgColor':'#f2ebd8','noteBorderColor':'#8a7548','noteTextColor':'#1f2840','labelBoxBkgColor':'#f0e2c2','labelBoxBorderColor':'#8a7548','labelTextColor':'#1f2840','transitionColor':'#1d8a80','transitionLabelColor':'#1f2840','stateLabelColor':'#1f2840','altBackground':'#f2ebd8'}}}%%
sequenceDiagram
participant Client
participant ConnectionManager_cs as ConnectionManager.cs
participant AppOrchestrator_cs as AppOrchestrator.cs
participant CommandHandler_cs as CommandHandler.cs
Client->>ConnectionManager_cs: UI sends slash command
ConnectionManager_cs->>AppOrchestrator_cs: forward command to orchestrator
AppOrchestrator_cs->>CommandHandler_cs: invoke command parsing and dispatch
CommandHandler_cs-->>AppOrchestrator_cs: return parsed action/result
AppOrchestrator_cs->>ConnectionManager_cs: dispatch action / send response
ConnectionManager_cs-->>Client: deliver response to UI
```
This guide explains how user-entered slash commands move from text input into application behavior and network actions. It describes the parsing and event surface (the command-to-event bridge), the central orchestrator that implements command handlers and coordinates UI-side concerns, and the connection manager that owns the live SignalR connection and performs the network work the orchestrator requests.
## CommandHandler.cs
Parses and executes chat commands; determines if input is a command.
The [CommandHandler](../Code/src/EchoHub.Client/Commands/CommandHandler.cs.md) class is the input-to-event bridge: it recognizes whether a text input is a slash command (via IsCommand) and runs a suite of HandleXxx parsing routines (for example HandleSetStatus, HandleSendAction, HandleCreateInvite, HandleExportData and many others listed in the source). It does not perform side effects itself; instead it exposes one event per supported command (OnSetStatus, OnSendAction, OnCreateInvite, OnExportData, etc.) and raises asynchronous events after parsing. The class also contains parsing helpers and semantics notes (status handling, StripQuotes, IsValidHex, ParsePathAndSizeFlag) so subscribers can depend on a consistent interpretation of user input. According to the topic relationships, this component is consumed by the [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md), which subscribes to those events to implement behavior.
## AppOrchestrator.cs
Central coordinator handling command-related actions and user commands across the app.
The [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md) wires the command parsing surface into application behavior: it subscribes to the events emitted by the [CommandHandler](../Code/src/EchoHub.Client/Commands/CommandHandler.cs.md) and implements the concrete handlers named in the source (a large set of HandleCmd* methods such as HandleCmdSetStatus, HandleCmdSendFile, HandleCmdJoinChannel, HandleCmdCreateInvite, HandleCmdExportData, HandleCmdKickUser, HandleCmdNukeChannel, etc.). It also owns UI-side responsibilities like BuildOutgoingAttachmentAsync, EnsureRoomUnlockedForSendAsync, CleanupPastedTempFiles, pending reply management, and resource cleanup (Dispose). Per its relationships the orchestrator depends on both [CommandHandler](../Code/src/EchoHub.Client/Commands/CommandHandler.cs.md) for parsing and [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) for performing network operations; the source shows it translating parsed commands into calls and requests that drive the connection layer. The file also documents many small, focused flow steps (ApplyAsciiSize, HandleChannelSelected, HandleEditProfile, etc.) that adapt command intent into concrete application actions.
## ConnectionManager.cs
`ConnectionManager` collaborates directly with `AppOrchestrator` and other members of this topic (4 dependency links).
The [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) owns the full lifecycle of a live chat connection: authentication and token handling, attempting to fetch and apply end-to-end encryption keys, instantiating and wiring the EchoHub (SignalR) connection, tracking which channels are joined, and forwarding SignalR callbacks as simple .NET events the UI can subscribe to. It exposes ConnectAsync semantics (reporting progress via an onStatus callback and throwing on authentication failure) and implements IAsyncDisposable so callers can call DisposeAsync to tear down the hub and underlying ApiClient. The file also defines the [ConnectResult](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) record (Login, Channels, Histories) that packages the login response, joined channels list, and message histories returned by ConnectAsync. Notes in the source call out important behaviors: failures to fetch encryption keys are non-fatal, forwarded events may arrive on background threads, and callers (principally the [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md)) must handle marshal-to-UI-thread concerns.
How the pieces fit
User input flows into [CommandHandler](../Code/src/EchoHub.Client/Commands/CommandHandler.cs.md), which parses text and emits a focused event per command. [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md) subscribes to those events and implements the HandleCmd* methods that translate parsed intent into application actions and requests; when a command requires network interaction, AppOrchestrator delegates to [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md). ConnectionManager manages the SignalR connection and returns results or raises network events back to the orchestrator, while AppOrchestrator handles UI concerns (attachments, pending replies, local state) and coordinates lifecycle and cleanup.
---
*Covers 3 of 3 source files identified for this topic.*
*Synthesised by Aurion on 2026-07-23 05:52:46 UTC*
@@ -0,0 +1,79 @@
# Encryption and room key management
> End-to-end encryption plumbing and secure handling of per-channel room keys.
*Figure: How Encryption and room key management works.*
```mermaid
%%{init: {'theme':'base','themeVariables':{'background':'#faf7ef','primaryColor':'#f0e2c2','primaryTextColor':'#1f2840','primaryBorderColor':'#8a7548','secondaryColor':'#d9efec','secondaryBorderColor':'#1d8a80','secondaryTextColor':'#1f2840','tertiaryColor':'#f2ebd8','tertiaryBorderColor':'#8a7548','tertiaryTextColor':'#1f2840','lineColor':'#1d8a80','titleColor':'#1f2840','fontSize':'14px','edgeLabelBackground':'#faf7ef','clusterBkg':'#f2ebd8','clusterBorder':'#8a7548','actorBkg':'#f0e2c2','actorBorder':'#8a7548','actorTextColor':'#1f2840','actorLineColor':'#8a7548','signalColor':'#1d8a80','signalTextColor':'#1f2840','activationBkgColor':'#d9efec','activationBorderColor':'#1d8a80','noteBkgColor':'#f2ebd8','noteBorderColor':'#8a7548','noteTextColor':'#1f2840','labelBoxBkgColor':'#f0e2c2','labelBoxBorderColor':'#8a7548','labelTextColor':'#1f2840','transitionColor':'#1d8a80','transitionLabelColor':'#1f2840','stateLabelColor':'#1f2840','altBackground':'#f2ebd8'}}}%%
sequenceDiagram
participant ConnectionManager
participant ClientConfig
participant RoomKeyProtector
participant RoomKeyStore
participant ClientEncryptionService
ConnectionManager->>ClientConfig: Load AccountPreset
ClientConfig->>RoomKeyProtector: Initialize/Acquire protector
RoomKeyProtector-->>ClientConfig: Protector instance
ConnectionManager->>RoomKeyStore: Initialize RoomKeyStore
RoomKeyStore->>ClientConfig: Read AccountPreset/config
ClientConfig-->>RoomKeyStore: Config data
RoomKeyStore->>RoomKeyProtector: Protect/Unprotect room keys
RoomKeyProtector-->>RoomKeyStore: Protected/Decrypted key
ConnectionManager->>ClientEncryptionService: Register IMessageEncryptionService
ClientEncryptionService-->>ConnectionManager: Encryption service ready
ConnectionManager->>RoomKeyStore: Request room key for channel
RoomKeyStore->>RoomKeyProtector: Decrypt room key
RoomKeyProtector-->>RoomKeyStore: Plain room key
RoomKeyStore-->>ConnectionManager: Return room key
ConnectionManager->>ClientEncryptionService: Encrypt/Decrypt message with room key
ClientEncryptionService-->>ConnectionManager: Encrypted/Decrypted payload
```
# Encryption and room key management
End-to-end encryption in the client is implemented as a few focused components: a runtime encryptor that mirrors the server format, a protector that encrypts per-channel room keys at rest, a store that binds persisted server entries to an in-memory cache, and a connection manager that wires those pieces into the live SignalR connection. This guide explains what each file actually implements, how they call each other, and where responsibilities (in-memory keys, persisted protected keys, and message-level cryptography) are split.
## ClientEncryptionService.cs
Implements IMessageEncryptionService for encrypting/decrypting messages.
The [ClientEncryptionService](../Code/src/EchoHub.Client/Services/ClientEncryptionService.cs.md) class is the client-side AES-256-GCM encryptor/decryptor that mirrors the servers encryption format so clients and server exchange the same payload shape. It exposes SetKey to accept a 32-byte, server-provided base64 key, Encrypt to produce a prefixed base64 payload containing nonce and ciphertext+tag, and Decrypt to reverse that encoding; before a key is set Encrypt is intentionally a no-op and returns plaintext, and Decrypt returns a sentinel failure message when decryption fails. Per the documentation, the service isolates cryptography behind a swappable implementation and is used by higher-level connection code to apply message encryption only when a key is loaded; in this topic it is referenced by [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md).
## RoomKeyProtector.cs
Provides protection around room keys for secure storage/usage.
The [RoomKeyProtector](../Code/src/EchoHub.Client/Services/RoomKeyProtector.cs.md) class is the single API for protecting and unprotecting per-user room content keys before they are written to or read from client configuration. Its Protect method returns a storage-ready string that is prefixed to indicate the protection method ("dp1:" for Windows DPAPI or "k1:" for an AES-GCM-encrypted master key file on other platforms), and TryUnprotect attempts to recover the raw room key while reporting whether the stored value was a legacy plain-base64 entry and whether unprotection succeeded. The class accepts a directory (to locate the master key file) and caches the master key after guarded loading; callers such as [ClientConfig](../Code/src/EchoHub.Client/Config/ClientConfig.cs.md) and [RoomKeyStore](../Code/src/EchoHub.Client/Services/RoomKeyStore.cs.md) rely on it to convert between in-memory bytes and protected storage strings without having to deal with platform-specific details.
## RoomKeyStore.cs
Stores and retrieves room keys securely for channels.
[RoomKeyStore](../Code/src/EchoHub.Client/Services/RoomKeyStore.cs.md) binds runtime state (a decrypted, in-memory cache of room keys) to persisted per-server entries so users don't re-enter passphrases every launch. You call LoadForServer(serverUrl) to bind the store to a SavedServer in [ClientConfig](../Code/src/EchoHub.Client/Config/ClientConfig.cs.md); the store will read that SavedServer's ChannelKeys, call into [RoomKeyProtector](../Code/src/EchoHub.Client/Services/RoomKeyProtector.cs.md) to unprotect them, and populate its thread-safe cache. The class exposes methods to TryGetKey, StoreKey, Replace/Remove keys, and TryStoreFromEnvelope (which unwraps a wrapped key with a KEK) and will upgrade legacy plain/base64 entries to the protected format when possible; changes are persisted back to the SavedServer through ClientConfig and unreadable entries are logged rather than failing hard. Connection-side code (notably [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md)) uses RoomKeyStore to determine which channels are encrypted and to retrieve keys for encrypting/decrypting messages at send/receive time.
## ClientConfig.cs
`ClientConfig` collaborates directly with `RoomKeyProtector` and other members of this topic (3 dependency links).
[ClientConfig](../Code/src/EchoHub.Client/Config/ClientConfig.cs.md) is the central container for a user's persisted preferences and runtime state, and it holds SavedServer entries that include the persisted, protected ChannelKeys consumed by [RoomKeyStore](../Code/src/EchoHub.Client/Services/RoomKeyStore.cs.md). ClientConfig provides the serialized place where RoomKeyProtector-generated strings live (the protector prefixes such as "dp1:" or "k1:" are stored here), and callers such as RoomKeyStore read and write these SavedServer entries to keep the on-disk picture in sync with the in-memory cache. Because RoomKeyProtector derives its key-file location from a directory you pass to its constructor, ClientConfigs location and usage patterns determine where the master key file will be stored and how RoomKeyStore persists upgrades from legacy entries.
## ConnectionManager.cs
`ConnectionManager` collaborates directly with `ClientEncryptionService` and other members of this topic (2 dependency links).
[ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) is the high-level lifecycle owner for authentication, establishing the EchoHub SignalR connection, and wiring end-to-end encryption into runtime behavior. During ConnectAsync it performs authentication (throwing on auth failure), attempts to fetch and apply an E2E encryption key (failure to fetch is non-fatal and the manager logs a warning), and then uses the [ClientEncryptionService](../Code/src/EchoHub.Client/Services/ClientEncryptionService.cs.md) to encrypt outbound messages and decrypt inbound ones when a key is present. It relies on [RoomKeyStore](../Code/src/EchoHub.Client/Services/RoomKeyStore.cs.md) to know which channels are encrypted and to obtain per-channel room keys, and it uses [ClientConfig](../Code/src/EchoHub.Client/Config/ClientConfig.cs.md) as the backing persisted configuration for saved servers; ConnectionManager forwards SignalR events as simple .NET events and implements IAsyncDisposable so callers can cleanly tear down network and API resources.
How the pieces fit
- ConnectionManager is the orchestrator: it authenticates, attempts to fetch the server-provided E2E key, wires SignalR events to the UI, and delegates message-level cryptography to [ClientEncryptionService](../Code/src/EchoHub.Client/Services/ClientEncryptionService.cs.md) when a key is present.
- RoomKeyStore sits between persisted state and runtime: it loads and persists ChannelKeys via [ClientConfig](../Code/src/EchoHub.Client/Config/ClientConfig.cs.md) and uses [RoomKeyProtector](../Code/src/EchoHub.Client/Services/RoomKeyProtector.cs.md) to unprotect/protect those keys so the on-disk config never contains raw base64 room keys (legacy unprotected values are upgraded when possible).
- RoomKeyProtector implements the platform-specific protection formats (DPAPI or a file-backed AES-GCM master key) and presents a stable Protect/TryUnprotect API so the higher-level store and config code do not need to handle cryptography details.
Together these components keep plaintext room keys out of persistent storage, keep a decrypted cache for active sessions, and ensure message encryption happens only when a server-supplied key has been loaded and applied by the client encryptor.
---
*Covers 5 of 5 source files identified for this topic.*
*Synthesised by Aurion on 2026-07-23 05:52:19 UTC*
@@ -0,0 +1,34 @@
# Real-time connection management
> Managing the SignalR hub connection lifecycle and connection state.
# Real-time connection management
This guide explains how the client-side pieces manage a SignalR-based chat connection, surface server events to the UI, and carry message and attachment DTOs across those boundaries. Read it to understand which types own the HubConnection lifecycle, which types represent messages and attachments, and how connection orchestration hands events and histories back to the UI layer.
## EchoHubConnection.cs
Encapsulates the SignalR connection to the server and join history with encryption info.
The [EchoHubConnection](../Code/src/EchoHub.Client/Services/EchoHubConnection.cs.md) type is a thin, SignalR-backed client wrapper that owns a HubConnection and translates server callbacks into plain .NET events (for example OnMessageReceived, OnUserJoined, OnChannelUpdated). It also integrates client-side encryption and room-key lookup: incoming payloads are decrypted before being raised to subscribers, and join history plus encryption metadata is tracked so callers can present past messages. EchoHubConnection declares focused exception types such as ChannelPasswordRequiredException (thrown when a join fails for password reasons) to enable UI-driven retry flows. According to the file relationships, EchoHubConnection consumes message and channel shapes from [ChatDtos.cs](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) and is instantiated and used by [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md).
## ConnectionManager.cs
Coordinates connection lifecycle and connection events across the client.
The [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) is the high-level owner of authentication, E2E key retrieval, HubConnection creation, wiring of SignalR callbacks, and tracking of joined channels. It exposes a small event surface that forwards the EchoHubConnection events to the UI (the doc notes AppOrchestrator subscribes), implements IAsyncDisposable to tear down both the hub wrapper and the underlying client, and reports progress from ConnectAsync via an onStatus callback while throwing on authentication failure. ConnectionManager also defines the [ConnectResult](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) record that packages the login response, a list of channel DTOs, and a dictionary of channel histories (the histories contain [MessageDto] entries defined in ChatDtos). Per the relationships, ConnectionManager depends on [ChatDtos.cs](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) for payload shapes and on [EchoHubConnection](../Code/src/EchoHub.Client/Services/EchoHubConnection.cs.md) to manage the live SignalR interactions.
## ChatDtos.cs
`AttachmentDto` collaborates directly with `ConnectResult` and other members of this topic (9 dependency links).
[ChatDtos.cs](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) defines the immutable DTOs used across the connection boundary: records such as AttachmentDto, ChannelDto, ChannelMetaDto, MessageDto, JoinChannelResult, and request shapes like SendMessageRequest. The [AttachmentDto](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) record carries metadata for file attachments (kind, URL, filename, filesize, optional ASCII preview) and is explicitly designed to work with end-to-end encrypted channels where the resource behind Url may be ciphertext the server cannot read. These DTOs are the concrete payload shapes that both [EchoHubConnection](../Code/src/EchoHub.Client/Services/EchoHubConnection.cs.md) and [ConnectionManager](../Code/src/EchoHub.Client/Services/ConnectionManager.cs.md) send, receive, and store in histories.
How the pieces fit
ConnectionManager is the orchestration layer: it authenticates, attempts to acquire E2E keys, builds and wires an [EchoHubConnection](../Code/src/EchoHub.Client/Services/EchoHubConnection.cs.md), and exposes forwarded events to the UI while tracking joined channels and histories. EchoHubConnection is the SignalR-focused implementation that manages the HubConnection lifecycle, maps server callbacks to events, performs decryption of incoming payloads, and throws focused exceptions (for example ChannelPasswordRequiredException) so the UI can prompt and retry joins. The DTOs in [ChatDtos.cs](../Code/src/EchoHub.Core/DTOs/ChatDtos.cs.md) are the shared, immutable shapes (messages, channels, attachments) that flow between the manager, the hub wrapper, and the UI; ConnectResult packages those DTOs back to callers after an initial connect sequence.
---
*Covers 3 of 3 source files identified for this topic.*
*Synthesised by Aurion on 2026-07-23 05:51:44 UTC*
+31
View File
@@ -0,0 +1,31 @@
# Theming and UI color management
> Representing themes, color palettes, and runtime theme application.
Theming and UI color management
The files in this topic define how the EchoHub client represents color themes, exposes a curated set of built-in and user-provided themes, and wires theme selection into the running application. Read these three artifacts to understand the Theme data model, the static ThemeManager API that discovers/applies/persists themes, and the AppOrchestrator entry point that reacts to user commands and delegates theme work to the manager.
## Theme.cs
Represents a UI theme.
The [Theme](../Code/src/EchoHub.Client/Themes/Theme.cs.md) class is the data container for a complete UI appearance. It exposes a required Name plus four area-specific palettes—Base, Menu, Dialog, and Status—each typed as a [ThemeColors](../Code/src/EchoHub.Client/Themes/Theme.cs.md) instance, and an optional Border palette that, when set, overrides only frame-border colors while leaving other chrome tied to Base. The writer notes sensible defaults: each palette initializes to a new ThemeColors so a Theme is usable with minimal configuration, and Border accepts hex literals or named colors to let designers tint edges without touching text palettes. This file is the canonical representation of a theme and is consumed by the [ThemeManager](../Code/src/EchoHub.Client/Themes/ThemeManager.cs.md) to build and persist theme choices and by the [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md) when the application needs to apply or react to theme changes.
## ThemeManager.cs
Loads, caches, and applies themes across the app.
[ThemeManager](../Code/src/EchoHub.Client/Themes/ThemeManager.cs.md) is a static API that bridges theme data and runtime application. It exposes discovery and retrieval functions such as GetAvailableThemes and GetTheme, mutation points like SaveTheme, and the runtime switch ApplyTheme; utility functions include ParseColor and BuildColorScheme, the latter ensuring colors for editable/read-only roles and transparency behave correctly so inputs remain legible under transparent themes. ThemeManager maintains a curated set of built-in theme factory methods (DefaultTheme, DraculaTheme, LightTheme, etc.), attempts to load additional themes from a user directory (ThemeDir), and falls back to built-ins if the directory cannot be read; SaveTheme is implemented best-effort and quietly swallows failures. Because it returns and manipulates [Theme](../Code/src/EchoHub.Client/Themes/Theme.cs.md) instances, ThemeManager is the component the [AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md) calls when the app needs to enumerate, choose, or persist a theme and when it needs the computed color scheme to apply to the UI.
## AppOrchestrator.cs
`AppOrchestrator` collaborates directly with `Theme` and other members of this topic (2 dependency links).
[AppOrchestrator](../Code/src/EchoHub.Client/AppOrchestrator.cs.md) is the application-level coordinator that owns the MainWindow and a large set of command handlers; among its many responsibilities it includes a handler named HandleCmdSetTheme which responds to theme-change requests. In practice the orchestrator calls into [ThemeManager](../Code/src/EchoHub.Client/Themes/ThemeManager.cs.md) to fetch or apply a [Theme](../Code/src/EchoHub.Client/Themes/Theme.cs.md) (for example via GetTheme and ApplyTheme) and then ensures the active UI reflects the manager-provided color scheme. The doc block lists the constructor and MainWindow property plus the command handlers (including HandleCmdSetTheme) so the intended runtime flow is: user or code issues a theme command to AppOrchestrator, AppOrchestrator delegates theme discovery/load/apply to ThemeManager, and the Theme instance shapes the MainWindow styling.
How the pieces fit
Theme is the immutable-ish data model for visual choices; ThemeManager is the static service that discovers, builds, parses, and persists those models and produces a concrete color scheme via BuildColorScheme; AppOrchestrator is the runtime conductor that responds to user commands and uses ThemeManager to fetch and ApplyTheme to the UI. The dependency direction is AppOrchestrator -> ThemeManager -> Theme, with ThemeManager also responsible for supplying built-in Theme instances and reading user themes from disk when available.
---
*Covers 3 of 3 source files identified for this topic.*
*Synthesised by Aurion on 2026-07-23 05:51:21 UTC*
@@ -0,0 +1,32 @@
# Update management
> Data and update flow: backup prior to updates and update checks.
Update management
This topic covers the client-side update workflow: detecting available versions from the running Terminal.Gui app, deferring heavy update work until the UI has shut down, and snapshotting the application state so you can roll back if an update goes wrong. The two files coordinate a safe in-place updater by separating user interaction and terminal ownership (in UpdateChecker) from the filesystem snapshot and metadata (in UpdateBackupService).
## UpdateBackupService.cs
Provides backup of user data before updates.
The file declares three related symbols that implement pre-update snapshotting. [BackupJsonContext](../Code/src/EchoHub.Client/Services/UpdateBackupService.cs.md) is an internal, source-generated JsonSerializerContext that supplies reflection-free JSON metadata for serializing the on-disk metadata type. The public [UpdateBackupService](../Code/src/EchoHub.Client/Services/UpdateBackupService.cs.md) static class performs the actual backup/rollback responsibilities: it creates a ZIP snapshot of the running application under ~/.echohub/update-backup/ (backup.zip) and writes a companion backup-info.json (the [BackupInfo](../Code/src/EchoHub.Client/Services/UpdateBackupService.cs.md) contract) that records the version, application directory, and UTC timestamp. The service exposes operations to CreateBackup before applying an update, to check presence via BackupExists, and to read metadata with GetBackupInfo; it also exposes an IsPostUpdate flag that lets startup logic detect a recent update backup and react accordingly. Because the JSON context is internal and generated, callers within the assembly configure JsonSerializerOptions with BackupJsonContext when they read or write backup-info.json.
The file is used by the update coordination logic in [UpdateChecker](../Code/src/EchoHub.Client/Services/UpdateChecker.cs.md): the checker defers the updater work but relies on UpdateBackupService to attempt a pre-update snapshot when the update is actually applied.
## UpdateChecker.cs
Checks for updates and coordinates update flow.
[UpdateChecker](../Code/src/EchoHub.Client/Services/UpdateChecker.cs.md) is a disposable helper that runs background polling and supports manual checks, while keeping all user interaction on the provided Terminal.Gui IApplication main loop. Its responsibilities are: poll for newer versions via an internal Updater, present a TUI confirmation dialog by marshalling callbacks with _app.Invoke, and — crucially — avoid performing download/extract/restart while the TUI still owns the terminal. When the user accepts an update, UpdateChecker sets PendingUpdate to an awaitable delegate (the internal ApplyUpdateAsync) and captures the chosen version, then signals the TUI to stop; the host is expected to call PendingUpdate after the main loop exits so the update can run headless and safely restart the process.
Concrete behaviors documented in the class include: Start() only activates the periodic poller in RELEASE builds; PendingUpdate is intentionally a Task-returning delegate to be invoked by the host after the console is restored; ApplyUpdateAsync attempts to create a pre-update backup by calling [UpdateBackupService.CreateBackup](../Code/src/EchoHub.Client/Services/UpdateBackupService.cs.md) and logs but does not fail the update flow if backup creation fails; ApplyUpdateAsync also sets Console.OutputEncoding = UTF8 while swallowing exceptions for non-interactive stdout; and CurrentVersion reads the assembly version with a fallback of "0.0.0".
How the pieces fit
- Update detection and user confirmation happen inside [UpdateChecker](../Code/src/EchoHub.Client/Services/UpdateChecker.cs.md) running on the Terminal.Gui main loop; when the user accepts an update, the checker defers the actual work by setting PendingUpdate and requesting the TUI to stop.
- The deferred update work (ApplyUpdateAsync) calls into [UpdateBackupService](../Code/src/EchoHub.Client/Services/UpdateBackupService.cs.md) to snapshot the application: it writes backup.zip and backup-info.json (the serialized [BackupInfo](../Code/src/EchoHub.Client/Services/UpdateBackupService.cs.md) using [BackupJsonContext](../Code/src/EchoHub.Client/Services/UpdateBackupService.cs.md)). Backup creation failures are logged but do not block the update.
- The host is responsible for invoking PendingUpdate only after the TUI main loop has fully exited and the console is restored, at which point the update runs headless (and may restart the process).
---
*Covers 2 of 2 source files identified for this topic.*
*Synthesised by Aurion on 2026-07-23 05:54:19 UTC*