Critical:
- crypto.rs (server): use BTreeMap for canonical JSON so key order
matches JS client's JSON.stringify sort — sig verification was always
failing silently
- heartbeat.js: capture sentSalt before rotating to next_salt so both
sides compute next_chain_hash with the same salt — chain was broken
after the first heartbeat
High:
- trust.rs: avg_speed = total_dist / total_time_ms (px/ms), not
distance/event_count — legitimate users were always rejected
- ratelimit.rs: add evict_stale() to drain expired entries and prevent
unbounded HashMap memory growth
- cleanup.rs: call rl.evict_stale() from the periodic cleanup loop
Medium:
- vm.rs: op 0x08 (NOT) is unary — split from binary-op arm so depth
is not decremented incorrectly
- wasm/crypto.rs: replace unwrap() panics in sign_message /
get_public_key with unwrap_or_default(); add JS-side guard
Low:
- shared/Cargo.toml, wasm/Cargo.toml: remove leftover add-this comments
- Dockerfile: rust:1.88-bookworm -> rust:1.87-bookworm (1.88 non-existent)