2 Commits
16 changed files with 215 additions and 14 deletions
+1 -1
View File
@@ -3,7 +3,7 @@ name: Cross-platform build
on:
workflow_dispatch:
push:
branches: [main]
branches: [main, codex/server-migration-20260917]
permissions:
contents: read
+19
View File
@@ -255,3 +255,22 @@ feed were signed with the existing local updater key and verified through
public HTTPS downloads. See `docs/release-0.1.6.md` and its committed receipt.
This records successful release/admission verification, not a Windows/macOS
cold install or OS signing/notarization certification.
## Server migration — launcher 0.1.7 (2026-09-17)
Minigames Quick Play now uses the fixed native endpoint `shacraft.ru:25568`.
It no longer pins the retired server IP in the application binary. The Fabric
admission client accepts the new actual socket IP `135.106.219.182` and retains
`135.106.154.86` for the temporary forwarding path; unrelated hosts and ports
remain rejected. The server published updated signed companion manifests.
The migration's full-platform packages are published from
`codex/server-migration-20260917`. Existing 0.1.6 installers still connect to the
old IP and need that forwarding path until upgraded. Version 0.1.7 uses a newly generated operator-held updater key and the fixed
`https://shacraft.ru/launcher/updates/stable-v2.json` channel. It requires one
manual installation. Preserve `stable.json` at the last old-key release; never
replace it with new-key metadata. Subsequent v2-channel releases use the new
key, kept only at `/home/emil/.local/share/shacraft-updater/production.key`.
All eight public HTTPS downloads, their signatures and the signed v2 feed were
verified after publication. See `docs/release-0.1.7.md` and its publication
receipt for provenance, checks and the limits of platform verification.
+1 -1
View File
@@ -13,7 +13,7 @@ The native launcher supplies `SHACRAFT_ADMISSION_TICKET` and
The client accepts a CONFIGURATION payload on `shacraft_admission:challenge`
with three Minecraft UTF strings: server ID (16), nickname (16), nonce (43).
It verifies server `minigames`, the exact current game nickname and actual
socket `135.106.154.86:25568`, then signs once with the ephemeral Ed25519 key.
socket `135.106.219.182:25568` (the previous IP remains accepted during migration), then signs once with the ephemeral Ed25519 key.
The response on `shacraft_admission:proof` contains ticket (43) and standard
Base64 signature (88). The transcript has no final newline:
@@ -62,6 +62,6 @@ public final class AdmissionProof {
if (allowLoopback && (host.equals("127.0.0.1") || host.equals("::1") || host.equals("[::1]") || host.equals("0:0:0:0:0:0:0:1"))) {
return port > 0 && port <= 65535;
}
return port == 25568 && (host.equalsIgnoreCase("shacraft.ru") || host.equals("135.106.154.86"));
return port == 25568 && (host.equalsIgnoreCase("shacraft.ru") || host.equals("135.106.154.86") || host.equals("135.106.219.182"));
}
}
@@ -23,7 +23,11 @@ class AdmissionProofTest {
assertThrows(IllegalArgumentException.class,()->AdmissionProof.transcript(v[0],v[1],v[2],v[3]));
}
@Test void trustsOnlyMinigamesSocketAndExplicitLocalTests() {
assertTrue(AdmissionProof.allowedTarget("shacraft.ru",25568,false));
assertTrue(AdmissionProof.allowedTarget("135.106.219.182",25568,false));
assertTrue(AdmissionProof.allowedTarget("135.106.154.86",25568,false));
assertFalse(AdmissionProof.allowedTarget("135.106.219.183",25568,false));
assertFalse(AdmissionProof.allowedTarget("135.106.219.182",25567,false));
assertFalse(AdmissionProof.allowedTarget("135.106.154.86",25567,false));
assertFalse(AdmissionProof.allowedTarget("127.0.0.1",25568,false));
assertTrue(AdmissionProof.allowedTarget("127.0.0.1",25570,true));
+17
View File
@@ -359,3 +359,20 @@ The integration is staged until server authentication, signed profile payload,
and a newer signed launcher release are deployed and checked together. The
existing public 0.1.5 binary cannot select the new profile by a website-only
catalog change. Preserve both catalog entries when publishing either profile.
## Server migration — launcher 0.1.7 (2026-09-17)
Minigames Quick Play now uses the fixed native endpoint `shacraft.ru:25568`.
It no longer pins the retired server IP in the application binary. The Fabric
admission client accepts the new actual socket IP `135.106.219.182` and retains
`135.106.154.86` for the temporary forwarding path; unrelated hosts and ports
remain rejected. The server published updated signed companion manifests.
The migration's full-platform packages are prepared on
`codex/server-migration-20260917`. Existing 0.1.6 installers still connect to the
old IP and need that forwarding path until upgraded. Version 0.1.7 uses a newly generated operator-held updater key and the fixed
`https://shacraft.ru/launcher/updates/stable-v2.json` channel. It requires one
manual installation. Preserve `stable.json` at the last old-key release; never
replace it with new-key metadata. Subsequent v2-channel releases use the new
key, kept only at `/home/emil/.local/share/shacraft-updater/production.key`.
Do not claim publication based on CI packages alone.
+5
View File
@@ -1,3 +1,8 @@
> From 0.1.7, new installations trust the new operator key and use
> `https://shacraft.ru/launcher/updates/stable-v2.json`. Migration from 0.1.6
> requires manual installation. Keep the old `stable.json` feed unchanged.
> For future releases use `stable-v2.json` in publication commands below.
# Signed launcher updates
The application updater is separate from the signed Aeronautics modpack
+63
View File
@@ -0,0 +1,63 @@
# Launcher 0.1.7 release — server migration
Published on 2026-09-17. Minigames Quick Play uses `shacraft.ru:25568`;
the Fabric admission companion accepts the new server's actual socket IP
`135.106.219.182`, the domain and the temporary old-IP forwarding path.
The owner approved replacing the unavailable updater signing key and requiring
one manual installation. Users of 0.1.6 and earlier must close Minecraft and
the launcher, then install 0.1.7 from [the download page](https://shacraft.ru/help#launcher).
Their installed game profiles do not need to be reinstalled. The new native
updater endpoint is `https://shacraft.ru/launcher/updates/stable-v2.json`.
The old `stable.json` remains byte-identical at 0.1.6 under its original key.
Never publish new-key signatures to that old channel.
## Provenance and verification
Runtime source: `b674347e867af3edb6f00201bd30f1db7af4d9d2` on
`codex/server-migration-20260917`.
All four jobs succeeded in [build run 35167814993](https://github.com/emil28092005/shacraft-launcher/actions/runs/35167814993).
[Checks run 35167815151](https://github.com/emil28092005/shacraft-launcher/actions/runs/35167815151)
passed native checks, publisher signature tests and the Java 25 Fabric build.
Downloaded artifact ZIP hashes match GitHub's SHA-256 digests and their run
metadata points to the exact runtime commit. Local checks passed 33 UI tests,
87 Rust tests (8 live/desktop tests ignored), TypeScript and Vite.
All eight packages were signed on the operator workstation, checked again on
the new server, and published after the metadata publisher's dry-run. Complete
public HTTPS downloads match the recorded hashes; all eight package signatures
and the v2 feed's metadata signature verify. The public feed bytes exactly match
the locally verified metadata and carry `Cache-Control: no-store`. The website
shows 0.1.7 links and manual installation instructions. See the
[publication receipt](verification/launcher-release-0.1.7.json).
Native executables extracted from Windows NSIS, Linux DEB and both macOS app
archives contain the domain endpoint, v2 channel and expected public key, with
no old IP literal. The CI-built Fabric companion was published at immutable
SHA-256 `6ef059192cef0242839db3d6a234228b771196f23b9b1e307a17a27669632a90`.
Its public profile signature uses the original profile key and verifies;
Java 25 target checks accept only the intended destinations. Minecraft status
queries work through both new and old public IPs (Paper 26.2, protocol 776).
This release verification does not establish a fresh Windows/macOS installation
or an authenticated game session on the migrated host. Authenticode and Apple
notarization remain separate from the updater signature.
## Operator state
The new updater private key is only at
`/home/emil/.local/share/shacraft-updater/production.key` (0600; parent 0700).
Its public companion's SHA-256, after trimming whitespace, is
`5ac34dd380307ab25fcfc1479ee6d653b9b43bce45b5a242950d09c01fe1b2f9`.
Maintain an encrypted owner-controlled backup. No private key was uploaded to
GitHub or the server. Future versions must use this same key and the v2 feed.
Production is `135.106.219.182`. Release evidence is under
`/root/shacraft/.release-staging/launcher-0.1.7`, with the exact runtime source
snapshot at `/root/shacraft-launcher-0.1.7`. The unversioned launcher checkout on
that host is older. The website image is `shacraft/backend:migration-017-20260917`.
The old host `135.106.154.86` only forwards ports 80, 443 and 25568. Keep it
until authoritative DNS and caches have updated **and** users of 0.1.6 have
manually upgraded: those binaries pin the old IP independently of DNS.
Do not restart old application containers or Hermes. Detailed migration and
rollback context is in `/context/migration-20260917.md` on the new host.
@@ -0,0 +1,93 @@
{
"source_sha": "b674347e867af3edb6f00201bd30f1db7af4d9d2",
"version": "0.1.7",
"build_run": 35167814993,
"new_channel": "https://shacraft.ru/launcher/updates/stable-v2.json",
"files": [
{
"name": "ShaCraft.Launcher_0.1.7_aarch64.app.tar.gz",
"bytes": 5877025,
"sha256": "c460fd5c766b1e1f64d55e23952bead6c1e6a1ecd395e8147ce625aeca4049f7"
},
{
"name": "ShaCraft.Launcher_0.1.7_aarch64.dmg",
"bytes": 6420405,
"sha256": "be869b3221363ddb9fcc755bf76a78d3e44264c0bc3a24bcd9d4396ee118a7cb"
},
{
"name": "ShaCraft.Launcher_0.1.7_amd64.AppImage",
"bytes": 83270136,
"sha256": "a2e2337e1b0ee07f062383fa2e3da8e8fc51c62e2ccacda89a45a1ea0d092351"
},
{
"name": "ShaCraft.Launcher_0.1.7_amd64.deb",
"bytes": 5997780,
"sha256": "b6b9913063600659dfd917c7939e3c07675ca81e35c34cf6a90edc61ef30328e"
},
{
"name": "ShaCraft.Launcher_0.1.7_x64-setup.exe",
"bytes": 3792580,
"sha256": "0b1167dae9fce7d85f1ad95b2857cce1df7d17fffcdd6c358901ff998c5ac6b6"
},
{
"name": "ShaCraft.Launcher_0.1.7_x64.dmg",
"bytes": 6591601,
"sha256": "9b6cc5660817f4dd1684282e01daa1639d98e987325ec4924b42b07ae07e44d5"
},
{
"name": "ShaCraft.Launcher_0.1.7_x64_en-US.msi",
"bytes": 5554176,
"sha256": "54d0e8425f0087f13c396efa464da5e8e95203e222353d66c11d68f1076abbb4"
},
{
"name": "ShaCraft.Launcher_0.1.7_x86_64.app.tar.gz",
"bytes": 6032631,
"sha256": "05748cc29462f850a12da3cd84336872af4ee8f5a5de0a3b10d91461c60fbad7"
}
],
"verified_at": "2026-09-17T01:09:31.123799+00:00",
"public_https_packages": [
{
"name": "ShaCraft.Launcher_0.1.7_aarch64.app.tar.gz",
"bytes": 5877025,
"sha256": "c460fd5c766b1e1f64d55e23952bead6c1e6a1ecd395e8147ce625aeca4049f7"
},
{
"name": "ShaCraft.Launcher_0.1.7_aarch64.dmg",
"bytes": 6420405,
"sha256": "be869b3221363ddb9fcc755bf76a78d3e44264c0bc3a24bcd9d4396ee118a7cb"
},
{
"name": "ShaCraft.Launcher_0.1.7_amd64.AppImage",
"bytes": 83270136,
"sha256": "a2e2337e1b0ee07f062383fa2e3da8e8fc51c62e2ccacda89a45a1ea0d092351"
},
{
"name": "ShaCraft.Launcher_0.1.7_amd64.deb",
"bytes": 5997780,
"sha256": "b6b9913063600659dfd917c7939e3c07675ca81e35c34cf6a90edc61ef30328e"
},
{
"name": "ShaCraft.Launcher_0.1.7_x64-setup.exe",
"bytes": 3792580,
"sha256": "0b1167dae9fce7d85f1ad95b2857cce1df7d17fffcdd6c358901ff998c5ac6b6"
},
{
"name": "ShaCraft.Launcher_0.1.7_x64.dmg",
"bytes": 6591601,
"sha256": "9b6cc5660817f4dd1684282e01daa1639d98e987325ec4924b42b07ae07e44d5"
},
{
"name": "ShaCraft.Launcher_0.1.7_x64_en-US.msi",
"bytes": 5554176,
"sha256": "54d0e8425f0087f13c396efa464da5e8e95203e222353d66c11d68f1076abbb4"
},
{
"name": "ShaCraft.Launcher_0.1.7_x86_64.app.tar.gz",
"bytes": 6032631,
"sha256": "05748cc29462f850a12da3cd84336872af4ee8f5a5de0a3b10d91461c60fbad7"
}
],
"old_feed_preserved": true,
"feed_sha256": "b46d9a6ef974e177fd3b0d945ff22efb0ec0afaaa71bae7f7a23003997682166"
}
+2 -2
View File
@@ -1,12 +1,12 @@
{
"name": "shacraft-launcher-ui",
"version": "0.1.6",
"version": "0.1.7",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "shacraft-launcher-ui",
"version": "0.1.6",
"version": "0.1.7",
"dependencies": {
"@tauri-apps/api": "2.11.1",
"lucide-react": "1.41.0",
+1 -1
View File
@@ -2,7 +2,7 @@
"name": "shacraft-launcher-ui",
"license": "MIT",
"private": true,
"version": "0.1.6",
"version": "0.1.7",
"type": "module",
"scripts": {
"dev": "vite",
+1 -1
View File
@@ -3361,7 +3361,7 @@ dependencies = [
[[package]]
name = "shacraft-launcher"
version = "0.1.6"
version = "0.1.7"
dependencies = [
"base64 0.22.1",
"ed25519-dalek",
+1 -1
View File
@@ -1,6 +1,6 @@
[package]
name = "shacraft-launcher"
version = "0.1.6"
version = "0.1.7"
description = "ShaCraft Minecraft launcher"
authors = ["ShaCraft"]
license = "MIT"
+2 -2
View File
@@ -247,7 +247,7 @@ fn build_command(request: &LaunchRequest) -> Result<Command, LaunchError> {
}
// This endpoint is native-owned; a manifest cannot redirect game admission.
if request.admission.server_id() == "minigames" {
command.args(["--quickPlayMultiplayer", "135.106.154.86:25568"]);
command.args(["--quickPlayMultiplayer", "shacraft.ru:25568"]);
}
command.current_dir(request.profile_dir);
@@ -313,7 +313,7 @@ mod tests {
assert!(arguments
.windows(2)
.any(|args| args == ["--accessToken", "0"]));
assert_eq!(arguments.windows(2).any(|pair| pair == ["--quickPlayMultiplayer", "135.106.154.86:25568"]), server_id == "minigames");
assert_eq!(arguments.windows(2).any(|pair| pair == ["--quickPlayMultiplayer", "shacraft.ru:25568"]), server_id == "minigames");
for secret in proof {
assert!(arguments.iter().all(|argument| !argument.contains(secret)));
for path in [
+1 -1
View File
@@ -14,7 +14,7 @@ use tauri::{AppHandle, Manager, Runtime};
use tauri_plugin_updater::{Update, UpdaterBuilder, UpdaterExt};
use url::Url;
pub(crate) const UPDATE_ENDPOINT: &str = "https://shacraft.ru/launcher/updates/stable.json";
pub(crate) const UPDATE_ENDPOINT: &str = "https://shacraft.ru/launcher/updates/stable-v2.json";
pub(crate) const MAX_METADATA_BYTES: usize = 192 * 1024;
const MAX_PAYLOAD_BYTES: usize = 64 * 1024;
pub(crate) const MAX_ARTIFACT_BYTES: usize = 256 * 1024 * 1024;
+3 -3
View File
@@ -1,7 +1,7 @@
{
"$schema": "https://schema.tauri.app/config/2",
"productName": "ShaCraft Launcher",
"version": "0.1.6",
"version": "0.1.7",
"identifier": "ru.shacraft.launcher",
"build": {
"beforeDevCommand": "npm run dev",
@@ -49,9 +49,9 @@
},
"plugins": {
"updater": {
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDk0N0MzODEwMjg1OUVCNDEKUldSQjYxa29FRGg4bEdKSkFWUzZUNDZhRFN4cGIwL0FvVnl0blhrOWtSMWhSOWxHMkU1aGs5L2oK",
"pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IEY3NUEyMDIwOUM3QTFFRTYKUldUbUhucWNJQ0JhOTFnUUo4d0Rmc1JxOVdyRElCYTRranJKRzZEYzloRGNXQ09NL1kvN042OEsK",
"endpoints": [
"https://shacraft.ru/launcher/updates/stable.json"
"https://shacraft.ru/launcher/updates/stable-v2.json"
],
"windows": {
"installMode": "passive"