Bans and Anti-Gaming
Two layers keep a queue fair: per-room anti-gaming rules that throttle join abuse, and a ban registry that keeps specific members out.
Rejoin cooldown
A cooldown stops leave-and-rejoin cycling for a better position. Set it
at room creation (or later via update); 0 disables it:
snug waiting-room create -r launch-day -c 100 --anti-gaming-rejoin-cooldown 60Verified: join, leave, then an immediate rejoin fails until the cooldown elapses:
{
"status": 429,
"msg": "Please wait 60 seconds before rejoining",
"error": "RATE_LIMITED"
}Join rate limit
Caps join attempts per member within a sliding window:
snug waiting-room create -r launch-day -c 100 \
--anti-gaming-rate-limit-max 2 --anti-gaming-rate-limit-window 60Verified: with a max of 2 per 60 seconds, the third join attempt inside
the window fails with 429 RATE_LIMITED -
Too many join attempts. Try again in 60 seconds. Both knobs take 0
to disable.
The service also watches request patterns - rapid join/leave cycling and suspiciously regular request timing - and can auto-ban members it flags; the thresholds are internal and not per-room configurable.
Rejecting with a ban
reject removes members from the queue; adding -b <seconds> also bans
them from rejoining:
snug waiting-room reject -r launch-day -m user-3 -R "abuse" -b 3600Verified: the rejected member's next join attempt fails with
403 FORBIDDEN - Banned until 2026-08-28T15:16:02+00:00.
The ban registry (admin)
Explicit bans are managed separately from rejection. All ban commands
require a platform admin token, except member-bans, which a member may
also call for themselves.
snug waiting-room ban -r launch-day -m user-4 -R "bot" -d 86400 # omit -d for permanent
snug waiting-room bans -r launch-day --include-expired
snug waiting-room ban-details -r launch-day -m user-4
snug waiting-room unban -r launch-day -m user-4
snug waiting-room member-bans -m user-4 # room IDs this member is banned frombans lists a room's bans soonest expiry first, permanent bans last, and
pages on the standard list contract (--limit, --cursor, --all).
An explicit ban records the full audit trail; captured live:
{
"room_id": "launch-day",
"member_id": "user-4",
"reason": "bot",
"banned_by": "docs-wave-admin",
"banned_at": "2026-08-28T14:16:12.838659Z",
"banned_until": "2026-08-28T16:16:12.838659Z"
}Two verified gotchas:
- A ban created via
reject -bblocks joins and appears in the room'sbanslist (member ID and expiry only), but it has no registry record:ban-detailson it comes back empty. Usebanwhen you need an auditable reason and actor. - Bans are per-room.
member-bansaggregates the rooms a member is banned from; there is no global ban.
Expired bans stop blocking joins immediately and are swept from the registry in the background (hourly by default). The exact endpoints are in the Waiting Room API reference.
