- Multi-arch (amd64/arm64) panel image: static musl binary on scratch, cross-compiled with cargo-zigbuild (no QEMU), non-root, healthcheck - docker-compose.yml + .env.example for one-command deployment - CI: fmt, clippy, tests, web type-checks, Windows launcher build, real-network installs of vanilla/Fabric/Quilt/Forge/NeoForge, Docker build - Release: Windows NSIS installer with baked-in panel URL, GHCR image push and GitHub release (tag push or manual dispatch) - README, admin guide, Microsoft auth setup, architecture, development - rustfmt config and formatting pass Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011ARcGWxLx21FwXJ3yfGriS
61 lines
3.7 KiB
Markdown
61 lines
3.7 KiB
Markdown
# Architecture
|
|
|
|
```
|
|
┌──────────────────────────┐ HTTPS (JSON) ┌──────────────────────────┐
|
|
│ Launcher (Tauri) │ ─────────────────────────▶ │ Panel (Axum + SQLite) │
|
|
│ Svelte UI ⇄ Rust shell │ manifest, instances, │ Svelte admin UI │
|
|
│ │ │ auth, stats │ /files, /uploads │
|
|
│ scopenet-core engine │ └──────────────────────────┘
|
|
│ ├─ Mojang / Java │ ──▶ piston-meta, libraries.minecraft.net, resources
|
|
│ ├─ Fabric/Quilt/Forge │ ──▶ meta.fabricmc.net, maven.minecraftforge.net, …
|
|
│ └─ modpack files │ ──▶ Modrinth/CurseForge CDNs, panel /files
|
|
└──────────────────────────┘
|
|
```
|
|
|
|
- **`crates/shared`** defines every JSON type exchanged, so the panel and launcher can't drift apart.
|
|
- **`crates/core`** has no UI dependencies. It's unit-tested, and CI runs real installs of vanilla, legacy, Fabric, Quilt, Forge and NeoForge against the live servers.
|
|
- The **panel** also uses `core` for version and loader lookups.
|
|
|
|
## Launch pipeline
|
|
|
|
1. Resolve the account (refreshing Microsoft tokens if needed).
|
|
2. Fetch the instance from the panel (cached for offline play).
|
|
3. `install`: vanilla version JSON → Java runtime (Mojang's own builds) → client jar, libraries, assets → loader profile (Fabric/Quilt), or replay the Forge/NeoForge installer's processors → merge → natives.
|
|
4. `sync`: download the admin's files; remove files the admin removed; never touch the player's own files. With an unchanged revision, only existence is checked.
|
|
5. Write `servers.dat` and keybinds, build the Java command (quick play / `--server`, memory, GC presets, `@argfile` for long classpaths), and start the game.
|
|
6. Stream logs to the console; on a crash, show the tail of the log with hints.
|
|
|
|
## Disk layout (launcher)
|
|
|
|
```
|
|
%APPDATA%\net.scopenet.launcher\
|
|
settings.json, accounts.json, secrets.bin (encrypted), manifest.json (cache)
|
|
minecraft\
|
|
versions\ libraries\ assets\ runtimes\ natives\ cache\
|
|
instances\<id>\ ← game directory (saves, mods, options.txt, …)
|
|
```
|
|
|
|
## HTTP API
|
|
|
|
Public (used by launchers). Send `Authorization: Bearer <token>` to see restricted instances:
|
|
|
|
| Method | Path | |
|
|
|---|---|---|
|
|
| GET | `/api/v1/launcher/manifest` | Branding, auth options, visible instances |
|
|
| GET | `/api/v1/launcher/instances/{id}` | Instance + file list |
|
|
| POST | `/api/v1/launcher/events` | Launch stats |
|
|
| POST | `/api/v1/auth/login` · `/register` | Panel accounts |
|
|
| GET | `/api/v1/auth/me` | Current user |
|
|
| GET | `/files/{instance}/{path}` | Hosted instance files |
|
|
| GET | `/healthz` | Health check |
|
|
|
|
Admin (`role = admin`): `/api/admin/{stats,users,groups,branding,settings,instances,uploads}` plus `instances/{id}/{import/modrinth,import/curseforge,import/upload,files,reset}` and meta/search proxies under `/api/admin/{meta,modrinth,curseforge}`.
|
|
|
|
## Security notes
|
|
|
|
- Passwords are hashed with Argon2id; tokens are HS256 JWTs (30 days); disabled accounts are rejected on every request.
|
|
- Server-provided paths are sanitised (`safe_join`) on both sides — no `..` or absolute paths.
|
|
- The panel never returns the CurseForge key; SVG uploads are refused (script risk).
|
|
- The launcher's CSP only allows scripts from the app itself; media may load from any HTTPS host (admin-chosen images).
|
|
- Hosted `/files` are public URLs. Don't put secrets in instance files.
|