Initial commit: AetherForge Linux (forge-mesh) v0.1.0-dev
Some checks failed
Test / test (push) Has been cancelled

This commit is contained in:
drjones
2026-07-04 09:31:23 +00:00
commit 3678b199d0
154 changed files with 21714 additions and 0 deletions

97
cmd/server/main.go Normal file
View File

@@ -0,0 +1,97 @@
package main
import (
"context"
"embed"
"flag"
"fmt"
"io/fs"
"log"
"net/http"
"os"
"os/signal"
"path/filepath"
"syscall"
"forge-mesh/internal/api"
"forge-mesh/internal/config"
"forge-mesh/internal/db"
"forge-mesh/internal/forge"
"forge-mesh/internal/stratum"
)
//go:embed webroot/*
var webroot embed.FS
const version = "0.1.0-dev"
func main() {
configPath := flag.String("config", "data/config.json", "path to config.json")
installTmpl := flag.String("install-tmpl", "scripts/install.sh.tpl", "install.sh template path")
flag.Parse()
cfg, err := config.Load(*configPath)
if err != nil {
log.Fatalf("config: %v", err)
}
if err := cfg.EnsureDataDirs(); err != nil {
log.Fatalf("data dirs: %v", err)
}
conn, err := db.Open(cfg.DatabasePath)
if err != nil {
log.Fatalf("database: %v", err)
}
defer conn.Close()
keyPair, err := forge.LoadOrCreateKey(cfg.Forge.SigningKeyPath)
if err != nil {
log.Fatalf("signing key: %v", err)
}
staticFS, err := fs.Sub(webroot, "webroot")
if err != nil {
log.Fatalf("webroot: %v", err)
}
srv, err := api.NewServer(cfg, conn, staticFS, version, *installTmpl, keyPair.PublicKeyHex())
if err != nil {
log.Fatalf("server: %v", err)
}
stratumProxy := stratum.New(cfg.Stratum)
if err := stratumProxy.Start(); err != nil {
log.Printf("stratum (non-fatal): %v", err)
} else {
defer stratumProxy.Close()
log.Printf("stratum: XMR %s RVN %s", cfg.Stratum.XMRListen, cfg.Stratum.RVNListen)
}
addr := cfg.ListenAddr
log.Printf("forge-mesh-server %s listening on %s (config: %s, db: %s)",
version, addr, absPath(*configPath), cfg.DatabasePath)
httpSrv := &http.Server{Addr: addr, Handler: srv.Handler()}
go func() {
if err := httpSrv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
fmt.Fprintf(os.Stderr, "server: %v\n", err)
os.Exit(1)
}
}()
sigCtx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
<-sigCtx.Done()
log.Println("shutting down...")
_ = httpSrv.Shutdown(context.Background())
}
func absPath(p string) string {
abs, err := filepath.Abs(p)
if err != nil {
return p
}
return abs
}

206
cmd/server/main_test.go Normal file
View File

@@ -0,0 +1,206 @@
package main
import (
"context"
"encoding/json"
"fmt"
"net"
"net/http"
"os"
"os/exec"
"path/filepath"
"testing"
"time"
)
func TestServerHealthViaSubprocess(t *testing.T) {
dir := t.TempDir()
port := freePort(t)
cfgPath := writeServerConfig(t, dir, port)
bin := buildServerBinary(t)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
cmd := exec.CommandContext(ctx, bin, "-config", cfgPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
t.Fatalf("start server: %v", err)
}
t.Cleanup(func() {
cancel()
_ = cmd.Wait()
})
base := fmt.Sprintf("http://127.0.0.1:%d", port)
waitForHealth(t, base+"/api/v1/health", 15*time.Second)
resp, err := http.Get(base + "/api/v1/health")
if err != nil {
t.Fatalf("health GET: %v", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
t.Fatalf("health status: got %d want 200", resp.StatusCode)
}
var body struct {
Status string `json:"status"`
Service string `json:"service"`
Version string `json:"version"`
}
if err := json.NewDecoder(resp.Body).Decode(&body); err != nil {
t.Fatalf("decode health: %v", err)
}
if body.Status != "ok" {
t.Fatalf("status: got %q want ok", body.Status)
}
if body.Service != "forge-mesh-server" {
t.Fatalf("service: got %q", body.Service)
}
if body.Version == "" {
t.Fatal("expected version in health response")
}
}
func TestServerUsesConfigDataDirAndPort(t *testing.T) {
dir := t.TempDir()
port := freePort(t)
cfgPath := writeServerConfig(t, dir, port)
cfgData, err := os.ReadFile(cfgPath)
if err != nil {
t.Fatal(err)
}
if !containsAll(string(cfgData), dir, fmt.Sprintf("127.0.0.1:%d", port)) {
t.Fatalf("config missing data_dir or listen_addr: %s", cfgData)
}
dbPath := filepath.Join(dir, "forge-mesh.db")
artifacts := filepath.Join(dir, "artifacts")
bin := buildServerBinary(t)
ctx, cancel := context.WithTimeout(context.Background(), 12*time.Second)
defer cancel()
cmd := exec.CommandContext(ctx, bin, "-config", cfgPath)
if err := cmd.Start(); err != nil {
t.Fatalf("start: %v", err)
}
defer func() {
cancel()
_ = cmd.Wait()
}()
waitForHealth(t, fmt.Sprintf("http://127.0.0.1:%d/api/v1/health", port), 12*time.Second)
for _, path := range []string{dbPath, artifacts, filepath.Join(dir, "signing.key")} {
if _, err := os.Stat(path); err != nil {
t.Fatalf("expected server to create %s: %v", path, err)
}
}
}
func buildServerBinary(t *testing.T) string {
t.Helper()
out := filepath.Join(t.TempDir(), "forge-mesh-server")
cmd := exec.Command("go", "build", "-o", out, "./cmd/server")
cmd.Dir = repoRoot(t)
if outBytes, err := cmd.CombinedOutput(); err != nil {
t.Fatalf("build server: %v\n%s", err, outBytes)
}
return out
}
func writeServerConfig(t *testing.T, dir string, port int) string {
t.Helper()
cfgPath := filepath.Join(dir, "config.json")
content := fmt.Sprintf(`{
"listen_addr": "127.0.0.1:%d",
"data_dir": %q,
"database_path": %q,
"auth": {
"basic_username": "admin",
"basic_password": "changeme",
"fleet_secret": "test-fleet-secret"
},
"forge": {
"signing_key_path": %q,
"artifacts_dir": %q
}
}`, port, dir, filepath.Join(dir, "forge-mesh.db"),
filepath.Join(dir, "signing.key"), filepath.Join(dir, "artifacts"))
if err := os.WriteFile(cfgPath, []byte(content), 0o644); err != nil {
t.Fatal(err)
}
return cfgPath
}
func freePort(t *testing.T) int {
t.Helper()
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
t.Fatal(err)
}
defer ln.Close()
return ln.Addr().(*net.TCPAddr).Port
}
func waitForHealth(t *testing.T, url string, timeout time.Duration) {
t.Helper()
deadline := time.Now().Add(timeout)
for time.Now().Before(deadline) {
resp, err := http.Get(url)
if err == nil {
resp.Body.Close()
if resp.StatusCode == http.StatusOK {
return
}
}
time.Sleep(200 * time.Millisecond)
}
t.Fatalf("server did not become healthy at %s within %s", url, timeout)
}
func repoRoot(t *testing.T) string {
t.Helper()
wd, err := os.Getwd()
if err != nil {
t.Fatal(err)
}
for {
if _, err := os.Stat(filepath.Join(wd, "go.mod")); err == nil {
return wd
}
parent := filepath.Dir(wd)
if parent == wd {
t.Fatal("go.mod not found")
}
wd = parent
}
}
func containsAll(s string, parts ...string) bool {
for _, p := range parts {
if !contains(s, p) {
return false
}
}
return true
}
func contains(s, sub string) bool {
return len(sub) == 0 || (len(s) >= len(sub) && indexOf(s, sub) >= 0)
}
func indexOf(s, sub string) int {
for i := 0; i+len(sub) <= len(s); i++ {
if s[i:i+len(sub)] == sub {
return i
}
}
return -1
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" fill="none">
<rect width="32" height="32" rx="6" fill="#111618"/>
<path d="M8 22 L16 8 L24 22 Z" stroke="#00e676" stroke-width="2" fill="none"/>
<circle cx="16" cy="18" r="2" fill="#ffb300"/>
</svg>

After

Width:  |  Height:  |  Size: 265 B

View File

@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en" class="dark">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/forge.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>AetherForge Command Deck</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap"
rel="stylesheet"
/>
<script type="module" crossorigin src="/assets/index-C7yIT9Qp.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-BJ9Sa22q.css">
</head>
<body>
<div id="root"></div>
</body>
</html>