Developer Architecture Guide
This guide documents how the application is structured for contributors working on desktop, Android, tests, or future frontends. It complements the user-facing docs and the Android planning documents.
Goals
- Keep Xbox communication and business rules reusable across desktop and Android.
- Keep Avalonia Views thin and platform-adaptable.
- Keep ViewModels free of platform UI APIs except data-binding concepts such as commands, observable state, and callback delegates.
- Keep services testable by depending on interfaces where practical.
- Keep UI-thread mutations centralized through
XBVault.Helpers.UIHelpersand service override points used by tests.
Layer Map
flowchart TD
Views[Views / AXAML]
ViewModels[ViewModels]
Services[Services]
Models[Models]
Platform[Platform Adapters]
External[Xbox Dev Portal / SSH / GitHub / File System]
Views -->|Bindings, commands, callbacks| ViewModels
ViewModels -->|Orchestration| Services
Services -->|DTOs and domain state| Models
Services -->|HTTP, SSH, disk, OS APIs| External
Services -->|guarded calls| Platform
Platform --> External
classDef ui fill:#2A2D33,stroke:#447F3E,color:#9ACA3C;
classDef core fill:#447F3E,stroke:#9ACA3C,color:#fff;
classDef data fill:#1A1D23,stroke:#447F3E,color:#9ACA3C;
class Views,ViewModels ui;
class Services,Platform core;
class Models,External data;
Layer Responsibilities
| Layer | Owns | Must Avoid |
|---|---|---|
| Views | AXAML layout, event wiring, drag/drop, dialogs, visual-only behavior | Xbox HTTP calls, package rules, persistent settings logic |
| ViewModels | Observable state, commands, workflow orchestration, user-facing status text | Direct file picker implementation, direct window ownership, platform-specific APIs without callbacks |
| Services | HTTP, WebSocket, SSH/SFTP, filesystem, cache, crypto, install flow, update checks | Avalonia controls, direct UI mutations, view navigation |
| Models | Plain serializable data and derived display properties | Network calls, file I/O, service dependencies |
| Platform Adapters | OS-specific operations such as dialogs, USB/WMI, window persistence | Business rules that should be shared with Android |
Service Contracts
Service interfaces under XBVault/Services are the boundary most useful for Android and tests.
| Contract | Purpose | Android Status |
|---|---|---|
IXboxAuthService |
Configure Xbox base URL, manage connection state, expose SSH credentials, fetch SMB password | Reusable; certificate bypass must remain scoped to Xbox hosts |
IXboxPackageService |
List, install, uninstall, launch, suspend, terminate packages | Reusable; multipart upload must be tested on device |
IXboxSystemService |
Screenshots, system info, crash dumps, power actions | Reusable; screenshots need mobile memory testing |
IXboxProcessService |
Running title, process list, kill process | Reusable |
IXboxNetworkService |
Network configuration and Wi-Fi scans | Reusable |
IXboxPerformanceService |
WebSocket metrics stream | Reusable; Android background lifecycle needs explicit disconnect |
ISftpService |
SSH/SFTP primitive operations | Reusable if SSH.NET works on target runtime |
IAppLogger |
Logging abstraction for services that need testable logs | Reusable; Android log sink can adapt later |
Service implementations should log enough context for failures but return structured values where callers need UI decisions. Prefer Result models or tuples for expected operational failures and exceptions for unexpected faults.
ViewModel Contract Pattern
ViewModels are shared frontend logic. They should expose:
- Observable state through
[ObservableProperty]and derived read-only properties. - Commands through
[RelayCommand]. - Cross-view actions through delegate properties such as
ShowConnectAction,ShowConfirmAsync, orOpenCustomInstallWithFileAction. - No direct dependency on
Window,StorageProvider, or platform pickers unless isolated behind callbacks.
Example flow:
sequenceDiagram
participant View
participant VM as ViewModel
participant Service
participant Xbox
View->>VM: Command executes
VM->>Service: Call async service method
Service->>Xbox: HTTP / SSH / WebSocket
Xbox-->>Service: Raw response
Service-->>VM: Model / result / error state
VM-->>View: Observable properties update
View Contract Pattern
Desktop Views currently provide platform UI services that Android may replace:
- File picker calls.
- Window/dialog creation.
- Drag/drop handlers.
- Popup/flyout animation.
- Clipboard access.
- Layout decisions tied to desktop dimensions.
When adding new behavior, prefer this shape:
- View wires UI event or platform-specific capability.
- View calls ViewModel command or callback.
- ViewModel delegates business rules to service.
- Service returns model/result.
Do not move Xbox API calls into Views. If Android needs different UI, it should reuse the same ViewModel and service path.
Threading Rules
Avalonia collections and UI-bound state must be mutated from the UI thread. Use UIHelpers.RunOnUI or UIHelpers.RunOnUIAsync instead of direct Dispatcher.UIThread calls.
Service-specific testability rule:
BackgroundTaskServiceusesPostToUiandMarshalso tests can override UI dispatch inline.- New services with UI-bound collections should follow the same pattern: expose a protected dispatch method when tests need deterministic execution.
Android Port Guidance
The Android frontend should reuse these layers as-is wherever possible:
| Reuse Directly | Adapt |
|---|---|
| Models | Mobile-specific view composition |
| Xbox HTTP services | Dialog and picker presentation |
| Catalog/cache/install services | File path UX and storage permission flows |
| ViewModels with callbacks | Main navigation shell |
| SFTP transfer orchestration | Clipboard/share intents |
Android-specific work should be placed behind small adapters rather than forks of core services. If a service needs platform behavior, prefer introducing an interface such as IFilePicker, IClipboardService, or IPlatformDialogService and provide desktop/Android implementations.
Error Handling Rules
- Expected Xbox failures should become user-facing status messages and logs.
- Unexpected failures should be logged with exception details and surfaced as concise UI messages.
- Cancellation should be represented distinctly from failure.
- Avoid throwing
Exception; use specific exception types or result objects. - Preserve response-body snippets for HTTP failures, but truncate long bodies before logging.
Documentation Rules
- Public service interfaces should have XML comments because they are cross-frontend contracts.
- ViewModels should have class-level comments when their workflow is not obvious.
- Do not add XML comments to every generated property or trivial UI wrapper.
- Markdown docs should explain responsibilities, data flow, platform assumptions, and risks.
- Diagrams must use Mermaid.
Porting Checklist For New Features
- Is business logic in a service or ViewModel, not the View?
- Does the ViewModel expose callbacks instead of constructing desktop windows directly?
- Are UI-bound updates dispatched through
UIHelpersor an overridable dispatch method? - Does the service have an interface if tests or Android need alternate implementations?
- Are file paths based on
SpecialFolder,Path.GetTempPath, or injected platform services? - Are Windows-only APIs guarded with
OperatingSystem.IsWindows()? - Does the feature have a doc note in
docs/androidif Android behavior differs?