Architecture

One engine. Many shells. One truth.

Every client, from a Discord bot to a microcontroller, runs the same deterministic engine. The server runs it too — and the server's run is the only one that counts. Everything else is a way of looking at the same river.

Clients (shells) · Desktop tray app · Web / WASM · /play · Discord bot · Native CLI · ESP32 firmware Shared engine core/idle_core.c integer-only, C99 deterministic ticks (also compiled to WASM) Server (Node, zero-dep) · HMAC + seq auth · witnessed-idle credit · anti-cheat flags · PvP arena / Elo · moderation + overseer · public site + /play verifier oracle build/idle-verify (same core) Postgres durable realm state (JSONB) Witness bots IRC · Matrix · … Overseer /admin (authenticated) signed sync / action runs same code persist presence

The engine is the single source of truth

core/idle_core.c is a small, integer-only, dependency-free C99 simulation. Given a seed and an elapsed number of ticks it produces a character's entire state deterministically — the same inputs always yield byte-identical output, on any CPU. Progress is never a stored score; it is always a function of (seed, class, name, creation_time, elapsed) plus a signed action log. That single fact is what makes cheating a non-problem.

The server re-simulates — it never trusts

The Node server (built on standard library only) owns the clock and the verdict. For any account it resumes from a compact checkpoint blob and runs the verifier oracle (build/idle-verify — the very same engine) forward to its own current time. The result is canonical. Client-reported numbers are compared only to raise tamper flags; they can never increase canonical state. If the verifier binary is ever missing the server runs in an explicit, clearly-flagged degraded mode rather than silently trusting input.

The protocol

Three headers accompany every authenticated request:

# HMAC-SHA256 over "<seq>.<raw JSON body>", keyed with your hex-decoded secret
x-idle-id    your account id
x-idle-seq   a counter that must strictly increase (replay guard)
x-idle-sig   hex HMAC of  "<seq>.<body>"

The secret is issued once at registration and never sent again. Witness bots use the identical scheme with their own x-witness-* credentials. Clock skew, request-rate, and claim-vs-canonical divergence are each detected and surfaced to the overseer.

Witnessed-idle credit

Canonical progress only ever advances to each account's credited_until mark, which every witnessed contact extends — capped per visit, and clamped hard to real wall-clock. One shared marker across all sources (sync, offline token, IRC, Matrix) means multiple witnesses are OR-combined: redundant, never additive. The plain-language version →

Durable storage

The realm's state lives in one process (canonical state is computed in-memory), persisted for durability. With DATABASE_URL set it writes to Postgres as a single JSONB document — essential on hosts with ephemeral filesystems, where a plain file would vanish on every restart. Locally, with no database configured, it falls back to an atomic JSON file so the whole thing still clones-and-runs with zero setup.

Deploy

A container image builds the C verifier and runs the Node server; point it at a Postgres add-on and set a few environment variables. Self-host it anywhere that runs a container.

# the knobs that matter
DATABASE_URL          durable Postgres (Heroku add-on sets this)
ADMIN_SETUP_TOKEN     bootstrap + reset the overseer account
PUBLIC_URL            canonical https origin for enrollment tokens
ADS_PROVIDER          'ethicalads' | 'carbon' | (unset = no ads)
IDLE_WITNESS_CAP_*    tune how far idle time may be credited per visit