Architecture

XB Homebrew Vault uses the MVVM pattern with CommunityToolkit.Mvvm and Avalonia UI 12, running on .NET 10.

Layered Architecture

graph TD
    subgraph Views["Views (Avalonia XAML)"]
        MW[MainWindow]
        SW[SplashWindow]
        SetupW[SetupWizardWindow]
        BV[BrowseView]
        IV[InstalledView]
        SV[SettingsView]
        TV[ToolsView]
        LV[LogsView]
        FV[FileExplorerView]
        InV[InspectorView]
        NotifP[NotificationsPanel]
        TasksP[TasksPanel]
        CW[ConnectionWindow]
        NIW[NetworkInfoWindow]
        PW[ProcessesWindow]
        SIW[SystemInfoWindow]
        CDW[CrashDataWindow]
        PerfW[PerformanceWindow]
        UsbW[UsbPermissionWindow]
        LbW[LoopbackExemptWindow]
        SS[SScreenshotWindow]
        CustW[CustomInstallWindow]
        ItemW[ItemDetailWindow]
        DelW[DeleteConfirmWindow]
        DiscW[DiscordPopup]
        SftpW[SftpInfoWindow]
    end

    subgraph ViewModels["ViewModels (CommunityToolkit.Mvvm)"]
        MVM[MainViewModel]
        BVM[BrowseViewModel]
        IVM[InstalledViewModel]
        SVM[SettingsViewModel]
        TVM[ToolsViewModel]
        FVM[FileExplorerViewModel]
        InVM[InspectorViewModel]
        CVM[ConnectionViewModel]
        NIVM[NetworkInfoViewModel]
        PVM[ProcessesViewModel]
        SIVM[SystemInfoViewModel]
        CDVM[CrashDataViewModel]
        PerfVM[PerformanceViewModel]
        RVM[RefreshViewModel]
        ConfVM[ConfirmViewModel]
        CIWM[CustomInstallViewModel]
        SWVM[SetupWizardViewModel]
        USBVM[UsbPermissionViewModel]
        ShVM[ScreenshotViewModel]
        LbVM[LoopbackExemptViewModel]
        DelVM[DeleteConfirmViewModel]
        TkVM[TaskCenterViewModel]
    end

    subgraph Services["Services"]
        Auth[XboxAuthService]
        Pkg[XboxPackageService]
        Proc[XboxProcessService]
        Net[XboxNetworkService]
        Sys[XboxSystemService]
        Perf[XboxPerformanceService]
        Parser[XboxResponseParser]
        CAS[CatalogApiService]
        PS[PackageInstallService]
        SSvc[SettingsService]
        CS[CryptoService]
        CSvc[CacheService]
        UDD[UsbDriveDetector]
        Sftp[SftpService]
        SftpT[SftpTransferService]
        Portal[PortalAppFilesService]
        XRay[XrayAgentService]
        UpdChk[GitHubReleaseCheckerService]
        PO[PackageOverrideService]
        BgT[BackgroundTaskService]
        ConnMon[ConnectionMonitorService]
        NotifC[NotificationCenterService]
        PreF[PreFlightChecker]
        WinSet[WindowSettingsService]
        UpdCache[UpdateVersionCache]
        Colorizer[InspectorConsoleColorizer]
        PDiag[PlatformDialog]
        L[Logger]
    end

    subgraph Models["Models"]
        CI[CatalogItem]
        IP[InstalledPackage]
        PI[ProcessInfo]
        NI[NetworkInfo]
        SI[SystemInfo]
        CD[CrashDumpInfo]
        PSnap[PerformanceSnapshot]
        XC[XboxConnection]
        AS[AppSettings]
        IPI[InstallProgressInfo]
        UDI[UsbDriveInfo]
        SftpE[SftpEntry]
        XA[XrayAgentInfo]
        BgTask[BackgroundTask]
        Notif[NotificationItem]
    end

    Views --> ViewModels
    ViewModels --> Services
    Services --> Models

    style Views fill:#1A1D23,stroke:#447F3E,color:#9ACA3C
    style ViewModels fill:#1A1D23,stroke:#447F3E,color:#9ACA3C
    style Services fill:#447F3E,stroke:#9ACA3C,color:#fff
    style Models fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
Layer Responsibility
Views Avalonia AXAML windows and user controls — purely declarative
ViewModels Commands, observable state, business-logic orchestration
Services All I/O: HTTP, WebSocket, SSH/SFTP, file system, settings, crypto, caching, WMI
Models Plain data classes — CatalogItem, InstalledPackage, PerformanceSnapshot, etc.

Data Flow

flowchart LR
    U[User Action] --> V[View]
    V -->|Command| VM[ViewModel]
    VM -->|HTTP/WS| S[Service]
    S -->|Parse| M[Model]
    M -->|Response| S
    S -->|ObservableProperty| VM
    VM -->|Binding| V
    V -->|Render| U

    style U fill:#447F3E,stroke:#9ACA3C,color:#fff
    style V fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
    style VM fill:#2A2D33,stroke:#447F3E,color:#9ACA3C
    style S fill:#447F3E,stroke:#9ACA3C,color:#fff
    style M fill:#9ACA3C,stroke:#447F3E,color:#000

App Startup

%%{init: {'theme': 'base', 'themeVariables': { 'primaryColor': '#1A1D23', 'primaryBorderColor': '#447F3E', 'lineColor': '#9ACA3C', 'secondBkgColor': '#2A2D33', 'tertiaryColor': '#447F3E'}}}%%
sequenceDiagram
    autonumber
    participant User
    participant Main as Program.Main
    participant PF as PreFlightChecker
    participant App as App.axaml.cs
    participant Splash as SplashWindow
    participant SSvc as SettingsService
    participant Setup as SetupWizardWindow
    participant MainW as MainWindow

    User->>Main: Launch
    Main->>Main: Single-instance mutex check
    alt Another instance running
        Main->>Main: Activate existing window, exit
    end
    Main->>PF: Pre-flight: validate/corrupt-repair settings + cache
    Main->>App: BuildAvaloniaApp()
    App->>Splash: Show()
    Splash->>App: 2s min delay
    App->>SSvc: Load settings
    alt First run (no settings)
        App->>Setup: ShowDialog() — 3-step wizard
        Setup->>App: credentials captured
    end
    App->>App: Compose services (auth, package, system, network, process, performance, sftp, portal, cache, catalog, override)
    App->>App: Start BackgroundTaskService + ConnectionMonitorService
    App->>MainW: new MainWindow
    App->>Splash: Close()
    App->>MainW: Show()
    MainW->>MainW: Register dialog actions
    User->>MainW: Interact

Services

Service Responsibility Lines
XboxAuthService WDP connection: HTTP client, Basic auth, CSRF cookie, connection test, SMB password fetch, credential state (IsConfigured, IsConnected) 334
XboxPackageService Package lifecycle: list installed, install (single + dependencies), uninstall, launch, suspend, terminate, running-package detection 504
XboxProcessService Process info: list processes, kill by PID, running title 90
XboxNetworkService Network config + WiFi interface/network listing 99
XboxSystemService System info, crash dumps (list/delete/control), screenshot, restart/shutdown 237
XboxPerformanceService WebSocket performance stream → PerformanceSnapshot 87
XboxResponseParser Shared WDP JSON parsing helpers for the Xbox services 169
CatalogApiService Fetches and parses the Emulation Revival catalog.json API (6h TTL, disk cache, stale fallback) 444
PackageInstallService Package analysis, dependency resolution, multi-phase install pipeline 515
PackageOverrideService Catalog ID lookup by PFN/name, embedded + remote override merging 183
SftpService SSH.NET SFTP connection + low-level ops for the File Explorer 694
SftpTransferService High-level transfers: upload file/folder/mixed/ZIP-extract, download, progress + cancel 789
PortalAppFilesService WDP file API (portal) for the File Explorer: list/upload/download/rename/delete 449
XrayAgentService XRay TCP agent discovery + log streaming for the Inspector 267
GitHubReleaseCheckerService Auto-update checker — compares installed version against latest GitHub release 72
BackgroundTaskService Recurring background job runner + task center registry 358
ConnectionMonitorService Periodic connectivity polling → notifications 90
NotificationCenterService In-app notification aggregation + dismiss/action routing 171
SettingsService Persists AppSettings to %APPDATA%/XBVault/settings.json 103
CryptoService XOR + Base64 credential obfuscation 47
CacheService In-memory catalog cache with expiry 116
UsbDriveDetector Lists USB drives via WMI (System.Management) — Windows-only (#if WINDOWS_BUILD) 218
PreFlightChecker Startup settings/cache integrity validation + corrupt-repair 270
WindowSettingsService Persists window size/position 43
UpdateVersionCache Update-availability memoization 83
InspectorConsoleColorizer Log/console colorization for the Inspector 37
PlatformDialog Platform-aware file dialogs (WPF/Avalonia interop) 135
Logger File + console logging (AttachConsole via DllImport — Windows-only) 351

Verified from main code analysis (Aug 2026). Line counts approximate.

Xbox Service Split

The former XboxDeviceService god class (1,433 lines, ~41 public members, complexity 205) was split into focused services, each behind an interface:

Service Interface Domains
XboxAuthService IXboxAuthService Connection, credentials, SMB password, test
XboxPackageService IXboxPackageService Install, uninstall, launch, suspend, terminate, list
XboxProcessService IXboxProcessService List, kill, running title
XboxNetworkService IXboxNetworkService Network config, WiFi
XboxSystemService IXboxSystemService Info, crash dumps, screenshot, restart, shutdown
XboxPerformanceService IXboxPerformanceService WebSocket performance stream

Each takes XboxAuthService (shared connection) as its only constructor dependency. The split removed the god class; ViewModels now inject only the interfaces they need. See Refactor Proposal.

Key connection patterns (inherited from the original design):

  • HTTP client recreation on Configure — a fresh HttpClient per connection works around BaseAddress immutability.
  • Certificate validation bypass — self-signed console certificates; dev-only.
  • CSRF token via CookieContainer — token attached automatically to requests.
  • WebSocket for performance — real-time metrics stream, separate from the REST surface.

ViewModel → Service Dependency Map

graph LR
    MVM[MainViewModel] --> Auth
    BVM[BrowseViewModel] --> CAS
    BVM --> CSvc
    BVM --> Auth
    BVM --> Pkg
    BVM --> PS
    BVM --> PO
    IVM[InstalledViewModel] --> Auth
    IVM --> Pkg
    FVM[FileExplorerViewModel] --> Auth
    FVM --> Sftp
    FVM --> SftpT
    FVM --> Portal
    SVM[SettingsViewModel] --> Auth
    SVM --> CSvc
    TVM[ToolsViewModel] --> Auth
    TVM --> Sys
    CVM[ConnectionViewModel] --> Auth
    CVM --> Net
    NIVM[NetworkInfoViewModel] --> Net
    PVM[ProcessesViewModel] --> Proc
    SIVM[SystemInfoViewModel] --> Auth
    SIVM --> Sys
    CDVM[CrashDataViewModel] --> Auth
    CDVM --> Sys
    PerfVM[PerformanceViewModel] --> Auth
    PerfVM --> Perf
    RVM[RefreshViewModel] --> CAS
    CIWM[CustomInstallViewModel] --> Pkg
    CIWM --> PS
    InVM[InspectorViewModel] --> Auth
    InVM --> XRay
    ShVM[ScreenshotViewModel] --> Sys
    LbVM[LoopbackExemptViewModel] --> Auth
    LbVM --> Sftp
    LbVM --> Pkg
    USBVM[UsbPermissionViewModel]
    SWVM[SetupWizardViewModel] --> Auth
    TkVM[TaskCenterViewModel] --> BgT

    Auth[XboxAuthService]
    Pkg[XboxPackageService]
    Proc[XboxProcessService]
    Net[XboxNetworkService]
    Sys[XboxSystemService]
    Perf[XboxPerformanceService]
    CAS[CatalogApiService]
    CSvc[CacheService]
    PS[PackageInstallService]
    Sftp[SftpService]
    SftpT[SftpTransferService]
    Portal[PortalAppFilesService]
    XRay[XrayAgentService]
    PO[PackageOverrideService]
    BgT[BackgroundTaskService]
ViewModel Window/View Key services
BrowseViewModel BrowseView CatalogApiService, CacheService, XboxAuthService, XboxPackageService, PackageInstallService, PackageOverrideService
InstalledViewModel InstalledView XboxAuthService, XboxPackageService
FileExplorerViewModel FileExplorerView XboxAuthService, SftpService, SftpTransferService, PortalAppFilesService
ToolsViewModel ToolsView XboxAuthService, XboxSystemService
InspectorViewModel InspectorView XboxAuthService, XrayAgentService
PerformanceViewModel PerformanceWindow XboxAuthService, XboxPerformanceService
ScreenshotViewModel ScreenshotWindow XboxSystemService
SettingsViewModel SettingsView XboxAuthService, CacheService
UsbPermissionViewModel UsbPermissionWindow none (WMI directly)
SetupWizardViewModel SetupWizardWindow XboxAuthService
TaskCenterViewModel TasksPanel BackgroundTaskService
ConnectionViewModel ConnectionWindow XboxAuthService, XboxNetworkService
NetworkInfoViewModel NetworkInfoWindow XboxNetworkService
ProcessesViewModel ProcessesWindow XboxProcessService
SystemInfoViewModel SystemInfoWindow XboxAuthService, XboxSystemService
CrashDataViewModel CrashDataWindow XboxAuthService, XboxSystemService

DI pattern: manual composition in App.axaml.cs (no DI container). Services constructed once, shared across VMs; dialog VMs constructed per-open with the services they need.

MVVM Patterns & Conventions

The app uses CommunityToolkit.Mvvm source generators throughout.

Observable properties & commands:

[ObservableProperty]
private string? selectedItem;            // generates SelectedItem + change notification

[RelayCommand]
private async Task BrowseItemAsync() { } // generates BrowseItemCommand (IAsyncRelayCommand)

ViewModel lifecycle: constructor injection of services → synchronous setup → async initialization fired from the View (e.g. Loaded) via a [RelayCommand].

public BrowseViewModel(PackageInstallService install, IXboxAuthService auth,
    IXboxPackageService packages, CatalogApiService catalog, PackageOverrideService overrides)
{
    _install = install;
    _auth = auth;
    _packages = packages;
    _catalog = catalog;
    _overrides = overrides;
}

[RelayCommand]
private async Task LoadCatalogAsync()
{
    var items = await _catalog.FetchCatalogAsync();
    Items.Clear();
    Items.AddRange(items);               // observable update — must run on UI thread
}

Async threading convention:

  • Service layer should use .ConfigureAwait(false) (no UI affinity required).
  • ViewModel layer intentionally omits ConfigureAwait — observable updates must stay on the UI thread.

The codebase does not yet apply ConfigureAwait(false) in services — tracked in Tech Debt.

flowchart TD
    MW[MainWindow] --> SB[Sidebar ListBox]
    SB -->|SelectedTab=0| BV[BrowseView]
    SB -->|SelectedTab=1| IV[InstalledView]
    SB -->|SelectedTab=2| FV[FileExplorerView]
    SB -->|SelectedTab=3| TV[ToolsView]
    SB -->|SelectedTab=4| InV[InspectorView]
    SB -->|SelectedTab=5| SV[SettingsView]
    SB -->|SelectedTab=6| LV[LogsView]
    MW -->|Dialogs| Dialogs
    MW -->|Panels| Panels
    subgraph Dialogs["Dialog Windows"]
        SetupW[SetupWizardWindow]
        CW[ConnectionWindow]
        NIW[NetworkInfoWindow]
        PW[ProcessesWindow]
        SIW[SystemInfoWindow]
        CDW[CrashDataWindow]
        PerfW[PerformanceWindow]
        CustW[CustomInstallWindow]
        ConfW[ConfirmWindow]
        RD[RefreshWindow]
        ED[ErrorDialog]
        AW[AboutWindow]
        SS[ScreenshotWindow]
        ItemW[ItemDetailWindow]
        UsbW[UsbPermissionWindow]
        SftpW[SftpInfoWindow]
        InD[InputDialog]
        DiscD[DiscordPopup]
        LbW[LoopbackExemptWindow]
        DelW[DeleteConfirmWindow]
    end
    subgraph Panels["In-Window Panels"]
        NotifP[NotificationsPanel]
        TasksP[TasksPanel]
    end

Dialogs are opened via delegate actions wired in App.axaml.cs (e.g. ShowConnectAction, ShowConfirmAsync, ShowDetailAction).

Note: FileExplorerView (tab 2) is a functional SSH/SFTP file explorer, powered by SftpService, SftpTransferService, and PortalAppFilesService. See SSH/SFTP & Path Handling.

Xbox WDP API Integration

The Xbox services communicate with the Xbox Developer Mode Device Portal:

Base URL: https://{xbox-ip}:11443 · Auth: HTTP Basic

Endpoint Method Purpose Service
/api/os/info GET Device info, connection test XboxAuthService
/api/app/packagemanager/packages GET List installed packages XboxPackageService
/api/app/packagemanager/package POST Install package XboxPackageService
/api/app/packagemanager/package DELETE Uninstall package XboxPackageService
/api/taskmanager/app POST Launch app by PackageRelativeId XboxPackageService
/api/taskmanager/app/state POST Suspend/resume/terminate package XboxPackageService
/api/resourcemanager/processes GET List running processes XboxProcessService
/api/taskmanager/process DELETE Kill process by PID XboxProcessService
/ext/app/runningtitle GET Get currently running title XboxProcessService
/api/app/debug/crashdump GET List crash dumps XboxSystemService
/api/app/debug/crashdump/{filename} DELETE Delete crash dump XboxSystemService
/api/app/debug/crashcontrol GET Get crash dump settings XboxSystemService
/api/app/debug/crashcontrol POST Enable/disable crash dumps XboxSystemService
/api/networking/networkconfig GET Get network configuration XboxNetworkService
/api/wifi/interfaces GET List WiFi interfaces XboxNetworkService
/api/wifi/networks?interface={guid} GET List WiFi networks XboxNetworkService
/api/systeminfo GET Get system information XboxSystemService
/ext/screenshot?download=true&hdr=false GET Capture screenshot XboxSystemService
/api/control/restart POST Restart Xbox XboxSystemService
/api/control/shutdown POST Shutdown Xbox XboxSystemService

Catalog API

CatalogApiService fetches the Emulation Revival catalog from a single JSON endpoint:

https://emulationrevival.github.io/catalog.json

The JSON is parsed into CatalogItem models covering categories: Emulator, Frontend, GamePort, App, Experimental, Media, Utility. Results are cached by CacheService (6h TTL) with a persistent disk cache and stale-fallback on API failure.

Previously: the catalog was scraped from 7 individual HTML pages using HtmlAgilityPack. That approach was replaced when Emulation Revival published the catalog.json API.

Performance WebSocket

XboxPerformanceService connects to a WebSocket endpoint for real-time performance:

wss://{xbox-ip}:11443/api/resourcemanager/processes

Receives JSON frames with PerformanceSnapshot data (CPU, memory, GPU clock, temperature per core). Rendered by PerformanceViewModel.

Settings Persistence

SettingsService reads/writes %APPDATA%/XBVault/settings.json. Passwords obfuscated by CryptoService (salt + XOR + Base64) — not encryption, just obfuscation to avoid plaintext in JSON.

USB Permission Wizard

UsbPermissionViewModel + UsbDriveDetector implement a Windows-only wizard that:

  1. Lists USB drives via WMI (System.Management)
  2. Grants ALL APPLICATION PACKAGES NTFS permissions via icacls
  3. Includes a spinner, 1-second minimum delay, and skips protected system directories

This allows Xbox Dev Mode to read ROM/media files from USB drives.

Loopback Exempt Wizard

LoopbackExemptViewModel + LoopbackExemptWindow (opened from Tools, in both full and quick mode) automate the X-Files package loopback-exempt workflow over SFTP/package services.

Window Pattern

All dialog windows share a common template:

  • WindowDecorations="None" — no OS chrome
  • Background="{StaticResource SurfaceBrush}" — dark gray #1A1D23
  • Root <Border> with BorderBrush="#447F3E" BorderThickness="2" Margin="1" — green border + 1px gap
  • Title bar: LinearGradientBrush from #447F3E#9ACA3C
  • Close button: transparent default, #CC3333 on hover
  • Content area: 20px padding
  • Drag via PointerPressed="OnTitleBarPointerPressed" + BeginMoveDrag()

See Window Template for the full AXAML template.

Design Decisions & Rationale

Key architectural decisions and the reasoning behind them:

# Decision Why
1 Multi-phase package install The Xbox package manager blocks while processing and requires all files present before the install request; pre-analysis avoids redundant uploads and enables progress reporting.
2 Case-insensitive dependency folders Creators use Dependencies/, deps/, or dep/ — detected via an OrdinalIgnoreCase set.
3 Task.Run wrapper for SFTP SSH.NET is synchronous; wrapping in Task.Run keeps the UI thread responsive during connect/transfer.
4 WebSocket for performance metrics Real-time samples (10+/sec) — server push is more efficient than HTTP polling and matches what WDP exposes.
5 6-hour catalog TTL + stale fallback The catalog changes infrequently; stale data beats no data during brief Emulation Revival downtime and enables offline browsing.
6 Obfuscation, not encryption, for settings Any key would be hard-coded in the assembly; XOR+Base64 only prevents casual plaintext inspection — acceptable for a dev tool.
7 Manual service composition (no DI container) Transparent and easy to follow at this size; would adopt Microsoft.Extensions.DependencyInjection if the service count grows substantially.
8 Shared window template WindowDecorations="None" + green border + gradient title bar + BeginMoveDrag() for consistent Blades styling. See Window Template.
9 Single credential reuse The same Xbox credentials drive HTTP Basic (WDP), SFTP (SSH.NET), and SMB (USB folders) — one credential simplifies the UX.
10 Split XboxDeviceService into focused services The 1,433-line god class mixed 8 unrelated domains; per-domain services + interfaces make each testable in isolation and let VMs depend only on what they use.

CI / Build

CI runs on every push and PR via GitHub Actions:

Job Runs on Steps
build Windows + Ubuntu (matrix) restore → build Release → test
release Windows + Ubuntu + macOS (tag push only) publish win-x64, win-arm64, linux-x64, linux-arm64, osx-x64, osx-arm64 → ZIP → GitHub Release

Release artifacts: XBVault-{version}-win-x64.zip, XBVault-{version}-win-arm64.zip, XBVault-{version}-linux-x64.zip, XBVault-{version}-linux-arm64.zip, XBVault-{version}-osx-x64.zip, XBVault-{version}-osx-arm64.zip (all self-contained, no client runtime required).


← Home · API Docs →