5.6 KiB
Moonwell Launcher Web API Spec
Scope
This document specifies the current launcher behavior for:
- authentication against the Moonwell Web API
- installation directory selection
- local file scan and hash calculation
- manifest-based synchronization
- client launch from
Wow.exe
The launcher no longer uses S3/MinIO directly. All server interaction goes through the Web API.
Configuration
The launcher API base URL is provided via:
MOONWELL_API_BASE_URL
Current integration mode is compile-time:
flutter run -d windows --dart-define=MOONWELL_API_BASE_URL=https://hostflutter build windows --dart-define=MOONWELL_API_BASE_URL=https://host
API Flow
The launcher uses these endpoints from openapi.json:
POST /api/launcher/loginGET /api/launcher/manifestGET /api/launcher/download/{path}
Authentication sequence:
- User enters launcher credentials.
- Launcher requests a bearer token from
POST /api/launcher/login. - Launcher requests the manifest from
GET /api/launcher/manifest. LauncherSessionandClientManifestare passed into the home screen.
File download sequence:
- Launcher resolves files that are missing, stale, or changed.
- For each required file, launcher calls
GET /api/launcher/download/{path}with bearer auth. - API returns JSON with a temporary presigned
urlandexpires_in. - Launcher downloads the file directly from storage using the presigned URL.
- Download is written into
*.moonwell.part. - Downloaded file is verified against manifest
sha256. - Temporary file replaces the destination file only after successful verify.
Installation Directory Rules
The user selects a single installation root directory.
All paths in the manifest are treated as relative to that root.
Path safety rules:
- backslashes are normalized to
/ - leading
./is removed - absolute paths are rejected
- path traversal via
..is rejected
Ignored Directories
The launcher excludes these top-level directories from verification:
CacheErrorsLogsScreenshotsWTF
Files under these directories:
- are not included in local scan
- do not participate in local
buildHash - are not compared against server manifest
Local Scan
For every non-ignored file in the installation directory, the launcher computes:
- normalized relative path
- file size in bytes
- file
sha256
The result is stored as a ClientInstallationSnapshot.
Hash Cache
To accelerate repeated scans, the launcher stores a local hash cache in:
<install-root>/.moonwell_launcher/hash_cache.json
This metadata directory is excluded from verification.
Each cache entry is keyed by normalized relative path and stores:
sizemodifiedMssha256
Cache reuse rule:
- if
path,size, andmodifiedMsstill match, the cachedsha256is reused - otherwise
sha256is recomputed and the cache entry is replaced
The cache is an optimization only. The server remains the source of truth via the manifest comparison.
Diagnostics
During sync, the launcher writes a log file to:
<install-root>/.moonwell_launcher/launcher.log
If an installation directory is not available yet, the launcher falls back to a temporary system log directory.
For failed downloads:
- HTTP and storage download failures are logged with file path and status code
- checksum mismatches log expected and actual
sizeandsha256 - invalid payloads are preserved as
*.moonwell.part.failedfor inspection
buildHash Algorithm
buildHash is deterministic and calculated identically for local snapshot and
remote manifest.
For each file entry, the launcher builds a canonical string:
<normalized-path>:<size>:<sha256-lowercase>
Then:
- sort all canonical strings lexicographically
- join them with
\n - compute
sha256of the resulting UTF-8 payload
This means file ordering in the manifest does not affect buildHash.
Sync Algorithm
The current sync flow is:
- Load manifest.
- Scan local installation.
- Compute local
buildHash. - Compare local files to manifest files by
path,size, andsha256. - Identify stale local files that are not present in the manifest.
- If local
buildHashmatches serverbuildHashand there are no stale files and no mismatches, finish successfully. - Delete stale local files outside ignored directories.
- Download changed and missing files.
- Verify every downloaded file by
sha256. - Re-scan the installation.
- Recompute local
buildHash. - Fail if final snapshot still differs from manifest.
Pause and Resume Semantics
Pause is implemented as cooperative cancellation:
- the current sync stream is cancelled
- the next sync starts a fresh comparison from current disk state
- already replaced files remain valid
- partial
*.moonwell.partfiles are removed before the next download attempt
Launch Behavior
When the user presses Play:
- launcher resolves
<install-root>/Wow.exe - launcher clears
<install-root>/Cache - launcher starts
Wow.exewith working directory set to installation root
If Wow.exe is missing, launch fails with an error.
Error Behavior
The launcher surfaces errors for:
- invalid API configuration
- authentication failure
- manifest load failure
- path traversal attempts
- checksum mismatch after download
- missing downloaded temp files before verification
- final verification mismatch after update
- missing
Wow.exe
Tested Invariants
The automated tests cover:
- deterministic
buildHash - path normalization used by
buildHash - exclusion of ignored directories during local scan
- cache cleanup behavior
- safe path resolution
- sync flow with fully up-to-date client
- sync flow with stale files and changed files