Repository navigation
GhostBus v0.5.6 — hardening round 5: load & resilience
Hardening round 5 — prove it under load, and close the abuse holes load exposes.
The load bench (new, scripts/load-bench.mjs): boots the real hosted server with per-agent tokens enforced, runs concurrent agents doing mixed register/heartbeat/send/inbox/task/file work, then reconciles EXACTLY — messages sent == stored, tasks created == done, files put == stored. Across repeated runs: 0 errors and exact reconciliation every time (e.g. 2,506 ops in 30s at 25 agents; 650/650 messages, 300/300 tasks, 300/300 files). Figures are this-machine evidence, not an SLA — and the honest ceiling is documented: the JSON store re-saves whole state per op, so throughput decays as a workspace grows (~83→57 ops/s between 0.9 and 1.2 MB of state). RSS stays in a bounded sawtooth; the trims hold.
SSE subscriptions were unbounded — now capped (100 per workspace, 1000 per server, clean 429, idempotent cleanup so churned clients never leak listeners).
Server timeouts, done carefully: Node's defaults were probed on Node 24 — headersTimeout left partial-header sockets alive far too long, and requestTimeout semantics are unsafe for long-lived responses. The shipped guard bounds header receipt (10s) and declared-body receipt (30s) and destroys only genuinely incomplete requests: SSE streams and long-polls are never time-bounded. An early cut of the guard killed live streams in testing; the shipped version arms only on a declared body — the suite pins that.
Recovery drill (in the suite): SIGKILL the server mid-load, restart on the same data dir — state parses (atomic rename), every acknowledged op is durable, stored messages form a contiguous prefix per agent, counts reconcile with the file.
Verified: 69 checks (was 64), serverless 6/6, both demos.