Skip to main content

Security

Security & Determinism Contract

Stellarch's combat engine is deterministic. Same seed + same teams + same battle config = byte-identical event stream every time. This page is the load-bearing trust statement for spectators, deck-builders, and any third-party tool that wants to verify a result.

How the seeded RNG works

Every match constructs one SeededRng instance from the battle's persisted seed (an Integer). That single instance is threaded through every engine call (Targeting, AttackResolver, DeathResolver, RoundResolver), every ability hook (Splash, Killstreak, Shock, Hemobane), and every ruleset hook (Earthquake, Reverse Speed). No engine or ability constructs its own Random.

Why replays are byte-identical

Three invariants enforce determinism. (1) All randomness flows through one SeededRng. (2) No file under the engine namespace uses Random.new, Kernel.rand, SecureRandom, or Array#sample — a load-bearing test scans every file and fails fast on any match. (3) No clock entropy: Time.current / Time.now are never used for randomness anywhere in the engine.

The no-raw-RNG guard

A dedicated spec scans every Ruby file under the engine namespace at every test run. If any non-seeded RNG source slips in, the spec fails immediately with the exact file + line. Only the SeededRng wrapper itself is exempt. This guard is run on every CI build.

How to verify a battle outcome

Take any persisted battle row. Re-run the simulator against the same seed and the same teams snapshot. The event stream that comes back will match the original event-by-event, including damage values, hit rolls, death order, and reflects. Replays are regenerated on every controller request and cached for 5 minutes — the byte-identical guarantee makes on-demand re-simulation safe.

Reporting issues

If you find a case where a replay deviates from the original, please file an issue. Include the battle slug, the original event count, and the event index at which divergence appears. The team treats determinism regressions as the highest-priority class of bug.