feat: install and launch Minecraft with NeoForge and Microsoft login

Wires up the actual game pipeline behind the existing ShaCraft manifest
sync: Mojang version resolution, Java 21 auto-provisioning via Adoptium,
headless NeoForge installation, real Microsoft/Xbox/Minecraft Services
login, and an offline account mode, then builds and spawns the java
process itself.

- mojang.rs: vanilla trust boundary, inheritsFrom version-JSON merge,
  asset/library downloading with a worker pool and per-file retries
- neoforge.rs: runs NeoForge's own installer headlessly, with live
  progress parsed from its output against its own install_profile.json
- runtime.rs / java.rs: detects a usable local Java or provisions one
  from Eclipse Temurin, with real download progress
- msa.rs: device-code OAuth -> Xbox Live -> XSTS -> Minecraft Services,
  gated on ShaCraft registering its own Azure AD app (see MSA_CLIENT_ID)
- session.rs / launch.rs: offline deterministic UUIDs and the merged
  java invocation itself
- download.rs: shared verified-download helper (temp file, hash,
  atomic rename, retries, progress) used across all of the above and
  refactored into profile.rs
- UI: account mode toggle (Microsoft/offline), login modal, and real
  per-stage install progress instead of start/done placeholders
This commit is contained in:
emil28092005
2026-09-06 05:09:50 +03:00
parent c37d38522e
commit cc19a24e45
19 changed files with 3270 additions and 180 deletions
+84
View File
@@ -0,0 +1,84 @@
# Game trust boundary (Mojang / NeoForge / Microsoft / Adoptium)
`docs/manifest-v1.md` and `AGENTS.md` cover the ShaCraft-signed manifest,
which governs **only** mods, configs, and which Minecraft/NeoForge/Java
version a profile needs. This document covers the four separate,
independently-hardcoded trust domains that install and run the game itself.
None of their hosts or URLs are ever taken from the ShaCraft manifest, and
the manifest can never point the launcher at a different host for any of
them — that boundary is load-bearing, not incidental.
## 1. Mojang (`mojang.rs`)
Hosts: `piston-meta.mojang.com`, `piston-data.mojang.com`,
`libraries.minecraft.net`, `resources.download.minecraft.net`.
Every artifact's SHA-1 comes from a parent document that was itself SHA-1
verified, back to `version_manifest_v2.json`: manifest -> version JSON ->
client jar / each library / asset index -> each asset object. `mojang.rs`
also owns the generic `inheritsFrom` version-JSON merge — the same
loader-agnostic algorithm any vanilla-compatible launcher uses to run a
Forge/NeoForge/Fabric profile, because that format is specifically designed
so third-party launchers don't need per-loader special-casing.
## 2. NeoForge (`neoforge.rs`)
Host: `maven.neoforged.net` only.
Downloads the official installer jar for `manifest.minecraft.loader.version`
and verifies it against the `.sha256` sidecar Maven publishes next to every
artifact (confirmed live, byte-for-byte). Runs it headlessly:
`java -jar neoforge-<ver>-installer.jar --installClient <game_dir>` — its
real main class is `net.minecraftforge.installer.SimpleInstaller`, which
supports this flag. **Empirically verified (2026-09-06)**: it refuses to
target a directory unless a `launcher_profiles.json` stub already exists
there ("you need to run the launcher first!") — `ensure_launcher_profiles_stub`
writes a minimal one. It then fetches and patches vanilla itself; no
pre-seeding needed. Its own downloads go straight to `maven.neoforged.net`/
Mojang, outside our control — an accepted trust delegation to NeoForge's
official tooling once the installer binary itself is verified.
Also verified: the resulting
`libraries/net/neoforged/neoforge/<ver>/neoforge-<ver>-client.jar` (the
patched, deobfuscated client) is **not** part of the generic classpath and
must not be added to it — FancyModLoader locates and loads it itself at
runtime via the `--fml.*` game arguments already present in the merged
profile. The classpath is just the ordinary union of rule-allowed vanilla +
NeoForge libraries plus the *vanilla* client jar (`client_jar_version_id` on
`MergedVersion`, not the NeoForge profile's own id — it has no jar of its
own on disk, confirmed).
## 3. Microsoft / Xbox Live / Minecraft Services (`msa.rs`)
Hosts: `login.microsoftonline.com`, `user.auth.xboxlive.com`,
`xsts.auth.xboxlive.com`, `api.minecraftservices.com`.
Real device-code OAuth login -> Xbox Live user token -> XSTS token ->
Minecraft Services login -> `GET /minecraft/profile` ownership check (404 =
doesn't own the game = nothing installs or launches). This is the actual
ownership gate; it is not optional and there is no fallback identity. See
`MSA_CLIENT_ID`'s doc comment in `msa.rs`: unlike the other three domains,
this one needs a deployment-specific value — ShaCraft's own Azure AD app
registration, approved for Minecraft API access via
`https://aka.ms/mce-reviewappid`. `start_device_code`/`refresh_microsoft_tokens`
refuse to run while it's still the placeholder.
## 4. Eclipse Adoptium (`runtime.rs`)
Host: `api.adoptium.net` (redirects to `github.com`/
`objects.githubusercontent.com` for the actual download — expected, still
verified).
Java 21 JRE, GPLv2+CE. The API returns the release's SHA-256 inline, verified
before extraction. Never touches a Java installation the user already has —
`java::ensure_java` only provisions here when `java::detect()` finds nothing
with at least the manifest's `javaMajor`.
## Why this separation matters
Each domain is hardcoded and verified independently so that a compromised or
malicious ShaCraft manifest — or a bug that lets manifest data flow into a
URL — cannot redirect a download to an attacker-controlled host in any of
these domains. When adding a new game-related download, verify its host is
one of the ones above (or add a new hardcoded constant following the same
pattern) rather than accepting a URL from anywhere else.
+43 -16
View File
@@ -2,22 +2,43 @@
## Current capability
The launcher can persist local settings, discover an installed Java runtime,
inspect a profile and synchronise Aeronautics files from the signed ShaCraft
v2 manifest. It does **not** launch Minecraft yet.
The launcher persists local settings, synchronises Aeronautics mod/config
files from the signed ShaCraft v2 manifest, installs the exact Minecraft +
NeoForge version the manifest specifies, and launches the game. Players can
launch either with a real Microsoft account or with a local offline profile
(nickname + deterministic offline UUID) — see `docs/game-trust-boundary.md`
and `AGENTS.md`'s trust model section.
Not yet implemented: a user-selectable profile directory, a "reset managed
files only" recovery action, and signed cross-platform release builds of the
launcher itself. Do not represent these as completed in UI or release notes.
## Data flow
Two independent pipelines feed one launch:
```text
signed-manifest endpoint
-> Ed25519 verification in remote.rs
-> manifest schema + URL/path validation
-> local profile inspection
-> temporary download, SHA-256 verification, atomic replacement
ShaCraft manifest (mods/config + which MC/loader/Java version to use)
signed-manifest endpoint -> Ed25519 verification (remote.rs)
-> manifest schema + URL/path validation (manifest.rs)
-> temporary download, SHA-256 verification, atomic replacement (profile.rs)
Game itself (never controlled by the manifest above)
Mojang version manifest -> SHA-1-verified version JSON (mojang.rs)
-> Java 21 via Adoptium if none installed (runtime.rs)
-> NeoForge's own installer, run headlessly (neoforge.rs)
-> generic inheritsFrom merge of the two version JSONs (mojang.rs)
-> real Microsoft/Xbox/Minecraft Services login (msa.rs)
-> java process spawned with the merged classpath/args (launch.rs)
```
Profiles live below Tauri's `app_data_dir()/profiles/<profile-id>`. Settings
live at `app_data_dir()/settings.json`. Neither location should be assumed to
Profiles (ShaCraft-managed mods/config, and the player's own worlds/
screenshots/resourcepacks) live below Tauri's `app_data_dir()/profiles/
<profile-id>` — this becomes `--gameDir`. The shared vanilla+NeoForge
install (versions/libraries/assets/runtime, reused across profiles that
target the same Minecraft version) lives at `app_data_dir()/game`. Settings
live at `app_data_dir()/settings.json`, the Microsoft refresh token at
`app_data_dir()/account.json` (mode 600). None of these should be assumed to
be the system `.minecraft` directory.
## Aeronautics contract
@@ -25,15 +46,21 @@ be the system `.minecraft` directory.
- Profile ID: `aeronautics`
- Manifest endpoint:
`https://shacraft.ru/api/launcher/v2/profiles/aeronautics/signed-manifest`
- Payload: manifest schema v1, 251 managed files at the time of writing.
- Download files: HTTPS only, exact hosts `shacraft.ru` and
- Payload: manifest schema v1; also carries `minecraft.{version, loader,
javaMajor}` (currently 1.21.1, NeoForge 21.1.248, Java 21) — the launcher
reads this rather than hardcoding it, so a server-side version bump needs
no launcher release.
- ShaCraft download files: HTTPS only, exact hosts `shacraft.ru` and
`cdn.shacraft.ru`.
## Planned but not implemented
1. Signed, cross-platform Java 21 runtime installation.
2. User-selectable profile directory and structured launcher logs.
3. Official Microsoft authentication and a compliant Minecraft/NeoForge launch
flow.
1. User-selectable profile directory and structured launcher logs.
2. "Reset managed files only" recovery action that doesn't touch player
worlds/screenshots/resourcepacks.
3. Signed, cross-platform release builds of the launcher itself.
4. Real per-stage byte progress for the Java/NeoForge install steps
(currently start/done only — the dominant, user-visible wait, asset
downloading, already reports real bytes).
Do not represent these as completed features in UI or release notes.