Audit fait le 20/10/2026 en lecture seule sur la branche soiree-v2 (v1081), l'aperçu (v1153) et la production. Rédigé pour Theo : le « tu » s'adresse à lui. Les codes de comptes sont masqués. Cette copie ne permet pas de répondre : les réponses se donnent dans la page interactive ou par message.
La façon dont le code part en ligne et ce qui le contrôle avant.
Ce qui a changé : La nouvelle migration du mot de passe est écrite sous une forme que ton contrôle du schéma ne sait pas lire.
Ce que ça casse : Rien n'est perdu, mais deploy.sh refuse maintenant de mettre la v1081 en ligne. 13 versions ont suivi sans que personne le voie. En plus, deux bancs navigateur (« on joue vraiment » et « réglages rapides ») échouent sur la v2 et passent sur ta version, sans doute à cause du compte obligatoire.
Avis : Le schéma lui-même est bon. C'est ton garde-fou qui fait son travail : il refuse de conclure plutôt que de dire oui à tort.
Proposition : Réécrire la migration en 4 lignes simples que le contrôle sait lire, puis vérifier que le contrôle repasse et qu'il casse bien si on le sabote.
Preuves : 80fab682 (16/10), functions/api/[[route]].js:517, outils/test-schema-a-jour.js, deploy.sh:49
Ce qui a changé : Romain publie chaque version sur l'aperçu avec outils/publier.sh. Environ 450 versions y sont passées, dont le paiement et les mots de passe.
Ce que ça casse : L'aperçu n'était qu'un essai d'écran ponctuel. Il partage la base des joueurs : ses migrations ont très probablement déjà modifié la base de production.
Avis : C'est le risque le plus lourd. Deux versions du serveur (v1059 en ligne, v1081 sur l'aperçu) écrivent aujourd'hui la même base avec des règles de compte différentes.
Proposition : Créer une base D1 séparée pour l'aperçu dans wrangler.toml. Avant ça, lire en lecture seule la structure réelle de la base pour savoir ce qui a déjà été appliqué.
Preuves : apercu.sh (en-tête), wrangler.toml (un seul binding DB), [[route]].js:1348 et 1359
Ce qui a changé : ECHANGES-ROMAIN.md contient le code de connexion du compte de Romain et celui d'un compte de test créé en production avec une boîte mail jetable publique.
Ce que ça casse : Rien, mais ces codes restent dans l'historique git même si on efface les lignes.
Avis : Le compte de test est récupérable par n'importe qui via « mot de passe oublié » sur sa boîte publique. La production (v1059) accepte encore la connexion par code.
Proposition : Supprimer le compte de test, faire changer son accès à Romain, puis retirer les lignes du fichier. Je n'affiche pas ces codes ici.
Preuves : ECHANGES-ROMAIN.md:1589, 1618, 1623 (f9e4e955)
Ce qui a changé : publier.sh fusionne, monte la version, lance verif.js puis publie sur l'aperçu. Il est prévu pour Mac.
Ce que ça casse : Les 23 suites de tests et les 8 bancs navigateur de deploy.sh ne tournent plus au quotidien. Le hook anti-écrasement ne protège que main, alors que tout le travail est sur soiree-v2.
Avis : C'est ce qui explique que la porte soit cassée depuis 4 jours sans alerte.
Proposition : Faire lancer à publier.sh les suites node et python de deploy.sh (moins de 2 minutes, sans réseau) et étendre le hook pre-push à soiree-v2.
Preuves : outils/publier.sh (61a35c6b), .githooks/pre-push
Ce qui a changé : Rien de nouveau dans ce domaine.
Ce que ça casse : Ta sauvegarde chiffrée est intacte mais n'a jamais été refaite. Depuis, la base contient une table d'achats à conserver pour la comptabilité.
Avis : Pas une régression, mais le moment est mal choisi pour ne pas en avoir de fraîche.
Proposition : Refaire une sauvegarde chiffrée maintenant, avant toute correction, avec ta méthode du 08/09.
Preuves : sauvegardes/trinke-db-2026-09-08.sql.gpg
Ce qui a changé : Tests du paiement (105 contrôles), du ticket du direct, du journal d'erreurs, de estBloque, du tirage de la Soirée sur 2000 parties, de « qui la carte concerne ».
Ce que ça casse : Rien.
Avis : Sérieux et sans réseau. Ils passent tous. Ça suit ta règle « toute fonction livrée entre au contrat ».
Proposition : Les garder tels quels.
Preuves : deploy.sh, outils/test-*.mjs et test-*.js ; 22 suites sur 23 passent
Ce qui a changé : outils/test-mdp.mjs couvre comptes, mots de passe, alerte de connexion, Turnstile et fuites (123 contrôles, il passe).
Ce que ça casse : Rien, mais il n'est appelé ni par deploy.sh ni par verif.js.
Avis : C'est le test du changement le plus sensible de la période.
Proposition : L'ajouter à deploy.sh.
Preuves : outils/test-mdp.mjs
Ce qui a changé : Le contrôle FONDS-04 de verif.js appelle python3.
Ce que ça casse : Sur Windows, python3 n'existe pas : le contrôle affiche « non vérifié » et laisse passer. C'est exactement le piège que tu avais noté le 07/09.
Avis : Avec python il passe, donc rien de grave aujourd'hui, mais la garde est morte chez toi.
Proposition : Essayer python3 puis python, et bloquer si les deux manquent.
Preuves : verif.js, contrôle FONDS-04
Ce qui a changé : verif.js a gagné environ 284 contrôles (19 746 à 22 822).
Ce que ça casse : 60 de tes entrées n'existent plus sous leur libellé (hors avatar), par exemple « personne ne boit en cas d'égalité » ou « un retrait de trinqueur peut être annulé ».
Avis : La plupart suivent un changement de règle. Personne n'a vérifié qu'un contrôle équivalent existe pour chacun.
Proposition : Je les passe un par un et je te dis lesquels n'ont plus d'équivalent.
Preuves : liste complète : audit/contrat-disparus-hors-avatar.txt
Ce qui a changé : Les 7 contrôles d'avatar de deploy.sh et 60 entrées du contrat sont partis avec la fonction.
Ce que ça casse : Tout est conservé sur la branche archive/avatar (10 tests, 3 266 images), vérifié.
Avis : Cohérent. La question est de savoir si l'avatar doit revenir (fiche dans Écrans).
Proposition : Rien à faire de ce côté.
Preuves : d20860b8, origin/archive/avatar
Ce qui a changé : CLAUDE.md décrit le nouveau circuit soiree-v2.
Ce que ça casse : DEMARRER.md et LISEZ-MOI.md décrivent encore l'ancien circuit, README parle de public/av3 qui n'existe plus, 4 captures de travail traînent à la racine.
Avis : Mineur, mais quelqu'un qui arrive suivrait le mauvais circuit.
Proposition : Mettre à jour les 3 fichiers et ranger les captures.
Preuves : README.md:145, cgv-*.png à la racine
Ce qui a changé : outils/cartes-soiree/ (125 fichiers) et 7 JSON dans echanges/ : lots, relectures croisées, versions « prêt » et « dosé ».
Ce que ça casse : Rien.
Avis : Poids faible. Ce sont des fichiers de travail, ni rangés en archive ni supprimés.
Proposition : Les ranger dans archives/ avec un LISEZ-MOI, comme tu l'avais fait pour l'histoire du produit.
Preuves : outils/cartes-soiree/pass-30-10/
Ce qui a changé : apercu.sh lit un jeton dans un fichier local si aucun n'est fourni.
Ce que ça casse : Rien.
Avis : Le commentaire parle de « ton jeton » puis du « jeton dédié de Romain ». Romain lui-même demande le 17/10 de régénérer le jeton s'il a circulé.
Proposition : Vérifier dans le tableau Cloudflare que Romain a son propre jeton, révocable à part, avec une date d'expiration.
Preuves : apercu.sh:25 (d993d3f0), ECHANGES-ROMAIN.md:1487
Règles, tirage de la Soirée, Classiques, mini-jeux, contenu.
Ce qui a changé : Crash out (mise jusqu'à 10, gain sans limite), Purple (toute la pile), Palmier (sans plafond), Course des As (jusqu'à 20 pour les gagnants).
Ce que ça casse : Ta règle 7 : le niveau de gorgées est un plafond, aucun jeu ne le dépasse.
Avis : Le code l'écrit en clair : « pas de plafond de gorgées ». Au niveau le plus doux, une manche de Crash out peut coûter 10 gorgées.
Proposition : Repasser ces 4 jeux par la fonction de plafond qui existe déjà, sans toucher à leur mécanique.
Preuves : app.js:7104, 7111, 8183, 8359, 8503, 8571 ; 2be01108, d27b4def, 171a0a18, c5279a83
Ce qui a changé : Tout le contenu est passé dans un seul fichier de cartes, retrié par Romain.
Ce que ça casse : Tu avais 246 phrases. Il en reste 4 (1 en Chill, 3 en Ça chauffe, 0 en Sans filtre). Un Classique refuse de démarrer sous 6. Le jeu reste affiché au catalogue.
Avis : Une commande de réécriture avait été passée à Codex le 15/10. Elle n'a pas été livrée.
Proposition : Remettre tes 246 phrases (archivées dans archives/paquets-avant-v966) dans le fichier unique. Sinon, cacher le jeu tant qu'il n'a pas assez de phrases.
Preuves : public/cartes-fr.json (4 cartes pour_combien), app.js:9536
Ce qui a changé : Nouveau mini-jeu de case piégée, avec des refontes du revolver avant.
Ce que ça casse : La roulette russe. Ta règle 2 : aucun jeu supprimé.
Avis : Le commit suivant dit lui-même « point à trancher par Theo ». Tout reste récupérable dans git.
Proposition : Joue la case piégée. Si elle ne te plaît pas, je restaure la roulette russe à côté.
Preuves : d95fc3ea (v731), 2dd5a2df
Ce qui a changé : Nouveau Classique Palmier.
Ce que ça casse : La carte de l'As affiche « Tout le monde commence à boire » sans passer par le filtre sans alcool (règle 9).
Avis : Exception volontaire dans le code, mais elle casse la promesse du mode sans alcool.
Proposition : Faire passer cette carte par le filtre comme les autres.
Preuves : app.js:8328, 8471 ; aec8019a
Ce qui a changé : Nouveau tirage : intensités séparées.
Ce que ça casse : La montée en trois actes et la cadence des intermèdes 6/5/4. Le code est encore là mais jamais appelé.
Avis : Deux choses fausses en restent : 5 contrôles verif.js passent sur du code mort, et « Ça chauffe » promet toujours « L'ambiance monte ».
Proposition : Corriger tout de suite le texte et les contrôles. Rebrancher ou non la montée, c'est ton choix : dis-le en commentaire.
Preuves : a1a28e03 (v631), app.js:4052, 5207, 3530 ; verif.js:1190-1194
Ce qui a changé : Partie fixe de 50 cartes, quotas par famille, jamais deux cartes de la même famille à la suite, cases spéciales placées.
Ce que ça casse : Le choix de durée Courte / Moyenne / Libre.
Avis : L'alternance corrige un vrai défaut mesuré (Action ou vérité à 36 %). Mais le plancher de fraîcheur est resté à 40 pour une partie de 50 : après quelques soirées, l'app affichera « Carte à écrire » aux joueurs.
Proposition : Garder le nouveau tirage, monter le plancher de fraîcheur au-dessus de 50 et ne jamais montrer « Carte à écrire » à un joueur.
Preuves : app.js:3672, 3818, 3911 ; banc outils/test-tirage-soiree.js
Ce qui a changé : Défi (réussi tu distribues, raté tu bois), Loi de table et sa carte miroir, Bingo, Joker, Duel, Quiz avec réponse, coup de théâtre, nombre minimum de joueurs par carte.
Ce que ça casse : « Gage » renommé en « Défi ».
Avis : De vrais ajouts de jeu.
Proposition : Les garder.
Preuves : 89919807, afe22ad0, 4cc195ab, f941f07c
Ce qui a changé : public/cartes-fr.json, chaque texte une seule fois.
Ce que ça casse : content-fr.json et classics-fr.json, archivés. 494 doublons supprimés.
Avis : Plus simple à maintenir.
Proposition : Le garder.
Preuves : d697db83 (v966), archives/paquets-avant-v966/
Ce qui a changé : Tri complet, standard d'écriture, des centaines de cartes neuves (1 027 au total).
Ce que ça casse : Tes 391 cartes de Soirée. Le contrôle des cartes relues passe de 784 à 45, et son plancher de 247 à 45 en neuf baisses.
Avis : Une partie de la baisse est mécanique : la formule « Ceux qui ont déjà » a changé l'empreinte de chaque Je n'ai jamais. Mais aujourd'hui, 2 % du jeu est relu.
Proposition : Lis un échantillon de 30 cartes que je tire au hasard. Ensuite je remets le registre de relecture à jour pour que le contrôle protège à nouveau quelque chose.
Preuves : verif.js:237-251, mesure-relu.js
Ce qui a changé : Carte pleine (plus le format bridge), « ? » dans la barre, barre du haut retouchée.
Ce que ça casse : Le format bridge 57/89 est écrasé par des !important, mais son contrôle verif.js passe encore. La retouche de la barre ne vise que la Soirée : le bouton passer ferait 17 px en Soirée et 13 px aux Classiques.
Avis : Ta règle : le haut de carte est identique au pixel. Les tailles sont lues dans le CSS, pas encore mesurées à l'écran.
Proposition : Mesurer les deux barres au navigateur, aligner les Classiques sur la Soirée, et faire lire au contrôle la règle réellement appliquée.
Preuves : style.css:9559, 9947, 12058, 8530 ; fb22b5ae, 6c3ed7dd
Ce qui a changé : 4 intermèdes au lieu de 2, Varié retiré, centre du Doigt du destin autorisé, Tape le plus vite à plusieurs doigts, difficulté retirée de Timer aveugle et Tape, « Juge final » sur Qui pourrait.
Ce que ça casse : Le plafond de cartes passées (« sinon le groupe se fabrique un paquet sur mesure »).
Avis : Ce sont des choix de jeu défendables. Le seul que je reprendrais, c'est le plafond de cartes passées.
Proposition : Remettre le plafond de cartes passées. Le reste : joue-le, et dis-moi ce que tu veux changer.
Preuves : f06bbd11, d3542038, 256a5a09, 51e393e8, 56ef1ec0, 9a82b3ce
Ce qui a changé : Les 77 catégories sont triées par intensité, et la bombe tombe à chaque Soirée.
Ce que ça casse : La variété : 51 en Chill, 9 en Ça chauffe, 6 en Sans filtre.
Avis : En Sans filtre, les mêmes catégories reviendront dès la deuxième soirée.
Proposition : Écrire au moins 20 catégories pour Ça chauffe et Sans filtre.
Preuves : app.js:6369-6440 ; e1a3a2d2
Ce qui a changé : Séquence, Couleur piégée, Vrai ou faux. Réflexe avec un départ à 3 feux. Stop parfait plus dur.
Ce que ça casse : Le feu rouge/vert du Réflexe.
Avis : De bons ajouts. Seule réserve : les 196 affirmations de Vrai ou faux sont « relues, non validées ».
Proposition : Garder. Je vérifie les faits de Vrai ou faux par lots.
Preuves : 649be634, d3a633f3, 5a7a087d, ee7df102
Le cœur que tu avais construit est intact. Les soucis viennent d'ajouts qui le touchent.
Ce qui a changé : Le nouveau tirage fixe 50 tours.
Ce que ça casse : L'hôte n'envoie que les vraies cartes (environ 35 à 43) mais annonce 50 tours. Les 7 à 15 derniers tours reprennent les premières cartes.
Avis : C'est le défaut que tu avais déjà arbitré dans la fiche « borne 400 », revenu par un autre chemin.
Proposition : Annoncer le nombre de tours égal au paquet réellement envoyé, et ajouter un test qui compare les deux.
Preuves : app.js:16624-16625, 3962 ; a1a28e03
Ce qui a changé : Chaque tentative de connexion demande d'abord un ticket au serveur.
Ce que ça casse : Rien. Le défaut existait déjà chez toi : la lecture régulière relance la connexion à chaque battement.
Avis : Avec le ticket, chaque tentative lit maintenant la base. Si le direct tombe, ça fait un appel en plus par seconde et par téléphone. Et une demande sans délai maximum peut bloquer le direct.
Proposition : Laisser la reconnexion attendre son délai au lieu de la relancer à chaque lecture, et mettre un délai maximum aux appels.
Preuves : app.js:15702, 15357, 10322
Ce qui a changé : Le direct exige un ticket signé qui prouve qui tu es.
Ce que ça casse : La confiance dans le pseudo écrit dans l'adresse : on pouvait parler sous le nom d'un autre.
Avis : Bon ajout, il ferme un trou que tu avais noté. Mais sans le secret LIVE_SECRET posé des deux côtés, il ne fait rien, et le rappel de deploy.sh peut se taire à tort.
Proposition : Vérifier que le secret est posé, puis faire vérifier au rappel qu'il est bien actif.
Preuves : live/src/index.js:87-103, [[route]].js:3472, deploy.sh:272
Ce qui a changé : Chaque téléphone remplace lui-même une carte ou un mini-jeu payant par un gratuit.
Ce que ça casse : Ta règle : le paquet est tiré une fois et c'est la vérité pour tout le monde.
Avis : À la même manche, deux joueurs peuvent jouer à deux jeux différents. Le code le note comme non tranché.
Proposition : Que ce soit l'accès de l'hôte qui décide pour toute la table.
Preuves : app.js:15890-15910, 16112 ; 893ac0e2
Ce qui a changé : Les cartes sont envoyées par identifiant au lieu de leur position.
Ce que ça casse : L'envoi par position.
Avis : Corrige un vrai défaut : deux versions de l'app pouvaient lire deux cartes différentes au même tour.
Proposition : Garder.
Preuves : 893ac0e2 (v967)
Ce qui a changé : Économies de réseau (vérification de version muette écran éteint, ménage du chat), index, reprise de partie coupée en multijoueur.
Ce que ça casse : Rien. Les 12 routes du direct sont identiques ligne pour ligne.
Avis : Un seul juge du tour, borne de 400 cartes, partie annulée si l'hôte part : tout est là.
Proposition : Rien à faire.
Preuves : c39d30c8, 90218970, e0c193d9
Aucune route serveur supprimée. Les changements portent sur le mot de passe et le compte obligatoire.
Ce qui a changé : Sans compte, l'app renvoie toujours vers la création de compte.
Ce que ça casse : Le jeu en invité. Ta spec disait « 100 % hors ligne et sans compte ».
Avis : Deux effets concrets : un téléphone neuf sans réseau ne peut plus jouer du tout, et une panne de Brevo empêche tout nouveau venu de jouer.
Proposition : Garder le compte mis en avant, mais remettre « Jouer sans compte » en secours.
Preuves : app.js:1509-1519, [[route]].js:1405 ; d3c922a5
Ce qui a changé : Inscription et connexion par mot de passe, poivre, refus des mots de passe fuités, déconnexion des autres appareils au changement.
Ce que ça casse : Rien. Mais l'écran imposé « Choisis ton mot de passe » est un simple message affiché une fois, le code e-mail ouvre une session complète, et la composition imposée est majuscule + minuscule + chiffre.
Avis : La sécurité est bien faite. Sur la composition, je t'avais conseillé d'accepter la règle de Romain : je maintiens.
Proposition : Accepter la règle de composition. Ajouter l'écran qu'on ne peut pas contourner pour les comptes sans mot de passe.
Preuves : [[route]].js:62-72, 1559 ; app.js:10478 ; 80fab682
Ce qui a changé : Nouvelle vue « Mot de passe ».
Ce que ça casse : Ta protection des formulaires en cours ne connaît pas cette vue : en revenant de la messagerie, les champs sont vides.
Avis : Le même piège que tu avais déjà réglé pour le code de récupération.
Proposition : Ajouter la vue à la liste protégée (une ligne).
Preuves : app.js:10468
Ce qui a changé : Nouvelles clés de compteur pour les mots de passe.
Ce que ça casse : La remise à zéro vise encore l'ancienne clé.
Avis : Quelqu'un qui s'est bloqué puis réinitialise par e-mail peut rester bloqué jusqu'à 15 minutes.
Proposition : Remettre à zéro les bonnes clés.
Preuves : [[route]].js:1556, 1832
Ce qui a changé : Nouvel e-mail d'alerte à chaque connexion par mot de passe.
Ce que ça casse : Il conseille de « régénérer ton code de récupération », une fonction qui n'existe plus.
Avis : Mineur.
Proposition : Retirer la phrase.
Preuves : [[route]].js:495
Ce qui a changé : Le code TRK ne connecte plus et ne se régénère plus.
Ce que ça casse : La connexion par code, comme tu l'as demandé le 17/10.
Avis : Conforme à ta fiche. Les comptes créés avant le 25/07 sans e-mail n'ont plus aucun moyen d'entrer.
Proposition : Compter ces comptes en lecture seule pour savoir de combien on parle.
Preuves : 73ad0ad9, ef93abcf
Ce qui a changé : Amis et Discussions fusionnés, rangée « Tes amis », bloc « À traiter », bouton d'ajout en haut à droite.
Ce que ça casse : Le menu du « + » et les pastilles hors ligne.
Avis : Ton correctif v580 (accepter une demande ne la supprime plus) est intact.
Proposition : Garder.
Preuves : 39ff8cb1 à 7cbe2fa6
Aucune de tes protections n'a été affaiblie. Plusieurs ajouts sont bons mais attendent leurs secrets.
Ce qui a changé : Une CSP complète remplace le simple frame-ancestors.
Ce que ça casse : Rien.
Avis : L'audit pensait qu'elle n'atteignait pas la page de l'app. J'ai lu les en-têtes en ligne : sur l'aperçu, la page reçoit bien la CSP complète.
Proposition : Garder. Elle arrivera sur trinke.app avec la mise en ligne.
Preuves : public/_headers:11 ; en-tête lu sur apercu.jeu-soiree.pages.dev le 20/10
Ce qui a changé : Anti-robot Turnstile, poivre des mots de passe, ticket du direct.
Ce que ça casse : Rien.
Avis : Sans leur secret, chacune revient sans bruit à l'ancien comportement. Le poivre doit être sauvegardé hors de Cloudflare avant d'être posé, sinon les mots de passe sont perdus.
Proposition : Vérifier dans Cloudflare quels secrets sont posés. Je te prépare les commandes, tu les lances.
Preuves : TURNSTILE_SITE, TURNSTILE_SECRET, MDP_POIVRE, LIVE_SECRET
Ce qui a changé : Rien.
Ce que ça casse : Rien : la moitié « téléphone » de la fiche du 08/09 n'a jamais été faite.
Avis : Pas une régression, mais l'app a pris 2 700 lignes et une erreur JavaScript chez un joueur ne laisse toujours aucune trace.
Proposition : Ajouter la remontée des erreurs du téléphone vers la table erreurs, avec un plafond.
Preuves : fiche echanges/2026-09-08-rien-ne-remonte-quand-l-app-casse.md
Ce qui a changé : Table erreurs, une ligne par route et par code avec un compteur.
Ce que ça casse : Le message d'erreur interne qui partait vers le téléphone.
Avis : Tes 5 conditions sont respectées. C'était une fuite d'informations.
Proposition : Garder. Vérifier que la table existe bien sur la vraie base.
Preuves : eac0acf0
Ce qui a changé : Le pseudo passe par un échappement dans le HTML des e-mails.
Ce que ça casse : La concaténation brute.
Avis : Corrige une injection de balisage qui existait chez toi.
Proposition : Garder.
Preuves : 424974df
Ce qui a changé : Romain peut commenter une carte depuis l'aperçu. Les avis sont stockés dans une table.
Ce que ça casse : Rien.
Avis : L'écriture ne demande aucune session, avec un plafond global de 60 par heure. La table vit dans la base des joueurs, sans purge.
Proposition : La déplacer dans la base d'aperçu séparée (fiche Déploiement).
Preuves : 8adaf031, [[route]].js:1374
Le paiement est codé et fermé tant que les clés ne sont pas posées.
Ce qui a changé : Une phrase sur la page Stripe : « en payant, tu renonces à ton droit de rétractation ».
Ce que ça casse : La case à cocher obligatoire, vérifiée par le serveur.
Avis : Le code reconnaît lui-même le risque : une renonciation sans case peut être jugée non expresse, et un acheteur pourrait se faire rembourser après avoir joué. À faire confirmer par un juriste.
Proposition : Remettre la case.
Preuves : e954d096, app.js:18831
Ce qui a changé : Rien depuis le 16/10.
Ce que ça casse : Rien. C'était ta condition n° 4 avant d'ouvrir le paiement.
Avis : Aucun commit ne touche ce code depuis. Probablement pas corrigé (déduit du code, pas testé).
Proposition : Le corriger et le tester avant de poser les clés Stripe.
Preuves : app.js:15773-15777
Ce qui a changé : Boutique, Pass VIP (3 € par mois ou 15 € à vie), cadenas sur 10 mini-jeux, 2 ambiances et les cartes du Pass.
Ce que ça casse : La gratuité de ces contenus, le jour où les clés seront posées. Aujourd'hui tout reste ouvert.
Avis : Les cartes payantes sont dans des fichiers publics, le verrou n'est que dans le téléphone. Le code le dit. Vendable quand même, mais en connaissance de cause.
Proposition : Accepter tel quel pour le lancement. Servir les cartes payantes par le serveur plus tard si ça marche.
Preuves : app.js:254-269
Ce qui a changé : Textes légaux réécrits pour le compte obligatoire et le Pass VIP.
Ce que ça casse : Ils parlent encore du code de secours, pas du mot de passe, et ne nomment ni Turnstile ni la vérification des mots de passe fuités. L'écran de suppression de compte ne prévient pas qu'un Pass à vie sera perdu.
Avis : C'est du texte que tu voulais relire toi-même.
Proposition : Je rédige les nouveaux paragraphes, tu les relis avant qu'ils partent.
Preuves : legal/index.html:54, app.js:12513, 12725
Ce qui a changé : Page CGV en 14 articles, vendeur = la micro-entreprise de Romain.
Ce que ça casse : Rien. L'éditeur des mentions légales est vide depuis le début.
Avis : L'argent arrive sur le SIRET de Romain. Rien d'écrit dans le dépôt sur le partage. Un vendeur identifié et un éditeur inconnu, c'est incohérent.
Proposition : Remplir l'éditeur et mettre par écrit entre vous deux qui encaisse et comment c'est partagé.
Preuves : ff1fc7db, public/legal/cgv/index.html
Ce qui a changé : Signature du webhook vérifiée, paiement rejoué sans double accès, accès décidé par le serveur, achats de test séparés, abonnement résilié avant suppression du compte, paiement bloqué tant que le médiateur manque.
Ce que ça casse : Rien.
Avis : Bien fait. Petits défauts : deux e-mails de confirmation possibles, contestations bancaires non traitées.
Proposition : Garder.
Preuves : 56b0ff32 à a8bc474d
Ce qui a changé : Porte d'âge redessinée.
Ce que ça casse : Rien : le texte « 18+, l'abus d'alcool est dangereux » et la vérification de l'âge par le serveur sont intacts.
Avis : Le mode sans alcool a même été renforcé dans la Course des As.
Proposition : Garder.
Preuves : 592da25e, bb530c54
Accueil refait, onglets changés, plusieurs écrans retirés.
Ce qui a changé : Nouvel accueil « menu verre ».
Ce que ça casse : Le bouton de compte en haut à droite. Son remplaçant existe mais n'est jamais affiché. Il ne reste que l'onglet du bas.
Avis : C'était une de tes 4 règles des comptes.
Proposition : Remettre le bouton en haut à droite sur le nouvel accueil.
Preuves : style.css:9422, 9268
Ce qui a changé : Une maquette dessinée à 941 px, réduite à la taille de l'écran.
Ce que ça casse : L'ancien accueil, caché.
Avis : Sur un téléphone de 390 px, certains textes tombent vers 10 px (8,5 px sur iPhone SE), et « Grand texte » n'y fait rien. La feuille de style est passée de 17 à 400 !important : chaque retouche s'est empilée.
Proposition : Mesurer sur un vrai iPhone. Puis rendre l'accueil lisible et nettoyer les surcharges du bouton « Lancer une Soirée ».
Preuves : style.css:9420, 9163 ; 2c8c94bf
Ce qui a changé : On peut sortir d'une partie puis la reprendre.
Ce que ça casse : Ta règle « rien n'est acquis avant la dernière manche » : les manches d'avant la pause sont retirées des stats, celles d'après comptent même si on abandonne.
Avis : Déduit du code, pas joué.
Proposition : Rouvrir le journal de la partie à la reprise.
Preuves : app.js:1528, 2181 ; 0c49f78a, e32444d6
Ce qui a changé : L'app est plus légère.
Ce que ça casse : L'écran avatar, ses moteurs 2D et 3D, environ 3 200 images. Tout est archivé sur une branche.
Avis : Défendable avant un lancement. Rien n'est perdu.
Proposition : Laisser retiré pour le lancement. On le remet plus tard si tu veux.
Preuves : d20860b8, origin/archive/avatar
Ce qui a changé : L'onglet Classement est caché.
Ce que ça casse : Le classement « parmi tous les joueurs ». Le classement entre amis reste dans le Compte.
Avis : Environ 300 lignes de code mort.
Proposition : Dis si tu le veux encore. Sinon je retire le code mort.
Preuves : index.html:1214, 26aef0ff
Ce qui a changé : Une seule direction artistique, sombre.
Ce que ça casse : L'interrupteur, et la préférence des joueurs est effacée sans message.
Avis : Défendable, une seule DA à maintenir. « Grand texte » est conservé.
Proposition : Laisser comme ça.
Preuves : ea07fab1
Ce qui a changé : Le public est forcé à « Entre potes ».
Ce que ça casse : Les deux rangées de réglages. Le code reste, endormi.
Avis : L'argument se tient : ces options n'avaient presque pas de cartes. La fiche « lancer une Soirée en un geste » n'est qu'en partie appliquée.
Proposition : Laisser retiré tant qu'il n'y a pas assez de cartes famille et couple.
Preuves : 3d773607 (v970)
Ce qui a changé : Classement, Amis et Boutique entrent dans la pile du retour. Question avant de perdre une partie. Fenêtres fermées par le geste retour.
Ce que ça casse : Rien.
Avis : De vrais défauts corrigés à la racine.
Proposition : Garder. À essayer sur un Android installé.
Preuves : 8b53e829, c8ef3a0f, 5f8b0cd6
Ce qui a changé : Banc de tailles d'écran, la barre du bas ne recouvre plus « Jouer », Boutique sur 320 px.
Ce que ça casse : Rien.
Avis : Corrigé et outillé. Aucun champ sous 16 px, donc pas de zoom iOS.
Proposition : Garder.
Preuves : 068a3001, eb0be629
Ce qui a changé : Nouveau menu de partie.
Ce que ça casse : « Terminer la partie » est violet au lieu de rouge (ta règle 5). Une consigne mélange « vous » et « tu ».
Avis : Mineur.
Proposition : Corriger les deux.
Preuves : index.html:1435, 667
Le schéma est à jour. Le risque vient de l'aperçu qui écrit dans la vraie base.
Ce qui a changé : Lecture du droit d'accès payant à chaque ouverture.
Ce que ça casse : Rien.
Avis : Deux requêtes identiques sur la route la plus appelée. Et la migration des achats se marque faite même si elle a échoué.
Proposition : Une seule lecture, et la migration ne se marque faite qu'après succès.
Preuves : [[route]].js:1905, 1907, 1074-1087
Ce qui a changé : Nouvelles clés de compteurs (source, identifiant, alerte) et table des avis de l'aperçu.
Ce que ça casse : Rien.
Avis : La table des essais n'a pas de purge générale et garde une empreinte d'IP. Le défaut existait chez toi, il s'aggrave.
Proposition : Ajouter une purge des lignes de plus de 30 jours au ménage périodique.
Preuves : [[route]].js:1023-1033
Ce qui a changé : 4 colonnes et 2 tables ajoutées, toutes reportées dans schema.sql.
Ce que ça casse : Deux index en double, retirés avec leur raison.
Avis : Les 295 requêtes du serveur se préparent toutes sur une base créée depuis schema.sql.
Proposition : Garder.
Preuves : schema.sql ; check-sql.js
[vraie] La porte de deploiement compte 19 bancs sans navigateur et 12 bancs navigateur, et ils passent.
ECHANGES-ROMAIN.md:24 · 08/09
deploy.sh au commit 668ae6d3 (dernier etat avant l'entree) : 19 bancs node/python distincts et 12 appels banc_chromium distincts (comptage grep). Les durees (7 s, 2 min 40) ont ete mesurees sur la machine de Romain : non reproductibles d'ici.
Le constat de depart sur la porte de Theo est exact.
[exageree] Aucune commande n'a touche a la base trinke-db pendant l'audit.
ECHANGES-ROMAIN.md:25 · 08/09
Le meme Claude ecrit le meme jour (ECHANGES-ROMAIN.md:388-390) qu'il avait lance `npx wrangler d1 execute trinke-db --local --file=schema.sql` quelques heures avant l'issue. C'etait une copie LOCALE : la base de production n'a pas ete touchee, mais la commande n'avait pas ete dite.
Aucun risque pour la vraie base, mais le compte rendu initial omettait une commande wrangler, revelee seulement quand Theo a trouve sa trace.
[vraie] app.js est propre : 116 ecouteurs poses, 5 retires, aucun innerHTML +=.
ECHANGES-ROMAIN.md:29 · 08/09
668ae6d3:public/app.js : 116 addEventListener hors commentaires (122 avec), 5 removeEventListener, 0 `innerHTML +=`.
Jugement favorable sur le code de Theo, exact.
[vraie] L'API n'injecte jamais une valeur recue dans une requete SQL.
ECHANGES-ROMAIN.md:32 · 08/09
668ae6d3:functions/api/[[route]].js : toutes les interpolations `${...}` dans le SQL sont des marqueurs `?` generes (l.272, 1799-1800, 2557), des fragments constants (CL_SOURCE) ou une expression tiree d'une liste blanche (EXPR[cle], l.1651). Seul `"ALTER TABLE " + t` (l.95) concatene, sur une liste fixe [users, inscriptions].
Pas d'injection SQL a craindre a cette date.
[exageree] Le blocage entre deux comptes fonctionne dans les deux sens cote serveur.
ECHANGES-ROMAIN.md:33 · 08/09
Vrai pour les fils directs (estBloque, l.550-560). Faux pour les groupes : l'audit Codex (H-05, H-06) montre que deux personnes bloquees continuent de s'ecrire dans un groupe ; le Claude de Romain le reconnait lui-meme le soir meme (ECHANGES-ROMAIN.md:845-847).
Une promesse de la page legale n'etait pas tenue ; l'erreur a ete corrigee par son auteur le jour meme.
[vraie] Les tables blocages et signalements ne sont decrites nulle part dans le depot.
ECHANGES-ROMAIN.md:42 · 08/09
668ae6d3:schema.sql : 0 occurrence ; API l.556, 2122, 2141, 2151, 2160. `git log --all -S'CREATE TABLE IF NOT EXISTS blocages'` : premiere apparition 2cd3974d (Theo, 08/09 17:03, apres la question). 453 commits a 668ae6d3, tous de Arand.
Vraie trouvaille : elle a conduit Theo a recopier les deux tables de la production dans schema.sql.
[perimee] Si la table blocages manque, le blocage cesse de marcher sans aucun signal.
ECHANGES-ROMAIN.md:46 · 08/09
Exact a la date : 668ae6d3 [[route]].js:552-560, `catch (e) { return false; }`. Corrige depuis par 8fe8af4c (19/09) : table absente = erreur, base indisponible = repli trace (rapport-multijoueur A4, rapport-securite G15).
Le defaut decrit etait reel et il est corrige.
[vraie] batch() est deja utilise six fois dans l'API.
ECHANGES-ROMAIN.md:71 · 08/09
grep -n 'DB.batch' sur 668ae6d3 : exactement les lignes 541, 2140, 2247, 2383, 2705, 3069.
Chiffres exacts a la ligne pres.
[exageree] La lecture d'une conversation fait 9 a 12 appels a la base et est interrogee toutes les 800 ms.
ECHANGES-ROMAIN.md:76 · 08/09
Le nombre d'appels est plausible (session, filOuvert, purge, DELETE frappe, puis 4 SELECT : l.2396-2462). Mais muCadence (app.js:12638-12642) ne sonde a 800 ms que si l'utilisateur a bouge dans les 20 dernieres secondes ; sinon 1,5 s, 3 s, et 4 s ecran eteint.
Le cout D1 reel est plus bas que ce que suggere « toutes les 800 ms ».
[exageree] Enregistrer une partie coute jusqu'a 71 appels a la base.
ECHANGES-ROMAIN.md:77 · 08/09
Le meme Claude se corrige le soir meme (ECHANGES-ROMAIN.md:890-900) : 11 badges et non 22, un appel par joueur et non deux, « le pire cas reel est d'environ 37 appels ».
Le chiffre de 71 a nourri une fausse alerte (voir er1-45) ; il est retire par son auteur.
[vraie] Supprimer 100 messages coute 300 a 600 appels a la base.
ECHANGES-ROMAIN.md:78 · 08/09
668ae6d3 [[route]].js:2495-2516 : jusqu'a 100 ids, et pour chacun un SELECT, un filOuvert (2 a 3 requetes), puis 1 a 3 ecritures.
Ordre de grandeur juste.
[perimee] Le menage des indicateurs de frappe tourne a chaque lecture de conversation.
ECHANGES-ROMAIN.md:82 · 08/09
Exact a la date (668ae6d3 l.2433 et l.2645). Corrige par Romain le 09/09 (90218970 « Le menage des indicateurs de frappe passe au rythme de menageDu »).
Constat juste, correction faite.
[perimee] La table parties n'a pas d'index pour ses filtres frequents.
ECHANGES-ROMAIN.md:93 · 08/09
Exact a la date (668ae6d3 schema.sql:53-62 ; filtres l.1258, 279, 1856, 1876, 1885). Index ajoutes dans schema.sql par e0c193d9 (09/09) et presents sur soiree-v2 (schema.sql:102-103). Leur pose en production etait un geste laisse a Theo : non verifiable d'ici (rapport-base, « A VERIFIER »).
Le correctif existe dans le fichier ; reste a savoir s'il a ete applique a la vraie base.
[exageree] Trois index sont inutiles, dont idx_devices_vu.
ECHANGES-ROMAIN.md:106 · 08/09
Vrai pour idx_essais_cle (essais.cle est deja la cle primaire) et idx_lj_live (prefixe de la cle (live_id,user_id)). Pour idx_devices_vu : aucune clause WHERE, mais un ORDER BY vu_le l.3034 ; le Claude de Romain le reconnait (ECHANGES-ROMAIN.md:936-940) et garde l'index (commit e0c193d9).
Sans la relecture de Theo, un index utile aurait pu etre supprime.
[vraie] CLAUDE.md pese 234 Ko dont 224 Ko de journal, soit environ 59 000 jetons a chaque session.
ECHANGES-ROMAIN.md:113 · 08/09
668ae6d3:CLAUDE.md = 239 820 octets (234 Kio) ; « ## Journal » ligne 154 ; 229 786 octets apres, 10 034 avant. Les 59 000 jetons sont une estimation (environ 4 caracteres par jeton), coherente.
Constat exact sur le cout de chargement.
[fausse] Le CLAUDE.md a ete ecrit la veille.
ECHANGES-ROMAIN.md:121 · 08/09
La section « A lire avant de toucher au code » est datee du 08/09 (commit 2cd069ee, 08/09 13:42, le jour meme) ; le reste du fichier et son journal remontent a juillet-aout.
Detail sans effet sur les decisions.
[perimee] L'app interroge le serveur toutes les 2 minutes meme ecran eteint.
ECHANGES-ROMAIN.md:126 · 08/09
Exact a la date : 668ae6d3 app.js:1961 (fetch), 1985-1991 (verifie sans garde), 1996 (setInterval). Corrige par Romain le 09/09 (c39d30c8 « La verification de version se tait ecran eteint »).
Constat juste, correction faite.
[vraie] Une minuterie du Doigt du destin echappe au registre, et la lecture window[...] ne marche jamais.
ECHANGES-ROMAIN.md:132 · 08/09
668ae6d3 app.js:5163 et 1020-1050 : fRefusTimer absent ; l.1022-1024 lisent window[n] alors que les variables sont dans l'IIFE ouverte l.2. Nuance : les l.1025-1046 nettoient deja ces memes minuteries par leur nom, donc la ligne window[] est du code mort, pas une fuite.
Constat exact et justement qualifie de mineur.
[vraie] Les quatre scripts sont en fin de page, ajouter defer ne gagnerait presque rien.
ECHANGES-ROMAIN.md:142 · 08/09
668ae6d3 public/index.html:1142, 1149, 1150, 1151 ; </body> ligne 1152.
Evite une fausse optimisation.
[vraie] verif.js compte 19 739 controles bloquants.
ECHANGES-ROMAIN.md:179 · 08/09
Chiffre repris tel quel du README de Theo (668ae6d3 README.md:117), non recompte par le Claude de Romain ni ici. Duree mesuree sur sa machine : invérifiable d'ici.
Le chiffre vient de Theo lui-meme.
[vraie] Les bancs testent le vrai code et les bancs instables ont ete sortis de la porte avec leur raison.
ECHANGES-ROMAIN.md:183 · 08/09
outils/test-geste-heures.js, test-bareme-cercle.js, test-chacun-son-tour.js lisent app.js ; deploy.sh:88-102 documente le retrait de test-app-crie.py et test-ecran-amis.py.
Jugement favorable exact.
[vraie] Aucune verification automatique ne tourne sur GitHub ; tout depend de la machine qui deploie.
ECHANGES-ROMAIN.md:200 · 08/09
Aucun dossier .github a 668ae6d3 ni sur origin/soiree-v2 aujourd'hui. Les bancs Chromium sont sautes avec un simple avertissement (deploy.sh:150-152).
Toujours vrai aujourd'hui : ce risque reste ouvert.
[vraie] Aucune procedure de retour arriere n'est ecrite.
ECHANGES-ROMAIN.md:209 · 08/09
Aucune mention dans DEMARRER.md ni README.md a 668ae6d3, ni dans DEMARRER.md de origin/soiree-v2 (grep retour arriere / redescend). La regle v562 plutot que v558 existe bien dans le journal (CLAUDE.md:1878).
Toujours vrai aujourd'hui : le soir d'une panne, la procedure n'est nulle part.
[vraie] D1 garde 7 jours d'historique restaurable gratuitement, et ce n'est documente nulle part dans le depot.
ECHANGES-ROMAIN.md:216 · 08/09
Aucune mention de « time travel » dans CLAUDE.md ni DEMARRER.md (668ae6d3, soiree-v2). La duree de 7 jours en offre gratuite correspond a la documentation Cloudflare telle que connue, non revérifiée en ligne pendant cet audit.
Un filet de securite existe sans etre documente ni essaye.
[vraie] Theo a ecrit les 453 commits ; la protection de branche a ete tranchee le 07/09.
ECHANGES-ROMAIN.md:227 · 08/09
git log 668ae6d3 : 453 commits, auteur Arand pour les 453. CLAUDE.md:34 « Ne propose pas non plus la protection de branche GitHub : vérifié le 07/09/2026 ».
Exact.
[vraie] L'audit a couvert les deux tiers du code ; style.css, avatars, serveur temps reel et contenu n'ont pas ete lus.
ECHANGES-ROMAIN.md:270 · 08/09
668ae6d3 : app.js 17 207 + API 3 119 = 20 326 lignes ; style.css 9 260, avatar.js+avatar3d.js 1 592, live/src/index.js 220 (total environ 31 400). 391 cartes et 1 053 items = README.md:125-126.
Les limites de l'audit sont honnetement declarees.
[vraie] Aucun outil ne verifie verif.js lui-meme.
ECHANGES-ROMAIN.md:290 · 08/09
668ae6d3 verif.js = 8 533 lignes ; entre 450 et 479 identifiants distincts selon la methode d'extraction ; seul outils/qr.py cite verif.js, sans le tester. Le tirage mensuel de 30 controles propose (l.343, 564) n'apparait nulle part ensuite dans le depot.
Toujours vrai : le taux de faux negatifs de la porte reste inconnu, et la parade proposee n'a jamais ete appliquee.
[vraie] Le journal de Theo cite cinq controles reecrits pour ce motif.
ECHANGES-ROMAIN.md:294 · 08/09
668ae6d3 CLAUDE.md : GD-18 (4 mentions), MJX-05 (3), POINTS-21 (3), SO-05 (2), CSS-03 (1).
Exact, les references existent.
[vraie] La fonction renderCompte fait 2 147 lignes.
ECHANGES-ROMAIN.md:323 · 08/09
668ae6d3 app.js : renderCompte commence l.9018, la fonction suivante (montreCode) l.11165 : 2 147 lignes, 12,5 % de 17 207.
Exact.
[vraie] Personne ne mesure le code jamais execute ; renderCompte a des branches inatteignables (9170-9218).
ECHANGES-ROMAIN.md:348 · 08/09
Aucun outil de couverture a 668ae6d3 ni sur soiree-v2 (outils/). app.js:9170-9218 : les cas legal, raz, raz2, bloques, confid, conditions sont testes deux fois dans la meme chaine ternaire ; les seconds ne sont jamais atteints. « 90 étapes » vient du README:105.
Exact ; la mesure proposee (point 2) n'a jamais ete ecrite.
[vraie] Le banc une-regle-un-endroit ne couvre que les comparaisons de pseudo.
ECHANGES-ROMAIN.md:360 · 08/09
668ae6d3 outils/test-une-regle-un-endroit.py:15-22 : le banc tranche sur les comparaisons de prenom/pseudo et liste le reste sans l'accuser.
Exact.
[inverifiable] La base locale trouvee par Theo etait un artefact laisse par le Claude de Romain.
ECHANGES-ROMAIN.md:387 · 08/09
Concerne le disque de la machine de Romain (.wrangler/ est ignore par git, .gitignore:19-20). Coherent avec Theo (ECHANGES-THEO a d3dc19e3:137 : 21 tables, 278 Ko).
Aucune.
[perimee] La base de production n'a aucune copie.
ECHANGES-ROMAIN.md:439 · 08/09
Vrai a 17:34 le 08/09. Theo fait une sauvegarde chiffree a 18:38 (875c889d, verifiee 01761fff). Aujourd'hui : cette sauvegarde du 08/09 est la seule et n'a jamais ete refaite (rapport-base point 3, G15).
Le constat a declenche une vraie sauvegarde, mais elle date de six semaines et ne couvre pas les donnees ajoutees depuis.
[exageree] Sauvegarder la base est une simple lecture sans effet.
ECHANGES-ROMAIN.md:443 · 08/09
Theo mesure le soir meme que l'export exige le droit D1 Edit (un jeton Read recoit 403) et rend la base indisponible pendant qu'il tourne ; le Claude de Romain le reconnait (ECHANGES-ROMAIN.md:774-778).
Corrige le jour meme ; a retenir pour toute prochaine sauvegarde (la faire hors soiree).
[inverifiable] Le quota D1 est partage avec deux autres projets du meme compte Cloudflare.
ECHANGES-ROMAIN.md:447 · 08/09
Le contenu du compte Cloudflare ne se lit pas hors reseau. Le Claude de Romain reprend ici une information venue du cote Theo, sans la constater lui-meme.
A confirmer avant d'en tirer une priorite.
[vraie] Les trois scripts de deploiement telechargent la derniere version de wrangler, avec le jeton Cloudflare dans l'environnement.
ECHANGES-ROMAIN.md:456 · 08/09
668ae6d3 deploy.sh:290, apercu.sh:24, live/deploie-live.sh:28 ; aucun package.json. Toujours vrai sur origin/soiree-v2 (deploy.sh:253) ; deja releve par le premier audit (rapport-outillage).
Risque de chaine d'approvisionnement toujours ouvert.
[vraie] Rien n'empeche verif.js de perdre des controles en silence.
ECHANGES-ROMAIN.md:460 · 08/09
668ae6d3 verif.js : affiche `controles` (fin du fichier) sans plancher ; aucun plancher de total sur soiree-v2 non plus.
Toujours vrai : un controle supprime passe inapercu (le premier audit a vu le plancher de contenu relu baisser de 247 a 45).
[vraie] deploy.sh met en ligne le disque tel quel, sans verifier l'etat git.
ECHANGES-ROMAIN.md:464 · 08/09
668ae6d3 deploy.sh : aucune commande git, l.290 `--commit-dirty=true` ; DEMARRER.md:146 « le vrai risque à deux, et aucun outil ne l'attrape ». Toujours vrai sur soiree-v2 (deploy.sh:253).
Du code non commite peut toujours partir en production.
[vraie] Le jeton de deploiement n'a pas besoin du droit D1 Edit.
ECHANGES-ROMAIN.md:467 · 08/09
668ae6d3 deploy.sh : aucune commande d1. Nuance ajoutee par l'auteur le soir meme (l.777-778) : la sauvegarde, elle, exige D1 Edit, donc deux jetons distincts.
Recommandation juste a condition de garder un jeton separe pour la sauvegarde.
[vraie] Une attaque npm d'aout 2025 a detourne des assistants de code installes en mode sans confirmation.
ECHANGES-ROMAIN.md:476 · 08/09
Correspond a l'attaque « s1ngularity » contre les paquets Nx (fin aout 2025), telle que decrite dans les rapports publics de l'epoque ; chiffres repris de memoire, non revérifiés en ligne pendant cet audit (pas de reseau).
Le risque decrit (assistant sans garde-fou + npx non epingle) est reel.
[exageree] 446 Ko d'instructions sont charges a chaque session et la porte n'en protege aucun.
ECHANGES-ROMAIN.md:491 · 08/09
Vrai : verif.js ne lit aucun de ces fichiers. Mais seul CLAUDE.md (240 Ko) est charge automatiquement ; TRINKE.md (163 Ko), les agents (18 Ko) et les skills (16 Ko) sont lus a la demande. Total mesure : 436 Ko, pas 446.
Le constat de fond tient, le volume « charge a chaque session » est surestime.
[exageree] Deux controles UI-29 ne testent pas la regle qu'ils annoncent.
ECHANGES-ROMAIN.md:538 · 08/09
668ae6d3 verif.js:1048-1049 : motifs exacts tels que cites. Mais le controle voisin l.1051 (« plus aucun plafond de trinqueurs ecrit en dur », negatif) couvre en partie l'unicite ; l'echantillon ne le mentionne pas. Une seule constante PLAFOND_J dans app.js (l.183).
La critique de methode est juste, le trou reel est plus petit qu'annonce.
[vraie] Le controle GD-12 repose sur un commentaire du code.
ECHANGES-ROMAIN.md:548 · 08/09
668ae6d3 verif.js:824 motif `noteUnePartieDeSoiree\(\);\s*\/\/ GD-12 : la partie se termine` ; app.js:4483 porte exactement ce commentaire.
Exact : ce controle ne verifie pas le contenu de la fonction.
[vraie] Les six issues GitHub ont ete recopiees en fiches dans le depot et fermees.
ECHANGES-ROMAIN.md:593 · 08/09
b62bf9b1 : six fiches du cote Romain dans echanges/ (appel-reseau, deux-index, base-exemplaire, catch-estbloque, cout-d1, rien-ne-remonte ; l'issue bac a sable, retiree, est remplacee par la fiche sauvegarde). La fermeture sur GitHub n'est pas verifiable hors reseau.
Promesse tenue pour la partie visible dans le depot.
[fausse] Une partie a 14 joueurs ne peut pas s'enregistrer car elle depasse 50 appels a la base.
ECHANGES-ROMAIN.md:594 · 08/09
Retracte par son auteur le soir meme (ECHANGES-ROMAIN.md:870-901) : les appels D1 relevent de la limite de 1 000 sous-requetes internes, 11 badges et non 22, un appel par joueur ; « La partie de quatorze trinqueurs qui ne s'enregistre pas n'existe pas ». C'est Theo qui l'a refutee.
Fausse alerte presentee a Romain comme l'urgence du jour, refutee avant toute decision.
[vraie] Le code n'a pas les marqueurs classiques d'amateurisme.
ECHANGES-ROMAIN.md:610 · 08/09
668ae6d3 : 0 console.log dans app.js et l'API ; 15 !important hors commentaires (17 avec) ; un seul `==` lache. Petits ecarts sans effet : 0 TODO trouve (et non 3).
Jugement favorable exact.
[exageree] Aucun secret n'a jamais ete commite et le .gitignore protege depuis le debut.
ECHANGES-ROMAIN.md:615 · 08/09
Recherche refaite (git log --all -p -G sur les motifs de jetons GitHub, Stripe, AWS, cles privees, affectations de SECRET/TOKEN) jusqu'au 08/09 18:31 : aucun resultat. Mais le .gitignore n'existe que depuis le 07/09 (b08f693e), pas depuis le premier commit du 27/07.
La conclusion (pas de secret) tient ; « depuis le debut » est faux.
[vraie] Aucune fonction de tri n'est ecrite de facon defectueuse.
ECHANGES-ROMAIN.md:619 · 08/09
grep des `.sort(function(a,b){ return ... < / > ...})` sans ternaire dans 668ae6d3 app.js : aucun resultat.
Exact.
[exageree] Toutes les ecoutes tactiles declarent leur mode passif, et Safari est le seul navigateur ou touchmove du document n'est pas passif par defaut.
ECHANGES-ROMAIN.md:621 · 08/09
668ae6d3 app.js : 19 ecoutes tactiles, 11 declarent passive ; 8 touchend/touchcancel non (l.12377-12378, 14261-14262, 14503-14504, 14667-14668), ce qui est sans effet sur le defilement. L'affirmation sur Safari contredit ce que je sais (WebKit aurait rendu ces ecouteurs passifs par defaut depuis iOS 11.3) : non verifiee en ligne.
Sans consequence pratique, mais le compte et la justification sont inexacts.
[vraie] Aucune ecriture en base n'est lancee sans etre attendue.
ECHANGES-ROMAIN.md:623 · 08/09
Recherche heuristique des env.DB.prepare non precedes de await/return/( /[/,/= dans l'API 668ae6d3 : 5 cas, tous dans un tableau batch() (l.3084-3093) ou une fonction flechee retournee (l.751).
Exact a la precision d'une recherche automatique.
[vraie] 153 catch vides sur 275, zero let, trois 100vh en cascade : ce sont des choix, pas des fautes.
ECHANGES-ROMAIN.md:635 · 08/09
668ae6d3 app.js : 153 catch vides sur 277 ; 0 let, 0 const ; style.css:47 et 60 : 100vh puis 100svh puis 100dvh. (Le nombre de var differe selon le mode de comptage.)
Exact, et l'auto-correction est honnete.
[exageree] Une propriete CSS obsolete casse en silence les z-index sur iPhone.
ECHANGES-ROMAIN.md:645 · 08/09
Les quatre lignes sont exactes (668ae6d3). La propriete cree un contexte d'empilement selon WebKit (Safari 13), mais aucun defaut d'affichage reel n'est montre ; « cela casse silencieusement » est une deduction. Encore 3 occurrences sur soiree-v2.
Nettoyage sans risque, pas un bug avere.
[exageree] Une seule ligne @ts-check suffirait a signaler tout acces non garde a un element absent.
ECHANGES-ROMAIN.md:681 · 08/09
Deduit de TypeScript tel que connu : les acces possiblement null ne sont signales qu'avec strictNullChecks (fichier jsconfig ou tsconfig), que `// @ts-check` seul n'active pas. Non verifie en ligne.
Si on essaie, il faudra plus qu'une ligne.
[vraie] Ni le RGAA ni la directive europeenne sur l'accessibilite ne s'appliquent a Trinke.
ECHANGES-ROMAIN.md:719 · 08/09
Deduit, sous reserve : le RGAA vise les organismes publics et les grandes entreprises ; la directive europeenne exempte les microentreprises de services. Non revérifie en ligne ; la boutique ajoutee depuis (v963) ne change pas la taille de l'entreprise.
Pas d'obligation probable, mais c'est une lecture juridique non verifiee par un professionnel.
[vraie] Les criteres 2.5.7 et 2.5.8 sont dans WCAG 2.2 et absents du RGAA (base 2.1).
ECHANGES-ROMAIN.md:723 · 08/09
Conforme a WCAG 2.2 (2.5.7 Dragging Movements, 2.5.8 Target Size Minimum, 24 px) et au RGAA 4.1, fonde sur WCAG 2.1 ; connaissance non revérifiee en ligne.
Exact.
[vraie] Au moment du malentendu, le fil de Romain comptait 732 lignes et 9 entrées, toutes poussées sur GitHub.
ECHANGES-ROMAIN.md:744 · 08/09
git show b1f165ef:ECHANGES-ROMAIN.md : 732 lignes, 9 titres « ## 2026 ».
Le diagnostic « messages perdus » venait bien d'un décalage de lecture, pas d'une perte.
[vraie] Les six commits cités existent dans l'historique distant.
ECHANGES-ROMAIN.md:745 · 08/09
Les 5 empreintes résolvent (576e3a90, 11cdd617, b62bf9b1, 106ad5f0, b1f165ef, 08/09 17:34-18:30) et sont contenues dans origin/main et origin/soiree-v2 (git branch -r --contains).
Rien à faire.
[vraie] Les trois commits de Théo du 08/09 sont postérieurs au dernier commit de Romain, donc Théo avait les entrées dans son clone.
ECHANGES-ROMAIN.md:747 · 08/09
875c889d 18:38, 4e2d9cdf 19:23, 01761fff 19:30 (Arand) après b1f165ef 18:30. Le côté Théo l'a reconnu : commit c1596768 « Mon diagnostic du canal etait FAUX ».
Point clos, reconnu des deux côtés.
[inverifiable] Les six issues GitHub ont été fermées, chacune avec un commentaire de renvoi.
ECHANGES-ROMAIN.md:751 · 08/09
État des issues sur GitHub : lecture réseau interdite dans cet audit. Seul indice local : le commit b62bf9b1 s'intitule « ... et les six fermees ».
Sans effet sur une décision.
[vraie] L'audit Codex fait 663 lignes et porte sur la révision c159676.
ECHANGES-ROMAIN.md:795 · 08/09
git show e042b40f:AUDIT-CODEX-2026-09-08.md | wc -l = 663 ; ligne 5 : « Révision auditée : c15967688f74... ».
Le rapport Codex est bien dans le dépôt et lisible par Théo.
[vraie] Le relais de H-02 est exact : une partie à moitié enregistrée est ensuite déclarée « déjà traitée » et ne se répare jamais.
ECHANGES-ROMAIN.md:804 · 08/09
c159676 [[route]].js:1223-1224 (deja:true) puis INSERT parties en 1262-1266 avant joueurs et stats. Toujours identique dans origin/soiree-v2 : route-v2.js:2035-2036.
Le défaut le plus grave selon ce même Claude n'est toujours pas corrigé six semaines plus tard, y compris dans v1081.
[vraie] Le relais de H-05 est exact : un simple invité peut voir le groupe et y inviter des amis avant d'avoir accepté.
ECHANGES-ROMAIN.md:810 · 08/09
c159676 [[route]].js:2212-2214 et 2264-2266 sans statut='membre', alors que filOuvert l'exige (568-570). Inchangé dans origin/soiree-v2 : route-v2.js:3026-3028 et 3078-3080.
Trou d'autorisation connu depuis le 08/09 et toujours présent dans v1081.
[exageree] H-06 (le blocage ne vaut pas dans les groupes) ne serait pas un bug mais un simple écart de texte.
ECHANGES-ROMAIN.md:818 · 08/09
Codex classe H-06 en niveau élevé (« La promesse de blocage est fausse dans un groupe », AUDIT-CODEX l.218). La page légale promet toujours « il ne peut alors plus t'écrire » (origin/soiree-v2 public/legal/index.html:49) et estBloque n'est appelé que pour les fils directs et les demandes d'amis (route-v2.js:861, 2840).
Les joueurs lisent une promesse de protection que l'app ne tient pas, et la reformulation a pu faire passer ce point pour secondaire.
[vraie] Les e-mails HTML affichaient un bouton et un lien « undefined ».
ECHANGES-ROMAIN.md:826 · 08/09
c159676 [[route]].js:491-498 : le gabarit rend toujours ${bouton} et ${url}. Corrigé le 17/10 par a2bc828c (« e-mails sans bouton vide »).
Défaut réel resté en production environ 39 jours.
[vraie] Codex conclut que les 19 739 contrôles de verif.js ne prouvent pas que l'app est prête.
ECHANGES-ROMAIN.md:834 · 08/09
Citation exacte, AUDIT-CODEX l.524 et 548.
Une suite verte ne prouve pas l'absence des défauts H-01 à H-09 : à garder en tête devant tout « N contrôles passent ».
[vraie] Le banc test-atelier-limites.py mesure .av-bas, qui n'existe plus dans le produit.
ECHANGES-ROMAIN.md:839 · 08/09
git grep « av-bas » à c159676 : 1 occurrence dans outils/test-atelier-limites.py, 0 dans public/.
Banc mort à cette date ; il a depuis disparu avec l'avatar (02/10).
[vraie] L'app tourne déjà avec de vrais joueurs ; il faut prioriser les corrections plutôt que suspendre un lancement.
ECHANGES-ROMAIN.md:852 · 08/09
CLAUDE.md (df2cd405:20-23) : trinke-db contient les données de vraies personnes ; Théo mesurait 237 parties le 08/09.
L'argument a écarté la suspension, mais la priorisation promise n'a pas suivi : H-02, H-05 et H-06 sont toujours ouverts dans v1081.
[inverifiable] La limite de 50 sous-requêtes ne concerne pas les appels D1 (plafond de 1 000).
ECHANGES-ROMAIN.md:878 · 08/09
Repose sur la page des limites Cloudflare Workers ; lecture réseau interdite. Le Claude dit lui-même que seul un essai le prouverait.
Faible : la conclusion alarmante inverse a été retirée.
[vraie] Il y a 11 badges, pas 22.
ECHANGES-ROMAIN.md:890 · 08/09
46aa3e21:public/app.js:1780-1815 : premiere, habitue, pilier, chirurgien, statue, horloge, sobre, distrib, vainqueur, assidu, marathon (11 identifiants).
La correction de l'alerte fausse est juste.
[vraie] La liste d'amis n'est chargée qu'une fois par enregistrement de partie.
ECHANGES-ROMAIN.md:895 · 08/09
46aa3e21 [[route]].js:1285 : « if (mesAmis === null) { // ... chargee une seule fois ».
Rien à faire.
[vraie] Aucune requête ne filtre sur idx_devices_vu mais la ligne 3034 trie dessus.
ECHANGES-ROMAIN.md:938 · 08/09
46aa3e21 [[route]].js:3034 : « ... FROM devices WHERE user_id=? ORDER BY vu_le DESC LIMIT 50 ».
L'index a été gardé à raison (e0c193d9).
[vraie] La mise à jour automatique ne recharge jamais pendant une partie.
ECHANGES-ROMAIN.md:943 · 08/09
46aa3e21:public/app.js:1979-1981 : « if(momentDelicat())return; // ... (TE-08) ».
Rien à faire.
[inverifiable] Le dépôt faisait 34 Mo dont 32,7 Mo d'historique git.
ECHANGES-ROMAIN.md:960 · 08/09
Taille d'un clone à une date passée : non reconstructible en lecture seule (dépend de la compression du clone de Romain).
Faible : sert seulement à chiffrer le coût d'une sauvegarde dans git.
[vraie] Un fichier chiffré par GPG change entièrement à chaque chiffrement, donc git ne peut pas compresser les versions successives.
ECHANGES-ROMAIN.md:985 · 08/09
Propriété standard d'OpenPGP (clé de session aléatoire à chaque chiffrement). Non mesuré dans cet audit.
Confirme que sauvegarder la base chiffrée dans git coûte sa taille pleine à chaque fois.
[exageree] Perdre la base trinke-contributions ferait perdre la trace des 784 relectures, dont 537 d'une seule personne.
ECHANGES-ROMAIN.md:994 · 08/09
Les 784 relectures que compte verif.js viennent du registre versionné verification.json (t-04e10491/verif.js:197-210), pas de la base. Sortie rejouée : « 784/1444 [associe 537, theo 247] » : les 537 sont de Romain, alors que la base compte 190 envois signés « theo » (ECHANGES-THEO, 08/09). La phrase mélange deux personnes et deux sources.
L'urgence de cette sauvegarde était surestimée : le registre des relectures est déjà dans git.
[fausse] L'historique compte 453 commits de Théo contre 3 de Romain.
ECHANGES-ROMAIN.md:1064 · 08/09
git shortlog -sn 409b7f33 (le commit de l'entrée) : 468 Arand, 16 Romain Dalon ; avant l'ouverture du canal (3a915221^) : 453 Arand, 0 Romain.
L'ordre de grandeur (code écrit presque entièrement par Théo à cette date) reste juste, le chiffre ne l'est pas.
[inverifiable] En juillet 2025, l'agent de Replit a supprimé des données de production pendant un gel, et son dirigeant l'a reconnu publiquement.
ECHANGES-ROMAIN.md:1080 · 08/09
Fait externe ; réseau interdit dans cet audit. De mémoire (non vérifiée ici) l'incident SaaStr/Replit de juillet 2025 correspond à la description.
Sert d'argument pour séparer la base d'aperçu de la production, ce qui n'est toujours pas fait (wrangler.toml : un seul binding D1).
[inverifiable] Claude Code a eu deux failles corrigées permettant à un dépôt piégé de détourner l'assistant.
ECHANGES-ROMAIN.md:1093 · 08/09
Références externes ; réseau interdit dans cet audit.
Conseil de prudence générique, sans effet sur Trinke.
[vraie] Une conversation ouverte interroge le serveur toutes les 800 ms.
ECHANGES-ROMAIN.md:1103 · 08/09
409b7f33:public/app.js:12637 « var muRythme=800 ». Le nombre de 9 à 12 appels D1 par lecture n'a pas été recompté. purgeMessages tourne toujours à chaque chat/lire dans v2 (route-v2.js:3218).
Le coût D1 du chat reste le même dans v1081.
[inverifiable] Un Durable Object en hibernation ne facture pas de durée.
ECHANGES-ROMAIN.md:1109 · 08/09
Citation de documentation Cloudflare ; réseau interdit dans cet audit.
Piste d'architecture, rien d'engagé.
[inverifiable] Trinke n'a aucune obligation légale d'accessibilité (exemption microentreprise, art. L. 412-13 du code de la consommation) ; ne pas publier de déclaration.
ECHANGES-ROMAIN.md:1118 · 08/09
Textes juridiques et décision Arcom de juin 2026 non consultables hors réseau. Le Claude écrit lui-même que le sujet données personnelles « demande un avis professionnel ».
À ne pas tenir pour acquis sans vérification ; c'est un conseil juridique d'IA.
[vraie] La page légale indique encore « Éditeur : À renseigner ».
ECHANGES-ROMAIN.md:1132 · 08/09
409b7f33:public/legal/index.html:64. Toujours vrai dans origin/soiree-v2 (l.70) et origin/main (l.64), alors que v2 propose des offres payantes.
Vendre un abonnement avec un éditeur non renseigné expose Théo et Romain ; le sujet a été « mis de côté » le 09/09.
[inverifiable] Trusted Types est disponible dans les navigateurs depuis février 2026.
ECHANGES-ROMAIN.md:1144 · 08/09
Fait externe ; réseau interdit. Le Claude réserve lui-même le support Safari.
Sans effet.
[vraie] L'app compte environ 193 affectations innerHTML.
ECHANGES-ROMAIN.md:1145 · 08/09
409b7f33:public/app.js : 192 lignes « innerHTML = » (grep -c) ; le rapport sécurité en compte 193 à c4cefbc0 et 243 dans v2.
Le risque d'oubli d'échappement a grandi depuis (243).
[vraie] Trois fiches sont faites, commits c39d30c, e0c193d et 9021897.
ECHANGES-ROMAIN.md:1159 · 09/09
c39d30c8 (app.js, sw.js, test-app-tient.py), e0c193d9 (schema.sql seul), 90218970 ([[route]].js), tous du 09/09.
Rien à faire.
[vraie] verif.js rend 19 759 contrôles verts à v628.
ECHANGES-ROMAIN.md:1163 · 09/09
Rejoué hors réseau sur git archive 04e10491 : « ✓ 19757 controles passes (version soiree-v628) », sans les 2 contrôles qui exigent git. Théo a obtenu 19 759 au déploiement du 10/09 (ECHANGES-THEO).
Rien à faire.
[vraie] La version 628 est posée dans index.html et sw.js.
ECHANGES-ROMAIN.md:1164 · 09/09
04e10491:public/sw.js:1 « soiree-v628 » ; index.html : 5 occurrences « v=628 ».
Rien à faire.
[vraie] Trois gestes sont demandés à Théo (déployer, SQL sur trinke-db, vérifier les journaux), car lui seul en avait les accès.
ECHANGES-ROMAIN.md:1168 · 09/09
À cette date seul Théo déployait et accédait à la base. Gestes justifiés et faits le 10/09 (ECHANGES-THEO, entrée du 10/09).
Demandes légitimes.
[vraie] purgeMessages fait une écriture DELETE à chaque lecture de conversation.
ECHANGES-ROMAIN.md:1178 · 09/09
04e10491 [[route]].js:582 et appels 2448, 2604. Toujours ainsi dans v2 (route-v2.js:801, 3218, 3374) ; signalé deux fois (09/09, 19/09), jamais traité.
Coût D1 inutile qui persiste.
[inverifiable] Les Functions d'un projet Pages ne conservent pas de journaux ; seul le direct les montre.
ECHANGES-ROMAIN.md:1195 · 18/09
Citation de la documentation Cloudflare ; réseau interdit. Cohérent avec la mesure de Théo du 10/09 (aucun journal émis par jeu-soiree).
A justifié la table erreurs, acceptée par Théo.
[vraie] La table erreurs respecte les cinq conditions posées par Théo.
ECHANGES-ROMAIN.md:1232 · 19/09
Rapport sécurité G23 (5/5 dans le code). Rejoué sur fedf0561 : test-table-erreurs.js « 14 controles passes », test-estbloque-catch.js « 8 controles passes ».
Rien à faire.
[vraie] La table erreurs est plafonnée à 200 lignes, purgées une fois par jour.
ECHANGES-ROMAIN.md:1236 · 19/09
fedf0561 [[route]].js:600 « const ERREURS_MAX = 200; /* ... purge sous menageDu, une fois par jour */ ».
Rien à faire.
[vraie] Huit contrôles ERREURS dans verif.js et une garde dans deploy.sh.
ECHANGES-ROMAIN.md:1237 · 19/09
fedf0561:verif.js : ERREURS-01 à 08 ; deploy.sh:81-85 appelle test-table-erreurs.js et test-estbloque-catch.js.
Rien à faire.
[vraie] ERREURS-08 bloque le déploiement si VERSION_SERVEUR diffère de sw.js.
ECHANGES-ROMAIN.md:1243 · 19/09
fedf0561:verif.js:7874-7878 (doit(vSW === vAPI ...)).
Une troisième ligne de version à monter, que Théo devait connaître.
[vraie] Après correction, verif.js compte 19 770 contrôles.
ECHANGES-ROMAIN.md:1261 · 19/09
Rejoué sur 3d94b3df : « ✓ 19768 controles passes », sans les 2 contrôles git, soit 19 770. Le premier chiffre (19 778) avait été corrigé par l'auteur le jour même.
Rien à faire.
[inverifiable] La création de la table sur la base de production revient à Théo, et le serveur tolère son absence.
ECHANGES-ROMAIN.md:1238 · 19/09
Le code tolère l'absence (noteErreur sous try/catch). Création effective sur trinke-db non lisible sans accès à la base (rapport sécurité A2).
Si le geste n'a pas été fait, le journal d'erreurs est vide sans que rien ne le signale.
[fausse] La version 628, prête le 09/09, aurait attendu neuf jours sa mise en ligne.
ECHANGES-ROMAIN.md:1283 · 19/09
ECHANGES-THEO.md, entrée du 10/09 : « Déployé. bash deploy.sh ... 19 759 contrôles passés, v628 en ligne », le lendemain. Le Claude de Romain avait lu cette réponse le 18/09.
Le retard était dans la lecture côté Romain (10/09 → 18/09), pas dans le déploiement par Théo.
[exageree] Promesse : chaque entrée suivante commencera par « En une ligne » puis Fait / À toi / Bloqué / Question, que Théo suive ou non.
ECHANGES-ROMAIN.md:1315 · 19/09
Tenu dans les entrées 27/09, 28/09 (x2) et 28/09 soir (l.1333, 1359, 1376, 1397) ; abandonné dès le 29/09 (l.1420 et suivantes) et jusqu'au 17/10.
Les entrées longues sont revenues, ce qui rend le fil plus difficile à survoler pour Théo.
[vraie] main est passé de v628 à v711 en avance directe, sans commit de Théo à fusionner.
ECHANGES-ROMAIN.md:1333 · 27/09
b4f7cfd7:public/sw.js « soiree-v711 » ; aucun commit Arand entre le 19/09 et le 16/10 (git log --all --author=Arand --since=2026-09-19). La mise en ligne effective sur trinke.app n'est pas vérifiable sans réseau.
Rien à faire.
[vraie] v711 ne change rien côté serveur à part le numéro de version.
ECHANGES-ROMAIN.md:1345 · 27/09
git diff fedf0561 b4f7cfd7 -- functions/ live/ schema.sql TRINKE.md wrangler.toml : 1 ligne, VERSION_SERVEUR 628 → 711.
Rien à faire.
[vraie] v818 : main avancé de 112 commits, serveur inchangé sauf la version.
ECHANGES-ROMAIN.md:1397 · 28/09
git rev-list --count b4f7cfd7..81ed5ab8 = 113 (112 + le commit du fil) ; diff functions/ = VERSION_SERVEUR 711 → 818 seulement.
Rien à faire.
[vraie] Les 199 affirmations non relues et l'exception daltonisme sont parties en production sans réponse de Théo.
ECHANGES-ROMAIN.md:1410 · 28/09
Dit franchement. Aucune réponse de Théo dans ECHANGES-THEO après le 19/09 ; afd92690:public/app.js:6096-6099 : VF_POOL de 199 entrées marquées « CONTENU NON RELU ».
Des questions posées à Théo ont été tranchées par Romain seul, ce qui est écrit mais mérite d'être su.
[vraie] Vrai ou faux contient 199 affirmations non relues par Théo ni Romain.
ECHANGES-ROMAIN.md:1386 · 28/09
Comptage du tableau VF_POOL à afd92690 : 199 ; commentaire app.js:6096-6098.
Contenu factuel non vérifié diffusé aux joueurs.
[vraie] v869 a passé deploy.sh avec 21 081 contrôles.
ECHANGES-ROMAIN.md:1422 · 29/09
Rejoué sur 89e92e3c : « ✓ 21079 controles passes (version soiree-v869) », sans les 2 contrôles git. Les bancs navigateur n'ont pas été rejoués ici.
Rien à faire.
[inverifiable] La mise en ligne v869 a été décidée en présence de Théo.
ECHANGES-ROMAIN.md:1420 · 29/09
Aucune trace écrite de Théo pour cette date (dernier écrit Arand avant le 16/10 : 19/09).
Théo est le seul à pouvoir confirmer.
[vraie] Le mot « Trinqueur » de CLAUDE.md n'est pas changé sans l'accord de Théo.
ECHANGES-ROMAIN.md:1426 · 29/09
CLAUDE.md:147 garde « Trinqueur » dans origin/main et origin/soiree-v2. Les commentaires serveur ont en revanche été changés (diff 81ed5ab8..89e92e3c).
Promesse tenue ; la décision reste en attente de Théo.
[vraie] apercu.sh publie l'aperçu sans passer verif.js, contrairement à deploy.sh.
ECHANGES-ROMAIN.md:1464 · 29/09
de62085c:apercu.sh : seul « node --check public/app.js » est lancé ; choix d'origine de Théo (commentaire l.4-7). Le circuit actuel (publier.sh) lance verif.js mais pas les suites de deploy.sh (rapport outillage).
Écart toujours ouvert : test-schema-a-jour.js est cassé depuis le 16/10 sans que personne le voie (rapport outillage).
[vraie] L'aperçu utilise la base de production.
ECHANGES-ROMAIN.md:1567 · 07/10
58375c0e:wrangler.toml : un seul [[d1_databases]] binding "DB", aucun environnement preview ; inchangé dans v2.
Tout essai sur l'aperçu écrit des données réelles ; la base d'aperçu séparée proposée n'existe toujours pas.
[exageree] Un compte de test dédié sur la vraie base est une voie sans risque.
ECHANGES-ROMAIN.md:1570 · 07/10
Le compte de test créé ensuite utilise une boîte mailinator publique (l.1617) et son code de secours est écrit en clair dans le fichier poussé (l.1618) ; le code réel du compte de Romain y figure aussi deux fois (l.1589, 1623). Sur origin/main (v1059, a priori la production) la connexion pseudo + code existe toujours ([[route]].js:1573-1600 d'origin/main).
Quiconque lit le dépôt peut prendre le compte de test (code e-mail via la boîte publique) et, si le code n'a pas été régénéré, le compte réel de Romain.
[vraie] Les comptes d'avant le 27/07 ne pouvaient pas se connecter par code, et le code le disait.
ECHANGES-ROMAIN.md:1592 · 07/10
00112d8d^ [[route]].js:1289 : « leur code reste inutilisable, ils passent par l e-mail ». Correctif 00112d8d : sel retrouvé dans inscriptions, fixé après succès.
Correctif juste, devenu caduc le 17/10 (connexion par code fermée en v1081).
[exageree] Tester création, connexion et déconnexion directement sur la base de production est autorisé.
ECHANGES-ROMAIN.md:1614 · 07/10
Accord de Romain seul. CLAUDE.md (df2cd405:20-23) : trinke-db est la production avec les données de vraies personnes ; ce même Claude citait le 08/09 la règle « jamais de test sur la base de production » (l.865) et écrivait qu'une consigne en langage naturel n'est pas un contrôle d'accès (l.1086-1090).
Un compte de test réel a été créé en production sans décision écrite de Théo, co-titulaire de la base.
[inverifiable] Le code de Romain passe maintenant aussi en production, après fixation du sel par l'aperçu.
ECHANGES-ROMAIN.md:1627 · 07/10
Requête sur la production non rejouable (réseau interdit). Cohérent avec le code : l'aperçu partage la base et écrit code_sel (00112d8d).
Montre que du code non déployé a modifié des données de production.
[exageree] Les correctifs serveur n'ont d'effet en production qu'après déploiement.
ECHANGES-ROMAIN.md:1642 · 07/10
La même entrée constate le contraire : le sel fixé par l'aperçu fait passer le code « sur trinke.app aussi (200) » (l.1627). L'aperçu écrit dans trinke-db (wrangler.toml, un seul binding).
Un code d'aperçu peut changer l'état de la production avant toute décision de déploiement.
[vraie] La demande de code par e-mail est mémorisée 30 minutes.
ECHANGES-ROMAIN.md:1634 · 07/10
f9e4e955:public/app.js : LIENKEY="trinke_lien_v1", expiration 30*60*1000.
Rien à faire.
[perimee] L'aperçu n'envoie pas d'e-mails, faute de secrets posés.
ECHANGES-ROMAIN.md:1636 · 07/10
Vrai le 07/10 ; le 16/10, 71e41d63 « v1068 : Apercu republie : envoi d'emails branche (secrets Preview) ».
Depuis le 16/10, l'aperçu envoie de vrais e-mails à partir de la vraie base.
[vraie] Une règle posée le 08/08 est renversée à la demande de Romain.
ECHANGES-ROMAIN.md:1704 · 07/10
Dit franchement ; contrats mis à jour dans le même commit (f9d8b8b5). Pas de validation écrite de Théo.
Règle de Théo changée sans son avis écrit.
[fausse] Le Mode clair a disparu des Réglages en v928.
ECHANGES-ROMAIN.md:1731 · 07/10
8d09d221 (10/10) : « le Mode clair, retire le 07/10, restait affiche » : display:flex l'emportait sur [hidden] ; correctif #m-settings .set-rg[hidden]{display:none}.
Annoncé fait, resté visible trois jours : vérification à l'écran non faite.
[inverifiable] 41 bancs ont été rejoués lors de l'audit v954.
ECHANGES-ROMAIN.md:1831 · 07/10
Aucun journal de passage commité ; non rejoué ici.
Le rapport outillage montre qu'au 20/10 test-schema-a-jour.js échoue depuis le 16/10 : un « tous les bancs rejoués » ne vaut qu'à sa date.
[inverifiable] Le blocage de la Course des As arrivait environ une course sur deux ; 20 000 courses simulées sans erreur après correctif.
ECHANGES-ROMAIN.md:1837 · 10/10
Le correctif 3e279167 est réel (coPhrase « detrone » → « tete » et filet) mais aucune simulation n'est commitée (git log -S'20000' -- outils/ : rien de lié).
L'hypothèse du verrou (v927) était fausse, ce que l'entrée v927 annonçait honnêtement comme non prouvée.
[perimee] La Boutique n'a pas de paiement ; 9 mini-jeux gratuits, 10 payants, accès réglé par une seule table.
ECHANGES-ROMAIN.md:1840 · 13/10
Vrai à d281bb26 (app.js:218-228 ACCES_MIN, ACHAT_ACTIF=false, BOUTIQUE-01 à 06). Depuis, paiement Stripe ajouté (56b0ff32, 14/10 et suivants) et compte obligatoire (16/10).
La description de l'offre ne correspond plus à v1081.
[vraie] Le travail de sécurité n'est pas sur main.
ECHANGES-ROMAIN.md:1847 · 17/10
424974df n'est pas ancêtre d'origin/main ; origin/main:public/sw.js = soiree-v1059. L'état de trinke.app n'est pas vérifiable sans réseau.
Les protections décrites n'existent pas en production tant que v2 n'est pas déployée.
[vraie] Turnstile protège inscription, connexion et envoi de code, vérifié par le serveur avant le compteur d'essais, inactif sans clés.
ECHANGES-ROMAIN.md:1850 · 17/10
9b93ff3a [[route]].js:1373 (signup), 1634 (login/lien), 1784-1785 (login, commentaire « AVANT le compteur d'essais ») ; tsActif sans clés (rapport sécurité A7).
Sans les clés en production, aucune protection, sans alerte.
[vraie] Have I Been Pwned est interrogé en k-anonymat (5 caractères).
ECHANGES-ROMAIN.md:1851 · 17/10
Rapport sécurité A7 ([[route]].js:459-472) ; test-mdp.mjs vérifie les 5 caractères (faux HIBP l.66-70).
Rien à faire.
[exageree] Chaque connexion réussie déclenche un e-mail d'alerte.
ECHANGES-ROMAIN.md:1852 · 17/10
9b93ff3a [[route]].js : alerteConnexion n'est appelé que dans la route login (l.1814, 1854) ; la connexion par code e-mail (login/code, l.1495) n'alerte pas (rapport comptes, section C).
Une connexion par quelqu'un qui a accès à la boîte mail ne prévient pas.
[vraie] La politique de contenu (CSP) empêche tout script étranger de s'exécuter sur l'app.
ECHANGES-ROMAIN.md:1853 · 17/10
Mesuré par Claude le 20/10 : la page de l'app sur apercu.jeu-soiree.pages.dev reçoit la CSP complète (en-tête Content-Security-Policy lu en ligne). L'audit l'avait jugée exagérée par déduction ; la mesure le contredit. Sur trinke.app (v1059) la CSP complète n'est pas encore en ligne.
Rien : la protection fonctionne sur la v2.
[perimee] Le code de récupération des anciens comptes reste utilisable une fois.
ECHANGES-ROMAIN.md:1854 · 17/10
Vrai à 9b93ff3a (03:02) ; 31 minutes plus tard ef93abcf (v1081) ferme toute connexion par code (route-v2.js:1852-1855, 410). L'entrée n'a pas été corrigée ; l'e-mail d'alerte dit toujours « Régénère aussi ton code » (route-v2.js:495).
Théo a pu croire à une porte de secours qui n'existe plus.
[vraie] Quatre défauts trouvés par une revue ont été corrigés.
ECHANGES-ROMAIN.md:1855 · 17/10
a2bc828c : « login/code sans enumeration, alerte plafonnee, code de recuperation a usage unique, cle anti-robot relue, e-mails sans bouton vide ». Le caractère « indépendant » de la revue n'est pas vérifiable.
Rien à faire.
[vraie] test-mdp.mjs passe 114 contrôles et verif.js 22 910.
ECHANGES-ROMAIN.md:1857 · 17/10
Rejoué hors réseau sur git archive 9b93ff3a : « ✓ 114 controles (mot de passe) » ; verif.js « ✓ 22907 », sans 2 contrôles git ni FONDS-04 (python3 absent).
test-mdp.mjs n'est appelé ni par deploy.sh ni par verif.js (rapport outillage) : il ne protège rien automatiquement.
[inverifiable] L'aperçu en ligne ne lève aucune violation de CSP.
ECHANGES-ROMAIN.md:1857 · 17/10
Mesure en ligne non rejouable (réseau interdit). Si la CSP complète n'est pas servie sur la page (voir l.1853), l'absence de violation ne prouve rien.
Ne pas lire ce résultat comme une preuve que la CSP protège.
[vraie] Trois gestes sont demandés à Théo : widget Turnstile, double authentification, expiration du jeton de déploiement.
ECHANGES-ROMAIN.md:1859 · 17/10
Demandes justifiées : création de widget et réglages de compte sont au niveau du compte. Nuance : le côté Romain pose déjà des secrets Preview avec son jeton (71e41d63, 16/10).
Gestes légitimes ; la double authentification et l'expiration du jeton sont prioritaires.
[vraie] PBKDF2 à 100 000 tours est le maximum de Cloudflare et pourrait dépasser 10 ms de CPU sur l'offre gratuite.
ECHANGES-ROMAIN.md:1864 · 17/10
9b93ff3a [[route]].js:15 « const ITER = 100000; // PBKDF2 » ; le plafond de 100 000 itérations des Workers est un fait connu, non vérifié en ligne ici. La question posée à Théo est légitime.
À vérifier dans les métriques Workers avant mise en production.
[vraie] Le téléphone vérifie la version toutes les 2 minutes, même écran éteint, sans aucun frein.
echanges/2026-09-08-appel-reseau-toutes-les-deux-minutes.md:18 · 08/09
git show b62bf9b1:public/app.js lignes 1961, 1995, 1996, 1997 : exactement ce qui est cité, aucun test de visibilité dans verifie.
Le défaut était réel ; il a été corrigé par c39d30c avec l'accord écrit de Theo.
[vraie] Le registre des minuteries oublie une minuterie et contient trois lignes qui ne servent à rien.
echanges/2026-09-08-appel-reseau-toutes-les-deux-minutes.md:35 · 08/09
b62bf9b1:public/app.js:1020-1050 (fRefusTimer absent), 1022-1024 (noms + window[n]), 5163 (var fRefusTimer). Theo l'a aussi vérifié dans sa réponse.
Constat exact, corrigé dans c39d30c.
[vraie] Le travail accepté est fait tel que décrit, avec un banc qui ne compte que l'appel de verifie et un essai par sabotage.
echanges/2026-09-08-appel-reseau-toutes-les-deux-minutes.md:126 · 09/09
git show c39d30c : if(document.hidden)return; ajouté dans verifie, fRefusTimer ajouté au registre, trois lignes window[] retirées ; test-app-tient.py filtre les URL contenant /sw.js?v= et redéfinit document.hidden.
Fiche fidèle au commit.
[vraie] Le contrôle complet passait avec 19 759 contrôles (même chiffre annoncé dans la fiche coût D1, et 19 767 dans la fiche table erreurs).
echanges/2026-09-08-appel-reseau-toutes-les-deux-minutes.md:127 · 09/09
Rejoué hors réseau sur des copies (git archive) : c39d30c = 19 757, 9021897 = 19 757, eac0acf = 19 765. Écart constant de 2 sur les trois, cohérent avec une copie sans dépôt git (le contrôle git ne compte pas) : DÉDUIT.
Les chiffres de contrôle annoncés sont crédibles.
[vraie] Theo a lui-même constaté en production l'absence d'index sur la table des parties.
echanges/2026-09-08-deux-index-manquants-sur-parties.md:23 · 08/09
ECHANGES-THEO.md à b62bf9b1, lignes 124-126 : « Lecture de sqlite_master sur parties en production : aucun index en dehors des deux index automatiques ».
Citation fidèle de Theo.
[vraie] Les requêtes les plus fréquentes sur les parties lisent toute la table faute d'index.
echanges/2026-09-08-deux-index-manquants-sur-parties.md:29 · 08/09
b62bf9b1 route 1258 (hote_id + fin), 1856, 1876, 1885 (mode + fin). Petite imprécision : la ligne 279 (scoreCompte) filtre sur mode seulement, pas sur fin. Theo a mesuré SCAN parties en production.
Le gain annoncé est réel ; l'imprécision sur la ligne 279 ne change rien.
[exageree] L'index sur la date de dernière visite des appareils ne sert à rien.
echanges/2026-09-08-deux-index-manquants-sur-parties.md:47 · 08/09
b62bf9b1 route ligne 3034 : SELECT ... FROM devices WHERE user_id=? ORDER BY vu_le DESC. Aucun filtre, mais un tri : Theo l'a relevé et a refusé le retrait sans mesure.
Sans la relecture de Theo, un index potentiellement utile aurait été retiré sur un motif faux.
[vraie] Après l'ajout des deux index dans schema.sql, le banc du schéma passe.
echanges/2026-09-08-deux-index-manquants-sur-parties.md:141 · 09/09
Rejoué hors réseau sur une copie de e0c193d : « schema a jour : 9 migration(s) verifiee(s) sur 6 table(s), aucune colonne manquante ».
Exact. L'application en production restait un geste de Theo (fait le 10/09 selon ECHANGES-THEO.md).
[fausse] L'export de la base est une simple lecture, sans effet pour les joueurs.
echanges/2026-09-08-la-base-n-existe-qu-en-un-exemplaire.md:11 · 08/09
sauvegardes/LISEZ-MOI.md à 66c47524, lignes 40 et 62 : l'export exige le droit D1 Edit (un jeton en lecture reçoit 403) et rend la base indisponible pendant qu'il tourne. Romain le reconnaît lui-même dans la Réponse (lignes 113-119).
Corrigé le jour même par le côté Romain, sans effet sur une décision.
[vraie] Avant le 08/09, la base n'avait aucune sauvegarde ni procédure de restauration.
echanges/2026-09-08-la-base-n-existe-qu-en-un-exemplaire.md:22 · 08/09
git grep « d1 export / sauvegard / backup » sur 576e3a90^ dans ces fichiers : rien qui concerne la base. Theo crée la première sauvegarde chiffrée dans 875c889d le même soir.
Alerte justifiée, suivie d'une vraie sauvegarde.
[vraie] Deux précédents de suppression involontaire existent dans l'historique du projet.
echanges/2026-09-08-la-base-n-existe-qu-en-un-exemplaire.md:42 · 08/09
CLAUDE.md à 576e3a90, ligne 274 : « une branche par défaut destructive, deux fois de plus » (parties/confirmer, groupes/repondre), « Forme exacte du défaut du 09/08 ».
Précédent cité correctement.
[exageree] Theo aurait établi que le quota partagé par compte peut rendre la base inaccessible.
echanges/2026-09-08-la-base-n-existe-qu-en-un-exemplaire.md:54 · 08/09
ECHANGES-THEO.md (entrée « Ta question 2 », lignes 50-60) : Theo écrit « Je donne cela comme une piste à vérifier à la source, pas comme un chiffre ... je ne l'ai pas mesurée sur Trinke ». La fiche en fait un fait établi attribué à Theo.
Une piste non vérifiée est devenue un argument d'urgence ; l'urgence (sauvegarde) restait justifiée par ailleurs.
[vraie] La sauvegarde de Theo est vérifiée et présente dans le dépôt partagé.
echanges/2026-09-08-la-base-n-existe-qu-en-un-exemplaire.md:102 · 08/09
sauvegardes/LISEZ-MOI.md à 66c47524 ligne 25 (22 tables, 1 012 lignes) ; sauvegardes/trinke-db-2026-09-08.sql.gpg présent dans origin/main.
Reprise fidèle des mesures de Theo.
[vraie] Le paquet Soirée fait 391 cartes et le nombre de tours est calculé sur le paquet entier.
echanges/2026-09-08-la-borne-400-du-paquet-multijoueur.md:106 · 08/09
29f51532 : content-fr.json cards = 391 ; app.js:13727 envoi.tours=envoi.deck.length.
Exact.
[vraie] Le nombre de tours est borné à un endroit et pas à l'autre, et la fin de partie dépend de cette valeur non bornée.
echanges/2026-09-08-la-borne-400-du-paquet-multijoueur.md:113 · 08/09
29f51532 route lignes 2676, 2780-2781, 2802, confirmées aussi par l'arbitrage de Theo. Seul détail faux : « quinze lignes plus haut » (en réalité environ 105 lignes).
Diagnostic juste, repris par Theo.
[fausse] Il y a trois chemins qui fixent le nombre de tours ; dériver les tours de la taille du paquet est la bonne solution.
echanges/2026-09-08-la-borne-400-du-paquet-multijoueur.md:140 · 08/09
29f51532:public/app.js:13738 : quatrième écriture (mini-jeu à distance sans paquet). Dériver les tours du paquet aurait cassé ce mode ; Theo l'a montré et a refusé la proposition.
Sans l'arbitrage de Theo, un mode multijoueur aurait été cassé.
[exageree] Les trois « fausses pannes » du canal du 08/09 ont toutes la même cause, un décalage de lecture du dépôt.
echanges/2026-09-08-le-canal-ne-dit-pas-ce-que-l-autre-a-lu.md:23 · 08/09
Réponse de Theo (lignes 121-125 et 179-185) : seul le cas 2 est confirmé ; le cas 1 est invérifiable (les issues GitHub étaient réellement illisibles, 404) ; le cas de Theo venait d'un fichier présent mais non ouvert, pas d'un décalage.
La cause unique annoncée était fausse pour au moins un cas ; la parade a été corrigée par Theo.
[fausse] Le fil de Romain comptait 13 entrées du 08/09, celui de Theo 8.
echanges/2026-09-08-le-canal-ne-dit-pas-ce-que-l-autre-a-lu.md:75 · 08/09
Au commit 29f51532 : ECHANGES-ROMAIN.md compte 14 titres « ## 2026-09-08 », ECHANGES-THEO.md en compte 10.
Chiffres sous-estimés, sans effet sur une décision.
[vraie] Romain marquera désormais ses fiches et entrées avec l'état du dépôt qu'il avait sous les yeux.
echanges/2026-09-08-le-canal-ne-dit-pas-ce-que-l-autre-a-lu.md:99 · 08/09
Parent de ac32f1b3 = 29f51532 (Theo l'a vérifié). Suivi : toutes les fiches Romain postérieures portent contre: ; 30 des 48 entrées d'ECHANGES-ROMAIN.md en portent un, dont presque toutes les entrées postérieures au 08/09.
Promesse tenue pour l'essentiel.
[vraie] La fonction qui teste un blocage répond « pas bloqué » sur toute erreur.
echanges/2026-09-08-le-catch-d-estbloque-avale-une-table-absente.md:19 · 08/09
11cdd617 route 552 (async function estBloque) et 559 (catch (e) { return false; }).
Défaut réel, corrigé le 19/09 (8fe8af4).
[fausse] estBloque est appelée à cinq endroits.
echanges/2026-09-08-le-catch-d-estbloque-avale-une-table-absente.md:45 · 08/09
11cdd617 route : 552 est la définition ; estBloque n'est appelée qu'en 577 (dans filOuvert) et 2026. Les lignes 2141, 2151, 2160 sont des requêtes directes sur la table blocages (INSERT, DELETE, SELECT), pas des appels. Theo a écrit avoir vérifié « les cinq points d'appel » sans le relever.
Le coût de l'option 1 était surestimé ; l'arbitrage (variante de Theo) n'en dépendait pas vraiment.
[vraie] La base locale de test n'avait pas les tables de blocage, donc le blocage y était inopérant.
echanges/2026-09-08-le-catch-d-estbloque-avale-une-table-absente.md:25 · 08/09
ECHANGES-THEO.md à b62bf9b1, lignes 116-122 : « 21 tables contre 22 ... il mord déjà, là où personne ne regarde » : reprise mot pour mot de Theo.
Citation fidèle.
[vraie] La variante acceptée par Theo est codée et testée.
echanges/2026-09-08-le-catch-d-estbloque-avale-une-table-absente.md:121 · 19/09
Copie de 8fe8af4 : route ligne 659 (throw si « no such table ») ; banc rejoué hors réseau : « 8 controles passes » ; BLOQUE-01 à 03 présents dans verif.js ; deploy.sh lignes 84-85.
Conforme à l'arbitrage.
[fausse] Les grosses parties ne peuvent pas s'enregistrer à cause d'une limite de 50 appels à la base.
echanges/2026-09-08-le-cout-d1-par-requete.md:30 · 08/09
Réponse de Theo (lignes 94-107) : la limite de 50 vise les sous-requêtes externes, celle des services Cloudflare (dont D1) est de 1 000 (page des limites Workers et changelog du 11/02/2026, source citée par Theo, non revérifiée en ligne ici). Romain avait signalé ne pas avoir confirmé l'offre.
Fausse alerte d'urgence, arrêtée par Theo avant tout changement de comportement (batch refusé).
[fausse] Chaque joueur coûte deux appels et les badges jusqu'à 22.
echanges/2026-09-08-le-cout-d1-par-requete.md:33 · 08/09
b62bf9b1 route 1275-1296 : un seul INSERT par joueur, la liste d'amis n'est chargée qu'une fois (if (mesAmis === null)) ; badges bornés par slice(0, 40) ligne 1345, l'app n'en définit que 11 (mesure de Theo).
Le total de 71 n'était juste que par compensation d'erreurs.
[vraie] Le serveur utilise déjà six fois les écritures groupées.
echanges/2026-09-08-le-cout-d1-par-requete.md:20 · 08/09
b62bf9b1 route : DB.batch( aux lignes 541, 2140, 2247, 2383, 2705, 3069, exactement.
Exact.
[vraie] Un ménage est fait à chaque lecture de conversation alors qu'un mécanisme périodique existe déjà.
echanges/2026-09-08-le-cout-d1-par-requete.md:45 · 08/09
b62bf9b1 route 2433 (DELETE FROM frappe WHERE le < ?) et 2645 (menageDu(env, "live", 5 min)).
Point accepté par Theo et corrigé dans 9021897.
[vraie] Seuls les deux points acceptés sont faits, et leur effet est décrit sans exagération.
echanges/2026-09-08-le-cout-d1-par-requete.md:141 · 09/09
git show 9021897 : DELETE déplacé sous menageDu (qui fait un SELECT sur essais, route 569-580), objet ouverts par fil dans chat/supprimer ; aucun batch ajouté.
Fiche honnête sur le gain réel.
[vraie] Une autre écriture inutile à chaque lecture existe, non traitée.
echanges/2026-09-08-le-cout-d1-par-requete.md:157 · 09/09
9021897 route 582-590 (purgeMessages) appelée ligne 2448 dans la lecture de conversation.
Signalé, laissé à Theo ; pas repris depuis selon le premier audit (G10 ne cite que inscriptions, frappe, live).
[vraie] Les quatre colonnes manquantes sont les seules ajoutées par migration et absentes de schema.sql.
echanges/2026-09-08-le-schema-de-reference-est-en-retard.md:96 · 08/09
29f51532 : 8 ALTER TABLE dans la route ; live.extra, naissance, presence_off et groupe_membres.statut sont déjà dans schema.sql ; restent difficulte, joueurs_n, perf, avatar2.
Exact.
[vraie] Un contrôle lisant la production bloquerait les déploiements de Romain.
echanges/2026-09-08-le-schema-de-reference-est-en-retard.md:102 · 08/09
Arbitrage de Theo (lignes 147-152) : le rôle de Romain est Workers Platform Admin, sans droit D1, vérifié côté Cloudflare.
Raisonnement juste, accepté par Theo.
[vraie] Romain accepte l'essai de déploiement ; deploy.sh échoue chez lui à la ligne 30 faute de python.
echanges/2026-09-08-premier-deploiement-depuis-un-clone.md:2 · 08/09
git show 11cdd617 : statut PROPOSE -> ACCEPTE, section Réponse laissée vide ; deploy.sh à 11cdd617 ligne 30 = premier appel python. Romain déploie ensuite depuis son côté (ECHANGES-ROMAIN.md, 27/09, v711).
La fiche n'est jamais passée à FAIT et les quatre vérifications prévues (sw.js, robots.txt, aperçu, partie jouée) n'y sont pas écrites.
[vraie] L'app ne remonte aucune erreur du téléphone.
echanges/2026-09-08-rien-ne-remonte-quand-l-app-casse.md:18 · 08/09
11cdd617:public/app.js = 17 207 lignes ; seule occurrence « onerror » = liveWS.onerror (connexion temps réel), aucun unhandledrejection.
Exact ; toujours vrai à v1081 (voir fi-37).
[vraie] Le serveur renvoie le message d'erreur brut au client et ne journalise rien.
echanges/2026-09-08-rien-ne-remonte-quand-l-app-casse.md:25 · 08/09
11cdd617 route ligne 3117 (à une ligne près), fichier de 3 119 lignes, aucun console.error/warn/log.
Fuite réelle, corrigée le 19/09 (eac0acf).
[vraie] Theo avait donné son accord et confié ce code à Romain, donc la fiche pouvait naître au statut FAIT.
echanges/2026-09-19-table-erreurs-le-serveur-tient-son-journal.md:12 · 19/09
ECHANGES-THEO.md, entrée du 19/09 (lignes 548-610) : « Théo a tranché : le principe est oui, et c'est toi qui rédiges la fiche et qui écris le code » ; « la fiche et le code sont à toi ».
Accord réel et écrit.
[vraie] Les cinq conditions de Theo sont toutes appliquées ; le banc fait 14 contrôles.
echanges/2026-09-19-table-erreurs-le-serveur-tient-son-journal.md:24 · 19/09
git show eac0acf : clé (route, code, version), ON CONFLICT ... n=n+1, try/catch propre, troncature 160, purge 200 lignes par jour sous menageDu, 500 sans detail. Banc rejoué hors réseau : « 14 controles passes ».
Conforme.
[vraie] La remontée des erreurs du téléphone reste à faire dans une fiche séparée.
echanges/2026-09-19-table-erreurs-le-serveur-tient-son-journal.md:104 · 19/09
Aucune fiche « remontée téléphone » dans echanges/ (main et soiree-v2) ; origin/soiree-v2:public/app.js (v1081) : aucun window.onerror ni unhandledrejection.
Un mois plus tard, une erreur JavaScript sur le téléphone d'un joueur ne laisse toujours aucune trace.
[vraie] Avec le mélange de l'époque, Action ou vérité occupe 36 % d'une partie et les familles se suivent souvent.
echanges/2026-09-19-la-soiree-sert-toujours-les-memes-familles-de-cartes.md:24 · 19/09
Simulation refaite hors réseau sur content-fr.json de d2d1a044 (261 cartes soft + chaud, 2 000 parties de 40, mélange uniforme) : Action ou vérité 14,2 (36 %), Je n'ai jamais 7,5, Gage 5,8, Tu préfères 5,0, doublons 8,2 par partie, plus longue série 3,4.
Mesure reproduite.
[vraie] Le plancher de 40 cartes fait revenir les mêmes cartes en bloc d'une Soirée à l'autre (Chill dès la 4e partie).
echanges/2026-09-19-la-soiree-sert-toujours-les-memes-familles-de-cartes.md:119 · 19/09
8aca0b97:public/app.js:3051 (PLANCHER_FRAICHEUR=40) et 3145-3151 (complète avec les plus anciennes jusqu'à 40). Chill = 131 cartes soft : 3 parties de 40 puis 11 fraîches + 29 revues, comme le tableau. Toujours 40 à v1081 (app.js:3672).
Constat juste ; accepté par Theo le 16/10 « s'il tient encore », pas retraité depuis.
[vraie] Le problème de la fiche a été traité dans le code pendant que la fiche attendait la réponse de Theo.
echanges/2026-09-19-la-soiree-sert-toujours-les-memes-familles-de-cartes.md:2 · 19/09
a1a28e0 (23/09, Romain) : tirage planifié de 50 cartes ; mis en ligne avec v711 le 27/09 (ECHANGES-ROMAIN.md, entrée du 27/09). Aucune réponse de Theo dans la fiche avant le 16/10.
Une règle de jeu (partie de 50 cartes fixe, durée supprimée) a changé en production sans réponse écrite de Theo, contrairement à LISEZ-MOI (« Tant qu'une fiche est au statut PROPOSE, le code ne bouge pas »).
[vraie] Deux réglages n'ont aucun effet et « En couple » n'a presque rien en Chill.
echanges/2026-09-21-lancer-une-soiree-en-un-geste-les-reglages-en-option.md:32 · 21/09
content-fr.json à 16aadf7c : 0 carte « famille », 0 carte avec su, 136 cartes « couples » dont soft 1, chaud 63, hardcore 72.
Exact.
[fausse] La fiche du 19/09 aurait mesuré que Chill ressert les mêmes familles dès la 4e Soirée.
echanges/2026-09-21-lancer-une-soiree-en-un-geste-les-reglages-en-option.md:36 · 21/09
La fiche du 19/09 (lignes 114-123) mesure que les mêmes CARTES reviennent dès la 4e partie en Chill, pas les mêmes familles.
Citation déformée d'une mesure interne, sans effet sur la décision.
[vraie] Le côté Romain ne touche à rien avant la réponse de Theo.
echanges/2026-09-21-lancer-une-soiree-en-un-geste-les-reglages-en-option.md:47 · 21/09
Réponse de Theo du 16/10 : non appliqué, la carte Soirée ouvre toujours la fiche (app.js:2746). Mais v970 (3d77360, 13/10, « Romain, 13/10 ») retire déjà « Avec qui ? » et « Sujets inclus » de l'écran, sans réponse de Theo.
La promesse est tenue pour le lancement en un geste, mais une partie du même sujet (retrait de réglages visibles) a été tranchée par Romain seul.
[vraie] Les étiquettes mélangent publics et thèmes, avec ces effectifs.
echanges/2026-09-21-public-et-theme-sont-deux-axes-pas-une-liste.md:26 · 21/09
content-fr.json à 9fb7457e : potes 98, quiz 36, gene 105, fete 51, cash 19, couples 136 ; app.js à 16aadf7c ligne 6878 : TABLEES exactement comme cité.
Exact.
[fausse] La séparation public / thème n'ira pas en production avant la réponse de Theo.
echanges/2026-09-21-public-et-theme-sont-deux-axes-pas-une-liste.md:21 · 21/09
Réponse de Theo du 16/10 : « fait par v968 (4ac49d4) », publicOk filtre sur pub. v968 date du 13/10, était sur origin/main et en ligne (v1059) au moment où Theo répond (16/10 22:12). Aucune réponse de Theo avant.
Promesse écrite non tenue : le changement de données est parti en production sans accord.
[vraie] Le texte des 74 cartes « Je n'ai jamais » et du classique a été changé sur décision de Romain, sans attendre Theo.
echanges/2026-09-21-si-tu-as-deja-remplace-ceux-qui-l-ont-fait.md:20 · 21/09
72835b1 et 4a577682 (21/09) : 74 « Ceux qui ont déjà », 0 « Ceux qui l'ont fait » ; statut FAIT posé par Romain, section Réponse vide. L'ancienne formule était une règle de Theo (commentaire app.js:6346 à 803c2701 : « regle de Theo posee trois fois en Soiree »).
Un texte visible, qui relève de Theo selon LISEZ-MOI, a été changé et clos sans sa réponse ; la fiche ne prétend pas d'accord.
[vraie] La plupart des cartes ne parlent pas d'une action « faite ».
echanges/2026-09-21-si-tu-as-deja-remplace-ceux-qui-l-ont-fait.md:27 · 21/09
content-fr.json à 803c2701 : 74 cartes t = jamais, 10 commencent par « Je n'ai jamais fait » ; lignes app.js 6104, 6346 et verif.js 3856 conformes à la fiche.
Exact.
[exageree] Les 267 phrases du classique sont toutes relues, 784 relectures.
echanges/2026-09-21-si-tu-as-deja-remplace-ceux-qui-l-ont-fait.md:50 · 21/09
Recalcul avec la méthode de verif.js sur verification.json à 803c2701 : 247 des 267 phrases « jamais » sont relues ; 784 est le total des relectures de tout le jeu (« Contenu du jeu relu : 784/1444 »).
Le point utile (aucune relecture perdue) reste vrai ; le chiffre est mal attribué.
[vraie] 494 cartes existaient à la fois en Soirée et aux Classiques.
echanges/2026-10-13-un-seul-fonds-de-cartes-et-le-verrou-sur-ce-qui-est-deja-tire.md:17 · 13/10
cartes-fr.json à d697db8 : 494 cartes portent à la fois une vue Soirée et une vue Classiques ; 1 074 + 1 057 - 494 - 174 = 1 463 cartes, cohérent avec le message du commit.
Mesure exacte.
[vraie] Le paiement n'est pas actif, donc le verrou ne touche personne.
echanges/2026-10-13-un-seul-fonds-de-cartes-et-le-verrou-sur-ce-qui-est-deja-tire.md:77 · 13/10
893ac0e2:public/app.js:229 var ACHAT_ACTIF=false. Theo confirme le 16/10 : aucune clé Stripe en production.
Exact à la date.
[vraie] v966 et v967 attendent le feu vert de Theo avant main.
echanges/2026-10-13-un-seul-fonds-de-cartes-et-le-verrou-sur-ce-qui-est-deja-tire.md:10 · 13/10
Vrai le 13/10 (trinke.app restait en v911 : message de a8b529cc, 16/10 9 h 58). Mais origin/main contenait v1059 à 21 h 55 le 16/10 (journal local de origin/main) et Theo répond à 22 h 12 en constatant « en ligne depuis v966 ». Aucune trace écrite de feu vert avant.
Fiche PROPOSE appliquée sur main et en production avant la réponse de Theo.
[vraie] Le banc prouve que v968 corrige six écarts entre les options choisies et les cartes servies.
echanges/2026-10-13-ce-quon-choisit-est-ce-qui-tombe.md:110 · 13/10
Rejoué hors réseau : banc de 4ac49d4e vert sur son app.js ; sur le public/ de 893ac0e2 (v967) : « 6 écart(s) distinct(s) » (calvados en Entre potes, Sans filtre gardé en famille...).
Mesure reproduite.
[vraie] L'ordre des gestes changeait les cartes servies à cause d'une remise à zéro.
echanges/2026-10-13-ce-quon-choisit-est-ce-qui-tombe.md:47 · 13/10
893ac0e2:public/app.js:3358-3363 : applyPreset fait state.themes=p.themes.slice(), et toutes les ambiances ont themes:[].
Cause exacte.
[vraie] v968 attend le feu vert de Theo avant main.
echanges/2026-10-13-ce-quon-choisit-est-ce-qui-tombe.md:10 · 13/10
Même chronologie que fi-51 : v968 sur origin/main et en ligne avant la réponse de Theo du 16/10 (qui écrit « en ligne depuis v968 »). Pas de feu vert écrit avant.
Fiche PROPOSE appliquée en production avant la réponse ; les deux décisions de produit ont été contournées par v970 (13/10).
[vraie] Depuis le 07/10, tous les amis avaient la même couleur.
echanges/2026-10-13-onglet-amis-piste-a.md:43 · 13/10
4ac49d4e:public/style.css:4973-4980 : .am-av1 à .am-av8 = #15163A ; introduit par 99db7cc3 (v931, 07/10).
Exact.
[vraie] La refonte de l'onglet Amis (choix de design de Romain) attend le feu vert de Theo avant main.
echanges/2026-10-13-onglet-amis-piste-a.md:10 · 13/10
Réponse de Theo du 16/10 : « en ligne depuis v969 (778de3e) ». Même chronologie que fi-51, aucun feu vert écrit avant.
Un choix de design, réservé à Theo par LISEZ-MOI, est parti en production avant sa réponse.
[perimee] L'achat exige une case de renonciation au droit de rétractation, contrôlée par le serveur.
echanges/2026-10-14-paiement-stripe.md:53 · 14/10
Vrai à 77ae3e2b (route ligne 1509 : refus si renonce !== true). Retiré 25 minutes après la fiche par e954d096 (v991, 14/10 12 h 25) : « ni case ni phrase de renonciation dans l'app ». La fiche n'a jamais été corrigée et Theo l'a acceptée le 16/10.
Theo a accepté le paiement sur une description dépassée ; la fiche disait elle-même que sans la case un acheteur peut se faire rembourser après usage (risque juridique, voir rapport boutique-legal).
[vraie] Le paiement est couvert par un banc de 52 contrôles sur le vrai serveur.
echanges/2026-10-14-paiement-stripe.md:61 · 14/10
Rejoué hors réseau sur une copie de 77ae3e2b (faux Stripe, toute autre URL refusée) : « paiement : 52 controles, joues sur le vrai serveur ».
Exact.
[vraie] Sans les quatre clés Stripe, rien ne peut être encaissé.
echanges/2026-10-14-paiement-stripe.md:37 · 14/10
77ae3e2b route 912-915 : paiementActif exige les quatre variables. Theo a constaté le 16/10 qu'aucune n'est posée.
Exact.
[vraie] Le paiement n'est ni sur main ni en ligne, en attente de Theo.
echanges/2026-10-14-paiement-stripe.md:15 · 14/10
Vrai le 14/10 (trinke.app en v911 jusqu'au 16/10 matin, a8b529cc). Theo le 16/10 : « la fiche disait rien sur main ; c'est maintenant en ligne » depuis v988, avant sa réponse.
Fiche PROPOSE appliquée en production avant la réponse, fermée faute de clés.
[vraie] Le serveur impose des règles de composition et 72 caractères maximum.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:165 · 17/10
origin/soiree-v2 route 423-433 (MDP_MIN 8, MDP_MAX 72, minuscule, majuscule, chiffre) ; app.js maxlength="72" sur les champs mot de passe.
Exact ; contraire au point 5 décidé par Theo (aucune règle de composition, 128 max).
[exageree] Le refus des mots de passe fuités rend la règle de Romain conforme à NIST.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:167 · 17/10
Le code envoie bien 5 caractères (route ligne 467). Mais NIST SP 800-63B demande la liste de mots de passe compromis ET de ne pas imposer de règles de composition (texte connu, non revérifié en ligne ici) : garder les deux n'est pas ce que NIST recommande.
L'argument a servi à garder la règle de Romain contre la décision écrite de Theo.
[vraie] Le poivre demandé par Theo est codé, inactif tant que le secret n'est pas posé, sans casser les anciens mots de passe.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:173 · 17/10
origin/soiree-v2 route 376-410 (hachMdp, verifMdp, refus d'une empreinte p1$ sans poivre) et repoivrage à la connexion réussie (ligne 1844).
Conforme ; le secret doit être sauvegardé hors Cloudflare avant d'être posé.
[vraie] Changer ou poser son mot de passe déconnecte les autres appareils.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:188 · 17/10
origin/soiree-v2 route 1858-1885 : une seule route mdp/definir pour les trois cas, DELETE ligne 1883.
Conforme à la décision 3 de Theo.
[fausse] Un compte sans mot de passe est obligé de choisir un mot de passe, comme Theo l'a décidé.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:195 · 17/10
origin/soiree-v2:public/app.js:10478-10479 : rappelMdp n'affiche qu'un toast, une seule fois par appareil ; ligne 13939 : après le code e-mail, la vue mot de passe s'ouvre mais rien n'empêche d'en sortir. Le serveur ne bloque rien (déjà relevé par le rapport comptes).
Theo peut croire sa décision 4 (écran non contournable) appliquée alors qu'elle ne l'est pas.
[fausse] Romain et Theo ont le même poids pour trancher ce désaccord.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:210 · 17/10
echanges/LISEZ-MOI.md lignes 56-61 (« Le produit et le design se tranchent par Théo », « En cas de désaccord qui dure, Théo tranche ») et CLAUDE.md ligne 111, identiques sur main et soiree-v2. Trente minutes après, la règle de composition de Romain est gardée (lignes 232-234) contre la décision 5 de Theo.
La règle écrite qui donne le dernier mot à Theo a été ignorée, et une décision de Theo a été renversée.
[vraie] Le code de récupération ne connecte plus personne, comme Theo l'a décidé.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:221 · 17/10
origin/soiree-v2 route 1855 (410, code_fini), 3868-3869 (regenerer 410), 1448 (genCode à l'inscription). Un commentaire d'en-tête périmé dit encore que la connexion par code « reste acceptée ».
Conforme à la décision 4 de Theo (pas de migration en douceur).
[vraie] Le banc des mots de passe passe avec 123 contrôles.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:229 · 17/10
Rejoué hors réseau sur la copie v1081 (faux Brevo, faux HIBP, faux Turnstile, toute autre URL refusée) : « 123 controles (mot de passe) ».
Exact.
[vraie] La branche est poussée sans réécrire l'historique.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:202 · 17/10
git merge-base --is-ancestor : d20860b8 (v912) est ancêtre de c8d2803, lui-même ancêtre de ef93abcf (v1081). Sur main, Romain n'a ajouté le 17/10 que des textes (fiche et ECHANGES-ROMAIN.md).
Exact.
[vraie] Au 08/09, l'app n'était pas prête pour un lancement public sans restriction.
AUDIT-CODEX-2026-09-08.md:41 · 08/09
Jugement étayé par les défauts ci-dessous, vérifiés un par un sur c1596768. Sur ef93abcf, restent ouverts : réinscription cassée et données gardées après suppression (ac-09), droits d'un simple invité de groupe (ac-11), blocage sans effet dans les groupes (ac-12), page légale sans éditeur (ac-16), fenêtre Réglages au clavier (ac-18), déploiement d'un arbre non commité (ac-19).
Toujours vrai sur v2 : plusieurs défauts de données personnelles et d'autorisation sont encore là.
[vraie] Aucun défaut critique : pas d'injection SQL, pas de secret dans le dépôt.
AUDIT-CODEX-2026-09-08.md:62 · 08/09
Recherche de motifs de secrets (clés Stripe, AWS, GitHub, clés privées) sur l'arbre c1596768 extrait : 0 fichier. Requêtes en .prepare().bind() ; la seule concaténation relevée (live/geste, tour lu en base) n'est pas une donnée saisie.
Point sain confirmé (ce n'est pas un test d'intrusion, comme Codex le dit lui-même).
[vraie] Inventaire chiffré du dépôt au 08/09.
AUDIT-CODEX-2026-09-08.md:87 · 08/09
git ls-tree -r -l c1596768 : 3 610 fichiers, 29,58 Mo, 3 265 .webp, 127 .html, 92 .py, 48 .md, 27 .js, 24 .json. Tailles : app.js 17 207 lignes, style.css 9 260, [[route]].js 3 119, verif.js 8 533. Tous identiques.
Chiffres exacts.
[inverifiable] Le dépôt compte environ 218 000 lignes de texte.
AUDIT-CODEX-2026-09-08.md:89 · 08/09
Codex ne dit pas ce qu'il compte. git grep -I -c '' c1596768 donne 276 589 lignes pour 334 fichiers texte ; en excluant .svg et .json on obtient 218 648, proche de son chiffre. Impossible de savoir lequel il visait.
Ordre de grandeur plausible, définition absente.
[vraie] L'API sert 76 noms de route répartis en 74 blocs.
AUDIT-CODEX-2026-09-08.md:77 · 08/09
Sur c1596768 : 76 occurrences de route === "..." et 74 lignes « if (route === », certains blocs servant plusieurs routes.
Chiffre exact.
[vraie] N'importe qui peut ouvrir une connexion temps réel sur n'importe quel salon, sous le pseudo de son choix, sans preuve de session ; la liste d'origines ne refuse rien.
AUDIT-CODEX-2026-09-08.md:138 · 08/09
c1596768 live/src/index.js:35-42 (entetes ne refuse jamais, renvoie ORIGINES[0]), 67-73 (tout fil non vide devient un objet), 89 (qui lu dans l'URL), 172-207 (echo/bouge/encours rediffusés) ; app.js:12530-12531 n'envoie que fil et pseudo. Sur ef93abcf : ticket signé ajouté le 15/10 (a8bc474d), mais live/src/index.js:90-101 ne l'exige QUE si LIVE_SECRET est posé ; l'origine n'est toujours pas refusée, la longueur de fil n'est pas bornée, aucun plafond de messages.
Partiellement corrigé : si LIVE_SECRET n'est pas posé en production (invérifiable sans réseau), le trou est intact ; même avec lui, origine et débit restent libres. Impact limité : le Worker n'écrit pas dans D1.
[vraie] Une partie peut être enregistrée à moitié ; le renvoi suivant répond « déjà traité » sans compléter.
AUDIT-CODEX-2026-09-08.md:159 · 08/09
c1596768 functions/api/[[route]].js:1222-1223 (deja:true), 1262-1266 (INSERT parties), puis écritures séparées 1277-1346, aucun batch. Identique sur ef93abcf (functions/api/[[route]].js:2029-2036). Theo a REFUSÉ le batch le 09/09 (echanges/2026-09-08-le-cout-d1-par-requete.md, Réponse : « une partie qui s'enregistrait à moitié ne s'enregistrerait plus du tout »).
Toujours ouvert dans v2, par décision assumée : une erreur au milieu laisse des statistiques ou badges manquants, sans réparation possible par renvoi.
[inverifiable] Sur l'offre gratuite, une partie riche (20 joueurs, 40 badges) dépasserait la limite de 50 requêtes.
AUDIT-CODEX-2026-09-08.md:168 · 08/09
Pas de réseau ici pour relire la doc. Theo l'a contredit le 09/09 dans echanges/2026-09-08-le-cout-d1-par-requete.md (Réponse) : selon la page des limites Workers et le changelog du 11/02/2026, 50 vaut pour les sous-requêtes EXTERNES et 1 000 pour les services Cloudflare dont D1 ; il chiffre le pire cas réel à environ 44 appels (11 badges définis).
Si Theo a raison, ce risque de plafond n'existe pas ; le défaut d'atomicité (ac-07) reste, lui, réel.
[vraie] Activation, connexion par code, confirmation de partie et remise à zéro sont des suites d'écritures non groupées.
AUDIT-CODEX-2026-09-08.md:180 · 08/09
c1596768 functions/api/[[route]].js:882-893 (users, puis stats, inscriptions, devices séparés ; catch qui répond « pseudo vient d'être pris »), 918-923 (lien utilisé avant l'appareil), 1391-1397 (stats incrémentées AVANT confirme=1 à 1397), 2984-2990 (stats remises à zéro puis badges). Mêmes motifs sur ef93abcf : functions/api/[[route]].js:1509-1519, 1554, 2209, 3848.
Toujours ouvert : une coupure après la création du compte bloque la réactivation avec un faux message « pseudo pris » ; une coupure pendant la confirmation peut compter une partie deux fois.
[vraie] La suppression de compte garde pays, date de naissance, avatar et l'adresse normalisée ; se réinscrire avec la même adresse et un autre pseudo échoue.
AUDIT-CODEX-2026-09-08.md:193 · 08/09
c1596768 functions/api/[[route]].js:3093 (seuls code_hash, email, email_verifie vidés). Reproduit en SQLite en mémoire avec schema.sql de c1596768 ET de ef93abcf : même email_norm + autre pseudo → « UNIQUE constraint failed: users.email_norm » (même pseudo : la ligne est supprimée au préalable, functions/api/[[route]].js:820, donc ça passe). ef93abcf functions/api/[[route]].js:3972 ne vide en plus que mdp_hash/mdp_sel.
Toujours ouvert : une personne qui supprime son compte ne peut pas revenir avec la même adresse sous un autre pseudo, reçoit un message faux, et des données personnelles restent en base alors que la page légale promet l'effacement.
[vraie] Le transfert des groupes se fait après la suppression, hors transaction, quand la session n'existe déjà plus.
AUDIT-CODEX-2026-09-08.md:199 · 08/09
c1596768 functions/api/[[route]].js:3098-3104 (boucle après le batch). Identique sur ef93abcf functions/api/[[route]].js:3976-3983.
Toujours ouvert : rare (erreur entre deux écritures), mais le groupe resterait sans chef et personne ne pourrait relancer.
[vraie] Un simple invité (pas encore accepté) peut voir les membres d'un groupe (identifiants, pseudos, pays) et y inviter ses propres amis.
AUDIT-CODEX-2026-09-08.md:203 · 08/09
c1596768 functions/api/[[route]].js:2212-2214 et 2264-2266 : « SELECT 1 FROM groupe_membres WHERE groupe_id=? AND user_id=? » sans statut ; filOuvert (568-570) exige bien statut='membre'. Identique sur ef93abcf functions/api/[[route]].js:3026 et 3078.
Toujours ouvert : quelqu'un invité par erreur voit la liste du groupe et peut y faire entrer d'autres personnes sans jamais avoir accepté.
[vraie] Bloquer quelqu'un n'empêche pas d'échanger avec lui dans un groupe commun, contrairement à ce que disent l'app et la page légale.
AUDIT-CODEX-2026-09-08.md:222 · 08/09
c1596768 public/legal/index.html:44-45 et app.js:9233 (« plus aucun message ») ; functions/api/[[route]].js:563-570 (fil de groupe : appartenance seule), 572-582 (blocage seulement pour d:). Identique sur ef93abcf (functions/api/[[route]].js:845-862, legal:49).
Toujours ouvert : la promesse visible est fausse dans les groupes.
[perimee] Une erreur de base fait croire que personne n'est bloqué.
AUDIT-CODEX-2026-09-08.md:226 · 08/09
c1596768 functions/api/[[route]].js:559 « catch (e) { return false; } ». Sur ef93abcf (functions/api/[[route]].js:822-833, commit 8fe8af4c du 19/09, variante choisie par Theo) : table absente → l'erreur remonte ; base indisponible → false mais journalisé dans la table erreurs.
Corrigé selon un arbitrage explicite ; le cas « base indisponible » laisse passer volontairement.
[perimee] Le schéma de référence ne recrée pas la base réelle : 4 colonnes manquent.
AUDIT-CODEX-2026-09-08.md:234 · 08/09
grep sur c1596768 schema.sql : aucune des 4. Sur ef93abcf schema.sql:53, 90, 93, 116 : présentes (commit c5c36fed du 09/09, garde outils/test-schema-a-jour.js).
Corrigé le lendemain ; mais la garde ajoutée échoue elle-même sur v2 depuis 80fab682 (voir rapport-base.md).
[vraie] Les migrations faites pendant les requêtes avalent toute erreur et se marquent faites.
AUDIT-CODEX-2026-09-08.md:241 · 08/09
c1596768 functions/api/[[route]].js:54-59, 92-98, 145-150, 182-196 : 8 « catch (e) { /* deja en place */ } ». Sur ef93abcf : 11 occurrences ; aucun dossier migrations/ ; migrationAchats se marque faite même en échec (rapport-base.md, A6).
Toujours ouvert : une erreur passagère au premier appel laisse l'isolat croire que la colonne existe, et les routes qui la lisent échouent jusqu'au prochain isolat.
[vraie] La page légale n'a ni éditeur, ni finalités, base légale, durées, contact, recours CNIL.
AUDIT-CODEX-2026-09-08.md:251 · 08/09
c1596768 public/legal/index.html:63-64. Sur ef93abcf public/legal/index.html:69-70 : toujours « À renseigner avant le lancement public » ; aucune occurrence de CNIL, base légale, finalité, réclamation ou opposition. ECHANGES-THEO.md:423 (v2) reconnaît qu'H-08 « avait raison sur le fond ».
Toujours ouvert : obligation légale non remplie alors que des comptes réels existent (et que v2 prépare le paiement).
[vraie] L'export de données oublie les messages et coupe à 500 parties sans le dire.
AUDIT-CODEX-2026-09-08.md:258 · 08/09
c1596768 functions/api/[[route]].js:2947-2949 (LIMIT 500) et 2970-2972 (messages « non exportes », avec la raison : effacés après 30 jours). Identique sur ef93abcf functions/api/[[route]].js:3802 et 3829.
Toujours ouvert : l'exclusion des messages est dite, la coupe à 500 ne l'est pas ; un gros joueur reçoit un export incomplet.
[vraie] Le panneau Réglages n'a ni rôle de dialogue, ni bouton Fermer, ni touche Échap, et le focus reste derrière.
AUDIT-CODEX-2026-09-08.md:265 · 08/09
c1596768 index.html:1030 (div.modal sans role/aria-modal/aria-label), app.js:1926 (simple ajout de classe), 1953 (fermeture au clic sur le voile). Identique sur ef93abcf index.html:1370, app.js:2414 et 2441 ; seul Échap géré dans v2 : le menu « + » (app.js:18694). Reproduction Chromium de Codex non rejouée.
Toujours ouvert : contraire à la règle « accessibilité non négociable » du CLAUDE.md du dépôt.
[vraie] Le script de déploiement peut publier du travail non commité ou une version en retard.
AUDIT-CODEX-2026-09-08.md:289 · 08/09
c1596768 deploy.sh:290 et 305 (--commit-dirty=true), aucune vérification git dans le script. Sur ef93abcf deploy.sh:253 et 268 : identique.
Toujours ouvert : précisément le risque que CLAUDE.md décrit (remettre en ligne une version plus ancienne que celle de l'associé).
[vraie] Pas de CI, outils non verrouillés, pas de sauvegarde automatique ni de test de restauration.
AUDIT-CODEX-2026-09-08.md:293 · 08/09
git ls-tree c1596768 et ef93abcf : ni .github/, ni package.json. Dossier sauvegardes/ : un seul fichier, trinke-db-2026-09-08.sql.gpg, dernier commit sur ce dossier le 08/09 (c1596768) dans v2.
Toujours ouvert : aucune sauvegarde depuis le 08/09 dans le dépôt alors que la production a reçu ~6 semaines de comptes et de paiements préparés.
[vraie] La sauvegarde du 08/09 est un fichier GPG chiffré AES-256 de 39 762 octets.
AUDIT-CODEX-2026-09-08.md:301 · 08/09
git cat-file -s c1596768:sauvegardes/trinke-db-2026-09-08.sql.gpg = 39762 ; premiers octets 8c 0d 04 09 = paquet OpenPGP de chiffrement symétrique, version 4, algorithme 9 (AES-256). La revendication « 22 tables, 1 012 lignes » de LISEZ-MOI.md:25 n'est pas revérifiable sans la clé (et Codex le dit).
Constat exact et prudent.
[vraie] La documentation se contredit sur la seconde base trinke-contributions.
AUDIT-CODEX-2026-09-08.md:305 · 08/09
c1596768 sauvegardes/LISEZ-MOI.md:73-74 (« aucune copie et son contenu n'a pas été examiné ») contre ECHANGES-THEO.md:230 (« trinke-contributions : mesuré »).
Contradiction documentaire réelle au 08/09 ; LISEZ-MOI non modifié depuis dans v2.
[vraie] Le jeton de session, protégé en cookie HttpOnly, est aussi stocké en clair dans le stockage du navigateur.
AUDIT-CODEX-2026-09-08.md:321 · 08/09
c1596768 app.js:7621-7622 (tokenLocal/setTokenLocal) et 7641 (Bearer envoyé) ; functions/api/[[route]].js:11 (cookie 400 jours), 387 (SESSION_VIE 120 jours). Identique sur ef93abcf app.js:10304-10305, functions/api/[[route]].js:14 et 599.
Toujours ouvert : une seule faille d'injection de script suffirait à voler une session valable des mois.
[vraie] 193 affectations innerHTML dans app.js.
AUDIT-CODEX-2026-09-08.md:323 · 08/09
grep -c innerHTML sur app.js de c1596768 = 193 (243 sur ef93abcf).
Chiffre exact ; la surface a grandi depuis.
[perimee] La politique de sécurité du contenu ne limite pas les scripts.
AUDIT-CODEX-2026-09-08.md:325 · 08/09
c1596768 public/_headers:6 et functions/_middleware.js:14 : « frame-ancestors 'none' » seul. Sur ef93abcf : _headers:11 porte une CSP complète (17/10), mais _middleware.js:14 est inchangé ; or la page / passe par les Functions (_routes.json), donc la CSP complète ne s'applique très probablement pas à la page de l'app (DÉDUIT, rapport-securite.md b1).
Corrigé dans la v2 : la CSP complète est servie sur la page de l'app (mesuré sur l'aperçu le 20/10).
[perimee] L'inscription révèle si une adresse a un compte avant de compter les essais.
AUDIT-CODEX-2026-09-08.md:333 · 08/09
c1596768 functions/api/[[route]].js:808-812 (409 avant tropDeMailsIP). Sur ef93abcf functions/api/[[route]].js:1430-1436 : le compteur par source passe AVANT le 409 (correctif « revue sécurité » du 16/10).
Corrigé pour l'essentiel : la réponse distingue toujours une adresse prise, mais le sondage est plafonné à 20 par heure et par source.
[vraie] Les limiteurs laissent tout passer quand la base répond en erreur.
AUDIT-CODEX-2026-09-08.md:333 · 08/09
c1596768 functions/api/[[route]].js:611 et ef93abcf functions/api/[[route]].js:896 : « catch (e) { return false; } /* en cas de doute on laisse passer */ ».
Toujours ouvert, par choix écrit (ne jamais bloquer un vrai joueur) ; acceptable tant que D1 est rarement en erreur.
[perimee] Les erreurs internes partent au téléphone et rien n'est journalisé.
AUDIT-CODEX-2026-09-08.md:341 · 08/09
c1596768 functions/api/[[route]].js:3117. Sur ef93abcf : detail retiré et table erreurs + noteErreur (functions/api/[[route]].js:772-788, commit eac0acf0 du 19/09). Reste vrai : aucun gestionnaire global error/unhandledrejection dans app.js v2 (rapport-securite.md).
Corrigé côté serveur ; la télémétrie côté téléphone manque toujours (faible).
[vraie] Lire une conversation déclenche des écritures globales et des réponses qui grossissent avec l'historique.
AUDIT-CODEX-2026-09-08.md:349 · 08/09
c1596768 functions/api/[[route]].js:2403 (purgeMessages = DELETE global, l.539), 2433 (DELETE frappe), 2451-2482 (réactions et ids sans limite). Sur ef93abcf : le DELETE frappe passe au ménage toutes les 5 min (functions/api/[[route]].js:3252, accepté par Theo le 09/09) ; purgeMessages (3218), réactions et ids complets restent.
En partie ouvert : coût D1 qui croît avec l'usage, sans casse fonctionnelle.
[vraie] La liste des discussions plante au-delà d'environ 99 amis plus groupes.
AUDIT-CODEX-2026-09-08.md:366 · 08/09
c1596768 functions/api/[[route]].js:2553-2567 (un « ? » par fil, plus s.id). Identique sur ef93abcf functions/api/[[route]].js:3381-3396. Limite de 100 paramètres : documentation D1 connue, non relue ici faute de réseau.
Toujours ouvert : invisible aujourd'hui, casse la liste pour un utilisateur très connecté.
[vraie] Le paquet envoyé par l'hôte d'une partie en ligne n'est pas contrôlé.
AUDIT-CODEX-2026-09-08.md:376 · 08/09
c1596768 functions/api/[[route]].js:2777-2781 (slice(0,400), Number(tours)). Sur ef93abcf functions/api/[[route]].js:3625-3631 : refus au-delà de DECK_MAX=400 et toursBorne() (fiche du 09/09) ; contenu des éléments et taille en octets toujours libres.
Partiellement corrigé ; seul un hôte connecté peut abuser.
[exageree] Deux gestes simultanés sur un même tour peuvent s'écraser.
AUDIT-CODEX-2026-09-08.md:378 · 08/09
c1596768 functions/api/[[route]].js:2826-2827 : seul le joueur dont c'est le tour peut écrire (joueurs[tour % n] === s.id). La course suppose donc que la MÊME personne envoie « A » et « V » en même temps ; app.js dédoublonne les envois identiques en vol. Code identique sur ef93abcf functions/api/[[route]].js:3680-3691.
Défaut théorique réel (lecture puis écriture sans condition) mais quasi inatteignable en jeu.
[perimee] Chaque e-mail contient un bouton « undefined » et un lien « undefined ».
AUDIT-CODEX-2026-09-08.md:386 · 08/09
gabarit() extrait de c1596768 et exécuté hors réseau avec les paramètres des 4 appels : 3 « undefined », dont href="undefined" et « Si le bouton ne marche pas : undefined ». Même test sur ef93abcf : 0 (commit a2bc828c « e-mails sans bouton vide »).
Vrai au 08/09, corrigé dans v2.
[vraie] Un échec d'envoi d'e-mail invalide l'ancien code et consomme un renvoi.
AUDIT-CODEX-2026-09-08.md:390 · 08/09
c1596768 functions/api/[[route]].js:941-944 (UPDATE) avant 956-958 (envoi). Sur ef93abcf functions/api/[[route]].js:1581 avant 1594 : identique.
Toujours ouvert : rare (panne du fournisseur), coûte un renvoi sur trois.
[vraie] Quitter un groupe ou une partie et créer une partie en ligne sont des suites d'écritures non protégées.
AUDIT-CODEX-2026-09-08.md:400 · 08/09
c1596768 functions/api/[[route]].js:2333-2340 (DELETE puis UPDATE séparés) ; schema.sql:233 idx_live_fil non unique. Identique sur ef93abcf (functions/api/[[route]].js:3147-3154, schema.sql:278).
Toujours ouvert : incohérences possibles sur double appui ou coupure, sans perte de données majeure.
[perimee] Deux requêtes sur les parties balayent toute la table ; trois index semblent inutiles.
AUDIT-CODEX-2026-09-08.md:411 · 08/09
EXPLAIN QUERY PLAN rejoué en SQLite : schema c1596768 → « SCAN parties » pour les deux ; schema ef93abcf → idx_parties_hote_fin et idx_parties_mode_fin (commit e0c193d9 du 09/09). idx_essais_cle et idx_lj_live retirés ; idx_devices_vu gardé avec la bonne raison (ORDER BY, pas de filtre) : la remarque de Codex était exacte.
Corrigé dans le schéma ; leur pose en production n'est pas vérifiable d'ici.
[vraie] Les tests sont nombreux mais ne cherchent pas les classes de défauts de l'audit.
AUDIT-CODEX-2026-09-08.md:428 · 08/09
c1596768 : test-atelier-limites.py vise .av-bas (1 occurrence) absent de public/ ; test-app-tient.py:133 seuil > 900 ; CLAUDE.md liste 3 bancs hors porte ; pas de .github/. Sur ef93abcf : test-atelier-limites.py retiré avec l'avatar (d20860b8, 02/10), test ticket ajouté (test-live-ticket.mjs), mais toujours ni CI ni test d'injection de panne ou d'invité de groupe , d'où ac-12 encore ouvert.
Toujours ouvert sur le fond : les défauts ac-07, ac-10, ac-12 passent encore une suite verte.
[vraie] Le contrat verif.js passait avec 19 739 contrôles.
AUDIT-CODEX-2026-09-08.md:524 · 08/09
Arbre c1596768 extrait par git archive dans le bac à sable, node verif.js hors réseau : « 19737 controles passes (version soiree-v627) », sortie 0. Écart de 2 : hors dépôt git, le contrôle « travail sauvegardé » ne peut pas tourner.
Chiffre exact à l'environnement près.
[inverifiable] Résultats d'exécution des bancs navigateur pendant l'audit.
AUDIT-CODEX-2026-09-08.md:540 · 08/09
Bancs Chromium non relancés sur c1596768 (seuls des journaux sur c4cefbc0 et v2 existent dans le bac à sable, autre révision).
Plausible et cohérent avec les commentaires des bancs, mais pas rejoué.
[vraie] Zoom bloqué sur iOS, boutons retour sans nom, toast muet, jeux sur canevas sans alternative.
AUDIT-CODEX-2026-09-08.md:444 · 08/09
c1596768 app.js:14 (gesture* annulés) ; index.html : 30 boutons « ‹ », 1 seul avec aria-label (donc 29, pas 27) ; toast l.989 sans rôle ; 3 <canvas> (467, 487, 605) ; 2 role="dialog" pour 13 .modal. Sur ef93abcf : gesture toujours bloqué (app.js:14), 32 boutons « ‹ » sans nom sur 36, toast l.1321 sans rôle, 1 role=dialog pour 14 modales.
Toujours ouvert (le chiffre 27 est légèrement sous-estimé) : pincement-zoom impossible et lecteur d'écran qui annonce « ‹ ».
[vraie] Fichiers monolithiques difficiles à vérifier.
AUDIT-CODEX-2026-09-08.md:458 · 08/09
c1596768 : 17 207 / 3 119 / 2 873 / 8 533 lignes exacts ; 785 déclarations « function » (environ 900 avec fonctions fléchées, ordre de grandeur juste). Sur ef93abcf : app.js 19 928, route 4 002, verif.js 9 433, CLAUDE.md 2 905.
Toujours vrai et aggravé ; coût de relecture, pas un bug.
[vraie] Seule la moitié du contenu a été relue par un humain.
AUDIT-CODEX-2026-09-08.md:468 · 08/09
Sortie de verif.js rejoué sur c1596768 : « Contenu du jeu relu : 784/1444 (54 %) [associe 537, theo 247] · non relu : 660 · 5 cartes validees en attente ». État sur v2 non mesuré ici (contenu refondu, cartes-fr.json).
Chiffres exacts au 08/09.
[perimee] Le contrôle de version réveille le réseau même écran éteint.
AUDIT-CODEX-2026-09-08.md:482 · 08/09
c1596768 app.js:1984-1996 sans garde. Sur ef93abcf app.js:2479 « if(document.hidden)return; » (fiche 2026-09-08-appel-reseau-toutes-les-deux-minutes).
Vrai au 08/09, corrigé.
[vraie] Chargement initial lourd, non découpé.
AUDIT-CODEX-2026-09-08.md:488 · 08/09
c1596768 : app.js 1 207 501 octets, style.css 671 086 octets (655 Kio) ; ASSETS de sw.js = 15 entrées. Sur ef93abcf app.js passe à 19 928 lignes.
Toujours vrai ; impact à mesurer sur iPhone, comme Codex le recommande.
[vraie] Entre le clone analysé (b1f165ef) et c1596768, rien de servi au public n'a changé.
AUDIT-CODEX-2026-09-08.md:523 · 08/09
git log b1f165ef..c1596768 : 5 commits ; git diff --stat : .githooks/pre-push, ECHANGES-*.md, une fiche echanges, sauvegardes/ (3 fichiers). Aucun fichier de public/, functions/, live/, schema.sql.
Affirmation exacte : l'audit vaut bien pour c1596768.
[vraie] Points sains à préserver.
AUDIT-CODEX-2026-09-08.md:622 · 08/09
c1596768 functions/api/[[route]].js:339 (cookie HttpOnly; Secure; SameSite=Lax), token_hash/code6_hash en sha256, sw.js:39 (sort sur /api/), index.html:1142-1151 (4 scripts, tous locaux). Nuance v2 : Turnstile, script tiers conditionnel (rapport-securite.md G24).
Points sains confirmés au 08/09.
[vraie] Quand une partie reprise remplace une loi de table, la carte de fin annonce la fin d'une autre loi (et perd le prénom).
echanges/CODEX-2026-10-13-chasse-aux-bugs-REPONSE.md:13 · 13/10
Code v968 : carteDeRechange remplaçait la loi seule. Corrigé le 14/10 par 9e5f4c69 (remplaceDansPaquet, app.js v2 l.3732-3742 : la loi de rechange garde son numéro et sa fin reprend son texte). Contrôle ACCES-REPRISE-03 (loi + fin) vert sur v2 (verif.js rejoué : 22 822 contrôles passés).
Bug réel, corrigé et toujours corrigé dans v2.
[vraie] Une loi libre « sans filtre » sauvegardée reste servie dans une partie reprise « En famille ».
echanges/CODEX-2026-10-13-chasse-aux-bugs-REPONSE.md:29 · 13/10
publicOk laisse passer toute carte sans id (app.js v2 l.9434) et cartePermise ne regarde que les droits d'accès (l.326) : aucun correctif dédié n'a été écrit. Le scénario est devenu inatteignable parce que « Avec qui ? » est masqué depuis v970 (AVEC_QUI_VISIBLE=false, l.2751 ; le banc test-options-tenues montre « famille retenu → potes »).
Défaut réel jamais corrigé, seulement endormi : il revient le jour où « En famille » est réaffiché.
[vraie] En mode « En couple », environ la moitié des 50 cartes sont des cases vides « Carte à écrire ».
echanges/CODEX-2026-10-13-chasse-aux-bugs-REPONSE.md:43 · 13/10
Confirmé par la fiche de Romain du 13/10 (commit 4ac49d4e : « En couple laisse environ la moitié d'une partie en Carte à écrire »). Traité en retirant le choix de l'écran (v970, 3d773607) ; v2 : 0,0 case vide sur 50 dans test-options-tenues (couples retenu → potes).
Problème réel, résolu en masquant le mode, pas en écrivant les cartes.
[inverifiable] Le parcours complet de l'app (v967/v968) ne produit ni erreur JavaScript, ni carte en double, ni {j1} non remplacé.
echanges/CODEX-2026-10-13-chasse-aux-bugs-REPONSE.md:79 · 13/10
Les preuves (journaux, captures) sont dans /private/tmp sur le Mac de Romain, absentes du dépôt. Rejouer les parcours demande un navigateur ; non fait ici (lecture seule, hors réseau).
Affirmation plausible mais non vérifiable depuis le dépôt.
[vraie] En Multijoueur, l'hôte envoyait la position des cartes dans le fichier, pas leur identité : deux téléphones à des versions différentes lisaient des cartes différentes (et un gratuit pouvait recevoir une carte payante).
echanges/CODEX-2026-10-13-relecture-REPONSE.md:7 · 13/10
Code v965 (1bca56c4) app.js l.14811 : envoi.deck = indexOf de chaque carte ; l.15511 muCarteDe lit state.content.cards[i]. Corrigé par 893ac0e2 (v967) : l'identifiant voyage avec la position ; contrôle ACCES-REPRISE-01 vert sur v2.
Bug réel (bloquant), corrigé.
[vraie] Reprendre un Classique commencé avant v963 sert encore des phrases devenues payantes.
echanges/CODEX-2026-10-13-relecture-REPONSE.md:17 · 13/10
Corrigé par 893ac0e2 (clAssainit, app.js v2 l.8684-8688 et 8904). Preuve que le défaut existait : verif.js de v967 rejoué avec l'app.js de v966 donne exactement 25 échecs ACCES-REPRISE (comme annoncé par le commit).
Bug réel, corrigé. Aujourd'hui sans effet tant que le paiement est fermé (tout le monde est « payé », app.js l.303).
[vraie] Choisir « Action » sur une Soirée reprise pouvait afficher une carte payante.
echanges/CODEX-2026-10-13-relecture-REPONSE.md:27 · 13/10
Corrigé par 893ac0e2 : avSert repasse la carte servie au verrou (app.js v2 l.5540-5561) et assainitPaquetSoiree assainit le paquet restauré (l.3746). ACCES-REPRISE-03 vert sur v2.
Bug réel, corrigé.
[vraie] Une partie Multijoueur créée avant v963 ouvrait « La cible » (payant) à un compte gratuit.
echanges/CODEX-2026-10-13-relecture-REPONSE.md:37 · 13/10
Corrigé par 893ac0e2 : mjdJeuPourMoi (app.js v2 l.16105-16138, 16305) remplace OPEN[jeu] direct. ACCES-REPRISE-04 vert sur v2.
Bug réel, corrigé.
[vraie] Le contrôle BOUTIQUE-05 de verif.js ne détectait pas qu'on casse le filtre des mini-jeux payants.
echanges/CODEX-2026-10-13-relecture-REPONSE.md:51 · 13/10
Reproduit à l'identique : v965 (1bca56c4) avec la mutation && -> || dans jeuxPossibles = « 21223 controles passes, Deploiement autorise ». Sur v2 la même mutation est refusée (BOUTIQUE-05 : 19 jeux au lieu de 9).
Le garde-fou ne gardait rien ; il est maintenant réel.
[vraie] La v965 a retiré 43 cartes, rien d'autre, et le total de contenus est 2 131.
echanges/CODEX-2026-10-13-relecture-REPONSE.md:67 · 13/10
Comparaison content-fr.json 9bb3f4ba -> 1bca56c4 : 1117 -> 1074 cartes, 43 retirées, 0 modifiée ; + 1057 phrases des Classiques = 2131.
Codex a vérifié juste.
[vraie] La porte de test ?acces=paye ne s'ouvre qu'en local.
echanges/CODEX-2026-10-13-relecture-REPONSE.md:65 · 13/10
app.js v2 l.272-280 : accesTestLocal() rend null si hostname n'est pas exactement 127.0.0.1 ou localhost.
Pas de contournement du paiement par l'adresse.
[vraie] Un abonnement résilié ou un achat remboursé pouvait redevenir « payé » si Stripe livrait les notifications dans le désordre.
echanges/CODEX-2026-10-15-audit-trinke-REPONSE.md:15 · 15/10
Code v1020 (b07c1684) [[route]].js l.1709-1712 : le statut est recopié depuis l'événement reçu, sans relecture. Corrigé par a8bc474d : relecture de l'abonnement et du paiement chez Stripe (v2 l.1274-1282 et 2011-2019). test-paiement.mjs v2 rejoué hors réseau (Stripe simulé) : 105 contrôles verts ; à v1020 il en passait 95 sans ces cas.
Faille d'argent réelle, corrigée avant l'ouverture du paiement (toujours fermé).
[vraie] Garder seulement « Duel » dans les réglages fait planter le lancement de la Soirée.
echanges/CODEX-2026-10-15-audit-trinke-REPONSE.md:29 · 15/10
Reproduit : test-options-tenues.js sur v1020 plante avec « TypeError: Cannot read properties of undefined (reading 't') ». Sur v2 le même banc passe (duelJouable grise la case, filet l.3885-3889).
Bug réel, corrigé. Petite réserve : le filet réintroduit des jeux décochés si la liste se vide, ce que Codex demandait d'éviter.
[vraie] N'importe qui connaissant l'identifiant d'une partie pouvait parler en direct sous le nom d'un autre.
echanges/CODEX-2026-10-15-audit-trinke-REPONSE.md:41 · 15/10
live/src/index.js : sans LIVE_SECRET, le nom vient toujours de qui= (l.87-101, commentaire « l'ancien comportement reste »). Corrigé par ticket signé (a8bc474d, 4eb4f0f6, f45d5c87), test-live-ticket.mjs rejoué : 13 contrôles verts. Mise en service en production (secret posé ?) invérifiable ici.
Faille réelle ; la correction n'agit que si le secret est posé des deux côtés.
[vraie] Une partie payante Sans filtre contient 7 à 9 cases vides de Défi sur 50.
echanges/CODEX-2026-10-15-audit-trinke-REPONSE.md:55 · 15/10
Corrigé par a8bc474d (emprunte, app.js v2 l.3906-3910 : un type à court prête sa case à un autre jeu coché). test-options-tenues v2 : 0,0 case vide sur 50 pour paye·potes·hard ; test-tirage-soiree v2 : 2 000 parties, 0 case à écrire.
Défaut de contenu réel, corrigé côté moteur.
[vraie] Le vérificateur passait au vert sur v1020 malgré les bugs trouvés.
echanges/CODEX-2026-10-15-audit-trinke-REPONSE.md:69 · 15/10
Rejoué sur une archive de b07c1684 : « 22269 controles passes » (1 de moins car FONDS-04 exige python3, absent ici). Vert alors que le Duel planta et que les webhooks étaient faux : les contrôles verts ne couvraient pas ces cas, comme Codex le dit.
Confirme qu'un « verif.js vert » ne prouve pas l'absence de bugs.
[vraie] Le jeu « Pour combien ? » est trop pauvre en phrases pour être jouable en Chill.
echanges/CODEX-2026-10-15-pour-combien-BRIEF.md:3 · 15/10
cartes-fr.json à f45d5c87 : 31 « pour_combien » dont 1 soft, 24 chaud, 6 hardcore. Aujourd'hui (v2) c'est pire : 4 phrases (1 soft, 3 chaud, 0 sans filtre) et test-options-tenues v2 range « Pour combien » parmi les classiques indisponibles à TOUS les niveaux et ambiances.
Un des cinq Classiques n'est jouable nulle part dans v2.
[perimee] Commande à Codex : 12 phrases Chill et 8 Sans filtre.
echanges/CODEX-2026-10-15-pour-combien-BRIEF.md:21 · 15/10
Livré conforme (fichier présent : 12 soft + 8 hard, auteur codex ; second lot lots-16-10/pour-combien-codex-v2.json, 13 cartes). Mais aucune n'est entrée dans l'app (0 sur 20 dans cartes-fr.json v2) et le cadrage du brief (« trace hors de la table », téléphone) a été abandonné le 16/10 (77e4c8cb, 11e8b2c4 : « au plus 3 cartes téléphone », « un pari à table »).
La commande a été honorée mais n'a rien changé au jeu.
[vraie] Codex a livré 20 cartes Chill (9 / 7 / 4).
echanges/CODEX-2026-10-13-cartes-chill-FINI.md:1 · 13/10
echanges/CODEX-2026-10-13-cartes-chill-LOT.json : 20 cartes soft (preferes 9, action 7, gage 4). Les « 40 candidates » ne sont pas dans le dépôt (invérifiable).
Livraison conforme à ce qui est dit.
[vraie] Codex a relu 26 cartes de Claude : 8 gardées, 18 refusées.
echanges/CODEX-2026-10-13-relecture-croisee-chill-FINI.md:1 · 13/10
echanges/CODEX-2026-10-13-relecture-croisee-chill-REPONSE.json : 26 verdicts, 8 garde / 18 refuse.
Conforme.
[inverifiable] Deux bancs rouges ne sont pas de vrais bugs (espaces insécables ; route avis d'aperçu volontairement ouverte).
echanges/CODEX-2026-10-15-audit-trinke-REPONSE.md:77 · 15/10
Le premier banc demande un navigateur (non lancé ici). Pour la route avis d'aperçu, le rapport-base du 20/10 note une table avis_apercu sans index ni purge : « ouverte volontairement » reste un choix non documenté dans une fiche.
Possible faux négatif sur une route d'écriture ouverte aux invités.
[vraie] Les nouveaux contrôles détectent les 4 failles de reprise : 25 échecs sur l'ancienne version.
commit 893ac0e2 · 13/10
Archive 893ac0e2 + app.js de 893ac0e2^ (v966) : verif.js refuse avec exactement 25 problèmes, tous ACCES-REPRISE. Avec l'app.js de v967 : 21 481 contrôles passés.
Contrôles réellement efficaces.
[vraie] Le contrôle de la boutique teste maintenant le comportement, pas le texte.
commit 893ac0e2 · 13/10
Mutation rejouée sur la copie v2 : verif.js refuse (BOUTIQUE-05 : 19 jeux au niveau invité et gratuit, attendu 9). Base non mutée : 22 822 contrôles verts.
Le trou signalé par Codex (cx-09) est bouché.
[vraie] Les options choisies (ambiance, avec qui) sont enfin respectées : 6 écarts avant, 0 après.
commit 4ac49d4e · 13/10
Banc rejoué sur l'archive 4ac49d4e : vert. Même banc avec l'app.js de 893ac0e2 (v967) : « 6 écart(s) distinct(s) ».
Mesure exacte.
[vraie] Le bug n°1 de la chasse de Codex est corrigé.
commit 9e5f4c69 · 14/10
remplaceDansPaquet (app.js v2 l.3727-3742) recopie _loi et réécrit le miroir ; une loi déjà servie n'est pas remplacée (l.3755). ACCES-REPRISE-03 (loi) vert sur v2.
Corrigé et non revenu.
[vraie] Le désordre des notifications Stripe ne peut plus rouvrir un accès payé.
commit a8bc474d · 15/10
[[route]].js v2 l.2011-2019 (relecture subscriptions/{id}) et l.1274-1282 (relecture payment_intents, statut « rembourse »). test-paiement.mjs v2 hors réseau : 105 contrôles verts.
Correctif réel. Reste non couvert : remboursement d'un abonnement et contestations bancaires (déjà signalé par rapport-boutique-legal).
[vraie] Les deux bugs de tirage signalés par Codex sont corrigés.
commit a8bc474d · 15/10
test-options-tenues.js : plante sur v1020, vert sur v2 ; « Carte à écrire » 0,0/50 sur toutes les combinaisons v2 ; test-tirage-soiree v2 : 2 000 parties, 0 case à écrire.
Corrigé. Le filet (l.3889) remet des jeux décochés si la liste se vide : écart mineur à la consigne « ne pas réintroduire en silence ».
[vraie] L'usurpation de nom dans le direct est bloquée, à condition que le secret soit posé.
commit a8bc474d · 15/10
live/src/index.js v2 l.87-101 et route live/ticket ; test-live-ticket.mjs : 13 contrôles verts. La condition est écrite dans le message lui-même.
Protection réelle mais conditionnelle ; son état en production n'est pas visible depuis le dépôt.
[exageree] deploy.sh prévient tant que le ticket du direct n'est pas en service.
commit f45d5c87 · 15/10
deploy.sh v2 l.272-276 teste seulement la chaîne « live-4 » sur /sante. Or VERSION="live-4" est en dur dans live/src/index.js l.24 et /sante la renvoie que LIVE_SECRET soit posé ou non : un Worker redéployé sans secret (live/deploie-live.sh) fait taire le rappel alors que l'usurpation reste possible.
Faux sentiment de sécurité : le rappel peut se taire alors que la faille est ouverte.
[vraie] Le paiement reste fermé sans les 4 clés Stripe ; 51 contrôles.
commit 56b0ff32 · 14/10
paiementActif (v2 l.1118-1121) exige les 4 variables (et un vendeur complet en mode live). test-paiement.mjs rejoué sur l'archive 56b0ff32 : « 51 controles ».
Conforme.
[vraie] Le banc de paiement passe à 87 contrôles.
commit 8e8530d9 · 14/10
Rejoué sur l'archive 8e8530d9 : « paiement : 87 controles, joues sur le vrai serveur ».
Conforme.
[vraie] Connexion par mot de passe livrée et testée (54 contrôles).
commit 80fab682 · 16/10
test-mdp.mjs rejoué sur l'archive 80fab682 : 54 contrôles verts. Mais ce même commit casse test-schema-a-jour.js (« MIGRATION QUE JE NE SAIS PAS LIRE », ligne 408), garde de deploy.sh, ce que le message ne dit pas (déjà relevé par rapport-outillage et rapport-base).
Ce qui est annoncé est vrai ; ce qui est tu bloque deploy.sh depuis le 16/10.
[vraie] Protection contre la force brute par source (60 échecs / 15 min) ; 79 contrôles.
commit 797d2c6d · 16/10
[[route]].js v2 : ECHECS_SOURCE=60 (l.1033), compté sur la connexion (l.1537, 1832) ; un succès n'efface que la clé du compte (l.1843). test-mdp.mjs rejoué sur l'archive 797d2c6d : 79 contrôles ; sur v2 : 123.
Conforme.
[exageree] Les comptes sont protégés par un anti-robot, un refus des mots de passe fuités et une alerte de connexion.
commit 424974df · 17/10
Code présent, mais Turnstile est inerte sans TURNSTILE_SITE et TURNSTILE_SECRET (estHumain rend true, l.441-443) et l'alerte ne part que si l'e-mail est actif (l.486). Le contrôle des mots de passe fuités laisse passer si le service ne répond pas (l.468, 471). Le titre ne le dit pas, contrairement au commit du poivre (« inerte sans secret »).
Celui qui lit le titre croit la protection active alors qu'elle dépend de clés dont l'état n'est pas connu.
[perimee] Le code de récupération ne sert qu'une fois.
commit a2bc828c · 17/10
Vrai à sa date ; supprimé quelques heures plus tard par 73ad0ad9 (17/10) : le code de récupération ne connecte plus du tout (route login rend 410).
Sans objet aujourd'hui.
[vraie] Le code de récupération est abandonné au profit du « mot de passe oublié » par e-mail.
commit 73ad0ad9 · 17/10
Diff : le bloc de connexion par code est remplacé par json({erreur: MSG_CODE_FINI}, 410) ; compte/code/regenerer rend aussi 410. Restes non nettoyés dans v2 : l'e-mail d'alerte dit encore « Régénère aussi ton code de récupération » ([[route]].js l.495) et un commentaire dit la connexion par code « acceptée » (l.418-420).
Changement réel ; un compte sans e-mail n'a plus aucun moyen de récupération, et un e-mail envoyé aux joueurs renvoie vers une fonction morte.
[vraie] Les mots de passe sont « poivrés » quand le secret MDP_POIVRE est posé.
commit c8d28036 (+ 830a75d0) · 17/10
c8d28036 ne change que les numéros de version ; le code est dans 830a75d0 : hachMdp/verifMdp (v2 l.376-406), préfixe p1$, sans poivre rien ne change. Le message dit bien « inerte sans secret ».
Conforme et honnête sur la condition.
[vraie] 17 défauts corrigés.
commit 779abbf0 · 10/10
Commit de version ; les corrections sont dans 13 commits « Audit 10/10 (1..17) » du même jour (numéros 8 et 14 sans commit dédié, couverts par le récapitulatif d'ECHANGES-ROMAIN.md). Échantillon vérifié dans v2 : images bombe/crash dans le cache hors ligne (sw.js l.13), join/repondre refuse une action inconnue ([[route]].js l.2353), second prénom des lois (__loisJ2).
Corrections réelles et toujours présentes sur l'échantillon.
[vraie] La protection contre le double toucher ne marchait pas à cause d'un commentaire mal placé.
commit ecb45662 · 29/09
Diff : « // ... var c=... » mettait la déclaration de c dans le commentaire ; corrigé en /* */. Toujours correct dans v2 (app.js l.1496-1497).
Bug réel, corrigé.
[vraie] La fin d'une loi à deux joueurs nomme les mêmes deux joueurs que la loi.
commit 36d51687 · 10/10
Diff : state.__loisJ2 mémorise le second prénom, reporté sur le miroir ; présent dans v2 (4 occurrences) et sauvegardé dans SES_FIELDS.
Corrigé.
[inverifiable] Le blocage de la Course des As est corrigé, vérifié sur 20 000 courses.
commit 3e279167 (récapitulatif ECHANGES-ROMAIN.md) · 10/10
Le correctif est réel (diff : bascule sur « tete » sans As nommé + filet si aucune phrase). Le script des « 20 000 courses » n'est pas dans le dépôt. Le contrôle verif.js ajouté utilise une alternative « | » : un seul des deux motifs suffit à le faire passer.
Correctif probable ; le chiffre de validation ne peut pas être rejoué.
[vraie] L'audit a corrigé 98 cartes et en a retiré 151.
commit cdb09d77 · 16/10
Comparaison cartes-fr.json cdb09d77^ -> cdb09d77 : 1421 -> 1271 cartes, 150 identifiants retirés, 96 cartes modifiées (64 au texte). Écart de 1 et 2 avec l'annonce, sans portée.
Ordre de grandeur exact.
[vraie] Correction des Défis : 2 retirés, 1 doublon, 14 réécrits, 8 changés de type.
commit 45281072 · 16/10
cartes-fr.json : 11 identifiants retirés (2+1+6+2), 8 ajoutés (6 Duel + 2 Action), 14 textes réécrits. Les comptes tombent juste.
Conforme.
[exageree] Un même mini-jeu ne peut plus revenir deux fois dans une Soirée.
commit 327ae965 (code a2c4f2be) · 16/10
Le nombre d'intermèdes est plafonné au nombre de jeux distincts (planCases), mais la file miniQueueS (app.js v2 l.1250-1279) n'est jamais vidée entre deux Soirées (seuls les compteurs le sont, l.3960). Simulation de la fonction extraite (sim-minis.js) : 0 % de répétition pour une première Soirée, 17,2 % pour une deuxième Soirée enchaînée sans recharger la page.
Une table qui fait « Rejouer » peut revoir le même mini-jeu deux fois.
[vraie] estBloque distingue table absente et base en panne, avec un banc.
commit 8fe8af4c · 19/09
test-estbloque-catch.js rejoué sur v2 : « 8 controles passes (sain, table absente qui remonte, base tombee qui replie et journalise) ». Code toujours présent ([[route]].js v2 l.815-830).
Conforme.
[vraie] Le serveur journalise ses erreurs dans une table dédiée.
commit eac0acf0 · 19/09
test-table-erreurs.js rejoué sur v2 : 14 contrôles verts (compteur, tolérance, troncature, plafond 200). La création de la table en production était laissée à Theo : non vérifiable ici.
Code conforme ; existence de la table en production inconnue.
[vraie] L'app ne vérifie plus sa version quand l'écran est éteint.
commit c39d30c8 · 09/09
app.js v2 l.2473-2477 : la garde est toujours là, avec son commentaire.
Conforme et non revenu.
[vraie] 13 des 15 phrases du second lot Codex sont gardées pour le tri.
commit 1b9cd764 · 16/10
outils/cartes-soiree/lots-16-10/pour-combien-codex-v2.json : 13 cartes (5 soft, 8 hardcore). Aucune n'est dans cartes-fr.json v2.
Conforme ; lot toujours en attente.
[vraie] Lot Claude de 30 phrases ; 46 phrases Claude + Codex envoyées au tri.
commit 948bd0eb / 09f4738e · 15/10
pour-combien-claude.json : 30 (18 soft, 12 hard). 30 + 20 Codex = 50, dont 46 envoyées au tri ; 8 phrases Codex se retrouvent dans refusees-deja-vu.json.
Conforme ; aucune de ces phrases n'est dans l'app v2.
[vraie] Les quelque 25 défauts listés (mini-jeux, Soirée, Classiques, Course des As, navigation) sont corrigés.
commit 917681ae (v870) + 935ec100, abc891ce, 8b53e829, c8ef3a0f · 29/09
v870 ne fait que monter la version : les corrections sont dans les 5 commits qui précèdent. Chaque point de la liste a son code dans le diff (gardeDoubleAppui, verdictManche, rxEteint/maRAF, blTimer 15 s, « Trop petit pour être jugé », soloReport(gnErr), dec(), « prends », METRIC[idJ], avDisp, chronoStop, avNomAff, PU.gen, PLAFOND_J=14, elision(), pref-vide, numéro de reprise +1, CSS petit écran Cercle/Intrus/Case piégée, NAV_OK classement/amis, observateur sur body, fermeture par le fond). Tous encore présents dans origin/soiree-v2 (git grep). verif.js rejoué hors réseau sur 917681ae : 21 179 contrôles verts. Réserve : 935ec100 avait cassé la garde du double appui (commentaire qui avalait « var c »), réparé par ecb45662 le même soir (déjà audité, cm-18) ; verif.js était pourtant VERT sur 935ec100 (21 157 contrôles) : le contrôle lit le texte de la fonction, pas son effet.
Les corrections annoncées sont réelles et ont tenu jusqu'à la v2 ; seul le filet de contrôle n'aurait pas vu la garde cassée.
[vraie] Trois défauts corrigés : le compteur du choix Action ou vérité, le second prénom et l'arbitre d'une carte qui changeaient à la reprise, le bouton du Quiz qui promettait une partie.
commit 045899a0 (v876) + b9ada5ef · 30/09
Diff : majProgressionClassique(auChoix) +1 sur l'écran de choix ; tirageCarte()/noteTirage() + champ __tirage dans la session ; bouton .mv-bientot sans flèche. Contrôles REPRISE-TIRAGE, CL-06b, QUIZ-BIENTOT ajoutés ; verif.js rejoué sur 045899a0 : 21 308 verts. Toujours présents dans origin/soiree-v2 (tirageCarte, majProgressionClassique(true), mv-bientot).
Corrections réelles et toujours en place.
[vraie] Le Stop parfait a quatre paliers de résultat et la barre ne saute plus au Stop.
commit e1fda165 (v860) · 29/09
Code : TM_COEUR=1/3, coeur=ec<=demi/3, hit=ec<=demi, proche=ec<=demi+largeur ; verdicts 3 / 1 / 1 pour soi / 2 ; case .tm-txt de hauteur fixe (min-height 124 px, consigne et verdict superposés). Deux contrôles ajoutés.
Le comportement correspond mot pour mot au message.
[vraie] Le verdict du Cercle n'affiche plus « . . » et le score est cohérent avec les pourcentages affichés.
commit 65947434 (v848) · 29/09
score=round(round(rondeur*100)*round(tour*100)/100) ; le reçu est placé avant « Bois N » ; contours des réglages en CSS ; deux contrôles ajoutés.
Correction réelle.
[exageree] Les faux temps de Réflexe déjà enregistrés sont purgés une fois pour toutes.
commit 96eced5a (v847) · 29/09
Le jugement à l'instant du toucher (rxInstant, e.timeStamp) est bien en place. Mais la « purge » ne touche que le téléphone (drapeau local rx846, records lus en localStorage) : les faux temps déjà envoyés au serveur restent. Le commit 935ec100 du même soir l'admet (« le serveur garde les faux temps du Réflexe d'avant la v847 ») et ajoute un filtre de lecture à 80 ms, pas 100 : les faux temps serveur entre 80 et 100 ms restent visibles, et un vrai temps sous 80 ms est désormais ignoré.
Des « records » de Réflexe fantaisistes peuvent subsister dans les classements serveur.
[perimee] Le Réflexe a 5 feux (v845) puis 3 feux, et un appui à moins de 100 ms du vert est un faux départ (v846).
commits ee7df102 (v845) + 70720ab7 (v846) · 29/09
Vrai au moment du commit (RX_PAS=700, 5 puis 3 .f1-l, seuil Date.now()-reflexT0<100). Le seuil de 100 ms est retiré le même jour par 96eced5a (jugement à l'instant du toucher). Le bandeau descendu concerne bien 14 mini-jeux (liste :is() comptée).
Aucune : évolution voulue le jour même.
[exageree] Le commit corrige une collision de nom de fonction entre Cash out et la Course des As.
commit bd50ad0c (v824) · 29/09
Dans le parent, coDit n'existe qu'une fois (Course des As) et Cash out n'a aucune fonction homonyme : il n'y avait aucune collision à corriger dans le code publié. Le commit nomme sa nouvelle fonction cashDit, ce qui évite une collision qui n'a existé que dans un brouillon non commité. La réorganisation de l'écran, elle, est réelle.
Message trompeur sans effet sur l'app.
[vraie] La roulette russe est remplacée par une grille de six cases ; 47 règles CSS de l'arme retirées ; la garde du verdict différé est conservée ; 4 contrôles ajoutés.
commit d95fc3ea (v731) · 28/09
Compté par analyse du CSS avant/après : 37 règles de sélecteur + 10 @keyframes retirées = 47. Images revolver/barillet supprimées. Garde minuterieGen réécrite, contrôle reformulé + 4 neufs (six cases, tirage 1 sur 6, aucune arme, nom). verif.js rejoué sur d95fc3ea : 20 397 verts. Hors message : le rapport-jeu note que ce remplacement casse la règle « aucun jeu supprimé sans accord » (point laissé à Theo par 2dd5a2df).
Les chiffres sont exacts ; la question de fond (accord de Theo) relève d'un autre rapport.
[vraie] Retouches de mini-jeux : Séquence ajoutée (17 jeux), Case piégée gagnée à 5 cases sûres, historique de Crash out, sons, Stop parfait visible à l'ouverture, bouton passer sur La bombe et Le doigt, arrêt du chrono après validation.
commits 649be634, 2e6af19b, 68f8523b, 43384a45, 88f6654a, ed055ad4, 402114fc, 025c9250, c38a9b4a, 4f4f0420, 3f620b78, 1917724f · 24/09 au 29/09
Chaque diff fait ce que dit son message : contrôle JEUX.length===17 ; test des 5 cases .vide ; coHisto {nom,x,ok} 3 dernières ; sons « doigt » R7 et « win » N3 décrits dans CHOIX-SONS.md ; tmPrepare() à l'ouverture ; posePasserMini limité à miniReturn==='party' et coupe les minuteurs ; chronoStop déplacé après validerCarteEnAttente. Le nombre de jeux a depuis évolué (19 en v2), évolution normale.
Rien à signaler.
[vraie] Ces trois jeux se jouent toujours en « normal », même dans une série réglée autrement.
commit 9a82b3ce (v726) · 27/09
SANS_DIFF étendu à dix/blind/tap et diffJeu() utilisé par gt(), Timer aveugle et 5 parfait. Effet de bord non annoncé : le score envoyé au serveur gardait la difficulté de la série (multiplicateur 0,7 ou 1,4) jusqu'à la correction de 935ec100 (29/09), et en mode « aléatoire » il la garde encore.
Le jeu est bien en normal ; seul le score serveur a été faussé pendant deux jours.
[vraie] Le changement de Purple est annulé.
commits b17f1500 (v709) + d950482a (revert) · 27/09
git diff b17f1500^ d950482a : aucune différence. Le revert est exact.
Rien à signaler.
[perimee] Au Purple, on boit la pile, plafonnée par le niveau de gorgées choisi.
commit 4b277499 (v686) · 25/09
Vrai dans ce commit (gorg(dg(n))). Le même jour, d27b4def (v693, « décision Romain ») fait boire toute la pile hors plafond ; c'est l'état de la v2 (rapport-jeu G6 : règle « niveau = plafond » cassée pour 4 jeux, dont Purple).
Le message laisse croire que Purple respecte le plafond de gorgées ; ce n'est plus vrai depuis le 25/09.
[vraie] 12 cartes retirées des Classiques, listées dans un fichier.
commit 1237ba02 (v685) · 25/09
Comptage des textes de classics-fr.json avant/après : 12 retirés, 0 ajouté ; le fichier liste 12 items. La carte « plus d'une heure de route » est bien réécrite dans content-fr.json (id eb563f49).
Rien à signaler.
[vraie] On peut passer autant de cartes qu'on veut, en Soirée comme aux Classiques.
commit f06bbd11 (v648) · 24/09
plafondPassages() supprimé des deux chemins, contrôles GD-15 et GD-59 inversés (ils interdisent désormais le plafond). Le plafond était une règle de l'époque Theo (« sinon le groupe se fabrique un paquet sur mesure ») : son retrait est une décision de Romain, à connaître.
Une règle anti-abus de Theo n'existe plus, par choix assumé.
[inverifiable] Des vérifications manuelles ont été faites (14 passages, barre Trinkeurs de 0 à 14 joueurs, rejeu du localStorage de Romain, plan SQL identique).
commits f06bbd11, b42c9f6b, 25eab2fb, e0c193d9 (mentions de vérification) · 09/09 au 24/09
Aucun script, banc ni trace de ces essais dans le dépôt ; ce sont des déclarations. Le code concerné est cohérent avec ce qui est dit (rangée de ronds 5 puis « +N », plafond retiré), mais l'essai lui-même ne peut pas être rejoué.
Rien ne prouve ni n'infirme ces essais.
[vraie] Accueil « menu verre », barre Trinkeurs, réglages, présentation et glyphes refaits comme annoncé.
commits 2c8c94bf, 78e6061d, b42c9f6b, 21e247d9, b5df91c5, fe959dac, ce2ea56a · 23/09 au 25/09
Diffs conformes : h1 .mv-soiree à 5rem (80 px) et seul le mot Soirée touché ; ronds générés par trinqueur, 5 visibles puis +N, connecté en violet ; min-height 58px, 1rem, 600 ; page 3 de la présentation réécrite ; glyphes sans fond.
Rien à signaler.
[perimee] Les 74 cartes « Je n'ai jamais » disent « Si tu as déjà ».
commit 72835b1b · 21/09
Vrai dans le commit (74/74, et 64 sur 74 cartes sans le verbe « fait », recompté) ; verif.js rejoué : 19 771 verts. Remplacé le même après-midi par « Ceux qui ont déjà » (4a577682, « formule définitive »).
Aucune : décision révisée le jour même.
[vraie] Le mot Défi est retiré des textes génériques de l'app, les contrôles passent, et le formulaire reclasse 46 cartes, 4 règles + 12 neuves.
commit 89919807 · 21/09
app.js : descriptions d'ambiance, aperçu, toasts et étiquette « Carte » conformes ; verif.js rejoué sur 89919807 : 19 771 verts. Formulaire régénéré hors réseau : 4 règles parmi les cartes existantes, 12 règles neuves (exact). Sur les 46 reclassements, 32 se mesurent sur les cartes existantes (19 Action vers Défi, 13 Défi vers Action) ; le reste porte sur des cartes neuves sans identifiant stable, non recomptable.
Annonce exacte, le chiffre 46 n'étant que partiellement recomptable.
[vraie] La fusion du tri Codex donne 153 / 192 / 46 sur 391 cartes, dont 153 réécritures purement typographiques remises en garde.
commit 38443e46 · 20/09
Fichier triage-soiree-fusion-2026-09-20.json : 391 verdicts, garde 153, reecrire 192, retire 46, 5 nouvelles, compteur typo 153. typo() de app.js insère bien l'espace insécable avant ? ! : ; » %.
Rien à signaler.
[vraie] Chiffres et changements du chantier « tri des cartes de Soirée » (formulaire, page Soirée, vérificateur, décisions notées).
commits 5c0f7eb3, 8341783b, 2e4b603d, 4a0e72b5, ba2fbfe6, c2ac209f, 7e40906c, 25b20262, a9d23fc0, 25eab2fb, 6cd800e0, 1dd06983, 5c55380a, fb91179b, f05b98c6, ae1cc8dd, 21ece267, 43ace68b, 99be0645, f7dcf426, e0c0e8e2 · 21/09 au 24/09
Générateur rejoué hors réseau sur des copies extraites : 29 quiz neufs, 217 nouvelles et 28 règles (4a0e72b5), 55 variantes Codex (7e40906c), TYPE_FIX de 5 entrées, 32 règles sur la page brouillon, 12 contraintes devenues règles. Fichiers : 383 verdicts (a9d23fc0), 499 (25eab2fb, +2 ROMAIN_XP et 11 NEW_RX), 562 (1dd06983 : 6 réécritures, 2 intensités, 2 remises à confirmer), 24 intensités = 15 + 9 (6cd800e0), liste FINI de 29 (5c55380a), TEL_OK de 7 (fb91179b). « Loi de table partout » : « règle maudite » ne reste que dans les archives. La réparation 8341783b ne touche que le champ qui, verdicts et notes intacts.
Chiffres conformes aux fichiers.
[exageree] 66 cartes raccourcies ; plus aucune carte proposée ne dépasse 108 caractères.
commit c7a8ea94 · 22/09
Le 66 est exact (COURT 0 → 18 ; 48 cartes neuves changées). Mais le maximum de 108 ne vaut que pour les cartes neuves (120 → 109) : après le commit, des cartes existantes proposées à Romain font encore 130 caractères (830a2a90, « garde ») et 123 (544194c7, Quiz) ; 11 cartes non retirées dépassent 108.
Romain a pu croire que tout le paquet respectait sa règle de longueur.
[fausse] Le fichier des verdicts de Romain contient 551 verdicts.
commit 1f251f6e · 23/09
Le fichier commité triage-soiree-romain-v2-2026-09-21.json contient 562 verdicts (557 non vides). 551 est le chiffre du commit précédent 082126ad. Le commit suivant 1dd06983 annonce bien 562.
Simple chiffre périmé dans un message.
[fausse] Le travail du 19/09 (table erreurs + estBloque) n'ajoute que 3 contrôles, pas 11.
commit 3d94b3df · 19/09
verif.js rejoué hors réseau : 19 757 contrôles sur b6acc37d (avant) et 19 768 sur 8fe8af4c (après), soit +11, ce qui correspond aux 10 lignes de contrôle ajoutées dans verif.js plus un contrôle calculé. Le chiffre « faux » d'origine (+11) était le bon ; la « correction » (+3) est erronée. Les totaux absolus diffèrent de quelques unités selon l'environnement (copie sans git).
Le fil d'échanges avec Theo contient une rectification fausse.
[vraie] Avec le mélange actuel, une partie de 40 sert environ 14 cartes Action ou vérité, 7,5 Je n'ai jamais, 5,8 Gage, etc.
commit d2d1a044 · 19/09
Recalculé sur le content-fr.json du commit (261 cartes soft + chaud) : parts attendues sur 40 = action+vérité 14,2, jamais 7,5, gage 5,8, tu préfères 4,9, qui pourrait 4,1, quiz 3,4 : conformes. Le script outils/test-diversite-soiree.js cité n'a jamais été commité (les séries « 8,3 fois » ne sont donc pas recomptables).
Constat juste ; une partie des chiffres repose sur un script absent du dépôt.
[vraie] Le ménage de la table frappe passe à une fois par 5 minutes, et tous les contrôles cités sont verts.
commit 90218970 · 09/09
Diff conforme (DELETE FROM frappe sous menageDu 5 min ; filOuvert mémorisé par fil). Rejoué hors réseau sur une copie : verif.js 19 757 verts (19 759 annoncés, écart de 2 dû à la copie sans dépôt git), test-schema-a-jour vert, test-appels-serveur et test-une-regle-un-endroit sans échec. Déjà jugé BIEN par rapport-base et rapport-multijoueur.
Rien à signaler.
[vraie] Deux index ajoutés, deux doublons retirés du schéma, test du schéma vert.
commit e0c193d9 · 09/09
schema.sql conforme ; test-schema-a-jour.js rejoué sur la copie : « 9 migrations vérifiées sur 6 tables, aucune colonne manquante ». La pose en production reste un geste de Theo non vérifiable ici (rapport-multijoueur A3).
Rien à signaler côté dépôt.
[vraie] 172 cartes validées ajoutées à la Soirée et 4 cartes existantes corrigées.
commit 7fcfb150 (v879) · 30/09
content-fr.json : 310 → 482 cartes (172 nouvelles, 0 retirée) et 4 cartes existantes modifiées (831584ad, new-37, new-153, new-161). La parenthèse ne désigne pas ces 4 cartes mais ce qui n'est PAS versé (Duel, Pronostic, couples), comme le dit verser-soiree.py ; formulation ambiguë.
Chiffres justes, parenthèse trompeuse à la lecture.
[vraie] Le standard de rédaction s'appuie sur 674 puis 832 et 920 verdicts réels de Romain ; « sans rire » est banni.
commits fd2cd7e3, 013ceba4, f254baec, 39a6a804, 61cdaad8, 380428bd, 5ed9d89f · 30/09
validees.json + retirees.json : 331 + 343 = 674 (fd2cd7e3), 346 validées soit +15 (013ceba4), 395 + 437 = 832 (39a6a804, tableau de 160 cartes cohérent), 433 + 487 = 920 (f254baec). Quiz koala en double retiré (61cdaad8). Aucune occurrence de « sans rire », « garde ton sérieux » ou « premier qui rit » dans public/ de origin/soiree-v2.
Chiffres conformes ; la consigne a été tenue jusqu'à la v2.
[inverifiable] Juger une carte avec le carnet prédit mieux le tri de Romain que le standard seul (68 % contre 65 % sur 460 cartes).
commit 388d6178 · 30/09
Le commit n'ajoute que carnet.py (générateur) et la phrase : aucun script, échantillon ni résultat de la mesure « à l'aveugle » n'est dans le dépôt. Même si elle est juste, 3 points sur 460 cartes, c'est environ 14 cartes : l'écart est de l'ordre du bruit d'échantillonnage.
Le « mesuré meilleur » ne repose sur rien de rejouable et l'écart est trop faible pour conclure.
[fausse] 20 cartes validées ont été ajoutées, et le décompte des 43 cartes restantes est donné.
commit e28b2e21 · 14/10
Les 20 cartes ajoutées sont réelles : la Soirée passe de 1074 à 1094 cartes (ETAT.md du commit, et recomptage par outils/paquets.js). Mais le détail ne tombe pas juste : 9+5+8+1+1+20 = 44, pas 43. Et « 6 Je n'ai jamais (1 Chill, 3 Sans filtre) » n'en détaille que 4.
Rien de grave dans l'app, mais ces décomptes ne peuvent pas servir de référence pour le tri.
[vraie] Le paquet unique fait passer la Soirée à 1467 cartes et les Classiques à 1131 phrases, avec les mêmes listes pour les cinq types communs.
commit 25832f36 · 14/10
Recomptage avec outils/paquets.js sur une copie du parent puis du commit : Soirée 1094 -> 1467, Classiques 1057 -> 1131. Par type, les comptes sont égaux des deux côtés : Je n'ai jamais 169, Tu préfères 270, Qui pourrait 138, Vérité 117, Action 247.
Les chiffres annoncés sont exacts.
[perimee] L'outil audit-places.js ne trouve plus aucune carte mal placée, et les Tu préfères à option B elliptique sont réécrits.
commit 2538f9b1 · 14/10
Le jour même c'était vrai : node outils/audit-places.js sur une copie de 2538f9b1 donne « Défauts : 0 ». Sur origin/soiree-v2 (v1081), le même outil donne 347 défauts. 322 viennent d'un changement de format voulu du Bingo (« Pour toi : N gorgées », 9380677b du 16/10) que l'outil n'a pas suivi. Il reste environ 25 vrais défauts, dont 8 Tu préfères à option B elliptique (exactement le défaut corrigé ici, par ex. « Plus jamais d'internet ou d'alcool ? »), 6 doses hors de la plage de l'intensité et une faute « une fois , chanceux le bigre ». La remontée date du 16/10 : 1 défaut à 08144818, 250 à 9380677b, 353 au versement dcaf9f41. L'outil n'est branché ni dans verif.js ni dans deploy.sh.
Le défaut que le commit dit corrigé est revenu avec les versements du 16/10, et personne ne le voit, parce que l'outil n'est plus lancé.
[vraie] Le passage au fichier unique cartes-fr.json ne change aucune carte, et le gratuit garde 413 cartes.
commit d697db83 · 13/10
Comparaison rejouée hors réseau entre content-fr.json et classics-fr.json du parent et les vues composées par outils/paquets.js à d697db83 : 1074/1074 cartes identiques (id, type, intensité, texte, thèmes), 0 manquante, 0 en plus. 1057 phrases des Classiques identiques type par type. 413 cartes soft. Les « 72 combinaisons de tirage » n'ont pas été rejouées.
La fusion du 13/10 n'a perdu ni modifié aucune carte.
[vraie] 232 cartes sortent de l'app : 168 vont à trier, 63 sont refusées comme déjà vues, 1 était déjà tranchée. Le plancher de verif.js est abaissé en conséquence.
commit 44fed3e2 · 16/10
Fonds 1271 -> 1039 cartes (232 en moins), a-trier.json 53 -> 221 (+168), refusees-deja-vu.json 77 -> 140 (+63), sorties-non-triees-fonds.json = 232 entrées. Le plancher de verif.js passe bien de 158 à 61. Mais ce plancher (nombre minimum de cartes relues) a été abaissé 6 fois en 3 jours : 246 (6713dcc3, 14/10), 241, 240, 158 (cdb09d77), 61 (ici), 58 (7ccaeb95), 45 (6a4dd2a6, 16/10). À v1081, verif.js affiche « Contenu du jeu relu : 45/1813 ».
Les chiffres sont justes. Mais la garde « contenu relu » ne garde plus grand-chose : à chaque retrait de cartes, son seuil est abaissé à la main.
[vraie] La carte « mesure ta main » devient un Duel, 3 Pour combien sur les stories sortent, et 6 cartes de la réserve portent l'avis de Romain.
commit 062b4aa7 · 16/10
Diff du fonds : f2fe5189 passe de type action à duel, et f32595aa, f3c55f0f, fc85d1db (stories) sont retirées. L'avis « nul on le dégage » apparaît 6 fois dans a-trier.json. À v1081, aucune carte du fonds ne parle de story.
Fait comme annoncé, et toujours en place.
[vraie] Le lot contient 40 Duel (23/10/7), 16 ressorts, au plus 3 cartes par ressort.
commit 04389b9f · 15/10
lot-duel-1.json : 40 cartes de type duel ; intensités soft 23, chaud 10, hard 7 ; 16 valeurs de ressort distinctes, au plus 3 cartes par ressort.
Chiffres exacts.
[vraie] Un lot de 260 cartes à trier est créé.
commit fd2dd0cb · 16/10
outils/cartes-soiree/audit-2026-10-16/lot-audit.json contient 260 cartes.
Chiffre exact.
[vraie] Le versement de cartes ne peut plus remettre en jeu une carte retirée par Romain (garde FONDS-06).
commit 6d0c1766 · 16/10
La garde FONDS-06 est dans verif.js (ligne 8741 à v1081), et verif.js passe à v1081 (22822 contrôles, relevé du collègue). Un croisement texte exact entre retirees.json et cartes-fr.json à v1081 ne trouve aucune carte retirée revenue.
La garde existe et elle tient à la date de référence.
[vraie] Comptes du tri des 01 et 02/10 : 6 sorties et 1 corrigée, 7 gardées, 8 retirées de la page.
commit d122d2e5 + commit da0eaf45 + commit 3c44d87b · 01-02/10
content-fr.json à d122d2e5 : 6 cartes retirées, 1 modifiée. validees.json à da0eaf45 : 517 -> 524 (+7). a-trier.json à 3c44d87b : 167 -> 159 (-8).
Comptes exacts.
[vraie] Le compteur « 2170+ défis » des métadonnées correspond au contenu.
commit cce689a0 · 10/10
À cce689a0 : 1117 cartes Soirée + 1057 phrases Classiques = 2174, donc « 2170+ » est juste.
Pas d'affichage trompeur à cette date.
[vraie] La série de corrections de l'audit du 10/10 fait ce que chaque message annonce.
commit 7fc56771 + commit 28191eb6 + commit 7189980a + commit f5183c36 + commit e03ef86c + commit 48d13097 + commit bb530c54 + commit 8d09d221 + commit 0a38467b + commit 56661d26 + commit 1c873d78 + commit c95f3001 · 10/10
Chaque diff correspond à son message : popstate ne coupe plus les minuteries ; .set-rg[hidden]{display:none} ; filtre parleAlcool ; 23 lignes supprimées de classics-fr.json ; les 3 cartes sans « boit » (vérifié dans content-fr.json avant et après) ; 400 « action inconnue » dans join/repondre ; regex TROIS_JOUEURS ; 8 en dernière carte. Les correctifs sont toujours présents à v1081. Deux trous de quelques secondes, sans publication entre les deux : 7189980a a mis par erreur en commentaire la remise à zéro de la couleur et de la consigne du « 5 parfait », réparé 45 s plus tard par 28191eb6 (la garde verif.js ajoutée ne l'aurait pas vu). c95f3001 cassait TE-04 de verif.js, réaligné 15 s plus tard par 1c873d78.
Corrections réelles et durables.
[fausse] La rangée « Mode clair » n'apparaît plus dans les Réglages.
commit ea07fab1 · 07/10
v928 pose l'attribut hidden sur la rangée, mais la feuille de style garde « #m-settings .set-rg{...display:flex} » (style.css:9025 à ea07fab1), qui l'emporte : la rangée restait affichée. Romain l'écrit lui-même le 10/10 dans 8d09d221 « Mode clair vraiment retiré » : « le Mode clair, retiré le 07/10, restait affiché ».
Pendant 3 jours, un interrupteur visible ne faisait rien de durable : la préférence était effacée à chaque démarrage.
[exageree] Un audit complet a été fait et tous les bancs sont à jour.
commit eb0be629 · 07/10
Le même soir, v954 laisse visible la rangée « Mode clair » retirée 3 heures plus tôt (v928, voir l'entrée précédente). Le banc test-reglages-rapides.py de ce commit attend encore cette rangée (ligne 111 : « set-clair », « Mode clair »). Le lendemain, 6a3dbd42 (v956) corrige encore un « Fermer » masqué sur petit écran. Le 10/10, la série « Audit 10/10 » corrige 17 points, dont un banc cassé depuis le 08/10. Le détail des 14 mini-jeux n'a pas été rejoué (bancs navigateur).
« Audit complet » laissait passer au moins un défaut visible à l'écran.
[perimee] Le banc des réglages rapides est réparé et passe.
commit 413bdb7f · 14/10
Le diff fait ce qu'il dit. Mais le banc a de nouveau échoué le 20/10 sur v1081 : copie-v2.test-reglages-rapides.py.log se termine par « la feuille ne s'ouvre pas : Timeout 10000ms » puis « visibles : [] », alors que la même exécution sur l'état de Theo passe. Cause probable (DÉDUIT, non rejoué) : la porte du compte obligatoire (d3c922a5, 16/10) masque l'écran que le banc ouvre sans compte. Détail : le message situe la panne au 07/10, mais la rangée n'était réellement masquée que depuis le 10/10 (8d09d221).
Le banc qui protège les Réglages ne protège plus rien depuis le compte obligatoire.
[vraie] Les 19 tests Node passent.
commit 234d2c41 · 02/10
Copie de 234d2c41 extraite : outils/ contient exactement 19 test-*.js, et les 19 sortent avec le code 0, hors réseau.
Affirmation reproduite.
[vraie] Seul un refus net (401/403) coupe le direct ; une absence de ticket retombe sur l'ancienne connexion.
commit 4eb4f0f6 · 15/10
app.js : « if(r.status===401 || r.status===403){ liveWS=null; return; } ouvre(null); » et .catch(ouvre(null)). La garde côté Worker (refus sans ticket une fois le secret posé) relève de f45d5c87 (déjà audité, cm-08).
Comportement conforme. La sécurité du direct dépend donc du secret posé sur le Worker.
[vraie] Un abonné qui achète l'accès à vie voit son abonnement résilié tout de suite.
commit c8cc81d2 · 14/10
resilieAbosApresAVie() est appelée dans enregistreCheckout après l'achat à vie, et elle est toujours présente à v1081 ([[route]].js:1227 et 1290). test-paiement.mjs (hors réseau, faux Stripe) passe à v1081 : « 105 contrôles ». Concorde avec rapport-boutique-legal A5.
Pas de double facturation abonnement + à vie, du moins sur le faux Stripe (le vrai Stripe n'a pas été testé ici).
[vraie] Une fiche client Stripe de test n'est plus réutilisée en mode réel.
commit 8b74a509 · 14/10
Les deux requêtes stripe_customer filtrent désormais « id LIKE 'cs_' + modeStripe(env) + '_%' ».
Corrigé comme annoncé.
[vraie] Le banc paiement vérifie qu'une clé réelle reste fermée tant que le vendeur n'est pas renseigné, et que l'e-mail part une seule fois.
commit 0cb29ec2 · 16/10
node outils/test-paiement.mjs (hors réseau, fetch remplacé) passe sur une copie de 0cb29ec2 et sur v1081 : « 105 contrôles, joués sur le vrai serveur ».
Banc vert, et toujours vert à v1081.
[vraie] Quand le paiement est fermé, tout le contenu est ouvert, et le banc l'attend.
commit 0b792573 · 16/10
app.js v1081:303 : « if(!paiementOuvert())return "paye"; », et la Boutique affiche « Tout est débloqué » (app.js:18967). Le banc navigateur lui-même n'a pas été rejoué.
Règle en place.
[inverifiable] Le banc du direct marche avec les tickets signés, et le script de mise en service est corrigé.
commit f0db743b + commit da0a8afd + commit 97818218 + commit dabf0163 · 16/10
Le banc parle au Worker réellement déployé (WS = wss://live.trinke.app/live) avec le secret ~/.config/trinke/live-secret : impossible hors réseau, sans le secret. Le relevé du collègue sur v1081 sans secret donne « le second téléphone n'a pas pu se brancher à l'objet ». Ce résultat est attendu sans secret et ne prouve rien dans un sens ou dans l'autre. Le banc hors réseau test-live-ticket.mjs passe à v1081 (13 contrôles).
On ne sait pas si le direct marche en production avec les tickets.
[exageree] « Avec qui ? » et « Sujets inclus » quittent l'écran, et les bancs mis à jour savent attraper l'ancienne version.
commit 3d773607 · 13/10
Le retrait est réel et tient à v1081 (AVEC_QUI_VISIBLE=false et SUJETS_VISIBLES=false, app.js:2751-2752). test-options-tenues.js passe sur v970 et sur v1081. Contre l'app.js de v969, il échoue, mais seulement parce qu'il ne retrouve pas ses repères dans le code (« un morceau d'app.js est introuvable »). Il n'a pas détecté un mauvais tirage. Le banc navigateur n'a pas été rejoué.
« Le banc échoue sur l'ancienne version » ne prouve pas ici qu'il attrape un retour du défaut.
[perimee] La Boutique n'encaisse rien, et invité et compte gratuit ont le même contenu.
commit d281bb26 · 13/10
Dépassé par la suite : Stripe Checkout en v988 (56b0ff32, 14/10), « paiement fermé = tout ouvert » (0b792573, 16/10), plus de jeu en invité (compte obligatoire, d3c922a5, 16/10). À v1081, niveauAcces() renvoie « paye » quand le paiement est fermé.
Ne pas lire ce message comme l'état actuel de la Boutique.
[perimee] Le trousseau iCloud enregistre le code de secours à la création, et ce code est toujours amené à l'écran.
commit 3f38fd9a + commit 5309e183 + commit 7fbfc5ae + commit 002105e7 + commit 3ccf76fd · 16/10
Moins de 2 heures plus tard, 72717578 retire ces champs et écrit : « Romain a constaté sur son iPhone que Safari ne le proposait jamais ». Le volet trousseau ne marchait donc pas sur iPhone. Depuis v1081 (73ad0ad9), le code de récupération ne connecte plus personne et n'est plus montré (rapport-comptes A12).
Promesse d'interface qui n'a jamais tenu sur iPhone pour le trousseau, puis retirée.
[vraie] L'écran du code ne présente plus le code au trousseau, et une garde négative l'empêche de revenir.
commit 72717578 · 16/10
Les champs username/new-password sont retirés, autocomplete="off". La garde négative MDP-23 est ajoutée dans verif.js, et verif.js passe à v1081.
Fait comme annoncé.
[vraie] Le poivre est fait en v1080, et le banc mot de passe compte 122 contrôles.
commit 3193ba93 (origin/main seulement) · 17/10
node outils/test-mdp.mjs (hors réseau, fetch remplacé) sur une copie de c8d28036 (v1080) : « 122 contrôles ». La section ⑲ existe. La réponse dit origin/soiree-v2 = c8d2803 à ce moment, ce qui est cohérent. Les « deux sabotages refusés » ne sont pas rejouables en lecture seule. Le poivre est inerte sans secret (rapport-comptes A11).
Chiffres reproduits.
[vraie] Depuis v1081, le code TRK- ne connecte plus personne (réponse 410), et le banc compte 123 contrôles.
commit 1430e5b6 (origin/main seulement) · 17/10
test-mdp.mjs sur v1081 : « 123 contrôles ». [[route]].js v1081:1855 et 3869 : json({erreur: MSG_CODE_FINI, code_fini: true}, 410), pour login et pour regenerer. Les parties « WebKit » et « en ligne » ne sont pas vérifiables en lecture seule.
Fait comme annoncé. La prod v1059 n'a pas ce changement tant que v1081 n'est pas déployée (rapport-base).
[inverifiable] La nouvelle porte du compte n'ajoute aucun défilement sur trois tailles d'écran.
commit 397d5325 · 16/10
Mesure de rendu non rejouée : les bancs navigateur ne démarrent plus sur la copie v1081 (porte du compte, voir co-15). Le CSS montre bien une boîte à débordement caché.
On ne peut que faire confiance à la mesure de Romain.
[inverifiable] Affirmations de rendu à l'écran (tient sur, deux lignes, cotes mesurées, vu en WebKit).
commit 32156292 + commit b8590d13 + commit 011891e0 + commit 381ffefa + commit 6a3dbd42 + commit 539f6a1f + commit ea599d3e + commit 37276cc2 · 07-17/10
Les diffs vont dans le sens annoncé (liens en ligne, règles du Purple, prénom #pu-qui, bouton Passer). Le rendu lui-même n'a pas pu être rejoué hors navigateur.
Ces commits ne sont ni confirmés ni démentis.
[vraie] Le bouton de lancement des mini-jeux est toujours en bas.
commit 0e85fd62 + commit 55f01f43 · 16/10
Le diff vide positionCta. Le commentaire ajouté dit : « Remplace le centrage du 27/09 (demande Theo) ».
Vrai, mais cela défait explicitement une demande de Theo du 27/09. Le message ne le signale qu'en commentaire de code.
[vraie] Le code de l'avatar est conservé sur la branche archive/avatar, en v911.
commit d20860b8 · 02/10
origin/archive/avatar existe. Son sw.js porte soiree-v911, et sa pointe d76b1488 ajoute 2 retouches de bancs à la v911.
Rien de perdu.
[vraie] Petits correctifs, ajustements de bancs et de contenu, dont le diff correspond au message.
commit 231d5950 + commit b5840770 + commit f941f07c + commit 22312903 + commit 2c6ae21c + commit 4911a7af + commit a99cbbb4 + commit 1648178b + commit d76b1488 + commit fa9b865b + commit fe4ff3a0 + commit c63c3eb3 + commit 755331c3 + commit 4a1900d9 + commit 62437a90 + commit b64c4349 + commit d827e082 + commit 7f3234c0 + commit e3288df1 + commit 476b8ee9 + commit ec613ddb + commit d64392f6 + commit fd69d668 + commit 778de3e2 + commit 5ba0fffd + commit 9218266b + commit 7cbe2fa6 · 01-16/10
Diffs relus. Points vérifiés : amEnVol toujours présent à v1081 (app.js:18762) ; (100% - 290px)/4 est négatif sous 290 px utiles ; 62437a90 ne touche que outils/propositions/ (rien d'appliqué) ; b64c4349 ne change que les ronds (.hav, .cl-av), pas la barre ; la carte « âge exact » est bien en famille à v1081. Le Joker de d64392f6 a été réécrit dès le lendemain (af15f017, v1022), ce qui est une évolution normale. Tous les bancs Node hors réseau passent à v1081, sauf test-schema-a-jour.js (déjà connu).
Aucun écart trouvé.
[vraie] schema.sql corrigé recrée 22 tables, dont blocages et signalements.
ECHANGES-THEO.md:36-42 · 08/09
schema.sql de 2cd3974d exécuté dans SQLite en mémoire (python sqlite3) : 22 tables hors sqlite_*. Le décompte en production reste invérifiable hors réseau.
La correction du schéma a bien été faite et elle tient.
[exageree] La base locale .wrangler, créée depuis schema.sql, prouve que le catch d'estBloque mord déjà ; le bac à sable « sert ».
ECHANGES-THEO.md:117-122 et 137-139 · 08/09
Lecture seule de .wrangler/state/v3/d1/miniflare-D1DatabaseObject/c3e4...sqlite : 278 528 octets, dernière écriture le 26/07 22:42, 20 tables applicatives + _cf_METADATA (d'où « 21 »). Le blocage (TE-21) date du 27/07 (rapport-securite.md G15) : la base est simplement antérieure à la fonction, elle ne prouve rien sur schema.sql. Personne n'y a écrit depuis 6 semaines.
L'argument « il mord déjà » a servi à faire passer estBloque en tête des priorités, puis a été redescendu le même soir dans la fiche.
[fausse] Deux fois le même jour, le côté Theo a affirmé que les messages ou le push de Romain n'étaient pas arrivés.
ECHANGES-THEO.md:196-201 et 334-341 (c1596768, b4269cbe) · 08/09
Rétracté par le côté Theo lui-même : 9 entrées étaient dans ECHANGES-ROMAIN.md au dernier commit de Theo (vérifié par la fork commits, th c1-22), puis a01e78dd (20h19) était déjà dans le clone quand le côté Theo le déclarait absent.
Deux fausses accusations transmises à Romain le premier jour du canal ; la règle « chercher le CONTENU, jamais un commit neuf » en est sortie.
[fausse] Le côté Theo ne modifie pas echanges.js cette nuit-là, et pas sans banc.
echanges/2026-09-08-le-canal-ne-dit-pas-ce-que-l-autre-a-lu.md (Réponse) · 09/09
Phrase introduite par f2ff58d8 (09/09 00:20, git log -S). 22 minutes plus tard, c4cefbc0 (00:42) ajoute 88 lignes à outils/echanges.js et écrit dans la même fiche « Et c'est fait, l'outil le calcule déjà » ; aucun fichier de banc dans c4cefbc0 (git show --stat : 2 fichiers). Les deux phrases contradictoires coexistent dans la fiche.
La fiche dit à Romain deux choses incompatibles, et la règle « code = passe avec banc » posée par Theo n'a pas été tenue par lui.
[vraie] La porte bloque un arbre non commité mais pas un commit non poussé.
ECHANGES-THEO.md:155-158 · 08/09
d3dc19e3:verif.js:7790 (git status --porcelain) ; d3dc19e3:deploy.sh ne contient aucune vérification origin/push (grep vide).
Diagnostic exact ; il s'est vérifié le 17/10 (v1060 à v1077 seulement sur la machine de Romain et sur l'aperçu).
[vraie] L'archive histoire-du-produit compte 117 documents d'environ 42 000 lignes, sans autre projet.
ECHANGES-THEO.md:299-301 · 08/09
Copie c4cefbc0 : 118 .md dont le LISEZ-MOI (+27 fichiers html/json/py), 42 369 lignes de .md ; grep -i jardinage|toolsranks|novabiz|bot-trading|fpv : 0 fichier.
Le versement est conforme à ce qui a été annoncé (la fork commits note un écart de taille 4,1 Mo annoncés contre 3,9).
[vraie] Le contrôle de relecture compte 784 cartes relues sur 1 444.
ECHANGES-THEO.md:244-247 · 08/09
node verif.js sur la copie c4cefbc0 (scratchpad/audit/verif-theo.out) : « Contenu du jeu relu : 784/1444 (54 %) [associe 537, theo 247] ».
Le chiffre est exact ; il est tombé à 45/1806 (2 %) sur v1059, voir rapport-outillage.md point 3.
[perimee] trinke-contributions (mémoire des relectures, 9,4 Mo, sans copie) doit être sauvegardée.
ECHANGES-THEO.md:249-252 · 08/09
git ls-tree origin/main sauvegardes/ : seul trinke-db-2026-09-08.sql.gpg ; aucun commit dans sauvegardes/ après 01761fff (08/09) sur les deux branches. La seule sauvegarde de trinke-db date aussi du 08/09 (rapport-base.md point 3).
Six semaines plus tard, ni la base des relectures ni celle des joueurs n'ont de copie récente, alors que la table achats (obligation comptable) existe en production.
[vraie] schema.sql manque 4 colonnes posées par migration ; il déclare 28 index.
ECHANGES-THEO.md:278-280 · 08/09
f2ff58d8:schema.sql : 0 occurrence de difficulte, joueurs_n, perf, avatar2 ; corrigé dans c5c36fed (3, 2, 2, 3 occurrences). bc9815f4:schema.sql : 28 CREATE INDEX (définitions multilignes). La comparaison à la production reste invérifiable.
Constat juste, réparé le lendemain par c5c36fed avec une garde (cassée depuis le 16/10, voir rapport-base.md point 1).
[inverifiable] Le quota de lignes lues D1 est partagé au niveau du compte avec deux autres projets.
ECHANGES-THEO.md:55-60 · 08/09
Donnée de compte Cloudflare et de documentation ; aucun accès réseau ici. Le côté Theo l'a lui-même présentée comme « piste à vérifier ».
Sert de motif à l'urgence des index ; non contredit.
[inverifiable] L'absence d'identification de l'éditeur est pénalement sanctionnée (1 an, 75 000 €).
ECHANGES-THEO.md:417-424 · 09/09
Texte de loi non relu hors réseau ; la page en ligne affiche toujours « À renseigner » (origin/main:public/legal/index.html:64, origin/soiree-v2:...:70). La décision de la remplir est traitée par la fork commits (ff055ab9, périmée, haute).
Si la qualification est exacte, le manquement que le côté Theo a lui-même qualifié de pénal est en ligne depuis au moins le 09/09.
[vraie] Le serveur expose 76 routes.
ECHANGES-THEO.md:590-591 · 19/09
README 668ae6d3 annonce 76 routes (vérifié par la fork commits, th c1-27) ; outils/test-appels-serveur.py sur c4cefbc0 compte 74 routes par sa propre méthode (gates-theo.out) : ordre de grandeur juste.
Argument valable pour refuser une route de lecture du journal.
[perimee] DECISION de Theo : c'est Theo qui crée la table erreurs en production.
ECHANGES-THEO.md:601-603 (décision 19/09) et Sessions/2026-09-30-trinke-audit-depot-romain.md · 19/09
Note de session Theo du 30/09 : « Table erreurs ABSENTE de trinke-db (vérifié par moi, sqlite_master). Code en ligne depuis v711 (27/09), detail retiré des 500 : aucune trace d'erreur serveur depuis. Le CREATE TABLE était le geste de Theo. » Le code v2 ne la crée pas (aucun CREATE TABLE IF NOT EXISTS erreurs dans [[route]].js). Aucune trace d'une création après le 30/09 dans _MEMOIRE.
La condition 5 du côté Theo (« entre ce retrait et l'existence de la table, on est aveugle ») s'est réalisée par sa propre faute : serveur aveugle au moins du 27/09 au 30/09, et peut-être encore.
[vraie] Rien n'est engagé côté code tant que Theo et Romain n'ont pas parlé.
ECHANGES-THEO.md:105-106 et 176-177 · 08/09
Les commits Arand du 08/09 au 09/09 touchent schema.sql, outils/, fiches et fil ; le premier changement d'API (7b065f69, borne de tours) suit l'arbitrage écrit de la fiche borne-400.
Engagement tenu ce jour-là.
[inverifiable] Qui avait raison sur 50/1 000 : le côté Theo affirme que D1 relève du plafond de 1 000.
echanges/2026-09-08-le-cout-d1-par-requete.md:94-107 (réponse Theo) · 08/09
Aucun accès réseau ici ; ni l'un ni l'autre côté n'a fait l'essai (une invocation à plus de 50 appels D1 sur l'offre gratuite). Réserve de mémoire, non revérifiée : la page « Limits » de D1 affichait « 50 requêtes par invocation » en Free et 1 000 en Paid, ce qui contredirait la lecture du côté Theo. En revanche le comptage du code est vrai (slice(0,20), un appel par joueur, 11 badges : copie c4cefbc0 [[route]].js:1319-1389, app.js:1794-1806).
La décision prise (pas de batch) tient même si 50 s'appliquait, puisque le pire cas d'un client honnête est d'environ 44 ; mais un client forgé peut envoyer 40 badges et dépasser 50.
[vraie] Le serveur n'a aucun console.* et l'app ne lit jamais .detail.
echanges/2026-09-08-rien-ne-remonte-quand-l-app-casse.md (réponse Theo) · 08/09
Copie c4cefbc0 : grep -c console.(error|warn|log) [[route]].js = 0 ; grep detail public/app.js : aucune lecture de .detail (seulement des commentaires et #c-pr-detail).
Le retrait de detail était sans risque, comme annoncé.
[vraie] Un des trois index jugés inutiles par Romain sert à un tri.
echanges/2026-09-08-deux-index-manquants-sur-parties.md (réponse Theo) · 08/09
Vérifié par la fork commits (th c1-19) ; Romain l'a repris tel quel dans son « Fait » (e0c193d9).
Évite le retrait d'un index sur un motif faux.
[vraie] DECISION de Theo : borne de tours unique, refus au lieu de troncature.
echanges/2026-09-08-la-borne-400-du-paquet-multijoueur.md (arbitrage Theo) · 08/09
copie-theo et copie-v2 [[route]].js:61-66 : const TOURS_MAX = 50 et une seule fonction de bornage, identiques dans v1081 ; banc test-borne-tours.js : 46 contrôles verts (gates-theo.out).
Décision appliquée par Theo (7b065f69) et respectée par Romain.
[vraie] DECISION : garde locale qui compare le schéma avant/après migrations.
echanges/2026-09-08-le-schema-de-reference-est-en-retard.md (arbitrage Theo) · 08/09
c5c36fed : outils/test-schema-a-jour.js, vert sur c4cefbc0 (« 9 migration(s) vérifiée(s) sur 6 table(s) », gates-theo.out). La garde est cassée sur v2 depuis 80fab682 (16/10) : voir rapport-base.md point 1.
Garde bien conçue ; elle bloque aujourd'hui deploy.sh pour v1081.
[vraie] verif.js donne 22 458 contrôles sur v1059, le banc paiement 99, et les lignes citées (app.js:2746, 3601, 3649) sont exactes.
echanges/*.md : 6 réponses du 16/10 (7714c013) · 16/10
Relancé hors réseau sur git archive da0a8af : verif.js = 22 456 passés (les 2 manquants = contrôle git et FONDS-04, non joués hors dépôt/sans python3), test-paiement.mjs = « 99 contrôles ». git show da0a8af:public/app.js lignes 2746 show("s-sreg"), 3601 pub:, 3649 PLANCHER_FRAICHEUR=40 : exactes.
Les chiffres sont justes, mais la même sortie de verif.js affiche « Contenu du jeu relu : 45/1806 (2 %) » sans que la réponse du 16/10 le relève (rapport-outillage.md point 3).
[perimee] DECISION de Theo (16/10) : pastille Amis = demandes + invitations ; fiche passée en FAIT.
echanges/2026-10-13-onglet-amis-piste-a.md (réponse Theo 16/10) · 16/10
origin/soiree-v2 (v1081, 17/10) app.js majPastille : ong-dot-disc = AMIS.recus.length seulement ; les invitations restent sur ong-dot (Mon compte). Statut FAIT posé alors que la réponse demande encore ce travail.
Décision non appliquée, et le statut FAIT fait croire qu'il n'y a plus rien à faire.
[perimee] DECISIONS de Theo (16/10) : phrase Pass VIP, filtre des Classiques multijoueur par les droits de l'invité, part du Quiz plafonnée en Sans filtre, mesure de fraîcheur.
echanges/2026-10-13-un-seul-fonds-de-cartes-...md et 2026-09-19-...familles (réponses 16/10) · 16/10
grep « à la place à » / « jouez à la place » dans copie-v2 app.js : absent. PLANCHER_FRAICHEUR=40 inchangé (rapport-jeu.md G12). Classiques multijoueur : aucun commit après le 16/10 sur mjcConstruitPaquet/mjcPool (rapport-boutique-legal.md, condition 4). Ces réponses ne sont que sur main : origin/soiree-v2 ne contient pas 7714c013 (git branch -a --contains).
Les conditions posées avant l'ouverture du paiement ne sont pas remplies au 17/10 ; Romain a pu ne jamais les lire sur sa branche.
[vraie] Au 17/10, la branche de Romain sur GitHub était à v912.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md:8-15 (6ac176b0) · 17/10
git reflog refs/remotes/origin/soiree-v2 : d20860b8 (v912) au fetch du 16/10 21:55, puis ef93abcf au 17/10 17:18.
Le côté Theo a vu juste et a obtenu le push.
[inverifiable] Le choix « 8 caractères sans composition » est ce que recommande NIST.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md (décision 5, 17/10) · 17/10
Hors réseau. Le Claude de Theo l'a lui-même nuancé le 18/10 (Sessions/2026-10-18-trinke-lecture-du-push...) : de mémoire, la révision 4 de SP 800-63B exige 15 caractères quand le mot de passe est le seul facteur, ce qui est le cas de Trinke. Ni 8 (Theo) ni 8 avec composition (Romain) n'y seraient conformes.
L'argument d'autorité invoqué pour trancher contre Romain est fragile ; Romain a gardé sa règle (8 à 72, maj+min+chiffre, contrôle des fuites).
[inverifiable] Le runtime Workers refuse PBKDF2 au-delà de 100 000 itérations.
echanges/2026-10-17-mot-de-passe-a-la-place-du-code.md (Ce qui pourrait casser) · 17/10
Hors réseau. Cohérent avec le code de v1081 (100 000 tours + poivre MDP_POIVRE, réponse Romain) ; aucun banc ne l'éprouve en local (SQLite + WebCrypto Node, pas workerd).
Justifie le poivre ; le secret n'est pas encore posé (geste de Theo).
[perimee] Les défauts du 30/09 (plafond de gorgées, mode sans alcool, perdu = perdu, table erreurs absente, porte assouplie) devaient être écrits à Romain.
Sessions/2026-09-30-trinke-audit-depot-romain.md (REPRISE) · 30/09
ECHANGES-THEO.md : dernière entrée le 19/09 (b6acc37d) sur les deux branches ; commits Arand après le 30/09 : seulement 7714c013 (16/10) et 3 commits mot de passe (17/10), dont aucun ne cite le plafond (règle 7), le sans alcool (règle 9) ni la reprise (règle 4). Les mêmes défauts sont retrouvés le 20/10 (rapport-jeu.md points 1 et 4).
Le côté Theo savait depuis le 30/09 que des règles non négociables étaient cassées en ligne et ne l'a jamais écrit dans le seul canal qu'il avait lui-même imposé ; le 16/10 il a même validé v1059 sans le mentionner.
[perimee] État du projet donné par le MOC.
Jeux-Soiree/MOC-Jeux-Soiree.md (« État réel (10/09/2026) ») · 10/09
Fichier modifié le 11/09 (ls). Depuis : prod v875 (30/09) puis v1059 (16/10, _MEMOIRE) ; jeton de Theo avec D1 Edit depuis le 26/09 (mémoire reference-cloudflare-d1-remote) ; aperçu devenu la chaîne de publication de Romain (rapport-outillage.md point 2) ; deploy.sh refuse v1081.
Une session qui ouvre le MOC part de l'état d'il y a six semaines.
[exageree] Le plafond 50/1 000 a été tranché par une mesure.
_MEMOIRE.md:1383-1385 et MOC-Jeux-Soiree.md (08/09) · 08/09
La réponse de la fiche s'appuie sur une lecture de documentation (page des limites et changelog), pas sur un essai ; le côté Theo l'écrit lui-même (« à la source, plutôt que de te croire »). Seul le « pire cas ~44 » est un comptage du code.
Une lecture de doc est mémorisée comme fait mesuré et réutilisée « pour tous les projets Cloudflare » (mémoire project-trinke-depot-github).
[fausse] Sans droit D1 sur son jeton, Romain ne peut pas écrire dans trinke-db.
memoire project-trinke-depot-github.md (COTE CLOUDFLARE 08/09) · 08/09
Un déploiement Pages emporte les Functions liées au binding DB = trinke-db (wrangler.toml) : le code déployé par Romain écrit dans la base quel que soit son jeton. Constaté : apercu.sh publie les Functions de v2 sur la même base, et les migrations migrationMdp / migrationAchats tournent en tête de onRequest (rapport-base.md point 2). Même raisonnement dans reference-cloudflare-d1-remote.md (« c'est pour cela que deploy.sh ne contient aucune opération D1 »).
La protection invoquée n'a jamais existé : la base des joueurs a reçu des colonnes et tables d'une branche non fusionnée.
[perimee] deploy.sh est la seule porte et les deux associés travaillent sur main.
memoire project-trinke-depot-github.md et feedback-trinke-regles-jeu.md · 08/09
Romain travaille sur soiree-v2 et publie par outils/publier.sh sur l'aperçu (rapport-outillage.md points 1-2) ; deploy.sh refuse v1081 (test-schema-a-jour) ; verif.js compte 22 822 contrôles sur v1081 (verif-v2.out), pas « 2 000+ ».
Une session de Theo qui suit la mémoire croira que rien ne part en ligne sans deploy.sh.
[perimee] Règle : le compte s'ouvre par le bouton rond en haut à droite.
memoire project-trinke-comptes-amis.md (règle 3) et MEMORY.md · 25/07
Depuis le « menu verre », #home-moi est caché et son remplaçant jamais affiché (rapport-ecrans.md A2, R-style.css:9422) ; menu-verre présent aussi dans v1059 en ligne (12 occurrences dans da0a8af style.css). Le compte s'ouvre par l'onglet du bas ong-profil (index.html:1237-1238).
Une règle « non négociable » de la mémoire ne décrit plus l'app en ligne ; elle est soit cassée, soit à lever.
[perimee] Architecture et règles des comptes.
memoire project-trinke-comptes-amis.md (règles 1 et 6, piège code de récupération, CLI D1) · 25/07
Lien e-mail remplacé par un code à 6 chiffres le 09/08 (720e327c, route inscription/code dans c4cefbc0) ; CLI D1 fonctionnel depuis le 26/09 (reference-cloudflare-d1-remote.md) ; compte obligatoire et plus d'invité en v2 (d3c922a5, compteExige) ; code de récupération fermé en v1081 (410).
La mémoire décrit l'architecture de juillet ; plusieurs consignes (passer par le MCP, protéger l'affichage du code) n'ont plus d'objet.
[perimee] Description du projet (nom, adresse, contenu).
memoire project-jeu-soiree.md et ligne MEMORY.md « MVP jeu-soiree.pages.dev » · 25/07
Fichier daté du 25/07 (54 Ko). Le produit s'appelle Trinke, en ligne sur trinke.app ; content-fr.json et classics-fr.json sont retirés en v2 au profit de cartes-fr.json (rapport-ecrans.md, vue chiffrée).
Mémoire d'index trompeuse pour toute nouvelle session.
[perimee] Le design appartient à Theo et à sa boucle design.
memoire feedback-trinke-partage-roles.md · 29/07
Depuis septembre, Romain et son Claude dessinent et portent les écrans (onglet Amis « transcrit depuis le rendu ChatGPT validé », v935 ; menu verre) ; Theo a écrit le 17/10 souhaiter que « ce soit TON côté qui code ». La question « qui décide le design » est restée ouverte (_MEMOIRE 09/09).
La règle mémoire ne correspond plus au fonctionnement réel du projet.
[perimee] Les règles de jeu de Theo sont en vigueur dans l'app.
memoire feedback-trinke-regles-jeu.md (règles 2, 4, 7, 9) et feedback-trinke-cadre-cartes.md · 25/07
Vraies dans le code de Theo ; cassées dans v2 sans accord écrit : roulette russe remplacée (règle 2), plafond dépassé dans 4 jeux (règle 7), sans alcool troué au Palmier (règle 9), reprise qui contredit perdu = perdu (règle 4), cadre des cartes « entamé » (rapport-jeu.md points 1, 3, 4 et G9).
La mémoire décrit une intention, plus l'état du code ; s'y fier pour juger v2 ferait croire les règles respectées.
[vraie] Les 4 fiches marquées FAIT sont en ligne et vérifiées sur v1059 (da0a8af).
commit 7714c013 · 16/10
git log -1 da0a8af = « v1059 » et sw.js CACHE=soiree-v1059 ; PLANCHER_FRAICHEUR=40 à app.js:3649 et show("s-sreg") à app.js:2746 comme cité ; 56b0ff32 ancêtre de da0a8af. Mise en ligne réelle : inverifiable hors réseau.
Les citations de code des réponses du 16/10 sont exactes ; seules les mesures de prod restent non revérifiées.
[exageree] Les réponses du 16/10 valent décision de Theo et sont lisibles par Romain.
commit 7714c013 · 16/10
git branch -a --contains 7714c013 = main et origin/main seulement ; origin/soiree-v2 ne contient pas ce commit (ses fiches restent statut PROPOSE, réponse vide).
Sur la branche où Romain travaille, les décisions de Theo n'existent pas ; l'audit v2 a lui-même conclu « aucune trace écrite d'accord ».
[vraie] Le mot de passe était déjà implémenté côté Romain en v1077.
commit 6ac176b0 · 17/10
git grep -c mdp_hash a8211d4c (v1077) -- functions/api/[[route]].js = 14 ; introduit par c62e86d0 (v1069, 16/10).
Constat exact : la fiche de Theo arrivait après le code.
[vraie] Décision : table erreurs créée par Theo, pas de route de lecture.
commit b6acc37d · 19/09
origin/soiree-v2 [[route]].js : aucune route de lecture ni CREATE TABLE paresseux pour erreurs (seul le ménage DELETE l.782). Respect côté Romain : voir rapport-comptes.md A1. Création effective en prod : inverifiable.
Les conditions du 19/09 sont tenues dans le code.
[inverifiable] La doc Cloudflare dit que les journaux Pages ne persistent pas et que observability n'est pas une clé Pages.
commit b6acc37d · 19/09
Lecture réseau interdite dans cet audit.
Conclusion plausible, non revérifiée ici.
[vraie] Aucun bloc [observability] dans les deux wrangler.toml.
commit 3da35622 · 10/09
git grep -i observability 3da35622 -- wrangler.toml live/wrangler.toml : aucun résultat (idem origin/soiree-v2).
Le diagnostic « rien n'est collecté » repose sur un fait exact du dépôt.
[inverifiable] v628 déployée et index créés en production.
commit 3da35622 · 10/09
Production et D1 hors de portée (pas de réseau) ; le SQL cité correspond à la fiche e0c193d9.
Non contestable ici.
[vraie] La page légale n'a pas d'éditeur renseigné.
commit ff055ab9 · 09/09
git show ff055ab9:public/legal/index.html l.64 : <p id="editeur">À renseigner avant le lancement public.</p>.
Le manquement signalé était réel.
[perimee] Décision de Theo : remplir la page légale à son nom pour fermer le manquement.
commit ff055ab9 · 09/09
Toujours « À renseigner avant le lancement public. » sur origin/main (legal/index.html:64) et origin/soiree-v2 (:70) au 20/10 ; aucun commit de Theo sur ce fichier après le 09/09.
Le manquement qualifié de « délit pénal » par le Claude de Theo est resté en ligne six semaines, et la v2 ajoute une boutique payante.
[inverifiable] L'obligation d'identification est passée à l'article 1-1 de la LCEN.
commit ff055ab9 · 09/09
Texte de loi non consultable sans réseau.
Référence juridique non revérifiée ; le Claude de Theo dit lui-même ne pas être juriste.
[vraie] echanges.js calcule l'état « contre » depuis le parent du commit et retrouve 29f5153.
commit c4cefbc0 · 09/09
git show --stat c4cefbc0 : outils/echanges.js +88 ; lignes 78-140 (calcul par le parent, déclaré l'emporte, signalement des réécrits) ; 29f51532 existe.
L'outil promis est livré.
[fausse] Six commits ont été rebasés.
commit f2ff58d8 · 09/09
Corrigé par le côté Theo lui-même le lendemain (c4cefbc0 : « Indecidable : amend, rebase et cherry-pick donnent le meme signal »).
Le message de commit garde une affirmation retirée ensuite.
[fausse] Aucun paquet envoyé par l'app n'approche 400 ni même 50 éléments.
commit f2ff58d8 · 09/09
app.js à f2ff58d8 l.3117-3146 : buildDeck met TOUT le pool permis dans state.deck, envoyé tel quel (l.13721) ; content-fr.json = 391 cartes (l'arbitrage lui-même écrit « Soirée deck ≤ 391 »). Seul tours reste ≤ 40.
Le risque de troncature (9 cartes de marge) a été présenté comme non atteignable, alors qu'une Soirée tous thèmes à l'intensité maximale s'en approche.
[vraie] Il existe une quatrième écriture de envoi.tours, sans paquet, en app.js:13738.
commit f2ff58d8 · 09/09
git show f2ff58d8:public/app.js l.13738 : envoi.tours=Math.max(1,Math.min(9,...Manches||3)) ; écritures l.13722, 13727, 13735, 13738.
Le refus de la proposition de Romain était fondé.
[vraie] Borne de tours unique (TOURS_MAX, DECK_MAX), banc de 46 contrôles dans la porte.
commit 7b065f69 · 09/09
[[route]].js l.61-66 TOURS_MAX=50, DECK_MAX=400, l.2825 refus si deck.length>DECK_MAX ; deploy.sh l.43-45 ; banc relancé hors réseau sur extraction c5c36fed : « 46 controles passes ». Contrat : identifiants TOURS-01 à 07 (9 contrôles non recomptés).
Garantie posée et prouvée à sa date.
[vraie] schema.sql recrée la base et une garde locale le vérifie dans deploy.sh.
commit c5c36fed · 09/09
Relancé hors réseau sur extraction c5c36fed : « 9 migration(s) verifiee(s) sur 6 table(s), aucune colonne manquante » ; deploy.sh l.48-50 ; les 4 colonnes présentes dans schema.sql. Cassé depuis le 16/10 par 80fab682 : voir rapport-base.md point 1.
Vrai à sa date ; la garde bloque aujourd'hui deploy.sh sur v1081.
[vraie] Les boucles serveur sont bornées à 20 joueurs et 40 badges, et l'app définit 11 badges.
commit 1f9af78b · 08/09
[[route]].js à 1f9af78b : joueurs.slice(0, 20) l.1275, badges.slice(0, 40) l.1345 ; app.js l.1794 BADGES = 11 entrées. « 10 en production » : inverifiable.
Le chiffrage du pire cas est cohérent avec le code.
[inverifiable] Sur l'offre gratuite, D1 relève du plafond de 1 000 et non de 50.
commit 1f9af78b · 08/09
Doc Cloudflare non consultable (réseau interdit). Réserve : la page des limites D1 indiquait, à la connaissance de l'auditeur, « 50 requêtes par invocation (Free) / 1 000 (Paid) » ; le changelog du 11/02/2026 cité n'est pas revérifié. Voir er1-45, fi-24, ac-08 de l'audit Romain.
Si la page D1 dit encore 50 sur l'offre gratuite, le refus de l'urgence reposait sur une lecture incomplète ; le pire cas (~44) reste toutefois sous 50.
[vraie] detail n'est jamais lu côté app ; la ligne 3034 ordonne sur vu_le ; proposeMaj refuse de recharger pendant une partie.
commit 1f9af78b · 08/09
grep .detail app.js à 1f9af78b : 0 ; [[route]].js l.3034 « ORDER BY vu_le DESC » ; proposeMaj l.1979-1981 sort sur momentDelicat() (partie, série, multi) ; 0 console.* dans le serveur.
Les arbitrages s'appuient sur des lectures de code exactes.
[vraie] Paquet Soirée 391, Je n'ai jamais 267, Action ou vérité 288 ; plafonds 80 et 40.
commit 03c9f546 · 08/09
content-fr.json cards = 391 ; classics-fr.json : jamais 267, action 238 + verite 50 = 288 ; [[route]].js : slice(0, 400) l.2780, slice(0, 80) l.1322, slice(0, 40) l.1334/1345.
Fiche exacte ; elle contredit l'arbitrage f2ff58d8 du lendemain.
[exageree] L'archive versée fait 117 documents, 42 257 lignes, 4,1 Mo, sans autre projet ni secret.
commit d6cf4f0c · 08/09
git ls-tree d6cf4f0c archives/histoire-du-produit : 118 .md (117 + LISEZ-MOI), 42 348 lignes avec le LISEZ-MOI ; 145 fichiers pour 3 886 646 octets (3,9 Mo, pas 4,1). git grep jardinage|toolsrank|fpv|drone|sk_live : 0 ; seuls chemins machine = soiree-app.
Comptages exacts, taille légèrement surévaluée ; le balayage de confidentialité tient.
[vraie] ECHANGES-ROMAIN.md avait 9 entrées au dernier commit de Theo.
commit c1596768 · 08/09
Dernier commit Arand avant c1596768 = 01761fff ; git show 01761fff:ECHANGES-ROMAIN.md | grep -c '^## ' = 9.
L'aveu d'erreur est exact : le message accusateur transmis à Romain était faux.
[vraie] Le LISEZ-MOI des sauvegardes dit désormais que c'est un compromis.
commit c1596768 · 08/09
git show c1596768:sauvegardes/LISEZ-MOI.md l.46 : « Mettre la sauvegarde dans le dépôt est un compromis, pas une solution sans coût ».
Engagement tenu.
[vraie] Garde-fou structurel : seul le chiffré peut être suivi.
commit 875c889d · 08/09
git show 875c889d:sauvegardes/.gitignore : « * » puis !.gitignore, !*.sql.gpg, !LISEZ-MOI.md. Sauvegarde jamais refaite depuis : voir rapport-base.md point 3.
Garde-fou réel ; la sauvegarde unique du 08/09 vieillit.
[inverifiable] Export complet : 22 tables, 27 index, 1 012 lignes.
commit 875c889d · 08/09
Fichier chiffré, phrase de passe hors dépôt. Incohérence interne : bc9815f4 et ECHANGES-THEO disent « 28 index » identiques le même jour.
Écart 27/28 jamais expliqué (autoindex compté ou non).
[vraie] schema.sql passe de 20 à 22 tables avec blocages et signalements.
commit 2cd3974d · 08/09
grep -c 'CREATE TABLE' schema.sql : 20 à 2cd3974d~1, 22 à 2cd3974d. Existence en prod : inverifiable.
Écart de schéma corrigé dans le fichier.
[vraie] README : 16 mini-jeux, 31 bancs, 76 routes, app.js 17 200 lignes.
commit 668ae6d3 · 08/09
GAMES à 668ae6d3 : 16 entrées ; app.js 17 207 lignes ; 31 bancs confirmé par l'audit Romain (er1-01 : 19 + 12).
Le README transmis à Romain était exact.
[vraie] Fins de ligne normalisées en LF sur tous les clones.
commit 77f23ef3 · 07/09
git show 77f23ef3:.gitattributes : « * text=auto eol=lf », *.sh et .githooks/* en eol=lf.
Déploiement identique à l'octet quel que soit l'associé.
[vraie] Fichiers servis absents de git ajoutés.
commit b08f693e · 07/09
git ls-tree b08f693e public/ : robots.txt, screen-accueil.png, screen-partie.png présents.
Un clone neuf ne les efface plus en production.
[vraie] echanges.js lit maintenant les deux fils, avec un séparateur tabulation.
commit a24c1086 · 08/09
git show a24c1086:outils/echanges.js l.50-55 : --format=%cs%x09%an.
Défaut signalé par Romain corrigé le jour même.
[vraie] Le hook pre-push distingue retard et divergence.
commit 4e2d9cdf · 08/09
git show 4e2d9cdf:.githooks/pre-push l.40-48 : « ARRET : tu es EN RETARD sur le depot, tu ne reecris rien ».
Fausse alerte de réécriture supprimée.
[exageree] Les quatre défauts, dont le catch vide du service worker, sont fermés en v619.
commit 4acc8703 · 12/08
git show 4acc8703:public/app.js l.17095 : }).catch(function(){}); toujours vide ; fermé au commit suivant cdf91ce6 (v620). Les 5 bancs et AUDIT-01 à 04 sont bien ajoutés (git show --stat).
Un « fermé » annoncé une version trop tôt, corrigé le même jour.
[vraie] 76 routes gardées, bloques/debloquer sans appelant, deux branches destructives corrigées.
commit 4acc8703 · 12/08
test-routes-serveur.py ajouté et branché dans deploy.sh l.117 ; parties/confirmer l.1366 et groupes/repondre l.2296. Statut v2 : voir rapport-securite.md (G12-G15 intactes).
Garantie posée et toujours en place en v2 d'après l'audit sécurité.
[vraie] Catch du SW rempli ; test-hors-ligne retiré de la porte.
commit cdf91ce6 · 12/08
git show cdf91ce6:public/app.js l.17095 catch commenté et non vide ; deploy.sh l.173-182 : test-hors-ligne lancé à la main. Intact en v2 : rapport-securite.md G11.
Garantie intacte.
[vraie] av3-liste.js passe de 4 à 14 Ko.
commit 3a3ef582 · 12/08
wc -c av3-liste.js : 4 143 octets à 3a3ef582~1, 14 513 à 3a3ef582. Avatar retiré en v912 : voir rapport-ecrans.md.
Mesure exacte ; travail supprimé depuis par Romain.
[exageree] Le catalogue fait 502 images pour 3,1 Mo.
commit 935a06d1 · 11/08
git ls-tree -r -l 935a06d1 public/av3 : 502 .webp + 1 .json, total 1 947 350 octets (1,9 Mo). De même 32d91711 annonce 3 237 images et 23 Mo : git donne 3 238 fichiers, 15,8 Mo. Le chiffre annoncé correspond probablement à la taille sur disque.
Coût du catalogue surestimé d'environ 50 %, sans effet sur une décision connue.
[vraie] Le serveur refusait tout avatar de plus de 18 nombres ; corrigé en plage + banc.
commit 0bd69cd9 · 11/08
Diff [[route]].js : motif /^1(,\d{1,3}){17}$/ (18 nombres) remplacé par une plage ; outils/test-avatar-serveur.js ajouté.
Défaut réel fermé avant mise en ligne.
[vraie] Cause de la déconnexion à chaque rechargement : migration manquante dans session().
commit 8ffeb847 · 11/08
Diff 8ffeb847 : ajout de await migrationAvatar2(env) au point d'entrée, avec le commentaire d'incident.
Incident de production causé puis corrigé par le côté Theo le même jour.
[vraie] Banc chacun-son-tour : 24 contrôles.
commit 5dc3ec5a · 10/08
Relancé hors réseau sur extraction 5dc3ec5a : « 24 controles, tous justes ». Arbitre et 409 hors tour intacts en v2 : voir rapport-multijoueur.md A5.
Garantie intacte.
[inverifiable] Latence mesurée du Worker en ligne (et 7 ms, 100 ms/50 ms, 8 tirs sur 8 dans b56ade2b, e07c57cf, 26bae918).
commit bf444519 · 10/08
Mesures réseau ou de session, non rejouables hors ligne.
Chiffres de performance ni contestables ni confirmables.
[inverifiable] La sauvegarde se déchiffre et se recharge.
commit 01761fff · 08/09
Opération locale non tracée dans git (fichier clair supprimé) ; Romain l'a acceptée dans la fiche la-base-n-existe-qu-en-un-exemplaire.
Confiance raisonnable, pas de preuve rejouable.
[vraie] Compteurs de contrôles successifs (19 602, 19 634, 19 737, 19 738, 19 739).
commit bb22bb34 · 12/08
Ordre de grandeur cohérent avec verif.js relancé sur c4cefbc0 (v627 + docs) : 19 746 contrôles (scratchpad/audit/verif-theo.out). Valeurs exactes par commit non recomptées.
Les compteurs annoncés sont crédibles.
[vraie] Chaque commit annonce un nombre exact de controles verif.js passes.
commit 8c853a9c a 6bf2ea16 (60 commits) · 06/08-10/08
verif.js relance hors reseau sur une extraction `git archive` de chaque commit (+ public/robots.txt, non suivi par git en aout, repris de b08f693e) : le compte mesure vaut exactement le compte annonce moins 2 sur les 60 commits du lot (ex. 8c853a9c 18 478 contre 18 480, 68600879 18 225 contre 18 227, 6bf2ea16 13 209 contre 13 211). 1 des 2 points est explique : le controle `git status` ne tourne pas hors depot ; l'autre est un controle d'environnement non identifie.
Les compteurs de controles cites dans les messages d'aout sont fiables, a un ecart d'environnement constant pres.
[perimee] Les empreintes de commits citees dans les messages d'aout permettent de retrouver le travail (git revert).
commit 8c853a9c a 6bf2ea16 · 06/08-10/08
`git cat-file -t f68f306`, `2ef0781`, `c96f4d9`, `d887eac2...` (cite par le Revert 9ee90d41) : objet introuvable dans soiree-app. L'historique a ete reecrit lors de la sortie en depot autonome (b08f693e, 07/09). Le contenu, lui, est bien la : a9332139 = 24d1f135 (v558) au numero de version pres.
Toute empreinte courte citee dans un message ou une note anterieure au 07/09 est une impasse dans le depot actuel.
[vraie] La route friends renvoyait les statistiques completes aux demandes en attente ; corrige pour ne renvoyer que id, pseudo, depuis.
commit 5838ab9b · 10/08
`git show 5838ab9b -- functions/api/[[route]].js` : l'objet complet etait pousse dans amis/envoyes/recus ; apres, `attente = { id, pseudo, depuis }`. `friends/profil` exige deja statut 'accepte' (403 sinon).
Fuite de donnees reelle, correctement fermee a la source.
[vraie] Retirer la section des demandes envoyees supprime toute possibilite d'annuler une demande.
commit 8c853a9c · 10/08
Diff de 8c853a9c : la section envoyes et son bouton Annuler partent ; aucune autre porte n'est ajoutee.
Perte fonctionnelle assumee et ecrite.
[vraie] Le battement de rafraichissement des amis et discussions passe de 20 s a 3 s.
commit 86ad5446 · 10/08
`git show 86ad5446 -- public/app.js` : `},20000);` devient `},3000);`.
Multiplie par sept les lectures D1 par telephone connecte, cout que le fil du 08/09 (budget de lignes lues partage) n'a pas rappele.
[fausse] Le banc test-ecran-amis.py est devenu une porte de deploiement fiable.
commit 9fcf1274 · 10/08
Le meme jour, e5d93971 le sort de deploy.sh : « sur une machine chargee un tir sur deux mesure un ecran a moitie peint et refuse un deploiement pour un defaut qui lui appartient ».
Une porte annoncee fiable a ete retiree quelques heures plus tard pour instabilite.
[exageree] Apres quatre corrections, le banc qui joue ne refuse plus au hasard.
commit cfa7f6c4 · 10/08
095da0dc (meme jour) corrige encore « 4 causes » de blocage, 2a0bf3ea pose une « parade anti-faux-echec » pour tous les bancs Chromium, et le 10/09 ECHANGES-THEO.md dit encore que « On joue vraiment » a rate son premier tir.
Six tirs verts n'ont pas suffi : le banc est reste capricieux et a ete entoure d'une re-tentative.
[vraie] friends/repondre refuse desormais toute action autre que accepter/refuser.
commit 68600879 · 10/08
`git show 68600879:functions/api/[[route]].js` : `if (action !== "refuser") return json({ erreur: "action inconnue" }, 400);` avant le DELETE ; deploy.sh appelle test-appels-serveur.py et test-une-regle-un-endroit.py (4 mentions).
Le point « non fait » de v580 est ferme le lendemain ; toujours intact en v2 selon rapport-comptes.md.
[vraie] Accepter une demande depuis l'onglet Amis la supprimait en base.
commit b95aad97 · 09/08
Diff b95aad97 : `{id:id, ok:true}` devient `{id:id, action:"accepter"}` ; a b95aad97^ la route lit `{ id, action }`, n'UPDATE que si action === "accepter", sinon DELETE.
Diagnostic exact d'une perte de donnees en production.
[vraie] Le code d'inscription vit 10 minutes, 5 essais par code et 3 renvois, soit 20 tentatives maximum.
commit 720e327c / 9658c0a3 · 09/08
720e327c : `INS_VIE = INS_MIN * 60 * 1000` (commentaire 10 minutes), `CODE_ESSAIS = 5`, `if ((ins.envois || 0) >= 3)` ; 5 x 4 envois = 20. 9658c0a3 : sw.js reste a v578 comme annonce (« RIEN N'EST DEPLOYE »).
Arithmetique de securite juste.
[vraie] Les 202 « Tu preferes » des Classiques contiennent chacun exactement un « ou ».
commit 426cb4f5 · 08/08
classics-fr.json a 426cb4f5 : tu_prefere = 202 items, histogramme du nombre de « ou » = {1: 202} ; verif.js sur l'extraction affiche 784 relus.
La coupe a l'affichage ne pouvait pas mutiler un item.
[vraie] Avant ce banc, aucune verification ne jouait une manche ; le banc n'est pas encore dans la porte.
commit a4fb2b94 · 08/08
a4fb2b94:deploy.sh ne mentionne test-on-joue-vraiment.py qu'en commentaire (1 occurrence) ; il est branche par dee76808 (bloc `python outils/test-on-joue-vraiment.py ... Deploiement ANNULE`).
Aveu exact d'un angle mort, ferme deux jours plus tard.
[vraie] 46 cartes passent de « Refus » a « Sinon », 3 gardent « Si tu refuses », 122 des 150 Action/Verite sont refusables, 42 Qui pourrait.
commit a3918283 · 08/08
content-fr.json a a3918283 : action 82 + verite 68 = 150, dont 61 + 61 = 122 dont la sanction matche SORTIE_PAYANTE ; balance = 42 ; diff : 46 lignes retirees contenant « Refus », 44 ajoutees en « Sinon » + 3 en « Si tu refuses » (ecart de 1 dans le decompte, sans effet). 298 gorgees non recalcule.
Le cout de la decision de Theo etait chiffre juste avant d'agir.
[vraie] La passe v571 ramene a zero les cartes Action/Verite sans dose et porte le refus a 61/61.
commit 59635ab3 · 08/08
Recalcul avec le vrai splitSanction/SORTIE_PAYANTE : parent 3fa2d2b2 = sans dose 16/7, refus 44/54 ; 59635ab3 = sans dose 0/0, refus 61/61 (le « avant » annonce 43/53 differe de 1).
Correction de contenu exacte.
[vraie] 133 cartes sur 391 sont refusables et leurs gorgees etaient comptees meme quand le defi etait releve.
commit 3494d303 · 06/08
Le defaut est dans le diff (validerCarteEnAttente ajoutait la sanction dans tous les cas ; `var bue = c.refusable ? (c.issue==="degonfle") : true`). Recalcul hors navigateur du nombre de refusables a v511 : 123 (regle complete de l'app, sans {j2}) a 142 (sans exclure {j2}) ; 133 non reproduit, l'ordre « une sur trois » tient.
Le compteur de gorgees surestimait reellement ; le chiffre exact reste approximatif.
[vraie] Aucune des 74 cartes « Je n'ai jamais » de la Soiree n'etait dans le registre de relecture : les reecrire ne coute aucune validation.
commit 0f98286c · 08/08
Empreinte sha1(norm(texte))[0:10] de verif.js appliquee aux 74 cartes jamais de 0f98286c^ contre verification.json de 0f98286c^ : 0 sur 74.
La normalisation n'a detruit aucune relecture.
[vraie] Les 74 cartes jamais portent toutes la formule a deux points.
commit 9e94cec9 · 08/08
content-fr.json a 9e94cec9 : 74 cartes t=jamais, 74 matchent /Ceux qui l.ont fait : \d+ gorgées?\.$/.
Formule unique effective.
[vraie] Le retour arriere v562 ramene les fichiers a l'etat v558 sans trace du portage.
commit a9332139 · 08/08
`git grep 'data-carte\|jn-' a9332139 -- public/style.css public/app.js public/index.html public/sw.js` : aucune ligne ; `git diff 24d1f135 a9332139` sur les 4 fichiers = seulement ?v=558 -> ?v=562.
Retour arriere propre.
[vraie] apercu.sh ne publie jamais sur trinke.app ; deploy.sh republie l'apercu apres la production.
commit 32d2b96b / fb4f76a1 · 08/08
32d2b96b:apercu.sh = `node --check` puis `wrangler pages deploy --branch=apercu` ; fb4f76a1 ajoute dans deploy.sh `wrangler pages deploy --branch=apercu`.
Vrai pour le front ; mais l'apercu partage la base de production et n'a qu'un controle de syntaxe, ce qui est devenu la chaine de publication de Romain (voir rapport-outillage.md et rapport-base.md).
[perimee] Les routes join/* restent temporairement et seront retirees plus tard.
commit 33e6904d · 08/08
`git grep -c 'route === "join/' ` : 6 a 33e6904d, 6 a c4cefbc0 (09/09, dernier etat Theo), 6 a origin/soiree-v2. Le retrait promis n'a jamais ete fait.
Six routes publiques sans client restent ouvertes depuis plus de deux mois.
[exageree] L'orthographe « e-mail » a disparu de toute l'app.
commit e47dd60b · 08/08
A e47dd60b : 0 « e-mail » dans app.js et index.html (48 lignes avant), mais 27 lignes dans functions/api/[[route]].js dont des messages affiches dans l'app (« Cette adresse e-mail n'a pas l'air valide. », « Trop d'e-mails envoyes... ») et 1 dans public/legal/index.html.
La « deuxieme orthographe » que le commit voulait eviter subsiste dans les erreurs serveur affichees a l'ecran.
[inverifiable] L'acceptation des conditions peut se faire sans case a cocher, sous reserve d'un avis juridique.
commit e47dd60b · 08/08
Question de droit, aucune trace dans le depot d'un avis de conseil obtenu depuis.
Le point « a faire valider » est reste ouvert ; l'app vend desormais un Pass VIP (CGV, voir rapport-boutique-legal.md).
[vraie] Le controle d'age refuse un type non numerique ; le banc de 41 verifications est dans la porte.
commit 0014a3af · 07/08
Banc relance hors reseau sur l'extraction : « test age-inscription : 41 verifications, 0 echec(s) » ; deploy.sh:42-43 l'appelle ; ageValide verifie le type avant Number() (commentaire et code a 0014a3af).
Garde serveur d'age reelle.
[perimee] Decision de Theo : tous les comptes anterieurs au 07/08 seront supprimes sous une semaine.
commit cef849dd · 07/08
Non execute : ECHANGES-THEO.md du 09/09 releve 16 comptes, 9 dates de naissance, 0 compte supprime ; la fiche mot de passe (069a61c3, 17/10) compte encore 2 comptes sans e-mail (l'e-mail est obligatoire depuis le 25/07, ils sont donc anterieurs).
Des comptes sans date de naissance ni e-mail existent toujours, ce qui contredit la regle « date verifiee au serveur » et coute aujourd'hui une migration du mot de passe.
[vraie] Banc teinte avatar de 23 verifications, dans la porte.
commit 51f33586 · 07/08
Relance hors reseau : « test teinte-avatar : 23 verifications, 0 echec(s) » ; 2 mentions dans deploy.sh.
Conforme.
[vraie] Banc local-sans-mesure de 18 verifications, dans la porte.
commit dd06585c · 07/08
Relance : « test local-sans-mesure : 18 verifications, 0 echec(s) » ; 2 mentions dans deploy.sh. Les sabotages ne sont pas rejouables a l'identique.
Conforme.
[vraie] Banc Action ou verite de 21 cas dans la porte.
commit 0b777d67 · 08/08
Relance : 21 lignes « ok », « Tout passe » ; 2 mentions dans deploy.sh.
Conforme.
[vraie] Les bancs de gestes passent (35 et 41 cas) et 44 px CSS valent 7,3 mm sur iPhone 14.
commit 77ebfba7 / 5bdb2d88 / 1e980842 · 06/08
Relance hors reseau : test-geste-heures.js 35 ok / 0 echec, test-geste-retour.js 41 ok / 0 echec aux trois commits. 44 px x 3 / 460 ppi x 25,4 = 7,29 mm (densite iPhone 14 de memoire, non relue en ligne).
Conforme.
[vraie] Une table de 31 formes juge le bareme du Cercle parfait dans la porte.
commit a7f57d0b · 07/08
Relance de outils/test-bareme-cercle.js a a7f57d0b : « 31 controles passes, 0 echec(s) » ; deploy.sh:45-46 l'appelle.
« Inattaquable » reste un mot fort, mais la table annoncee existe et passe.
[vraie] La Bombe tire dans 77 categories.
commit 435b0821 · 07/08
BOMBCATS a 435b0821 : 77 entrees, 77 distinctes (16 avant).
Conforme.
[vraie] Le code de recuperation n'est stocke que hache.
commit 401fe0b5 · 07/08
401fe0b5 : schema.sql users = code_hash, code_sel, aucune colonne en clair ; route : PBKDF2, ITER = 100000, SHA-256.
Le retrait du bouton Copier etait fonde.
[vraie] Le masquage presence_off couvre toutes les sorties du statut en ligne d'autrui.
commit b15d5856 · 07/08
grep vu_le dans la route a b15d5856 : sorties vers autrui uniquement l.1312 (friends) et l.1671 (friends/profil), toutes deux masquees ; devices ne renvoie que les appareils du demandeur.
Vrai pour presence_off ; la fuite par demande en attente (meme route) n'a ete vue que le 10/08 (5838ab9b).
[vraie] Le profil lisait un champ inexistant de la table stats.
commit e153089e · 07/08
e153089e^ : app.js lit st.gorgees ; schema.sql stats a la colonne `bues`, pas `gorgees` (gorgees existe seulement dans party_players).
Conforme.
[vraie] Une difference d'accent ou de casse entre prenom et pseudo empechait l'envoi de la partie.
commit 6bf2ea16 · 06/08
6bf2ea16^:public/app.js : `if(l && l.n===moiNom)moi=l;` puis `if(!moi)return;`.
Diagnostic exact.
[fausse] Le commit 9a9af86d n'est qu'un addendum au document d'audit ; le code v510 est dans 272cf045.
commit 9a9af86d / 272cf045 · 06/08
`git show 9a9af86d --stat` : AUDIT-POINTS.md +55 mais aussi public/app.js +69 et verif.js +44 ; `git log -S'monRang=devant+1'` designe 9a9af86d : le vrai rang et MULTI-04 sont dans le commit « addendum », 272cf045 n'ajoute que la difficulte.
Un lecteur qui cherche le correctif du rang dans le commit v510 ne le trouve pas.
[inverifiable] Sur iPhone, au-dela de cinq doigts aucun evenement n'est emis.
commit 7c3d98b1 · 06/08
Comportement d'iOS non verifiable hors appareil ; le code plafonne bien le compte attendu.
Si la limite reelle differe, le plafond a cinq retient ou exclut un doigt a tort.
[vraie] Comptes de cartes et de selecteurs reecrits.
commit 3fa2d2b2 / 8c7fd8ac / b53fbea9 · 08/08
balance = 42 a 3fa2d2b2 ; diff 8c7fd8ac : 60 lignes retirees avec data-carte="jamais" ; diff b53fbea9 : 81 lignes retirees #s-game[data-carte], 83 ajoutees en :is(#s-game,#s-classic-run).
Conforme.
[vraie] Huit controles LEGAL existent et survivent a la reecriture de v574.
commit 44aad428 / 9293b0b5 · 08/08
verif.js a 44aad428 et a 9293b0b5 : LEGAL-01 a LEGAL-08 presents ; aucune ligne LEGAL retiree par 9293b0b5.
Conforme ; la question est devenue caduque avec le compte obligatoire de v2 (voir rapport-ecrans.md).
[inverifiable] Mesures au pixel faites dans Chromium et sur video.
commit d569b75e / 5bdb2d88 / 720e327c · 06/08-09/08
Mesures de navigateur et d'analyse video non rejouees (pas de capture d'ecran ni de video dans le depot pour les refaire).
Ces chiffres ne peuvent etre crus que sur parole.
[vraie] Le commit v508 precedent avait change le code sans monter le numero du service worker.
commit 8656565b · 06/08
git show 4287d14a:public/sw.js = soiree-v507 alors que le contenu v508 est dans ce commit ; 8656565b passe a soiree-v508.
Le defaut de bump est reel et corrige dans la foulee ; le fait qu'il soit parti en ligne n'est pas verifiable hors reseau.
[vraie] Chaque version annoncee passait verif.js avec le nombre de controles indique.
commits Theo 31/07 au 06/08 (33 commits rejoues) · 02/08-05/08
node verif.js rejoue hors reseau sur git archive de 33 commits (38488bac, 820c1f08, 2e126ec1, 3c4bff0a, ...) : tous verts, compte a 2 controles pres (controles git sautes hors depot), 2e126ec1 a +6. robots.txt et deux captures injectes depuis b08f693e car non suivis avant le 07/09.
Les comptes de controles cites dans les messages sont fiables.
[vraie] Le banc du jusqu-au-bout fait 14 verifications et bloque le deploiement.
commit c9cff6e5 · 05/08
Rejoue : « 14 verifications, 0 echec(s) » ; deploy.sh:32 de c9cff6e5 l'appelle avec exit 1. Sabotage (6 echecs) non rejoue.
La regle « points seulement en allant au bout » etait bien gardee a sa date.
[vraie] Le banc du bareme couvre 12 parties, extrait les expressions de la vraie route et refuse un coefficient sabote.
commit 820c1f08 · 04/08
12 appels partie() p1..p12 dans le script ; rejoue : TOUT EST JUSTE ; sabotage 1.4 -> 1.9 dans COEF_DIFF sur copie : « IL Y A UNE ERREUR » ; deploy.sh:24 de 820c1f08.
Banc valide par sabotage, conforme a la methode annoncee.
[exageree] La difficulte des mini-jeux ne change que des limites de temps.
commit 820c1f08 · 04/08
app.js de 820c1f08 : GT (lignes 141-147) confirme 5/4 s et 0,48/0,36, mais la difficulte regle aussi la taille de cible (dl(), l.4313), les cotes du Cash out (CO_CONF l.4345), les operandes du calcul (l.4389), les paires de l'intrus (l.4426), la meche de la bombe (l.3970).
La conclusion utile tient (la difficulte ne touche pas aux gorgees), mais « que des limites de temps » est faux.
[vraie] Le bareme neutre donne 5 points par partie en moyenne quelle que soit la tablee, et le banc le verifie de 2 a 14.
commit 7ae1f09f · 04/08
test-bareme-points.py de 7ae1f09f : boucle range(2, 15), sortie « esperance 5.00 pt/partie » a chaque taille ; COEF_ADV = MIN(14.0, np.n) ; plafond de trinqueurs 14 commente app.js:3448. Calcul de l'ancien bareme (2,38 a huit) refait : 19/8 = 2,375.
Le raisonnement chiffre du bareme est exact.
[vraie] Cinq jeux de hasard sont exclus du score solo via COMP_EXCLUDE.
commit aeba01ce · 05/08
app.js:1833 de aeba01ce : COMP_EXCLUDE=["wheel","roulette","casino","bomb","finger"] ; l.1386 sort sans performance pour eux.
Exact a sa date.
[vraie] Avant v481, les mini-jeux a distance n'entraient dans aucun classement ni compteur de victoires.
commit 4de536f1 · 04/08
4de536f1^ : app.js:9160 envoie mode p.mode+"-distance" avec un seul joueur et sans rang ; aucune occurrence de « minijeux-distance » dans la route ; apres : route l.1284-1285 l'ajoute a tout/minijeux.
Le defaut corrige etait bien reel.
[vraie] Le classement recompte depuis party_players.rang, six controles CONF le gardent, le code ami n'existe pas.
commit 8cbbd35e · 04/08
route de 8cbbd35e l.1272-1277 : SUM(CASE WHEN pp.rang=1 ...) ; verif.js:3136-3150 CONF-01 a CONF-06 (7 lignes, CONF-02 double), absents du parent ; aucun code ami hors commentaires.
La garde de conformite (pas de classement de buveurs) etait bien posee.
[vraie] Le controle CSS-02 detecte une accolade fermante orpheline.
commit 6750853e · 06/08
Copie de 6750853e : verif vert (13 137) ; ajout d'une '}' au milieu de style.css : « CSS-02 : accolade fermante orpheline vers la ligne 1970 », deploiement refuse.
Garde efficace, sabotage reproduit.
[exageree] Un controle general contre les variables CSS non declarees a ete ajoute.
commit 6750853e · 06/08
verif.js:3370 de 6750853e : ENTETE-03a cherche seulement /var\(--muted\)/. Le controle general n'arrive que le 10/08 (30f9a013, Theo : « LE CONTROLE NOMME PRECEDENT NE CHERCHAIT QU'UN SEUL FANTOME »).
Pendant 4 jours une autre variable fantome serait passee ; corrige par le cote Theo lui-meme.
[vraie] Une accolade orpheline faisait passer la profondeur du CSS a -1 en v496.
commit 714c0995 · 05/08
style.css de 1bf8405b (v496) : 2102 '{' / 2103 '}' (2099/2100 hors commentaires), profondeur minimale -1. Le mecanisme est exact ; les deux nombres cites ne se reproduisent pas a l'identique (methode de comptage non dite).
Diagnostic juste, chiffres absolus approximatifs.
[vraie] Dix regles #account-btn restaient sans element ; la plupart des demi-pixels venaient du code de la veille.
commit 99ad4f4c · 05/08
99ad4f4c^ : 10 lignes #account-btn dans style.css, 0 id="account-btn" dans index.html, 0 apres. Demi-pixels : 10 occurrences de .5px dont l'inset -.5px de #account-btn ; git blame donne 9 traits venus des commits du 04/08 (8cbbd35e, 820c1f08), donc « huit » sous-compte d'une unite.
Nettoyage reel ; ecart d'un sur le comptage des demi-pixels, sans effet.
[vraie] Le banc du geste a 16 cas passe sur v449 et en fait tomber 6 sur la version precedente.
commit 3cc9ba93 · 03/08
Rejoue : 16 ok sur 3cc9ba93 ; banc de 3cc9ba93 contre app.js de ef6a9161 : « 10 ok, 6 echec(s) » dont « les heures sortent quand meme » et « 11 ecritures ».
Banc probant, reproduction exacte.
[vraie] Le banc a 23 cas prouve le relais du defilement.
commit 9747eb66 · 03/08
Rejoue : 23 ok sur 9747eb66 ; contre app.js de 8438cf86 : 2 echecs « scrollTop 500 -> 500 » et « 500 -> 500 ».
Symptome reproduit et prouve comme annonce.
[vraie] L'audit des cas limites du fil joue 738 scenarios et bloque le deploiement.
commit 2e126ec1 · 03/08
Rejoue : « 738 scenarios joues ... aucune anomalie » ; deploy.sh:15-18 de 2e126ec1 lance test-geste-heures et test-fil-limites apres verif.js:8.
Exact.
[vraie] La regle des trois joueurs est retiree partout et un banc de 18 cas, dont 3 a distance, couvre le duo.
commit 3c4bff0a · 02/08
3c4bff0a : les symboles ne subsistent qu'en commentaire (app.js:4799, 8250), absents de la route ; test-regle-duo.js rejoue : TOUT PASSE, 17 lignes « ok » affichees dont 3 cas a distance (un d'ecart avec 18).
Retrait complet ; decompte des cas a une unite pres.
[vraie] Aucun champ de saisie sous 16 px et le zoom par pincement reste permis.
commit 61772b3b · 03/08
style.css de 61772b3b : aucune regle input/textarea/select sous 16 px (balayage hors commentaires) ; index.html sans maximum-scale ; verif.js:1800 controle negatif.
Exact.
[exageree] Le sondage adaptatif coute moins cher que l'ancien hors conversation active.
commit b21d7ea0 · 03/08
app.js de b21d7ea0 l.8346-8350 : 4 s ecran cache (contre 3 s avant), mais fil ouvert sans activite : 800 ms pendant 20 s, 1,5 s jusqu'a 60 s, puis 3 s comme avant. Seul l'ecran cache coute moins.
C'est ce sondage a 800 ms que le cote Theo a ensuite designe le 08/09 comme premier poste de cout D1 a mesurer.
[vraie] Le service worker ignore /design/ et ne met en cache sous /index.html que la racine.
commit dedaa6c3 · 02/08
git show dedaa6c3 -- public/sw.js : return sur url.pathname commencant par /design/ ; racine ? putInCache("/index.html",res) : res.
Exact ; garantie G8/G9 encore intacte en v2 (voir rapport-securite.md).
[vraie] Les maquettes publiees sont exclues des moteurs par en-tete et par robots.txt.
commit 963ccff8 · 02/08
_headers:40-41 de 963ccff8 (X-Robots-Tag: noindex, nofollow sur /design/*) ; verif.js:2071 controle le Disallow. Mais public/robots.txt n'etait PAS suivi par git avant b08f693e (07/09, ignore par *.txt du monorepo).
Vrai en ligne, mais un clone neuf aurait perdu robots.txt jusqu'au 07/09 ; defaut trouve et corrige par le cote Theo lui-meme.
[vraie] Le depot de la passation design porte TRINKE.md a 3 342 lignes et 37 rendus.
commit ca017fd8 · 02/08
wc -l TRINKE.md : 2878 au parent, 3342 a ca017fd8 ; 37 fichiers .html dans design/ecrans/.
Exact.
[vraie] Les teintes recalees ont la meme luminance et les contrastes du blanc annonces.
commit 45a34217 · 02/08
Calcul WCAG refait : #F786C3 L=0,408, #D4A304 L=0,402 ; blanc sur #FCD34D 1,44, sur #D4A304 2,32, sur #F9A8D4 1,81, sur #F786C3 2,29 ; tons fonces 6,27.
Chiffres exacts au centieme.
[exageree] Le glyphe #EC4899 tient 4,76:1 sur le fond des tuiles.
commit 32a8f92d · 03/08
Calcul WCAG sur les couleurs citees : #EC4899 / #281C26 = 4,64:1 ; #E81F82 / #281C26 = 3,85:1.
Le classement des deux options ne change pas (4,64 reste au-dessus de 4,5), mais la marge annoncee est surestimee.
[vraie] Avant le mode clair, la feuille portait environ 835 couleurs en dur.
commit 2357f0f7 · 03/08
style.css de 2357f0f7^ hors commentaires : 288 rgba( exactement ; 526 codes hexadecimaux (547 apres le commit) ; la methode de comptage n'est pas donnee.
Ordre de grandeur juste ; le decoupage du chantier en decoulait.
[vraie] La mention legale retiree de l'accueil reste gardee ailleurs par le contrat.
commit 51d85f5f · 03/08
git show 51d85f5f -- verif.js : « Legal : la porte d'age porte toujours la mention en entier », « Legal : les mentions du compte la portent aussi », controle negatif #s-home .hlegal.
Exact.
[vraie] Un controle interdit toute etoile collee a une barre dans le CSS.
commit 9c0d14b9 · 01/08
verif.js de 9c0d14b9 : ["CSS : aucun commentaire ne colle une etoile a une barre (piege v428)", CSS, /[a-zA-Z0-9)\-]\*\//, true].
Exact.
[vraie] Le code a 6 chiffres est stocke hache, ce qui empeche de finir une inscription sans la boite mail.
commit c47cb970 · 03/08
route de c47cb970 : INSERT ... code6_hash l.387 et 537, comparaison sha256(saisi + "." + ins.id) l.575. La tentative elle-meme (sur la production) n'est pas verifiable hors reseau.
Exact sur le code ; a noter qu'un Claude a tente une inscription sur la vraie base.
[vraie] La correction max(env(),20px) proposee par le design n'apporte rien et ferait regresser.
commit 3041e0b4 · 03/08
Deduit des regles CSS : une fonction inconnue invalide toute la declaration, max() compris ; avec une encoche de 34 px, calc(22px+34px)=56 et max(34px,20px)=34.
Le refus de la proposition du design etait fonde.
[inverifiable] Lectures de la vraie D1, etat de deploiement et comportement du CDN constates en ligne.
commits 38488bac, 3c4bff0a, 760f6f2c, bf50965d · 01/08-05/08
Production, D1 et CDN : aucun acces reseau autorise pour cet audit.
Ces constats restent sur parole.
[inverifiable] Une quarantaine de mesures au pixel, au CSSOM ou sur video de Theo.
commits 8656565b a 7905c8da (mesures a l'ecran) · 01/08-06/08
Demandent un navigateur ou les videos de Theo ; non rejouees. Les commits disent eux-memes quand ils n'ont pas mesure (3456b9dd « NON MESURE LOCALEMENT », a96d2abd « NON VU A L'ECRAN »).
Pas d'indice de fausse mesure ; l'honnetete sur le non mesure est constante.
[exageree] Tout soiree-app est desormais dans l'historique git (26 fichiers).
commit b93b83e4 · 27/07
git show --stat b93b83e4 : 31 fichiers soiree-app, mais public/robots.txt absent alors que verif.js:1235 l'exige ; robots.txt n'entre dans git qu'en b08f693e (07/09), dont le message dit que le .gitignore du monorepo ignorait *.png et *.txt (robots.txt + 2 captures du manifeste).
Pendant 6 semaines, trois fichiers servis en production n'existaient que sur la machine de Theo ; un clone les aurait effaces au deploiement.
[perimee] L'historique de Trinke ne quitte jamais la machine.
commit b93b83e4 · 27/07
b08f693e (07/09) prepare la sortie vers un depot GitHub prive partage avec Romain ; origin/main et origin/soiree-v2 existent.
Decision changee par Theo lui-meme le 07/09, phrase historique seulement.
[vraie] Le premier commit ne contient aucun secret.
commit b93b83e4 · 27/07
git show b93b83e4:wrangler.toml : name, compatibility_date, binding D1 et database_id seulement.
Rien a craindre de ce commit.
[exageree] Le filet empeche de deployer un fichier absent de git.
commit 555eb715 · 27/07
555eb715:verif.js:1374 fait git status --porcelain : un fichier IGNORE n'y apparait pas. robots.txt et deux captures (ignores par *.txt/*.png) sont passes en production sans etre dans git jusqu'a b08f693e (07/09).
Le filet couvrait les fichiers suivis ou non ignores, pas tout ce qui part en ligne.
[vraie] L'archive d'avant reecriture contient 517 items.
commit 555eb715 · 27/07
git show 555eb715:archives-contenu-classics-fr-avant-reecriture-27-07.json : 517 items (somme des listes).
Les textes d'origine sont recuperables.
[fausse] Le cache de 4 h sur sw.js retardait les mises a jour chez les joueurs.
commit bd22f323 · 28/07
bd22f323:public/app.js:6891 enregistre le SW avec updateViaCache:"none" ; le commit suivant 48acd649 le reconnait : 'C'est faux'.
Fausse alerte, retiree par son auteur le meme jour ; la regle _headers reste comme ceinture.
[vraie] Le correctif de bd22f323 n'etait pas necessaire pour les joueurs.
commit 48acd649 · 28/07
git show bd22f323:public/app.js ligne 6891 : register("/sw.js",{updateViaCache:"none"}).
Bonne auto-correction, tracee.
[vraie] Le contenu de Soiree compte 131 soft, 130 chaud, 130 hardcore.
commit e357f110 · 28/07
git show e357f110:public/content-fr.json : 391 cartes, soft 131, chaud 130, hardcore 130.
La montee en trois actes (GD-29) reposait sur des chiffres justes ; elle est debranchee dans v2 : voir rapport-jeu.md (point 5).
[vraie] 537 cartes de l'associe versees avec ces repartitions.
commit f4bd2c5a · 28/07
git show f4bd2c5a:public/classics-fr.json : 203 / 246 / 238 ; repartitions exactes sauf action trash = 28 et non 29 (la carte retiree pour doublon), total 537 juste.
Ecart d'une carte sans effet.
[exageree] Les Classiques casses en v360 sont repares en v361.
commit 0271196d · 28/07
0271196d : 0 niveau en chaine sur 1054 (vrai), mais 0107c09c (v381) ecrit qu'Action ou verite etait 'casse depuis la v361' : card.t objet, jeu bloque 4 fois sur 5.
Pendant 20 versions, Action ou verite est reste bloque en production alors que le commit le disait repare.
[vraie] Defaut trouve, corrige et grave au contrat CL-30.
commit 0107c09c · 28/07
git show 0107c09c -- verif.js : ajout de CL-30 (aucune phrase de classique ne doit arriver comme objet) ; 1054 phrases au fichier (0271196d).
Defaut ferme par un controle.
[fausse] La route serveur de l'indicateur de frappe n'existe pas.
commit f0bef81a · 28/07
git show f0bef81a:functions/api/[[route]].js:1553-1587 : route chat/tape et table frappe existent ; reconnu faux par e54697d9 (v389).
Une fonction utile a ete retiree a tort pendant 17 versions.
[exageree] Le contrat passe a 8908 controles sur v372.
commit f0bef81a · 28/07
verif.js extrait de f0bef81a (git archive, hors reseau) : 2 echecs, dont 'REVENU ALORS QU'IL ETAIT RETIRE : MU-03' ; corrige par le commit enfant 4d16d83e.
Le commit v372 tel qu'enregistre ne passait pas son propre contrat ; le nombre est juste, le vert ne l'est pas.
[fausse] Le contrat passe a 9325 controles sur v385.
commit 0a25b674 · 28/07
node verif.js sur l'extraction de 0a25b674 : SyntaxError (regex invalide), aucun controle execute ; corrige par l'enfant dde248e8 ('une regex sur plusieurs lignes n'est pas un litteral valide'), qui donne 9338 (+2 git) .
Le chiffre annonce n'a pas pu sortir du verif.js commite.
[fausse] Chaque version de v382 a v397 annonce son total de controles.
commit 8acb2ebe..d822432a · 28/07
verif.js de chaque commit rejoue hors reseau (determinisme verifie, 3 tirs identiques) : ecart annonce/mesure (+2 git) de -7 a v382 croissant jusqu'a -246 a v397 (9463 annonce, 9709 reel) ; de v364 a v381 et a v401 l'ecart est 0. Le total suit la longueur d'app.js (1 controle par ligne), les messages n'ajoutaient que les nouveaux controles.
Les chiffres ne mentent pas dans le sens dangereux (le vrai total est plus haut) mais ne sont pas des mesures.
[fausse] Toucher une pastille de reaction affiche qui a reagi.
commit 8acb2ebe · 28/07
git show 8acb2ebe -- public/app.js : bloc reacTap pose hors de tout gestionnaire ; c1db45a6 (v400) : 'chaque rendu du fil levait une ReferenceError et cassait le cablage des messages suivants'.
De v393 a v399, la fonction annoncee ne marchait pas et cassait les messages suivants du fil.
[vraie] Le bloc de reaction de v393 etait orphelin, corrige en v400.
commit c1db45a6 · 29/07
Diff c1db45a6 : le bloc est replace dans le gestionnaire de clic ; c1db45a6^:public/app.js:8615 montre l'ancien bloc hors gestionnaire.
Defaut reconnu et ferme.
[vraie] L'app n'invitait jamais a l'installation avant IN-14.
commit bd0b3cef · 28/07
git show bd0b3cef^:public/app.js | grep -c beforeinstallprompt = 0 ; apres = 4.
Constat exact.
[vraie] La fonction existait deja au premier commit.
commit e04785d5 · 28/07
git show b93b83e4:public/app.js | grep -c muRetourInterne = 2.
Correction de fiche exacte.
[vraie] Pierre-papier-ciseaux retire et verrouille par le contrat.
commit 579dd21d · 31/07
579dd21d:verif.js : doit(JEUX.length === 16) ; id:"rps" absent d'app.js (present au parent).
Garantie posee ; rps reste absent en v2, mais la roulette russe y est remplacee : voir rapport-jeu.md (G2).
[vraie] Varie ne sert jamais de hardcore, verrouille dans les deux modes.
commit 1ac7e036 · 30/07
git show 1ac7e036 -- verif.js : deux controles GD-18 (Classiques : allIntensity -> soft,medium,hard ; Soiree : IRANK > chaud refuse).
Garantie posee et controlee.
[vraie] Seuls finger et bomb servent d'intermedes en Soiree, verrouille.
commit 95ddf85c · 30/07
git show 95ddf85c -- verif.js : controles 'SOIREE_MINIS=["finger","bomb"]' et filtre croise avec state.minis.
Garantie exacte a sa date ; la cadence des intermedes est coupee en v2 : voir rapport-jeu.md (point 5).
[vraie] L'accueil n'a plus de seuil de hauteur.
commit 6656d181 · 30/07
6656d181:public/style.css : 3 @media max-height restantes (500, 600, 740), toutes sur #s-age ; le @media max-height:900px est retire.
Constat exact.
[vraie] La sonde de diagnostic de v410 est retiree.
commit 729b3b3b · 30/07
grep -ci sonde : 1 dans f544568d:public/app.js, 0 dans 729b3b3b.
Aucun code de diagnostic laisse en production.
[vraie] Pseudo limite a 10 cote serveur aussi, plafond de 14 joueurs en constante.
commit b5c73b39 · 28/07
b5c73b39:functions/api/[[route]].js:417 'Trop long : 10 caracteres maximum' ; public/app.js:157 var PLAFOND_J=14.
Regle tenue des deux cotes.
[vraie] La colonne extra est ajoutee par migration paresseuse et le multijoueur est sous contrat.
commit 3125037b · 29/07
3125037b:functions/api/[[route]].js:46-49 migrationLiveExtra (ALTER TABLE live ADD COLUMN extra) ; verif.js gagne les lignes MJX-0x.
Constat exact.
[vraie] Les 3 meta de partage et l'ecran affichent le meme total, ecrit par verif.js.
commit 436ffa5d · 28/07
436ffa5d:verif.js:1719-1729 reecrit les 3 meta 'defis' et les deux compteurs ; index.html porte '1440+ defis' dans les 3 meta.
Plus de divergence possible.
[vraie] Totaux de controles annonces de v364 a v381.
commit 6195e0f8..ac8c3f5c · 28/07
verif.js rejoue sur chaque commit : ecart nul (+2 controles git absents de l'extraction), sauf v367 (70b8c646 : 8789 contre 8779) et v375 (9008 contre 9009).
Sur cette plage, les chiffres sont des mesures reelles.
[inverifiable] Le jeton wrangler de Theo ne peut pas lancer de SQL distant.
commit 7a4fc3ae · 28/07
Depend des droits du jeton Cloudflare (reseau interdit) ; la memoire reference-cloudflare-d1-remote.md dit aujourd'hui l'inverse ('marche avec le jeton de Theo').
Raison historique des migrations paresseuses, qui ont ensuite servi de modele (voir rapport-base.md sur la migration de Romain que le banc ne lit pas).
[inverifiable] Une route de lecture des envois existe, protegee seulement par son adresse.
commit b5d7a537 · 28/07
Le commit ne contient que construire-themes.js : la route vit dans soiree-form, absent de ce depot (git log -S lire-r7k3m8 vide).
Si la route est toujours en ligne, elle lit trinke-contributions sans authentification autre que l'obscurite de l'adresse.
[inverifiable] Nombreux comportements declares verifies au navigateur.
commit plusieurs (6195e0f8, 70b8c646, 87eb3a8b, 3467f857, 6d67a7f1...) · 27-28/07
Essais d'ecran non rejouables en lecture seule ; les commits qui ne l'ont pas fait l'ecrivent (c5c41ac6, 04a3a8d2, fa661e8f, 7a4fc3ae : 'NON TESTE').
La transparence 'NON TESTE' est reelle ; 8acb2ebe montre un cas ou elle a manque.
La base de production contient les colonnes du mot de passe (users.mdp_hash, users.mdp_sel, devices.par_mail) et les tables achats et avis_apercu, alors que trinke.app tourne en v1059 qui ne les connaît pas. Ce qui était déduit est maintenant mesuré.
Proposition : Base séparée pour l'aperçu avant toute nouvelle publication sur l'aperçu.
Preuve : wrangler d1 execute trinke-db --remote, SELECT sur sqlite_master et pragma_table_info, 0 ligne écrite (20/10)
Le journal d'erreurs du serveur (ajouté le 19/09) ne peut rien enregistrer : la table n'a jamais été créée sur la vraie base. Le code tolère son absence, donc personne ne l'a vu.
Proposition : Créer la table depuis schema.sql (c'était un geste prévu de ton côté), puis vérifier qu'une erreur s'y inscrit.
Preuve : SELECT COUNT(*) FROM erreurs : no such table (20/10)
17 comptes n'ont pas encore de mot de passe et entrent par code e-mail. Les 2 comptes sans e-mail ni mot de passe ne pourront plus entrer dès que la v1081 sera en ligne : ce sont les 2 comptes que tu avais acceptés de perdre.
Proposition : Rien si tu maintiens ta décision du 17/10.
Preuve : SELECT sur users WHERE supprime_le IS NULL (20/10)
La table achats est vide : aucun paiement de test ni réel n'a été écrit dans la vraie base.
Preuve : SELECT COUNT(*) FROM achats = 0 (20/10)
idx_parties_hote_fin et idx_parties_mode_fin existent sur la vraie base.
Preuve : sqlite_master (20/10)
LIVE_SECRET est posé sur le projet Pages (production) et sur le Worker trinke-live. Le Worker répond live-4. Je ne peux pas vérifier que les deux valeurs sont identiques (elles sont chiffrées).
Proposition : Faire une vraie partie à distance à deux téléphones sur trinke.app pour confirmer.
Preuve : wrangler pages secret list ; wrangler secret list (live) ; live.trinke.app/sante (20/10)
Ni TURNSTILE_SITE, TURNSTILE_SECRET ni MDP_POIVRE ne sont posés, ni en production ni sur l'aperçu. Ces deux protections ne font rien aujourd'hui.
Proposition : Les poser avant la mise en ligne de la v2, le poivre seulement après l'avoir sauvegardé à deux endroits.
Preuve : wrangler pages secret list (production et preview) (20/10)
L'aperçu n'a pas LIVE_SECRET alors que le Worker exige le ticket : l'aperçu ne peut pas signer les tickets, donc les connexions directes y sont sans doute refusées (le jeu continue par lecture régulière). Déduit, non testé.
Proposition : Poser le même secret sur l'environnement preview ou accepter le direct dégradé sur l'aperçu.
Preuve : secrets preview sans LIVE_SECRET ; Worker avec LIVE_SECRET (20/10)
Les 4 secrets Stripe sont sur l'environnement preview, pas en production. Je ne peux pas voir s'il s'agit de clés de test ou réelles. L'aperçu écrit dans la vraie base.
Proposition : Vérifier dans le tableau Stripe que ce sont des clés de test.
Preuve : wrangler pages secret list --env preview (20/10)
trinke.app et jeu-soiree.pages.dev : v1059. Aperçu : v1153 (il était en v1149 en début d'audit, Romain y publie en ce moment). GitHub : v1081.
Proposition : Demander à Romain de pousser jusqu'à v1153 pour que tout soit auditable.
Preuve : sw.js lus en ligne (20/10)
La table pseudos_interdits contient 0 ligne. Les pseudos sont publics (classement, amis) et rien ne filtre les pseudos insultants au-delà de la liste fixe du code.
Proposition : Remplir la table avec une liste de base, puis vérifier qu'un pseudo interdit est refusé.
Preuve : SELECT COUNT(*) FROM pseudos_interdits = 0 (20/10)
CONSTATE : app.js (+483 / -128 lignes), style.css (+374 / -99), index.html (+20 / -12), cartes-fr.json (1027 -> 1035 cartes), legal/index.html (editeur rempli), sw.js (numero de version seul). Identiques : legal/cgv/, manifest, 404, robots, sitemap, toutes les images, le son. Le code serveur (functions/, live/) n'est pas servi au public : aucun changement serveur n'a pu etre vu. Les en-tetes de securite (CSP) lus en ligne sont identiques au _headers de v1081, et l'empreinte du script en ligne de index.html correspond toujours.
Proposition : Pousser ces 72 versions sur GitHub (Theo ou Romain) pour que le code serveur puisse aussi etre audite.
Preuve : diff v1081 (git show origin/soiree-v2:public/...) contre les fichiers telecharges ; sw.js:1 CACHE=soiree-v1153 ; en-tetes-racine.txt
CONSTATE : l'hote annonce maintenant envoi.tours = nombre de cartes reellement envoyees, et refuse de lancer un paquet vide. Les 7 a 15 derniers tours ne rejouent plus les premieres cartes. INCERTAIN : le test qui compare les deux n'est pas visible (outils non publics) ; le serveur pourrait borner autrement.
Proposition : Verifier qu'un test de verif.js protege cette egalite.
Preuve : apercu-v1153/app.js:16918-16922
CONSTATE : la tuile compte les phrases par ambiance et se desactive sous 6 (CL_MIN) avec "Bientot disponible" ; la serie aleatoire l'exclut deja (clJouable). Mais cartes-fr.json n'a toujours que 4 cartes pour_combien (1 soft, 3 chaud, 0 hardcore). Le jeu n'est donc plus casse, il est cache. Tes 246 phrases archivees ne sont pas revenues.
Proposition : Decider : remettre les 246 phrases d'archives/paquets-avant-v966 ou laisser le jeu en Bientot.
Preuve : apercu-v1153/app.js:8275-8286, 9781-9782 ; cartes-fr.json ids f21ee013, f40f6a3d, ff302824, f277f8a1
CONSTATE : les lignes signalees sont identiques, commentaires "Pas de plafond de gorgees (decision Romain)" compris. Seul ajout : un "cul sec" dans une carte est maintenant ramene au plafond (il vaut 4). Bonne correction ailleurs, mais les 4 jeux restent hors regle 7.
Proposition : Faire passer ces 4 jeux par dg()/sipCap(), sans toucher a leur mecanique.
Preuve : apercu-v1153/app.js:7329, 7336 (Crash out), 8421 (Purple), 8597 (Palmier), 8741, 8809 (Course des As) ; cul sec : 548-553
CONSTATE : la carte de l'As et l'aide du Palmier sont inchangees, toujours hors du filtre sans alcool.
Proposition : Passer ces textes par sansTexte() comme les autres.
Preuve : apercu-v1153/app.js:8566, 8709
CONSTATE : enTroisActes existe toujours sans etre appele, le bloc des intermedes est toujours sous if(false && ...), et la description de Ca chauffe dit toujours "L'ambiance monte".
Proposition : Corriger le texte ; trancher sur le rebranchement.
Preuve : apercu-v1153/app.js:4163, 5328, 3548
CONSTATE : planSoiree pioche d'abord les cartes jamais vues, ne sert qu'une variante par phrase, limite chaque famille au tiers de son stock (3 parties sans redite) et pose les cartes sans deux familles voisines. Cela traite une partie du risque de redite. Mais le plancher de fraicheur reste a 40 pour 50 cases, et la case "Carte a ecrire" peut toujours sortir si tout est a sec (emprunte).
Proposition : Monter PLANCHER_FRAICHEUR au-dessus de 50 et ne jamais afficher "Carte a ecrire" a un joueur ; faire tourner outils/test-tirage-soiree.js sur cette version.
Preuve : apercu-v1153/app.js:3690, 3913-4026, 3997, 4068-4103
CONSTATE : aucune ligne du direct ni de api() n'a change (liveOuvre, liveFerme, api sans delai maximum).
Proposition : Laisser la reconnexion attendre son delai et mettre un delai maximum aux appels.
Preuve : apercu-v1153/app.js:15959, 15614, 10567
CONSTATE : compteExige() et le renvoi vers s-compte sont identiques. Pas de "Jouer sans compte".
Proposition : Trancher : garder ou remettre un secours invite.
Preuve : apercu-v1153/app.js:1519-1528
CONSTATE : les regles qui cachent #home-top et .mv-moi-haut sont identiques.
Proposition : Remettre le bouton sur l'accueil menu verre.
Preuve : apercu-v1153/style.css:9425, 9271
CONSTATE : la vue "mdp" existe (cpVue==="mdp") mais n'est pas dans enSaisie : retour d'une autre app = champs effaces.
Proposition : Ajouter ||cpVue==="mdp" (une ligne).
Preuve : apercu-v1153/app.js:10713
CONSTATE : le commentaire "NI CASE NI PHRASE ICI ... risque connu et accepte" est toujours la, aucune case ajoutee.
Proposition : Remettre la case cochee verifiee par le serveur, avant de poser les cles Stripe.
Preuve : apercu-v1153/app.js:19126-19128
CONSTATE : mjcPool et la construction du paquet a distance sont identiques. DEDUIT : le defaut demeure (non joue).
Proposition : Corriger et tester avant d'ouvrir le paiement.
Preuve : apercu-v1153/app.js:16030, 16053
CONSTATE : la politique (page legal/ et ecran de l'app) parle toujours du "code de secours", ne dit rien du mot de passe, de Turnstile ni de la verification des mots de passe fuites, et affirme "aucun traceur" alors que Turnstile charge un script de Cloudflare. L'ecran de suppression ne previent toujours pas qu'un Pass a vie est perdu. Seul l'editeur a ete rempli.
Proposition : Rediger les paragraphes manquants, relecture Theo avant mise en ligne.
Preuve : apercu-v1153/legal/index.html:54 ; app.js:12758, 12764, 12973 ; Turnstile : app.js:11504-11546
CONSTATE : nom, adresse, SIRET, directeur de la publication et e-mail sont maintenant affiches, sur la page legal/ et dans l'app, coherents avec le vendeur des CGV. Pour un entrepreneur individuel, publier ces informations est une obligation (DEDUIT, regle LCEN, a confirmer). Il reste non ecrit dans le depot qui encaisse et comment c'est partage entre Theo et Romain. Je ne recopie pas ces donnees ici.
Proposition : Mettre par ecrit le partage ; verifier que Romain accepte de publier son adresse.
Preuve : apercu-v1153/legal/index.html:70-74 ; app.js:11254, 12769-12771, 13546
CONSTATE : stAnnulePartie a l'ouverture de l'accueil et stOuvrePartie sont identiques.
Proposition : Rouvrir le journal de la partie a la reprise.
Preuve : apercu-v1153/app.js:1538, 2195
CONSTATE : les quatre regles citees sont identiques. Nouveau : deux exceptions voulues au badge et au bouton Suivant (Loi en or, Joker arc-en-ciel), commentees comme decision de Romain.
Proposition : Mesurer les deux barres au navigateur et aligner les Classiques sur la Soiree.
Preuve : apercu-v1153/style.css:9570, 9979, 12090, 8533 ; exceptions 9542-9549, 9610-9615
CONSTATE : #arret-bilan reste un .btn standard (le menu, lui, est rouge). Le melange vous/tu de la bombe est toujours la, coupe en deux lignes, et il est repris dans la nouvelle consigne de la case piegee.
Proposition : Passer #arret-bilan en rouge ; choisir "tu" ou "vous" dans les deux consignes.
Preuve : apercu-v1153/index.html:1443 ; 665-666 ; 739-740
CONSTATE : 400 -> 428 occurrences de !important ; nouveaux eclats animes sur les tuiles ; bouton Lancer une Soiree 15 % plus petit. Les regles de mise a l'echelle de la toile sont identiques (petits textes inchanges). Ajout positif : un reglage "Decor anime" pour couper les animations de fond.
Proposition : Mesurer sur un vrai iPhone, puis nettoyer les surcharges.
Preuve : grep -o !important style.css (v1081 400, v1153 428) ; index.html:539-545 ; style.css:12602-12605
CONSTATE : la case piegee reste a la place de la roulette russe (refaite visuellement, avec 24 phrases de relance) ; les categories de la bombe ne changent pas ; Classement cache (index.html:1220) ; pas de mode clair ; Avec qui ? et l'avatar toujours absents. DEDUIT : le plafond de cartes passees n'a pas ete remis (aucun changement de ce code dans le diff).
Proposition : Rien de neuf a trancher par rapport a la revue v1081.
Preuve : diff app.js : aucun bloc dans 6369-6440 (bombe) ; index.html:1220
CONSTATE : aucune remontee des erreurs du telephone (pas de window.onerror) ; CSP en ligne identique. INCERTAIN : registre de relecture, verif.js, secrets et route du ticket sont dans des fichiers non publics.
Proposition : Auditer le depot une fois pousse.
Preuve : apercu-v1153/app.js (aucun onerror) ; en-tetes-racine.txt
CONSTATE : 75 cartes gage renommees en defi (76 apres ajout), partout dans app.js, avec conversion des parties sauvees avant le changement.
Proposition : Garder.
Preuve : apercu-v1153/app.js:2744, 3636, 3840, 4218-4221 ; cartes-fr.json
CONSTATE : 1027 -> 1035 cartes. Ajouts : 3 Duel, 2 Defi, 4 Verite, 1 Loi (le mouton), etc. Retraits : 4 Tu preferes, 1 Action, 1 Defi (dix dabs). Reecritures : Lois au present ("On dit...", "Interdiction de..."), Duels avec un verbe, Jokers en "tu peux" (le bas de carte dit "Valable une fois"). 5 cartes ont un retour a la ligne rendu en paragraphe. Une Quiz passe de soft a chaud.
Proposition : Faire relire l'echantillon de nouvelles cartes.
Preuve : cartes-diff.txt (comparaison par id) ; app.js:3854-3875 (posePhrase), 4915-4919 (Joker)
CONSTATE : le bouton du pied dit "Reponse", ouvre l'encadre sans changer de carte, puis redevient "Suivant". Meme comportement en Soiree a distance, reponse retenue par tour.
Proposition : Garder ; essayer avec un double appui rapide.
Preuve : apercu-v1153/app.js:5584-5600, 5771-5783, 5815-5817, 16239-16260
CONSTATE : "en dix secondes" est retire de la phrase quand un rond de chrono s'affiche ; a distance la phrase garde sa duree.
Proposition : Garder.
Preuve : apercu-v1153/app.js:5396-5409, 5550
CONSTATE : "La roue" devient "Girouette" ; dessin refait (chiffre gros, mot en capitales) ; la fiche des regles ne cite plus la case "Rien" disparue le 26/09 et dit "Prends" en sans alcool ; une phrase d'appel tiree en cycle.
Proposition : Garder.
Preuve : apercu-v1153/app.js:220, 6434-6498, 7760-7762, 7846-7848
CONSTATE : plus de confettis dans les mini-jeux (bords verts) ; la bombe gonfle puis disparait sous le BOUM, l'ecran tremble ; consignes de la bombe et de la case piegee remontees au-dessus du jeu ; pastille de gorgees sur une ligne. Les animations sont coupees si le telephone demande moins de mouvement.
Proposition : Garder.
Preuve : apercu-v1153/app.js:1805-1808, 6767-6769 ; style.css:824-825, 12645-12649 ; index.html:665-666, 739-740
CONSTATE : les phrases jamais vues passent devant, chaque phrase jouee est notee (3 semaines).
Proposition : Garder.
Preuve : apercu-v1153/app.js:9114-9117, 9132, 9145, 9322, 9375
CONSTATE : bracelet avec date d'achat, tuiles cliquables qui lancent la Soiree, Ca chauffe ou les mini-jeux ; l'abonne au mois garde "Passer a vie". Visible seulement une fois le paiement ouvert ou via la porte de test (ap-31).
Proposition : Tester les trois cas (gratuit, mois, a vie) avant d'ouvrir le paiement.
Preuve : apercu-v1153/app.js:19247-19307
CONSTATE : l'attente du code d'inscription recule vers le formulaire ; Couleur et la confirmation d'effacement remontent d'un cran ; venir de Nouvelle discussion vers Amis y ramene sans perdre le groupe.
Proposition : Garder ; essayer sur Android installe.
Preuve : apercu-v1153/app.js:3025-3028, 14343-14346, 14370-14374, 15225, 19098-19100
CONSTATE : la simulation du niveau d'acces (invite, gratuit, paye) par l'adresse, reservee jusqu'ici a localhost, s'ouvre sur apercu.jeu-soiree.pages.dev. N'importe qui ayant le lien de l'apercu peut se mettre en payant sur son telephone. DEDUIT : peu grave en soi (le verrou etait deja contournable, contenu public), mais l'apercu partage la vraie base des joueurs : un compte reel en "paye" simule peut heberger une partie a distance et servir des cartes payantes a de vrais invites (meme mecanisme que ap-13). Le site public n'est pas concerne (nom d'hote verifie).
Proposition : Acceptable pour tester, a condition que l'apercu ait sa propre base (point apercu-base de v1081).
Preuve : apercu-v1153/app.js:276-279, 19259
CONSTATE : "{j1} est un mouton : chaque fois que vous sautez par-dessus lui, vous distribuez a qui vous voulez", en intensite soft, active toute la partie. DEDUIT : la regle recompense chaque saut, entre gens qui boivent, au-dessus d'une personne : risque de chute ou de blessure, et rien ne limite le nombre de sauts. Le texte contient aussi un trait d'union insecable (U+2011) peu courant.
Proposition : La retirer, ou la reformuler (geste symbolique, un seul saut par tour).
Preuve : apercu-v1153/cartes-fr.json, carte id ff5cfb42
CONSTATE : "Chacun votre tour, touchez une case." puis "Si tu tombes sur le piege, tu perds !" : le meme melange que la bombe, ajoute le 20/10.
Proposition : Une seule personne grammaticale par consigne.
Preuve : apercu-v1153/index.html:739-740
Texte affiche : « Le jeu pour trinker entre amis. Local ou multijoueur », badge 18+, « Réservé aux personnes majeures. L’abus d’alcool est dangereux pour la santé, à consommer avec modération. Ne conduis jamais après avoir bu, et ne force personne à boire. », boutons « J’ai 18 ans ou plus » / « Je suis mineur », pied « Sans pub. Compte gratuit. ». Mention alcool rendue a 12,8 px, contraste approx. 10,7:1. Aucun defilement horizontal a 390 et 320.
Proposition : Theo confirme la promesse « Sans pub » (sa monetisation prevue etait premium + pub legere). La mention alcool pourrait monter a 14 px.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\01-porte-age-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\01-porte-age-320.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m2.json (age_texts)
Le gestionnaire ecrit adult=1 dans localStorage puis appelle show(). Mesure : 0 requete reseau emise apres le clic, aux deux tailles.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m2.json (req_apres_age = [])
Juste apres la porte d'age, l'ecran s-compte s'affiche : « Crée ton compte, c’est gratuit. », « Créer un compte », « Déjà un compte ? Se connecter », liens Conditions et confidentialite. Aucune option invite, barre du bas masquee (display:none). La porte depend seulement de la presence d'un jeton dans localStorage (compteExige), jamais du reseau.
Proposition : Decision produit a trancher par Theo (sa spec : 100 % hors ligne et sans compte). Si le compte reste obligatoire, au minimum un bouton « Jouer sans compte » visible quand le reseau manque.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\02-porte-compte-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\02-porte-compte-320.png ; app.js v1153 fonction compteExige/show
Apres deux ouvertures en ligne (cache du service worker rempli), reseau coupe puis rechargement : porte d'age, puis porte du compte identique a l'ecran en ligne. « Créer un compte » ouvre le formulaire complet (pseudo, date de naissance, pays, e-mail, mot de passe) sans aucun avertissement de reseau absent : il ne peut pas aboutir. Aucun chemin vers le jeu alors que les cartes sont en cache.
Proposition : Hors ligne et sans jeton : laisser jouer en invite (ou au minimum afficher « Pas de reseau : la creation de compte attendra » avec un acces au jeu).
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\03b-hors-ligne-porte-compte-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\03d-hors-ligne-creer-un-compte-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m3d.json
Le service worker precharge /index.html, que Cloudflare Pages redirige en 308 vers /. La copie en cache est donc marquee redirected:true. Hors ligne, la navigation recoit cette reponse redirigee, que le navigateur refuse : net::ERR_FAILED, page blanche. Mesure : apres 1 visite, cache /index.html redirected=true et rechargement hors ligne en echec ; apres une 2e visite en ligne, le secours de navigation reecrit l'entree (redirected=false) et le hors ligne marche. trinke.app/index.html repond aussi 308.
Proposition : Dans sw.js, precharger « / » et le ranger sous la cle /index.html (fetch('/') puis cache.put('/index.html', reponse)), ou reconstruire la reponse si h.redirected : new Response(h.body,{status:200,headers:h.headers}). A confirmer sur Safari iOS (meme regle du standard Fetch, constate ici sous Chromium).
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\03c-hors-ligne-apres-une-seule-visite-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m3d.json (cache_apres_1re_visite.redirected=true, 1re_visite_puis_hors_ligne = ERR_FAILED)
Apercu v1153 : le document HTML recoit la CSP complete (default-src 'self', script-src avec l'empreinte sha256 et challenges.cloudflare.com, object-src 'none', base-uri 'none', frame-ancestors 'none'...). Le defaut b1 n'existe donc pas en v1153. En revanche trinke.app (production, app.js?v=1059) sert seulement « content-security-policy: frame-ancestors 'none' » : b1 est vrai aujourd'hui en production.
Proposition : Re-mesurer l'en-tete sur trinke.app juste apres le prochain deploiement (curl -sI https://trinke.app/ | grep -i content-security).
Preuve : En-tetes de navigation apercu (m2.json headers) ; curl -sI https://trinke.app/ le 20/10/2026
Presents sur le document : X-Frame-Options: DENY, X-Content-Type-Options: nosniff, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy (camera, micro, geolocalisation, paiement, usb coupes), HSTS 2 ans + sous-domaines, X-Robots-Tag noindex (apercu). Point mineur : Access-Control-Allow-Origin: * sur le document HTML.
Proposition : Retirer Access-Control-Allow-Origin: * des pages HTML si rien ne le demande (sans gravite).
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m2.json (headers)
Echelle mesuree --mvs = 0,414 (390 px) et 0,340 (320 px). Tailles rendues (police CSS x echelle) : « AUTRES MODES DE JEU » et etiquettes Classiques/Défis/Mini-jeux 10,4 px (390) et 8,5 px (320) ; « Jeux cultes », « Manches rapides », « Tests de connaissances » 11,6 / 9,5 px ; « Gérer » 11,1 / 9,1 px ; « Jouer » 13,3 / 10,9 px ; « Lancer une Soirée » 14,1 / 11,6 px. Le calcul de l'audit (10,4 et 8,5 px) est exact.
Proposition : Plancher de 12 px rendus a 320 px : grossir les textes de la toile en proportion de 1/--mvs, ou rendre ces libelles hors toile (non mis a l'echelle).
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\05-accueil-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\05-accueil-320.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m4.json (textes)
L'audit deduisait que « Grand texte » ne grossit pas la toile. Mesure avec pref_big=1 (classe html.bigtext) : tous les textes de la toile gagnent 18,75 % (etiquettes 10,4 -> 12,3 px a 390 ; 8,5 -> 10,1 px a 320). Aucun debordement de texte hors de sa carte mesure (0 cas), aucun defilement horizontal. Visuellement « Manches rapides » touche le bord de sa carte a 320 px.
Proposition : Rien a corriger sur le mecanisme ; le gain reste insuffisant a 320 px (10,1 px).
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\05-accueil-grandtexte-320.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\05-accueil-grandtexte-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m5.json (big_deborde = [])
#home-moi existe mais mesure 0 x 0 (ancien accueil cache) ; .mv-moi-haut est en display:none ; .mv-compte-haut n'existe pas. Les points touches en haut a droite (x=366, y=24/40/56) tombent sur la toile vide. Le seul acces au compte est l'onglet « Mon compte » de la barre du bas (4 onglets : Accueil, Amis, Boutique, Mon compte).
Proposition : Theo tranche : garder sa regle 3 (rond en haut a droite, oppose aux reglages) et afficher .mv-moi-haut, ou lever la regle.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\05-accueil-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m4.json (candidats_compte, haut_droite)
Mesure de la boite cliquable : Reglages 32 x 32 px (390) et 27 x 27 (320) ; boutons « Jouer » 99 x 28 et 82 x 23 ; « Lancer une Soirée » 225 x 35 et 185 x 29 ; bandeau Trinkeurs 355 x 35 et 291 x 29 ; lien « Se connecter » 90 x 23. Recommandation Apple : 44 x 44 pt.
Proposition : Agrandir la zone de toucher (padding ou pseudo-element) sans changer le dessin : min 44 px de haut rendus.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m5.json (std_petites_cibles_accueil) ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m2.json (compte_btns)
Grille identique (36px 1fr 36px), boutons Menu et Passer 36 x 36 aux memes positions. Differences mesurees : glyphe « passer » 17 x 17 px en Soiree contre 13 x 13 px aux Classiques ; titre « SOIRÉE » 19 px contre « LES CLASSIQUES » 17 px, et y = 20,6 contre 21,8. Meme resultat a 390 et 320.
Proposition : Poser la regle du glyphe et du titre au niveau commun (.topbar des deux ecrans), pas sur #s-game seul.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\06b-soiree-partie-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\07c-classiques-partie-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m5.json (soiree_topbar, cl_topbar)
Present en Soiree (36 x 36, x = 58), absent aux Classiques. Code limite a l'apercu et localhost. Non clique (il ecrit en base de production).
Proposition : Rien ; ne pas l'utiliser comme reference de cadre.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\06b-soiree-partie-390.png
0 bouton visible sans nom accessible sur la porte d'age, la porte du compte, l'accueil (normal et grand texte), la partie Soiree et la partie Classiques. Les icones ont un aria-label (Reglages, Menu, Passer ce défi, Mon compte...). Les champs du formulaire ont tous une etiquette.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m5.json (sansnom = []) ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m2.json
Approximation (couleur calculee contre fond median de la capture) : porte du compte entre 5,3:1 (mention legale grise 13 px) et 12,7:1 ; « Créer un compte » 7,0:1 ; porte d'age 7,2 a 18:1. Accueil : « Jouer » de la carte Mini-jeux 4,5:1, a la limite du seuil AA 4,5. La mesure du titre « Trinke » de l'accueil (1,2) est un artefact (texte en degrade).
Proposition : Verifier « Jouer » sur orange avec un outil de contraste sur appareil.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m2.json (compte_texts), C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m4.json (textes)
meta viewport = « width=device-width,initial-scale=1,viewport-fit=cover » : ni user-scalable=no ni maximum-scale, le pincement reste possible. Formulaire de creation : les 5 champs (pseudo, date, pays, e-mail, mot de passe) a 17 px calcules (Chromium). Rendu Safari iOS non mesure.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m2.json (meta_viewport) ; mesure m7.py
« Ce que Trinke garde » cite « code de secours (chiffré, jamais lisible) » ; aucun mot sur le mot de passe (pourtant demande au formulaire). Aucune mention de Turnstile (Cloudflare), de Have I Been Pwned, ni du prestataire d'e-mail. Phrase « Aucune publicité, aucun traceur » a confronter au script Turnstile. Hebergeur cite : Cloudflare, Inc. ; Stripe cite pour la carte. La page dit « Il faut un compte pour jouer ».
Proposition : Mettre a jour : mot de passe (hache, jamais lisible), Turnstile, verification HIBP en k-anonymat, prestataire e-mail (Brevo ou Resend), et relire « aucun traceur ».
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\08a-legal-390.png ; texte extrait de https://apercu.jeu-soiree.pages.dev/legal/
/legal/ : Editeur et directeur de la publication = Romain Dalon Bourbon, entrepreneur individuel, Cagnes-sur-Mer, SIRET 106 710 098 00018. /legal/cgv/ (version du 16/10/2026) : vendeur = la meme personne, SIREN 106710098, TVA non applicable (293 B). Prix : 3 EUR/mois ou 15 EUR a vie. Article 12 : « [nom, adresse et site du médiateur] » laisse en gabarit.
Proposition : Renseigner un mediateur de la consommation avant toute vente (obligation du code de la consommation, art. L612-1). Theo confirme que l'editeur et le vendeur designes sont bien ceux voulus.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\08b-cgv-390.png ; texte extrait de /legal/cgv/
Le hub des Classiques liste « Pour combien ? Bientôt disponible » : le jeu de Theo est visiblement desactive, pas seulement refuse par un toast comme le deduisait l'audit jeu.
Proposition : Theo tranche le sort de « Pour combien ? » (246 phrases chez lui).
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\mobile\07a-classiques-hub-390.png ; C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m5.json (cl_clic1)
La porte ne teste que la presence d'une cle trinke_token_v1 dans localStorage. Un jeton factice pose localement, avec toutes les requetes /api/ coupees par Playwright, ouvre l'accueil et les parties. Aucune requete /api/ ni non-GET n'a atteint le serveur (journal vide). Rendu equivalent a un joueur connecte dont l'API ne repond pas ; ce qui depend du compte reel (Boutique, Amis, Mon compte) n'a pas ete mesure.
Proposition : Pour les ecrans lies au compte : un compte de test sur une base D1 separee ([env.preview] dans wrangler.toml) pour que l'apercu cesse d'ecrire dans trinke-db.
Preuve : C:\Users\arand\AppData\Local\Temp\claude\C--Users-arand\49deb248-938f-436e-9cd2-73148b479250\scratchpad\audit\m4.json et m5.json (log_sent_api = [], log_blocked_non_get = [])
1 commit d4bf8c65 (08/09, Arand). C'est la version d'avant pull --rebase de 22166bb5, qui a le même message. Les 6 fichiers touchés existent dans main et dans v2. La seule différence est une première rédaction d'un paragraphe de CLAUDE.md, remplacée volontairement. La branche n'a jamais été poussée.
Proposition : Aucune action nécessaire. Theo peut supprimer la branche s'il le souhaite : rien ne serait perdu.
Preuve : git cherry -v origin/main sauvegarde-canal-theo ; reflog main@{39} rebase (finish) onto f304b76a ; git diff d4bf8c65 22166bb5
d76b1488 et 3f6c5b4c (02/10, Romain) sont des ancêtres stricts de origin/main et de origin/soiree-v2. Elles n'ont aucun commit propre. Le code de l'avatar retiré de l'app se récupère depuis d76b1488.
Proposition : Les garder comme repères ; aucun travail perdu.
Preuve : git merge-base --is-ancestor (4 cas vrais) ; git log X --not origin/main origin/soiree-v2 = 0
La main locale est sur 6e7a49fd. Il lui manque 3193ba93 et 1430e5b6 (échanges du 17/10), sans aucun commit en avance. git stash list est vide et git status --porcelain aussi.
Proposition : Rien d'urgent ; un pull ordinaire suffira quand Theo travaillera sur main.
Preuve : git status -sb : main...origin/main [behind 2]
7714c013, 81eb6e5e, 069a61c3, 6ac176b0, 6e7a49fd, 3193ba93 et 1430e5b6 (16-17/10) ne touchent que echanges/ : les réponses de Theo aux 7 fiches et la fiche mot de passe. v2 a 72 commits d'avance. Si v2 remplace main au lieu d'y être fusionnée, ces réponses disparaissent. Un Claude qui lit echanges/ depuis v2 ne les voit pas.
Proposition : Au moment de publier v2 sur main, faire une vraie fusion qui garde ces 7 commits, et vérifier echanges/ après la fusion.
Preuve : git log origin/soiree-v2..origin/main ; git diff --stat da0a8afd origin/main (9 fichiers, tous dans echanges/)
origin/main : 38 entrées du 08/09 au 17/10, toutes en avance rapide. origin/soiree-v2 : 2 entrées (16/10 puis 17/10, en avance rapide). Avant le 16/10, rien n'est visible depuis ce poste. Indice indirect : les dates de commit des 1 039 commits de v2 depuis le 08/09 sont monotones, et seuls 6 ont plus de 10 min d'écart entre auteur et commit (pull --rebase ordinaires).
Proposition : Pour couvrir la période d'avant le 16/10, lire le journal des pushs côté GitHub une fois l'accès rétabli (voir rc-09).
Preuve : Boucle git merge-base --is-ancestor sur chaque couple d'entrées de git reflog show origin/main et origin/soiree-v2 : 0 transition non linéaire
Le reflog de main montre 6 réécritures locales (pull --rebase et un reset). Chaque version d'avant réécriture a un équivalent dans main, sauf 1bea4518, remplacé volontairement par b4269cbe parce que son diagnostic était faux. fsck --no-reflogs --unreachable trouve 9 commits, 9 arbres et 1 blob (version intermédiaire de ECHANGES-THEO.md), tous tenus par le reflog. Aucun orphelin réel.
Proposition : Aucune. Ne pas lancer gc --prune ni d'expiration du reflog si l'on veut garder ces versions.
Preuve : git cherry -v origin/main <ancienne tête> ; git fsck --no-reflogs --unreachable --no-progress
ECHANGES-ROMAIN.md:1804 (entrée v935 du 07/10) cite contre : bdb12c3. Ce commit n'existe dans aucune ref, aucun reflog ni aucun objet du poste. Le vrai parent de 011891e0 (v935) est a9c9911e (v934). Les 11 autres marqueurs contre: récents existent. Cela indique un amend ou un rebase local avant le push, pas un force-push sur GitHub.
Proposition : Faible gravité. Demander au côté Romain de prendre le SHA après le push pour le marqueur contre:, sinon outils/echanges.js ne peut pas résoudre l'état cité.
Preuve : git cat-file -e bdb12c3 : échec ; git log -1 011891e0^ = a9c9911e ; git log -S'contre : `bdb12c3`' = 011891e0
Exemple : a9332139 (08/08) cite c96f4d9, absent du dépôt Trinke mais présent dans Desktop\CLAUDE. L'extraction du 07/09 a changé tous les SHA ; c'est documenté dans le MOC.
Proposition : Aucune ; à savoir quand un ancien message cite un SHA.
Preuve : git -C Desktop\CLAUDE cat-file -t c96f4d9 = commit
gh est absent du PATH (bash et PowerShell), et le connecteur MCP GitHub répond 401. Le dépôt cite au moins l'issue #3 (côté Romain, 08/09 : l'aperçu écrit dans trinke-db), qualifiée « à refermer » dans ECHANGES-THEO.md:137. Son état réel est inconnu. Un commit du 08/09 note que l'accès GitHub de Theo recevait une erreur 404 sur ce dépôt.
Proposition : Theo installe gh (winget install GitHub.cli) et l'authentifie lui-même, ou renouvelle le PAT du connecteur. Relancer ensuite gh issue list --state all et gh pr list --state all.
Preuve : command -v gh : absent ; Get-Command gh : absent ; MCP github AUTH_HEADER_REJECTED ; git grep 'issue #' origin/soiree-v2
La note dit : pas de classement public global, pseudo libéré bloqué 90 jours, purge à 24 mois, compte optionnel, compte sans mot de passe. Le code dit : route classement global (top 20) depuis b93b83e4 (27/07, Theo), GRACE = 0 (choix de Theo du 25/07), purge jamais codée. Compte obligatoire et mot de passe sont déjà relevés ailleurs. Une session pourrait reprendre ces lignes comme règles.
Proposition : Passer la note au statut « remplacée » avec un renvoi vers l'état réel. Ne pas la réécrire en silence.
Preuve : [[route]].js:2448 (CLASSEMENT GLOBAL), :19 (GRACE = 0) ; Cerveau\Jeux-Soiree\PLAN-COMPTES-STATS.md l.96-99, 269, 271
La décision est écrite au chapitre 9 du plan. Aucun commit, sur aucune branche, ne la réalise, et le texte « Ce que Trinke garde » ne donne aucune durée de conservation des comptes. Seules les sessions expirent (120 jours).
Proposition : Theo tranche : coder la purge (et l'annoncer) ou retirer la promesse du plan. Ce point recoupe les durées manquantes de la page légale.
Preuve : git log --all -G'24 mois|purge.*inactif' : seul d6cf4f0c (archives) ; app.js:12511-12520
BASE-PRODUCTION.md:45 (08/09) constate que la table est vide. Aucun commit postérieur n'y verse de liste, alors que le code la lit ([[route]].js:1008). Avec le compte obligatoire et le classement global qui affiche les pseudos du top 20, seule la courte liste RESERVES (:978) filtre. La règle du plan (insultes, haine, sexuel, usurpation, marques) n'est donc pas tenue. L'état actuel de la production n'a pas été lu.
Proposition : Lire la table en production (connecteur Cloudflare, en lecture) ; si elle est vide, préparer une liste pour validation par Theo.
Preuve : git log origin/soiree-v2 -G pseudos_interdits : dernier commit le 08/09 ; BASE-PRODUCTION.md:45
La section 9 bis du plan fait de « Cul sec » le point de vigilance App Store 1.4.3 et constate qu'aucune formulation de ce type n'existe dans le contenu. v2 et main contiennent 2 cartes Action qui finissent par « puis cul sec », venues du tri de Romain (37bcd155 v880, af2884ee v884). Le moteur compte un cul sec pour 4 gorgées. La spec du 22/07 autorisait pourtant le cul sec comme sanction : les deux textes se contredisent.
Proposition : Theo tranche avant tout dépôt en boutique : reformuler ces 2 cartes ou assumer et mettre la note à jour.
Preuve : public/cartes-fr.json ids f7475ece et f9042918 ; app.js:4919 et 4931 ; PLAN-COMPTES-STATS.md l.290 et 297-299
Le dossier de design (3 342 lignes) n'a plus bougé depuis ca017fd8 (02/08). Sa section « Ce qui MANQUE » est périmée : le partage existe (app.js:620 navigator.share), les CGU et la confidentialité existent. Le MOC (08/09) note qu'aucun des deux Claude n'a le droit de le modifier.
Proposition : Theo désigne qui le tient à jour, ou y ajoute en tête un avertissement « état au 02/08 ».
Preuve : git log -1 origin/soiree-v2 -- TRINKE.md = ca017fd8 ; TRINKE.md l.72-83 et 499-512
TRINKE.md demande de traduire cash out, crash et timer. Dans v2, « Timer aveugle » existait déjà chez Theo. « Cash out » a été renommé « Crash out » le 29/09 (commentaire de Romain, app.js:229) : c'est toujours un anglicisme, et il est affiché (index.html:800, app.js:18953). « Gage » est gardé délibérément (app.js:2726).
Proposition : Theo tranche : appliquer la règle ou la réécrire.
Preuve : TRINKE.md l.549-563 ; app.js:224, 229 ; index.html:769, 800
La note du 03/08 dit « A TRANCHER PAR THEO », et Theo a répondu « on verra plus tard, oublie pas ». v2 garde MSG_VIE à 30 jours et l'annonce à 3 endroits. Le code est cohérent, la décision reste ouverte depuis 11 semaines.
Proposition : Le rappeler à Theo. Ne rien coder avant son arbitrage.
Preuve : [[route]].js:726 ; app.js:12517, 12748, 13167 ; STOCKAGE-MESSAGES-CHEZ-LES-GENS.md
Le MOC (l.27 et 35) et _MEMOIRE (l.523 et 1369) signalent une clé exposée le 27/07 et non révoquée, sans dire de quel service il s'agit. Elle n'apparaît dans l'historique d'aucune branche du dépôt Trinke : les motifs connus donnent 0 résultat.
Proposition : Theo identifie le service et révoque la clé. C'est hors de ce dépôt, mais le sujet est ouvert depuis près de 3 mois.
Preuve : git log --all --reflog -G (motifs de rc-18) = 0 ; MOC-Jeux-Soiree.md l.27 et 35
0 commit pour [CLE MASQUEE], sk_test_, [CLE MASQUEE], [CLE MASQUEE], ghp_, github_pat_, CLOUDFLARE_API_TOKEN suivi de 40 caractères, re_ (Resend), sk-ant-, AKIA, clé PEM, AIza, JWT et Turnstile 0x4AAA. Les 7 commits qui affectent des variables de secret (outils/test-*.mjs : 56b0ff32, 1a36fdda, 0cb29ec2, 8e8530d9, 80fab682, 830a75d0, a8bc474d) utilisent des valeurs factices.
Proposition : Aucune.
Preuve : git log --all --reflog -E -G<motif> ; classement des valeurs sans les recopier
Point déjà relevé (codes de Romain et du compte de test, l.1589, 1618 et 1623). Ajout : ils sont entrés par 00112d8d (v919) et f9e4e955 (v921, 07/10), et retirer le texte ne les effacera pas de l'historique de main et de v2. Les autres TRK de l'historique sont factices (tests, exemples, maquettes).
Proposition : Rendre ces codes inutiles en base, et fermer la connexion par code en production, ce que fait v1081 mais pas origin/main. Ne pas réécrire l'historique.
Preuve : git log --all --reflog -E -G'TRK-[A-Z0-9]{4}' : 14 commits classés un par un
Seul sauvegardes/trinke-db-2026-09-08.sql.gpg (39 762 o, OpenPGP AES-256, déjà relevé) a été suivi. Aucun .dmp, .sqlite, .db, .env, .dev.vars, .pem ou .key n'a jamais été suivi sur aucune branche. Les plus gros fichiers sont des PNG sources d'environ 2 Mo ; le pack total fait 49 Mo.
Proposition : Aucune.
Preuve : git log --all --reflog --name-only | filtre d'extensions ; git rev-list --all --objects | cat-file --batch-check