Files
SCOPENET-MC/docs/architecture.md
T
Claude 5dc8a4f2f1 Add Docker image, Compose, CI/CD workflows and docs
- 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
2026-09-28 05:19:36 +00:00

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.