feat: add server-side anti-cheat (option A + D)

Option A — state validation on every save:
- Cap all resources to RESOURCE_CAP (server enforces, not just client)
- Block boss status rollback (defeated can't become non-defeated)
- Block quest status rollback (completed can't become non-completed)
- Block achievement rollback (unlockedAt can't be cleared or future-dated)
- Block prestige count rollback (count can only go up)

Option D — HMAC signed save chain:
- Server signs the saved state with ANTI_CHEAT_SECRET (env var)
- Signature returned from both /game/load and /game/save
- Client stores signature in localStorage, sends it with every save
- Server verifies signature matches the previous DB state before accepting
- Gracefully degrades: if secret unset or first save, checks are skipped

Both options combine: a valid signature doesn't bypass A-validation;
A-validation runs regardless and silently corrects tampered fields.
This commit is contained in:
2026-03-06 19:06:11 -08:00
committed by Naomi Carrigan
parent 5ad2c44399
commit 46f095ff8b
3 changed files with 117 additions and 9 deletions
+6
View File
@@ -10,10 +10,14 @@ export interface AuthResponse {
export interface SaveRequest {
state: GameState;
/** HMAC-SHA256 signature of the previous save's state, for anti-cheat chain verification */
signature?: string;
}
export interface SaveResponse {
savedAt: number;
/** HMAC-SHA256 signature of the saved state — store and include in next save request */
signature?: string;
}
export interface LoadResponse {
@@ -22,6 +26,8 @@ export interface LoadResponse {
offlineGold: number;
/** Seconds the player was offline (capped at 8 hours) */
offlineSeconds: number;
/** HMAC-SHA256 signature of the loaded state — store and include in next save request */
signature?: string;
}
export interface BossChallengeRequest {