Files
LINUX-AETHERFORGE/scripts/e2e-test.sh
drjones 3678b199d0
Some checks failed
Test / test (push) Has been cancelled
Initial commit: AetherForge Linux (forge-mesh) v0.1.0-dev
2026-07-04 09:31:23 +00:00

202 lines
8.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# AetherForge Linux end-to-end operator flow tests
set -euo pipefail
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
cd "$ROOT"
# shellcheck source=scripts/e2e-lib.sh
source "${ROOT}/scripts/e2e-lib.sh"
PORT="${E2E_PORT:-18989}"
STRATUM_XMR_PORT="${E2E_STRATUM_XMR:-33333}"
STRATUM_RVN_PORT="${E2E_STRATUM_RVN:-33388}"
BASE="http://127.0.0.1:${PORT}"
CONFIG="${E2E_CONFIG:-/tmp/forge-mesh-e2e-config.json}"
FLEET_SECRET="${E2E_FLEET_SECRET:-e2e-fleet-secret-test}"
E2E_USER="${E2E_USER:-admin}"
E2E_PASS="${E2E_PASS:-changeme}"
SERVER_PID=""
AGENT_PID=""
MOCK_OLLAMA_PID=""
MOCK_TG_PID=""
cleanup() {
[[ -n "${AGENT_PID}" ]] && kill "${AGENT_PID}" 2>/dev/null || true
[[ -n "${MOCK_OLLAMA_PID}" ]] && kill "${MOCK_OLLAMA_PID}" 2>/dev/null || true
[[ -n "${MOCK_TG_PID}" ]] && kill "${MOCK_TG_PID}" 2>/dev/null || true
e2e_stop_server
}
trap cleanup EXIT
start_mock_ollama() {
if curl -fsS http://127.0.0.1:11434/api/tags >/dev/null 2>&1; then
e2e_pass "Ollama already available — using live instance"
return 0
fi
python3 - <<'PY' &
import json
from http.server import BaseHTTPRequestHandler, HTTPServer
class H(BaseHTTPRequestHandler):
def log_message(self, *a): pass
def do_GET(self):
if self.path.startswith("/api/tags"):
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.end_headers()
self.wfile.write(json.dumps({"models": [{"name": "mock"}]}).encode())
else:
self.send_response(404)
self.end_headers()
HTTPServer(("127.0.0.1", 11434), H).serve_forever()
PY
MOCK_OLLAMA_PID=$!
sleep 0.5
e2e_pass "mock Ollama listening on :11434"
}
start_mock_telegram() {
# Telegram is disabled in e2e config; mock not required unless enabled.
e2e_pass "Telegram disabled in test config (mock skipped)"
}
e2e_log "building server + agent"
make server agent
e2e_log "writing L4 test config"
e2e_write_config "${CONFIG}" "${PORT}" 4 "${STRATUM_XMR_PORT}" "${STRATUM_RVN_PORT}"
e2e_log "starting server (start/stop lifecycle)"
e2e_start_server "${CONFIG}"
e2e_pass "server started pid=${SERVER_PID}"
e2e_log "health check"
HEALTH="$(curl -fsS "${BASE}/api/v1/health")"
echo "${HEALTH}" | grep -q '"status":"ok"' || { echo "health failed: ${HEALTH}"; exit 1; }
e2e_pass "GET /api/v1/health"
e2e_log "basic auth rejection/acceptance"
CODE="$(curl -s -o /dev/null -w '%{http_code}' "${BASE}/api/v1/fleet")"
[[ "${CODE}" == "401" ]] || { echo "expected 401 without auth, got ${CODE}"; exit 1; }
e2e_pass "unauthenticated fleet → 401"
FLEET="$(e2e_curl_auth "${BASE}/api/v1/fleet")"
echo "${FLEET}" | grep -q '"hosts"' || { echo "fleet list failed: ${FLEET}"; exit 1; }
e2e_pass "authenticated fleet → 200"
e2e_log "public install.sh render + bash syntax"
INSTALL="$(curl -fsS "${BASE}/install.sh")"
echo "${INSTALL}" | grep -q 'forge-mesh' || { echo "install.sh missing marker"; exit 1; }
TMP_INSTALL="$(mktemp)"
echo "${INSTALL}" > "${TMP_INSTALL}"
bash -n "${TMP_INSTALL}"
rm -f "${TMP_INSTALL}"
e2e_pass "GET /install.sh valid bash"
e2e_log "forge build + public download"
BUILD_RESP="$(e2e_curl_auth -X POST "${BASE}/api/v1/forge/builds/trigger" \
-H "Content-Type: application/json" -d '{"public":true}')"
echo "${BUILD_RESP}" | grep -q '"ok":true' || { echo "forge trigger failed: ${BUILD_RESP}"; exit 1; }
LATEST="$(curl -fsS "${BASE}/api/v1/public/builds/latest?os=linux&arch=amd64")"
BUILD_ID="$(e2e_json_field "${LATEST}" id)"
[[ -n "${BUILD_ID}" ]] || { echo "no build id in ${LATEST}"; exit 1; }
DOWNLOAD_BYTES="$(curl -fsS "${BASE}/api/v1/public/download/${BUILD_ID}" | wc -c | tr -d ' ')"
[[ "${DOWNLOAD_BYTES}" -gt 100 ]] || { echo "download too small: ${DOWNLOAD_BYTES}"; exit 1; }
e2e_pass "forge build + public download (${BUILD_ID})"
e2e_log "agent register via REST + WS subprocess"
REGISTER="$(e2e_curl_fleet -X POST "${BASE}/api/v1/fleet/register" \
-H "Content-Type: application/json" \
-d '{"hostname":"e2e-rest-host","fingerprint":"127.0.0.2","arch":"amd64"}')"
HOST_ID="$(e2e_json_field "${REGISTER}" host_id)"
[[ -n "${HOST_ID}" ]] || { echo "register failed: ${REGISTER}"; exit 1; }
e2e_pass "POST /api/v1/fleet/register"
AGENT_HOST="e2e-ws-agent"
FORGE_FLEET_SECRET="${FLEET_SECRET}" FORGE_HOST_ID="${AGENT_HOST}" \
./bin/forge-mesh-agent -deck "${BASE}" -secret "${FLEET_SECRET}" -host-id "${AGENT_HOST}" &
AGENT_PID=$!
sleep 3
e2e_log "fleet appears in API"
FLEET2="$(e2e_curl_auth "${BASE}/api/v1/fleet/hosts")"
echo "${FLEET2}" | grep -q "${AGENT_HOST}" || echo "${FLEET2}" | grep -q 'e2e-rest-host' || {
echo "fleet missing enrolled hosts: ${FLEET2}"; exit 1
}
WS_HOST_ID="$(echo "${FLEET2}" | sed -n 's/.*"hostname":"\('"${AGENT_HOST}"'\)".*"id":"\([^"]*\)".*/\1/p')"
[[ -z "${WS_HOST_ID}" ]] && WS_HOST_ID="${HOST_ID}"
e2e_pass "fleet hosts visible"
e2e_log "mining profile push"
PROFILE_RESP="$(e2e_curl_auth -X POST "${BASE}/api/v1/fleet/${WS_HOST_ID}/mining-profile" \
-H "Content-Type: application/json" \
-d '{"wallet_address":"e2e-wallet-addr","name":"E2E profile"}')"
echo "${PROFILE_RESP}" | grep -q '"ok":true' || { echo "profile push failed: ${PROFILE_RESP}"; exit 1; }
e2e_pass "POST /api/v1/fleet/{id}/mining-profile"
e2e_log "stratum port open"
e2e_wait_port 127.0.0.1 "${STRATUM_XMR_PORT}"
e2e_wait_port 127.0.0.1 "${STRATUM_RVN_PORT}"
# Send minimal stratum-ish payload (accept-only mode)
(printf '{"id":1,"method":"mining.subscribe","params":[]}\n' | nc -w 2 127.0.0.1 "${STRATUM_XMR_PORT}") >/dev/null 2>&1 || true
e2e_pass "stratum XMR:${STRATUM_XMR_PORT} RVN:${STRATUM_RVN_PORT} listening"
e2e_log "/spread/ lander serves"
SPREAD="$(curl -fsS "${BASE}/spread/?c=e2e-campaign")"
echo "${SPREAD}" | grep -qi 'spread\|summon\|install' || { echo "spread lander unexpected: ${SPREAD}"; exit 1; }
e2e_pass "GET /spread/"
e2e_log "policy snapshot"
SNAP="$(e2e_curl_auth -X POST "${BASE}/api/v1/policy/snapshot")"
SNAP_TOKEN="$(e2e_json_field "${SNAP}" token)"
[[ -n "${SNAP_TOKEN}" ]] || { echo "snapshot create failed: ${SNAP}"; exit 1; }
SNAP_BODY="$(curl -fsS "${BASE}/api/v1/public/policy-snapshot/${SNAP_TOKEN}")"
echo "${SNAP_BODY}" | grep -q 'policy_from_server' || { echo "snapshot fetch failed: ${SNAP_BODY}"; exit 1; }
e2e_pass "policy snapshot create + public fetch"
e2e_log "crucible endpoint (L4)"
CRUC="$(e2e_curl_auth -X POST "${BASE}/api/v1/crucible/batch" \
-H "Content-Type: application/json" \
-d "{\"command\":\"status\",\"host_ids\":[\"${WS_HOST_ID}\"]}")"
echo "${CRUC}" | grep -q '"status":"completed"' || echo "${CRUC}" | grep -q '"status":"running"' || {
echo "crucible failed: ${CRUC}"; exit 1
}
e2e_pass "POST /api/v1/crucible/batch"
e2e_log "ws ticket"
TICKET="$(e2e_curl_auth -X POST "${BASE}/api/v1/ws/ticket")"
echo "${TICKET}" | grep -q 'ticket' || { echo "ws ticket failed: ${TICKET}"; exit 1; }
e2e_pass "POST /api/v1/ws/ticket"
start_mock_ollama
start_mock_telegram
e2e_log "clearance gate blocks L0 actions — restart with operator_clearance=0"
kill "${AGENT_PID}" 2>/dev/null || true
AGENT_PID=""
e2e_stop_server
L0_CONFIG="/tmp/forge-mesh-e2e-l0.json"
e2e_write_config "${L0_CONFIG}" "${PORT}" 0 "${STRATUM_XMR_PORT}" "${STRATUM_RVN_PORT}"
e2e_start_server "${L0_CONFIG}"
ME="$(e2e_curl_auth "${BASE}/api/v1/operator/me")"
echo "${ME}" | grep -q '"clearance_level":0' || { echo "operator/me: ${ME}"; exit 1; }
DENIED_CODE="$(e2e_curl_auth -X POST "${BASE}/api/v1/fleet/${HOST_ID}/command" \
-H "Content-Type: application/json" \
-d '{"action":"shell","args":{"command":"id"}}' \
-o /dev/null -w '%{http_code}')"
[[ "${DENIED_CODE}" == "403" ]] || { echo "expected 403 for L0 shell, got ${DENIED_CODE}"; exit 1; }
CRUC_CODE="$(e2e_curl_auth -X POST "${BASE}/api/v1/crucible/batch" \
-H "Content-Type: application/json" \
-d "{\"command\":\"status\",\"host_ids\":[\"${HOST_ID}\"]}" \
-o /dev/null -w '%{http_code}')"
[[ "${CRUC_CODE}" == "403" ]] || { echo "expected 403 for L0 crucible, got ${CRUC_CODE}"; exit 1; }
e2e_pass "L0 operator blocked from shell + crucible"
echo ""
echo "✓ e2e full operator flow passed ($(grep -c 'e2e_pass\|✓' "$0" || echo 18) checks)"