Release 2.7.3.1: harden proxy recovery, updates and local API.

Restore orphaned system proxy after crash, require update SHA-256, add macOS /api auth token, fix UDP ping false positives, HTTPS-only subscriptions, and keep the UI responsive during connect.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
M4
2026-07-29 18:48:54 +03:00
co-authored by Cursor
parent dc700f2bac
commit 041cbb1250
32 changed files with 346 additions and 108 deletions
+14 -12
View File
@@ -18,11 +18,11 @@ import (
// CurrentVersion is the product/semver used for update eligibility (feed "version").
// Keep major.minor.patch only — no build suffix here.
const CurrentVersion = "2.7.2"
const CurrentVersion = "2.7.3"
// BuildNumber is the monotonic build within CurrentVersion (Windows FileVersion 4th part,
// macOS CFBundleVersion suffix, Android versionCode low digits). Bump on every release build.
const BuildNumber = 2
const BuildNumber = 1
// DefaultManifestURL is the update feed (hosted in the project git repo).
const DefaultManifestURL = "https://git.evilfox.cc/test2/navi/raw/branch/main/dist/update.json"
@@ -289,16 +289,18 @@ func prepareDownload(ctx context.Context, manifestURL string) (latest, url, sha,
}
}
}
if wantSHA != "" {
sum, err := fileSHA256(tmp)
if err != nil {
_ = os.Remove(tmp)
return "", "", "", "", "", err
}
if !strings.EqualFold(sum, wantSHA) {
_ = os.Remove(tmp)
return "", "", "", "", "", fmt.Errorf("checksum mismatch")
}
if wantSHA == "" {
_ = os.Remove(tmp)
return "", "", "", "", "", fmt.Errorf("в манифесте нет sha256 — обновление отклонено")
}
sum, err := fileSHA256(tmp)
if err != nil {
_ = os.Remove(tmp)
return "", "", "", "", "", err
}
if !strings.EqualFold(sum, wantSHA) {
_ = os.Remove(tmp)
return "", "", "", "", "", fmt.Errorf("checksum mismatch")
}
return st.Latest, st.URL, wantSHA, exe, tmp, nil
}
+16
View File
@@ -10,6 +10,7 @@ import (
"os/exec"
"path/filepath"
"strconv"
"strings"
"syscall"
"time"
@@ -73,6 +74,11 @@ func MaybeFinishUpdate(args []string) bool {
self, _ = filepath.Abs(self)
target, _ = filepath.Abs(target)
// Only allow replacing Navis.exe in the same directory as this pending updater.
if !safeUpdateTarget(self, target) {
return true
}
waitPIDExit(uint32(pid), 120*time.Second)
time.Sleep(400 * time.Millisecond)
@@ -93,6 +99,16 @@ func MaybeFinishUpdate(args []string) bool {
return true
}
func safeUpdateTarget(self, target string) bool {
selfDir := filepath.Clean(filepath.Dir(self))
targetDir := filepath.Clean(filepath.Dir(target))
if selfDir != targetDir {
return false
}
base := strings.ToLower(filepath.Base(target))
return base == "navis.exe"
}
// CleanupStaleDownloads removes leftover update temps from failed/old runs.
func CleanupStaleDownloads() {
exe, err := os.Executable()