Anti-triche du jeu
Le jeu qu'un visiteur joue quelques secondes est la partie que tu vois. En dessous se trouve le système anti-triche qui fait compter le jeu comme preuve d'un humain. Caputchin emprunte le manuel de jeu que les jeux multijoueurs compétitifs utilisent contre les tricheurs : le serveur fait autorité sur chaque manche, le jeu tourne dans un bac à sable verrouillé, et le résultat est re-dérivé en rejouant les entrées du joueur. Le jeu peut être joué, pas truqué.
C'est le troisième gate de vérification, empilé avec le proof of work et l'instrumentation. Il se configure par clé sur la page Sécurité.
Le cycle de vie
Une manche traverse trois phases : mise en place sur le serveur avant le jeu, exécutée en bac à sable dans le navigateur pendant le jeu, et revérifiée sur le serveur après le jeu.
Avant la manche : mise en place qui fait autorité côté serveur
Tout ce qui décide ce qu'est la manche se produit sur le serveur, jamais dans le navigateur. C'est le principe « ne jamais faire confiance au client » de l'anti-triche multijoueur : le client envoie l'intention, le serveur décide la réalité.
- Un ticket signé à usage unique génère la manche. Il est de courte durée et ne peut être dépensé qu'une fois. Un ticket capturé ne peut pas être rejoué en une seconde réussite.
- Le jeu et sa graine aléatoire sont choisis côté serveur et portés dans le ticket. Le navigateur ne peut pas choisir un jeu plus facile ni une graine plus aimable, parce qu'il ne fait jamais ce choix.
- Un jeu différent du pool éligible à chaque fois. Un solveur ne sait jamais quel jeu il affrontera, donc il ne peut pas se pré-entraîner sur une seule cible statique. Les opérateurs peuvent restreindre la rotation, mais le serveur choisit toujours dans l'ensemble autorisé. Le pool lui-même ne contient que des jeux qui ont passé une vérification de conformité au moment de l'indexation. Vois bâtir un jeu pour le marketplace.
Pendant la manche : un jeu en bac à sable
Le jeu tourne dans le navigateur du visiteur, mais à l'intérieur d'une frontière qui protège à la fois le site du visiteur et l'intégrité de la manche.
<caputchin-game> monte chaque jeu dans un iframe isolé sans accès same-origin, donc le jeu a une origine opaque et ne peut pas atteindre les cookies, le stockage, le DOM ni le réseau same-origin de la page hôte. Sa content-security-policy en ligne épingle le script exactement au bundle du jeu et bloque les appels réseau sortants, et le bundle est vérifié contre un hash connu avant de tourner (un décalage échoue en mode fermé). La propre politique de sécurité de la page hôte est intacte. La forme précise du bac à sable et de la politique est documentée dans comment Caputchin met les jeux en bac à sable.
À retenir : le jeu est non-fiable-par-défaut et contenu. Il ne peut rien exfiltrer, et il ne peut pas altérer la page dans laquelle il est intégré.
Après la manche : rejeu déterministe
Quand le visiteur finit, le navigateur soumet la trace d'entrées enregistrée. Le serveur ne prend pas la parole du navigateur pour le résultat. Il rejoue la trace.
- La manche est re-simulée sur le serveur sous la même graine dérivée du serveur, dans un isolat scellé sans accès réseau et avec un budget de temps strict. C'est la même propriété sur laquelle s'appuie le lockstep déterministe dans les jeux de stratégie : graine identique plus entrées identiques reproduisent un jeu identique. Une trace qui n'a pas réellement réussi le jeu ne reproduit pas un résultat gagnant.
- Réussite ou échec est pris de ce rejeu, jamais d'un nombre que le navigateur a rapporté. Un client ne peut pas revendiquer un score qu'il n'a pas gagné.
- Un token signé n'est émis que si le rejeu confirme le jeu. Ce token est lui-même à usage unique quand ton backend le confirme plus tard au moment de la vérification.
Ce que Caputchin ne fait pas
La plupart des CAPTCHA de jeu et interactifs s'appuient sur des signaux comportementaux : entropie de la trajectoire de souris, timing des taps, télémétrie d'appareil nourrie à un classifieur qui devine bot-contre-humain. Caputchin ne le fait délibérément pas. Il ne collecte aucun profil comportemental du joueur. Au lieu de deviner comment les entrées ont été produites, il re-dérive si elles réussissent réellement le jeu à partir de premiers principes. C'est à la fois une posture de confidentialité et une de sécurité : il n'y a aucun modèle comportemental à duper, seulement de la physique à reproduire.
Une limite honnête
Le gate n'est aussi fort que le jeu. La machinerie anti-triche prouve qu'une manche a été véritablement jouée et non truquée, mais elle ne peut pas rendre un jeu facile difficile. Un jeu trivial (un plateau statique, le coup gagnant lisible dans le DOM, « clique le point rouge pour passer ») est bon marché à résoudre pour un script, et le rejeu déterministe confirmera fidèlement que ces entrées scriptées gagnent, parce qu'elles gagnent. La résistance aux bots vient du jeu lui-même étant dur à résoudre par programme : des réactions rapides, sensorielles, à la fraction de seconde, sans solution posée dans le DOM. La couche anti-triche garantit que le jeu était réel ; la conception du jeu décide si le vrai jeu était dur à automatiser. Choisis et bâtis des jeux avec ça en tête, vois bâtir un jeu pour le marketplace.
Réussite ou échec est décidé par la propre logique de chaque jeu ; le serveur rejoue fidèlement cette logique mais ne remet pas en question ce qu'un jeu donné considère comme une victoire. L'anti-triche du jeu est plus forte composée avec le proof of work, l'instrumentation, et le reste des réglages de sécurité d'une clé.