Anti-gaming et three strikes: comment Auction riposte
Rapid-bid bursts, retraction patterns, deposit timeouts - et le trigger qui blocklist automatiquement les recidivistes.
Quand on lit "anti-gaming", on imagine spontanément un modèle machine-learning sophistiqué qui classe les bidders en "honest" et "fraudulent." Ce n'est pas ce qui tourne. Ce qui tourne, ce sont deux choses plus simples, toutes deux plus efficaces qu'elles n'en ont l'air sur papier.
Continuous détection at placeBid
Chaque bid entrant passe par un check avant d'être accepted. Le check regarde l'activité récente du bidder sur quatre fenêtres : les 60 dernières seconds, les 5 dernières minutes, la dernière hour et les 24 dernières hours. À partir de cette activité, il calcule deux signals — rapid-bid count (combien de bids dans la fenêtre la plus courte) et retraction count (combien de ces bids ont été withdrawn). Les signals sont pondérés par des thresholds platform-tunable et produisent un suspicion score low / medium / high.
Si le score est high, le bid est auto-rejected. Si le score est medium, le bid est accepted mais flagged for review sur la page anti-gaming de l'opérateur. Les signals restent cached sur la company row du bidder, donc le bid suivant de la même company ne relance pas toute la window query — assez rapide pour ne pas ralentir le bidding feed, assez précis pour attraper les pires patterns.
Les thresholds sont réglés par les admins plateforme ReVend OS via /admin/auction/risk-settings. Les defaults sont calibrés platform-wide ; les tenants ne peuvent pas les assouplir à la publication.
Three-strikes auto-ban
Continuous détection attrape les mauvais comportements du moment. Three-strikes attrape le pattern visible seulement sur plusieurs auctions. Le strike type pertinent en v1 est escrow_deposit_timeout — un bidder a gagné un lot, le système a créé un pending-deposit escrow, et le buyer n'a jamais wired les funds dans la fenêtre de 7 jours. L'escrow auto-cancels, et un strike est enregistré contre la company du buyer.
La table strikes (auction_strikes) est purpose-built. Elle enregistre le strike type, le source context (escrow_id, deal_id, lot_id selon le strike), la recorded date, une colonne JSONB details pour le contexte additionnel que le source flow veut attacher, et un trio de clearance (cleared_at, cleared_by_user_id, cleared_reason) pour les compliance pardons. Les cleared strikes restent dans la table pour audit ; ils ne comptent simplement plus vers le threshold.
Le threshold est hard-coded à three strikes en 180 days. Quand le troisième active strike arrive, un AFTER INSERT trigger bascule companies.bidder_blocklisted à true avec une system reason. Le trigger G3 BEFORE INSERT existant sur auction_bids rejette ensuite chaque bid attempt suivante avant qu'elle atteigne la logique placeBid. Le bidder est, en pratique, retiré de l'auction sans que quelqu'un doive s'en souvenir.
Pardons and audit
Compliance peut pardonner des strikes individuels depuis la page admin strikes (/admin/auction/strikes/[companyId], platform-staff uniquement). Le pardon exige une reason d'au moins 5 characters, écrite dans la colonne cleared_reason. Compliance peut aussi lever toute la blocklist via l'action existante clearBidderBlocklist. Dans tous les cas, l'audit row reste — le pardon est documenté, pas effacé. Parce que la prochaine fois que quelqu'un demande "pourquoi ce bidder est de retour ?", la réponse est dans une colonne, pas dans la mémoire de quelqu'un.