Skip to content

feat(anticheat): агрегация античит-событий по аккаунтам + автобан (итер. 40) - #44

Merged
Azazlokus merged 1 commit into
mainfrom
feat/anticheat-backend
Aug 18, 2026
Merged

Azazlokus merged 1 commit into
mainfrom
feat/anticheat-backend

Conversation

@Azazlokus

Copy link
Copy Markdown
Owner

Что

Итерация 40 — античит-бэкенд: события из итер. 25 привязываются к аккаунту, копятся
в БД и при пороге ведут к автобану (связка с модерацией итер. 39). Автобан по умолчанию
выключен.

Зачем

Метрики итер. 25 были глобальными по виду (per-room). Чтобы разбирать конкретных
игроков и реагировать (флаг/автобан), сигнал нужно копить по аккаунту.

Как

  • game — tryFire привязывает клампнутое античит-событие к Player.AccountID в
    транзиентный World.acEvents (вне Checksum/реплея, как счётчики ac итер. 25; гости
    AccountID 0 не пишутся; в реплее AccountID=0 → no-op). Комната сливает
    DrainAntiCheatEvents и шлёт PersistAntiCheat через тот же неблокирующий
    sendPersist. Провод/симуляция/Checksum НЕ тронуты.
  • store — миграция 0005 anticheat_stats(account_id,kind,count); AddAntiCheat
    (апсерт-инкремент + возврат суммы по аккаунту), AntiCheatByAccount, TopAntiCheat.
  • persist — recordAntiCheat копит; при Config.AntiCheatBanThreshold>0 и
    превышении суммы — autoBan (если ещё не забанен) с отзывом сессий; CreatedBy 0
    (система). Порог 0 (дефолт) — только накопление, без бана.
  • api — GET /api/mod/anticheat (moderator+) — топ по флагам.
  • cmd/server — env ARENA_ANTICHEAT_BAN_THRESHOLD (0=выкл) / ARENA_ANTICHEAT_BAN_DURATION.
  • docs — README RU/EN + docs/architecture.md.

Границы и аудит

Первое game-касание за сессию — аудит по коду (изменение маленькое, повторяет уже
одобренный стражами паттерн ac итер. 25):

  • determinism — acEvents транзиентно, вне Checksum (регресс-тест
    TestAntiCheatEventsNotInChecksum) и вне лога реплея; AccountID читается только для
    не-Checksum записи; обхода map в Step нет; determinism-сьюта зелёная.
  • concurrency — новых горутин/каналов нет; acEvents/drain на горутине комнаты (как
    ac); persist через существующий неблокирующий sendPersist; persister — существующая
    горутина; -race зелёный (вкл. TestRoomPersistsAntiCheat).
  • protocol — провод не тронут (античит идёт в бэкенд через persist-канал, не клиенту);
    internal/protocol/web/game.js не менялись.
  • security-review — findings нет (kind — фикс. enum, не ввод; клиент накручивает лишь
    свой счётчик → само-бан, чужой аккаунт подставить нельзя; автобан системный, под порогом).

Клиент не трогал — автобан всплывает через баннер бана итер. 39.

Тестирование

  • make check + make integration — зелёные.
  • Bench: Tick/50ent 0 allocs, Tick/200ent 0 allocs, CombatTick 0 allocs — без регресса.
  • Покрытие: game (атрибуция к аккаунту, гость не привязан, не в Checksum, эмит из комнаты),
    store (апсерт/сумма/топ; Postgres-сьют дополнен anticheat_stats), persist (накопление,
    автобан+отзыв сессий, порог/ниже-порога), api (/api/mod/anticheat под ролью).

BENCHMARKS.md не трогал — горячий путь без изменений (0 allocs подтверждён).

…ер. 40)

Поверх античит-метрик итер. 25: событие теперь привязывается к аккаунту, копится в
БД и при пороге ведёт к автобану (связка с модерацией итер. 39). Автобан по умолчанию
ВЫКЛЮЧЕН (rewind_stale может быть высоким пингом, не читом).

- game: tryFire привязывает клампнутое событие к Player.AccountID в транзиентный
  World.acEvents (вне Checksum/реплея, как счётчики ac; гости AccountID 0 не пишутся);
  комната сливает DrainAntiCheatEvents и шлёт PersistAntiCheat через тот же неблокирующий
  sendPersist. Провод/симуляция/Checksum не тронуты.
- store: миграция 0005 anticheat_stats(account_id,kind,count); AddAntiCheat (апсерт-
  инкремент + возврат суммы аккаунта), AntiCheatByAccount, TopAntiCheat.
- persist: recordAntiCheat копит; при cfg.AntiCheatBanThreshold>0 и превышении —
  autoBan (если ещё не забанен) с отзывом сессий; CreatedBy 0 (система).
- api: GET /api/mod/anticheat (moderator+) — топ по флагам.
- cmd/server: env ARENA_ANTICHEAT_BAN_THRESHOLD (0=выкл) / ARENA_ANTICHEAT_BAN_DURATION.
- docs: README RU/EN + architecture.

Аудит (по коду, паттерн ac из итер. 25 уже одобрен стражами): determinism — acEvents
вне Checksum/реплея (регресс-тест TestAntiCheatEventsNotInChecksum), AccountID только
для не-Checksum записи; concurrency — новых горутин/каналов нет, всё на горутине комнаты/
persister, -race зелёный; protocol — провод не тронут. security-review — findings нет
(kind — фикс. enum, клиент накручивает лишь свой счётчик). Tick 0 allocs/op, без регресса.
Покрытие: game (атрибуция/гость/Checksum/эмит), store, persist (накопление+автобан+порог),
api (эндпоинт под ролью). make check + integration зелёные.
@Azazlokus
Azazlokus merged commit 47a60b6 into main Aug 18, 2026
10 checks passed
@Azazlokus
Azazlokus deleted the feat/anticheat-backend branch August 18, 2026 16:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant