Local load-testing dashboard for Eaglercraft Minecraft servers (WebSocket). For **authorized** testing only — you must own the target server or have written permission.

## What it does

Spawns a configurable number of fake MC 1.12.2 (Protocol 340) clients over WebSocket, routes them through a SOCKS proxy pool, performs the EaglerV2 + MC login handshake, optionally sends `/register`/`/login` and chat messages, and keeps them alive on keep-alive packets. The dashboard shows live bot state, proxy health, and structured logs.

## What's new in v2

- **MC protocol fix:** proper length-prefixed packet framing, `Set Compression` handling, and correct `Position and Look` parsing (Little Endian, bitmask, VarInt teleport ID).
- **Compression-aware:** bots negotiate compression when the server enables it (zlib raw).
- **Auth state machine:** structured matching on `translate` keys (`commands.register.success`, etc.) instead of brittle substring search.
- **Proxy registry v2:** JSON persistence, scoring (0–100), weighted picking strategies (`best-score`, `round-robin`, `least-used`, `random`), per-proxy inflight caps, EMA latency, automatic retest-after-cooldown.
- **Per-bot inspector:** click "Inspect" on any bot to see packets, proxy, last error, and chat from a single bot.
- **Rate limits:** login, proxy upload, test start, broadcast chat all rate-limited.
- **Security:** `helmet` CSP, `httpOnly` + `sameSite=strict` cookies, HMAC-SHA256 session tokens, constant-time password compare, refuses to boot with default `SESSION_SECRET`.
- **Observability:** `/healthz`, `/metrics` (Prometheus), `/api/diagnostics`, structured JSON daily logs, log throttling.
- **Frontend:** score-colored proxy table, log filter, search, level toggles, per-bot inspector panel.

## Quick start

```bash
cp .env.example .env  # if you don't have one
# Edit .env: set SITE_PASSWORD and SESSION_SECRET

npm install
npm start
```

Open `http://localhost:6070` and enter your `SITE_PASSWORD`.

## Tests

```bash
npm run check   # syntax check on all source files
npm test        # unit tests (packets, codec, compression, auth, registry)
npm run smoke   # boot the server, hit endpoints, verify shape
```

## Project layout

```
src/
  config.js          config loading + env validation
  state.js           shared mutable state + event bus
  auth.js            HMAC tokens, cookie parser, constant-time compare
  io.js              Socket.IO + throttled broadcaster
  validate.js        input validation
  server.js          bootstrap (express, helmet, routes, lifecycle)
  proxy/
    registry.js      ProxyRegistry class (scoring, persistence, picking)
    lease.js         per-test proxy lease
    workerPool.js    generic async worker pool
  bot/
    packets.js       VarInt, strings, MC framing helpers
    codec.js         Eagler + MC 1.12.2 packet parsers/builders
    compression.js   zlib threshold handling
    auth.js          AuthStateMachine
    bot.js           Bot class — state machine
  routes/
    auth.js          /api/auth/*
    test.js          /api/test/*
    proxy.js         /api/proxy/*
    bots.js          /api/bots/*
    stats.js         /api/stats, /api/logs
    health.js        /healthz, /metrics, /diagnostics
  util/
    log.js           structured logger (daily rotation)
    throttle.js      throttle + coalescer
test/                node:test unit tests
scripts/
  smoke.js           end-to-end smoke test
  migrate-proxies.js one-shot proxies.txt → proxies.json
```

## Environment

| Var | Required | Description |
|---|---|---|
| `SITE_PASSWORD` | yes | Dashboard login password |
| `SESSION_SECRET` | yes | Random secret for HMAC-signed cookies. Refuse to boot if unset or default. |
| `PORT` | no | Override `config.yaml` server.port |
| `HOST` | no | Override `config.yaml` server.host |

## Configuration

`config.yaml` is non-sensitive. Top-level keys:

- `server.{port, host}` — defaults to 6070 / 0.0.0.0
- `bots.{max_bots, default_rate, default_spawn_delay, max_spawn_delay, max_packet_rate, password, join_delay_ms, chat_messages, auth_phrases, auth_timeout_ms}` — bot limits and defaults
- `proxy.{test_timeout_ms, concurrency, max_list_size, probe_host, probe_port, score_decay_ms, score_penalty_per_fail, score_recovery_after_ms, alive_latency_max_ms, per_proxy_inflight_cap, default_strategy}` — proxy pipeline tuning
- `logging.{max_log_entries, max_dom_logs, daily_log_dir}` — log buffering
- `auth.session_hours` — cookie lifetime
- `rate_limits.*` — per-route limits
- `cors.origins` — CORS allowlist; empty = same-origin only
- `quick_commands` — list of `/command` strings available in the dashboard's quick-actions panel

## Threat model

This tool is intended for **local development and authorized load testing** of servers you own or have explicit written permission to test. Use against systems without authorization is illegal.

The dashboard binds to `0.0.0.0` by default; if you're on a multi-tenant host, override `HOST` in `config.yaml` to `127.0.0.1`. The default rate limits and CORS are tuned for single-user local use; if you expose this beyond localhost, add a reverse proxy with auth and tighten further.

## License

MIT
