Skip to content

feat(antibot): a ban is told, with its end and a link to the rules - #445

Merged
raphoester merged 2 commits into
mainfrom
claude/shadowban-feedback-messaging-62ce4e
Oct 20, 2026
Merged

raphoester merged 2 commits into
mainfrom
claude/shadowban-feedback-messaging-62ce4e

Conversation

@raphoester

Copy link
Copy Markdown
Owner

Why

The shadow ban answered a banned caller's clicks OK and dropped them. Most of the callers the rules banned in October 2026 were people (stamina Oct 7, cadence Oct 9, roam Oct 10, rotator Oct 18). For them, a click that did nothing looked like a bug, and they could not ask to be unbanned because they did not know they were banned.

What changed

Backend

  • Click, DropBomb and PlaceShield refuse a banned caller with PermissionDenied and a new planet.v1.BanRefusal detail (banned_until_unix_ms). No reason goes out.
  • New ban_click decorator, outside the throttle: a refused click spends no token (otherwise the client would show a 429) and reaches no watchdog.
  • antibot_click only judges now. The click that earns a ban goes through; the next one is refused.
  • A banned caller's clicks no longer feed the jury, so the ban end the player is told does not move. Only an accomplice's click (rotator ring) can still extend it.
  • Bombs and shields are refused before they are spent. The Dud flag is gone from both use cases. bonus_bombs_dropped_total{outcome} now says banned instead of shadowbanned.
  • Antibot API: Guard.Banned → Guard.EnforcedSentence(scope, account) (Sentence, bool). Guard.Inspect returns nothing.

Frontend

  • New BannedError. A permission_denied with the detail is a ban; without the detail it is still the VPN block.
  • New "Clicks paused" dialog with the end time (describeEnd, now shared with the chat mute) and a "Read the game rules" link to /terms#play-fair.
  • fakeBackend.ban(minutes) reproduces it in fake mode.

Terms (please review the wording)

  • id="play-fair" on the "Play fair" heading. BannedModal.test.tsx pins it.
  • New rule: "play several accounts, or switch between accounts, to get more clicks".
  • "ignore your clicks" → "pause your clicks". Date updated to 20 October 2026.

Rename

  • Package antibot/internal/shadowban → antibot/internal/bans, and its Bans type → bans.Book.
  • Config antiBot.shadowBan.* → antiBot.bans.*, in deploy/vps/backend.yaml and example.yaml.
  • Metrics shadowbanned_clicks / shadowban_flagged / shadowban_flags → banned_clicks / banned_callers / ban_flags. The poller filter in docker-compose.yaml is updated.

For the reviewer

  • Config rename in one step: the deploy pulls the repo and recreates the backend from the same commit. TestTheProductionConfigEnforcesBans fails if production stops reading bans.enforce; I checked it against the old key.
  • Rollback: an older image with this backend.yaml does not read bans, so bans stop being enforced, with nothing in the logs, until you redeploy.
  • Metrics history: files the poller wrote before the deploy day keep the old names. The deploy README says so.
  • Deploy backend and frontend together: an old cached frontend shows the VPN dialog to a banned player until it reloads.
  • Antibot scenario tests: their test stack still sends every click to the jury. What they pin is when a ban first falls, and that has not changed.
  • Not checked in a browser: the in-app browser pane was hidden, so the globe never registered a test click. The dialog path is covered by unit tests: BannedModal, reportClickFailure, reportClaimFailure and the planetBackend mapping.

Tests

  • Backend: full make test (including e2e), lint, deadcode, check-format (pre-push hook passed after merging main). New: ban_click, planetban, the bomb and shield gates, TestABannedCallerIsToldUntilWhenAndSpendsNoToken over HTTP, TestTheProductionConfigEnforcesBans.
  • Frontend: 2137 vitest tests, lint and build.

🤖 Generated with Claude Code

raphoester and others added 2 commits October 20, 2026 18:05
A banned caller's clicks were answered OK and dropped. Most of the
callers the rules banned in October 2026 were people, and for them a
click that did nothing read as a bug, with no way to ask.

Click, DropBomb and PlaceShield now refuse a banned caller with
PermissionDenied and a planet.v1.BanRefusal detail: when the ban ends.
No reason goes out. ban_click sits outside the throttle, so a refused
click spends no token and feeds no watchdog, and the end the player is
told does not move. The bomb or the shield stays in hand.

The client shows "Clicks paused" until that time, with a link to the
terms' Play fair section, which now names switching accounts.

The shadowban package, config block and metrics are renamed to bans,
antiBot.bans and banned_clicks / banned_callers / ban_flags.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@raphoester
raphoester merged commit 2edbdaa into main Oct 20, 2026
4 checks passed
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