Commit Graph

67 Commits

Author SHA1 Message Date
Valentin ROBIN e70f0c85bb Corrige la compression d'image sur Safari/iPhone (repli PNG au lieu de JPEG)
Build and deploy / deploy (push) Successful in 37s
canvas.toBlob demandait du WebP en dur pour compresser avant l'envoi. Safari ne sait pas l'encoder et retombe silencieusement sur du PNG (imposé par la spec) — un format quasi sans perte, bien plus lourd qu'un JPEG pour une photo, au point de dépasser la limite de taille du bucket malgré une photo source raisonnable (vécu en prod : 4 Mo sur iPhone). Le support WebP est maintenant détecté une fois, avec repli explicite sur JPEG plutôt que de laisser le navigateur choisir. S'applique au Mur (déjà corrigé pour l'extension/Content-Type) et maintenant aussi aux avatars (/profile, /signup).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 15:04:08 +02:00
Valentin ROBIN 358bed0c2e Passe de polish visuel sur tout le site
Corrige deux incohérences trouvées en chemin : le compteur de passages dans le char en gold-bright sur marbre (même défaut de contraste déjà vu ailleurs), et le point du Crieur toujours rouge même pour un honneur positif. Réutilise les ornements existants mais jamais appelés (meander-divider entre le podium et le classement, DiamondDivider sur /profile avec une nouvelle convention de carte secondaire). Ajoute une ambiance discrète (fond qui respire très lentement, halo doré sur les cartes marbre, désactivés sous prefers-reduced-motion), étend les confettis et un nouveau son à Icare pour la parité avec la Corne d'Abondance, des loading.tsx sur les pages les plus consultées, et un petit ornement sur les états vides plutôt qu'un texte brut.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-26 15:03:52 +02:00
Valentin ROBIN 187cdec0e2 Affiche le n°1 d'Icare et de la Corne d'Abondance sur /leaderboard
Build and deploy / deploy (push) Successful in 36s
Nouvelle section (game-highlights.tsx) juste sous les raccourcis : avatar, pseudo et score du meneur actuel de chaque mini-jeu, cliquable vers le jeu correspondant. Même règle que les podiums existants : rien affiché tant que le meneur est à 0. Score en text-sea (pas gold-bright, peu lisible sur fond marbre — même choix déjà fait pour Icare/Corne/l'Urne).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 19:39:38 +02:00
Valentin ROBIN 3aa2ea451c Corrige un décalage Content-Type/extension à l'upload d'images sur le Mur (Safari/iPhone)
Build and deploy / deploy (push) Successful in 36s
canvas.toBlob demandait du WebP en dur, mais un navigateur qui ne sait pas l'encoder (Safari, historiquement) retombe silencieusement sur du PNG — le fichier était quand même uploadé étiqueté "webp". L'extension et le Content-Type suivent maintenant le type réel du blob. Remplace aussi le message générique "Une erreur est survenue" par des messages distincts par étape (compression/upload/validation serveur), avec le détail technique loggé en console pour diagnostiquer plus vite la prochaine fois.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 19:33:36 +02:00
Valentin ROBIN 6922d33e39 Ajoute une pastille sur le raccourci du Mur de la Honte
Nombre de publications du jour, façon notification iOS, sur le raccourci /mur de /leaderboard — via wall_notes_for_date() (une lecture directe de wall_notes ne montrerait, à cause de la RLS, que ses propres notes, pas le total).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 19:33:29 +02:00
Valentin ROBIN 0eaebb7a05 Permet de consulter les jours précédents du Mur de la Honte, pour tout le monde
Build and deploy / deploy (push) Successful in 36s
wall_notes_today() devient wall_notes_for_date(p_date default null) — même garantie d'anonymat qu'avant, juste paramétrée par jour plutôt que figée sur aujourd'hui. Nouvelle RPC wall_note_days() (dates ayant au moins une note, sans contenu ni auteur) peuple un sélecteur de jour au-dessus de la grille, visible par tous — pas seulement les Archontes via l'historique complet, qui lui révèle l'auteur. wall_note_reaction_counts() gagne le même paramètre p_date. Le compteur "X/12 aujourd'hui" et l'éligibilité à publier restent toujours basés sur aujourd'hui, peu importe le jour consulté.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 18:15:34 +02:00
Valentin ROBIN 203afafec2 Ajoute des raccourcis vers les autres pages sur /leaderboard
Build and deploy / deploy (push) Successful in 36s
L'Agora sert déjà de page d'accueil de fait (/ y redirige) mais n'offrait aucun accès direct aux autres pages sans passer par le menu déroulant du chip. Ajoute une rangée de raccourcis (Icare, Corne d'Abondance, Char, Mur de la Honte, Urne, Crieur) juste au-dessus du classement, responsive (3 colonnes mobile, 6 en ligne sur écran plus large), mêmes icônes que le menu du header pour rester cohérent.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 17:54:49 +02:00
Valentin ROBIN 4532403c95 Rend les photos du Mur de la Honte cliquables pour les agrandir
Build and deploy / deploy (push) Successful in 36s
Ajoute une visionneuse plein écran (mur du jour, sa propre note, et l'historique complet côté Archontes). Corrige au passage un bug introduit avec l'ouverture du Mur aux Archontes (V14) : leur propre note du jour ne se rafraîchissait jamais après le chargement initial, le refetch la filtrait encore par rôle.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 17:46:19 +02:00
Valentin ROBIN ede1d6c74d Ajoute un son de fusion dans La Corne d'Abondance
Build and deploy / deploy (push) Successful in 36s
Pas de fichier audio dans le projet, donc un petit "pop" synthétisé via Web Audio (src/lib/melon/sound.ts), joué à chaque fusion. La hauteur baisse avec le palier de la pièce obtenue, pour que fusionner deux grosses pièces sonne différemment de deux petites.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 17:42:04 +02:00
Valentin ROBIN 5e75939b94 Ouvre Le Mur de la Honte aux Archontes, plafond quotidien relevé à 12
Build and deploy / deploy (push) Successful in 36s
post_wall_note() n'a plus de vérification de rôle : un Archonte peut désormais publier une note anonyme comme n'importe quel Citoyen. La policy Storage d'upload sur wall-images perd aussi son filtre par rôle (sinon possible de poster une note mais pas d'y joindre une image). Limite quotidienne relevée de 10 à 12 notes pour couvrir tout le groupe plutôt que les seuls Citoyens.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 17:30:46 +02:00
Valentin ROBIN 40a10170bb N'affiche plus de podium quand tout le monde est encore à 0
Build and deploy / deploy (push) Successful in 37s
Le classement "compétition" fait partager le rang 1 à tous les ex-aequo — sans score, tout le groupe se retrouvait sur la 1ère marche du podium. Le podium ne s'affiche plus tant que le meneur n'a pas dépassé 0, sur /leaderboard, /icare et /corne.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 17:05:09 +02:00
Valentin ROBIN 9f91856c53 Améliore la lisibilité de la Détection de triche sur /admin
Build and deploy / deploy (push) Successful in 36s
Ajoute l'avatar du joueur signalé (admin_list_members() le renvoyait déjà, juste jamais propagé), l'heure de début/fin de la partie (déduite de created_at et de la durée annoncée), et remplace la ligne de détails en flex-wrap par une grille à étiquettes qui reste lisible sur mobile.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 17:02:14 +02:00
Valentin ROBIN 00743067cc Ajoute un ping serveur régulier comme troisième couche d'anti-triche sur Icare et la Corne
Build and deploy / deploy (push) Successful in 36s
duration_ms/actions/merges restaient entièrement déclaratifs (calculés et envoyés par le client en une fois à la fin), donc falsifiables par un appel RPC direct. Le client envoie maintenant un ping toutes les 5s pendant la partie (ping_game_run), horodaté par le serveur, jamais par le client. submit_icarus_score/submit_melon_score corrèlent le nombre de pings et leur écart réel avec la durée annoncée (parties ≥ 15s uniquement) et signalent toute incohérence dans game_cheat_flags (missing_pings, ping_span_mismatch) — toujours en signalement silencieux, jamais de blocage, comme pour le reste de l'anti-triche.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 16:58:51 +02:00
Valentin ROBIN 088cd92e5f Resynchronise schema.sql avec l'anti-triche par signalement d'Alexandre
submit_icarus_score/submit_melon_score (appliquées directement en base, jamais commitées) sont récupérées mot pour mot via pg_get_functiondef : signalement dans game_cheat_flags plutôt que rejet serveur, le score reste toujours accepté. L'ancienne couche par rejet strict (icarus_runs/start_icarus_run) devenue orpheline est explicitement supprimée plutôt que laissée à traîner. CLAUDE.md documente le nouveau mécanisme (V12) et n'a plus aucune mention de l'ancien.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 16:42:26 +02:00
Valentin ROBIN 50b354f11c Corrige la ligne de danger de la Corne (franchissement complet, pas au contact) et redesigne l'échelle de repère
Build and deploy / deploy (push) Successful in 36s
La pièce devait déjà entièrement dépasser la ligne rouge (bord bas, pas juste le sommet) pour compter dans le délai de grâce avant game over. L'échelle des tailles en bas de page passe d'une seule ligne à défilement horizontal à un flex-wrap sans scroll, avec un titre — l'intérêt d'une échelle de repère est de tout voir d'un coup d'œil. Corrige aussi une violation de react-hooks/purity (Date.now() en argument direct de useRef) introduite par le mécanisme anti-triche fusionné depuis main.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 16:21:11 +02:00
alexandre 6134bf22d0 fix build error
Build and deploy / deploy (push) Successful in 36s
2026-08-24 12:11:50 +02:00
alexandre b7f3f8b0fa Add discreet anticheat mechanism for the games
Build and deploy / deploy (push) Failing after 32s
2026-08-24 12:07:10 +02:00
Valentin ROBIN 35704e50fc Resserre les plafonds de score, ajoute une vérif par temps réel écoulé sur Icare, corrige le contraste de l'Urne
Build and deploy / deploy (push) Successful in 36s
5000 restait trop haut pour être un vrai plafond réaliste : Icare abaissé à 500 (calculé sur le rythme le plus rapide théoriquement atteignable dans le jeu), Corne à 2000 (estimation plus prudente, économie de score plus dure à borner). Ajoute icarus_runs/start_icarus_run() : le serveur enregistre l'instant réel de début de partie et rejette un score incohérent avec le temps écoulé, sans jamais faire confiance à une durée envoyée par le client. Corrige aussi le nombre de jetons de /urne, peu lisible en gold-bright sur fond marbre (passe à text-sea, même convention qu'Icare/Corne).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 11:28:02 +02:00
Valentin ROBIN dc99af6bb3 Durcit la sécurité : plafond de score réaliste, REVOKE explicites, banque de questions du Char réservée aux juges
Build and deploy / deploy (push) Successful in 36s
Un score falsifié envoyé directement à submit_icarus_score/submit_melon_score pouvait se convertir en vraies gloires au Tribunal (plafond abaissé de 1 000 000 à 5000, contrainte + RPC). Les fonctions cron-only award_*_points_if_due() n'étaient protégées que par un commentaire, pas un vrai REVOKE. Le bucket avatars n'avait aucune limite de taille/type. La banque complète des questions du Char (spoiler du jeu) était lisible par tout Citoyen via /char ou un appel direct — RLS restreinte aux juges, /char passe désormais par la RPC chariot_revealed_question().

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 04:41:39 +02:00
Valentin ROBIN 3503dc2593 Corrige les pièces qui débordaient du bac à droite/en bas
Build and deploy / deploy (push) Successful in 36s
La bordure était posée directement sur le conteneur aux coordonnées
physiques (300x420) : à cause du box-sizing, la bordure mangeait sur
l'espace intérieur réel (292x416) sans que matter-js le sache, donc les
pièces pouvaient visuellement dépasser le cadre. La bordure vit
maintenant sur un conteneur externe non dimensionné, qui s'ajuste
automatiquement autour du conteneur physique sans réduire sa zone utile.

Ajoute aussi l'échelle de repère (ordre de fusion, taille proportionnelle
au rayon) et le second aperçu de la pièce suivante, travaillés en même
temps.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 04:02:40 +02:00
Valentin ROBIN b0bf54f20c Corrige le lâcher qui ignorait un simple tap sans glissement
Build and deploy / deploy (push) Successful in 36s
Sur mobile, taper sans glisser ne déclenche pas forcément pointermove
avant pointerup, donc la position de visée n'était jamais mise à jour
avant le lâcher : la pièce tombait à l'ancienne position plutôt qu'à
l'endroit tapé. La position se resynchronise maintenant au contact
(pointerdown) et juste avant le lâcher (pointerup).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 01:04:58 +02:00
Valentin ROBIN 05aa15cec0 Corrige la marge excessive de lâcher près des bords du bac
Build and deploy / deploy (push) Successful in 36s
Le calcul de position ajoutait WALL_THICKNESS (20px) en plus du rayon de
la pièce, alors que les murs physiques sont déjà à ras des bords visuels
du bac. Cette marge fixe pénalisait surtout les petites pièces, qui ne
pouvaient pas s'approcher des bords. Seul le rayon compte désormais.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 01:01:25 +02:00
Valentin ROBIN 4dd3dbef85 Affiche la deuxième pièce à venir dans La Corne d'Abondance
Build and deploy / deploy (push) Successful in 36s
Petit badge "Puis" à côté du score, taille d'affichage fixe (juste
informatif, pas de position à viser) — la file glisse d'un cran à chaque
lâcher : ce qui était annoncé en second devient la pièce à viser.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 00:58:03 +02:00
Valentin ROBIN 493ae444b4 Permet de fixer manuellement certains Citoyens à un palier précis
Build and deploy / deploy (push) Successful in 35s
TIER_OVERRIDES (id de profil → index de palier) + applyTierOverrides()
placent d'abord les Citoyens fixés à la main, puis remplissent le reste
dans l'ordre alphabétique existant. Épicure est placé en position 7.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 00:55:38 +02:00
Valentin ROBIN 3b64e1cdb5 Ajoute La Corne d'Abondance, jeu de fusion façon Watermelon Game
Build and deploy / deploy (push) Successful in 35s
Nouveau mini-jeu à /corne : des avatars de Citoyens tombent dans un bac
(physique matter-js), deux avatars de même taille qui se touchent
fusionnent en un plus gros, jusqu'au débordement soutenu (5s de grâce,
pièces clignotantes pour prévenir) qui met fin à la partie. Même
mécanique de gloires que Le Vol d'Icare (record personnel, classement,
gel + attribution automatique au Tribunal via pg_cron).

Un palier de taille par Citoyen (pas les Archontes) plutôt qu'un nombre
arbitraire : citizens[tier] donne l'association palier → Citoyen, fixe
pour tout le monde (les Citoyens sont triés par pseudo côté serveur, un
ordre déterministe). Rendu en DOM pour réutiliser le composant Avatar
existant (étendu pour accepter une taille en pixels arbitraire) plutôt
que de redessiner des images sur canvas — position et rotation de chaque
pièce appliquées en impératif depuis la boucle physique, jamais via
setState.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-24 00:52:07 +02:00
Valentin ROBIN c3a3577769 Corrige la distance du boost et ajoute des filets de vitesse continus
Build and deploy / deploy (push) Successful in 35s
La fenêtre de 3-8 colonnes du bouclier est maintenant une vraie distance :
chaque colonne rencontrée décompte, qu'elle soit touchée (cassée au lieu
de tuer) ou franchie sans contact (non cassée) — avant, seules les
colonnes touchées consommaient le bouclier, qui pouvait donc durer bien
plus longtemps que prévu.

Ajoute aussi des filets de vitesse continus autour d'Icare pendant toute
la durée du bouclier (pas seulement au bond initial de cueillette), pour
que la sensation d'accélération reste lisible même si Icare est figé.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 23:52:44 +02:00
Valentin ROBIN bdeeb68845 Rend le boost du Vol d'Icare aléatoire et incontrôlable
Build and deploy / deploy (push) Successful in 35s
Le nombre de charges (colonnes cassables) est désormais tiré entre 3 et 8
à chaque cueillette, au lieu d'un nombre fixe. Pendant que le bouclier est
actif, Icare est immobile (gravité coupée, taps/barre d'espace sans
effet) et le défilement accéléré (×1,7) : impossible d'agir sur la
trajectoire jusqu'à épuisement des charges, où le contrôle reprend.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 23:38:42 +02:00
Valentin ROBIN b6a025c23f Ajoute un boost (éclair de Zeus) et le support clavier au Vol d'Icare
Build and deploy / deploy (push) Successful in 35s
Rare et exceptionnel (intervalle large de 15-25 colonnes, pas de plafond
par partie) : ramasser l'éclair donne un bouclier de 5 charges — toucher
une colonne (mortel normalement) la casse au contact et consomme une
charge, une par une, plutôt que de détruire un nombre fixe de colonnes
d'un coup à la cueillette. Cueillette animée d'un bond en avant d'Icare
avec traînée de vitesse, halo pulsant sur l'éclair, éclat de particules
sur chaque colonne cassée et liseré doré tant que le bouclier est actif.

Ajoute aussi le support clavier (barre d'espace = tap) pour jouer au
clavier sur ordinateur.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 23:29:19 +02:00
Valentin ROBIN 47ca05f1c6 Ajoute images et réactions sur les notes du Mur de la Honte
Build and deploy / deploy (push) Successful in 36s
Chaque note peut désormais porter une image facultative : compressée et
redimensionnée côté client (resizeImageToBlob, sans forcer un carré comme
pour les avatars) avant l'upload, avec une limite dure côté bucket
Supabase (3 Mo, webp/jpeg/png uniquement) en filet de sécurité. Le chemin
de stockage ne contient jamais le user_id, contrairement aux avatars,
pour ne pas faire fuiter l'auteur via l'URL publique de l'image.

Ajoute aussi des réactions emoji (👍😂😱❤️🔥) sur chaque note, avec le
même principe d'anonymat que le reste du Mur : le total par emoji est
public (wall_note_reaction_counts), mais personne ne voit qui a réagi.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 23:01:40 +02:00
Valentin ROBIN e8a9a0ddb9 Ajoute des justifications anonymes aux votes de L'Urne de l'Agora
Build and deploy / deploy (push) Successful in 35s
Un Citoyen peut désormais laisser un motif facultatif en déposant son
jeton (toujours deux étapes avant l'envoi). Le classement permet de
consulter les justifications reçues par une personne via une nouvelle RPC
urn_vote_reasons() — même principe que wall_notes_today : le contenu est
public, l'auteur ne l'est jamais, ce qui préserve la garantie de L'Urne
que personne (Archontes compris) ne voit qui a voté pour qui.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 22:48:25 +02:00
Valentin ROBIN 0dfd3e7e90 Passe Le Vol d'Icare en plein écran avec podium animé pour le top 3
Build and deploy / deploy (push) Successful in 35s
Le classement (dont un nouveau podium top 3, réutilisant celui de L'Agora)
vit maintenant dans une modale entièrement détachée de la mise en page du
jeu : une mise à jour Realtime du classement pendant une partie ne peut
plus redimensionner le canvas et casser la partie en cours. Le jeu occupe
tout l'écran disponible (contain avec letterboxing) au lieu d'une carte
fixe en haut de page. Corrige aussi le score du classement, en bleu au
lieu de doré (contraste insuffisant sur fond marbre clair).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 22:41:08 +02:00
Valentin ROBIN e542b09807 Migre le domaine vers agora.alxczl.fr et corrige la doc de déploiement
Build and deploy / deploy (push) Successful in 35s
.env.docker.example suit le nouveau domaine. README/CLAUDE.md décrivaient
encore un déploiement Vercel jamais réellement utilisé : corrigés pour
refléter le vrai pipeline self-hosted (Docker Compose + Traefik + CI Gitea
Actions via webhook).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 22:12:38 +02:00
Valentin ROBIN 86756c41da Corrige les comptes invités qui restaient bloqués sans mot de passe
Le pseudo temporaire fixe "Nouveau membre" entrait en collision (contrainte
unique) dès qu'une 2e personne était invitée avant que la 1re ait fini son
inscription ; il inclut maintenant un suffixe d'uuid. Le token d'invitation
pouvait aussi s'établir sur n'importe quelle page (pas seulement /signup),
laissant certains comptes connectés sans jamais voir le formulaire de mot
de passe — /signup affiche désormais un état de chargement au lieu d'un
écran vide, et le proxy renvoie systématiquement vers /signup tant que le
compte n'est pas finalisé.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-23 22:12:31 +02:00
Valentin ROBIN 1eef52a101 Retire Le Calendrier des Dieux du menu, affiche la date du Tribunal sur L'Agora
Build and deploy / deploy (push) Successful in 35s
/calendrier disparaît de la navigation (route toujours fonctionnelle
pour les Archontes qui y accèdent directement) : la date du Tribunal,
seule info largement utile au quotidien, est reprise en en-tête de
/leaderboard. Extrait la logique de décompte dans un helper partagé
src/lib/tribunal-date.ts plutôt que de la dupliquer.

Corrige au passage un espace JSX manquant sur /urne oublié lors du
dernier commit ("Tu as voté pour Xaujourd'hui").
2026-08-23 19:29:31 +02:00
Valentin ROBIN d02f1543e9 Ajoute L'Urne de l'Agora
Build and deploy / deploy (push) Successful in 36s
Nouvelle page /urne : vote quotidien inspiré du vote à l'urne de
l'Athènes antique. Chaque Citoyen dépose un jeton par jour sur une
autre personne (jamais lui-même), avec confirmation à deux temps
avant l'envoi — le vote est définitif pour la journée, aucune RPC de
modification. Les jetons s'accumulent sur toute la semaine dans un
classement public et cumulatif, identique pour tout le monde y
compris les Archontes : contraste volontaire avec Le Mur de la Honte,
ici personne (Archontes compris) ne voit qui a voté pour qui, seul le
total par personne est public.

Nouvelle table urn_votes (append-only, comme points_log) + deux RPC :
urn_vote_counts() agrège les votes sans jamais exposer une ligne
individuelle, cast_urn_vote() applique les règles (pas de vote pour
un juge ni pour soi-même, un vote par jour). Les Archontes ne votent
pas et ne peuvent pas recevoir de jetons.
2026-08-23 18:02:12 +02:00
Valentin ROBIN ab599d55c9 Ajoute Le Mur de la Honte
Build and deploy / deploy (push) Successful in 35s
Nouvelle page /mur : chaque Citoyen peut publier une note anonyme par
jour (dix places max sur le mur, remis à zéro chaque jour — filtrage
par date, jamais de suppression). L'anonymat n'est qu'à moitié réel :
les Archontes voient une section "Historique complet" (filtrable par
jour) avec l'auteur de chaque note, cohérent avec le thème du site où
les Archontes ont un ascendant sur les Citoyens.

Nouvelle table wall_notes + deux RPC : wall_notes_today() ne renvoie
jamais l'auteur (seul moyen de garantir l'anonymat côté serveur, la
RLS ne pouvant pas masquer une colonne pour certaines lignes) et
post_wall_note() applique les règles (un juge ne publie pas, une note
par jour, mur plafonné à 10). Pas de gel lié à la date du Tribunal :
contrairement au Char, c'est une mécanique de toute la semaine.
2026-08-23 17:14:12 +02:00
Valentin ROBIN ec6b1920af Ajoute l'historique des versions des questions soumises par les Citoyens
Build and deploy / deploy (push) Successful in 35s
Nouvelle table chariot_submission_history (append-only, comme
points_log) : chariot_submissions ne garde que la valeur actuelle
(upsert), donc sans ce journal les Archontes ne voyaient jamais les
versions précédentes d'une question modifiée plusieurs fois.
submit_chariot_question() y écrit désormais à chaque changement réel.

Sur /char/questions, chaque suggestion affiche un lien "Historique (N)"
(visible seulement si la personne a déjà modifié sa proposition) qui
déplie les versions précédentes avec leur date.
2026-08-22 00:16:42 +02:00
Valentin ROBIN 6badff38af Désactive le bouton d'enregistrement de la question quand rien n'a changé
Build and deploy / deploy (push) Successful in 35s
Ajoute un suivi de la dernière valeur sauvegardée (comme le pattern
déjà utilisé dans admin-members-table.tsx et profile-form.tsx) : le
bouton "Enregistrer" se grise et affiche "Déjà enregistrée" tant que
le texte n'a pas été modifié depuis la dernière sauvegarde, dès le
chargement de la page si la question n'a pas bougé.
2026-08-21 17:26:24 +02:00
Valentin ROBIN 76fa8cd451 Ajoute les suggestions de questions des Citoyens et les emails sur Admin
Build and deploy / deploy (push) Successful in 35s
Chaque Citoyen peut proposer une question pour Le Char depuis /profile
(upsert via submit_chariot_question, figée dès la date du Tribunal
comme les scores d'Icare). Les Archontes modèrent ces suggestions
directement sur /char/questions (ajouter à la banque ou rejeter).

/admin affiche maintenant l'email de chaque membre via une nouvelle
RPC admin_list_members(), seule façon d'exposer auth.users.email sans
passer par la service_role key côté client.

Corrige au passage deux bugs découverts pendant les tests : la
policy interne de admin_list_members() référençait id/role sans les
qualifier, ambigus avec les colonnes du RETURNS TABLE (erreur
Postgres 42702) ; et l'auteur d'une suggestion s'affichait toujours
comme "un Citoyen" car le embed profiles(...) avait été mal retypé en
tableau alors qu'il est retourné en objet à l'exécution.
2026-08-19 01:22:36 +02:00
Valentin ROBIN 0c4814f4d6 Corrige le Realtime qui ne diffusait aucun événement à travers l'app
Build and deploy / deploy (push) Successful in 37s
Les canaux Realtime (Char, Gardien, classement, journal, calendrier,
Icare) s'abonnaient juste après createClient(), avant que la session
ne soit chargée de façon asynchrone — le canal rejoignait donc
Supabase en rôle "anon" au lieu de "authenticated", et les policies
RLS "to authenticated" bloquaient silencieusement tous les événements
(l'abonnement lui-même réussissait, ce qui masquait le problème).

Ajoute waitForRealtimeAuth() dans src/lib/supabase/client.ts, qui
attend la session et pousse explicitement le token avant de
s'abonner. Vérifié avec deux sessions navigateur distinctes : les
changements se propagent maintenant réellement sans rechargement.
2026-08-19 00:40:02 +02:00
Valentin ROBIN 1e7ff621e4 Applique la police et l'icône console d'Admin aussi dans le menu
Build and deploy / deploy (push) Successful in 35s
Partage la police JetBrains Mono (déjà utilisée sur /admin) via un
module commun src/lib/fonts.ts, et l'applique à l'entrée "Admin" du
menu déroulant. Remplace son icône générique par une nouvelle icône
terminal (IconTerminal), cohérente avec la rupture volontaire de
thème sur cette page technique.
2026-08-11 18:51:12 +02:00
Valentin ROBIN 8c952b017b Fusionne La Roulette dans Le Jeu de l'Agora, corrige la Roulette et renomme Admin
Build and deploy / deploy (push) Successful in 35s
Déplace La Roulette de sa page dédiée vers une section de /char (tout
l'outillage de la soirée du Tribunal au même endroit) et retire la
route /roulette. Corrige un bug de superposition où le pointeur doré
de la roulette passait devant le menu déroulant du header (isolation
de contexte d'empilement manquante). Renomme "Le Conseil des
Archontes" en "Admin" avec une police monospace, rupture volontaire
avec le thème grec pour cette page technique.
2026-08-11 18:45:55 +02:00
Valentin ROBIN f30f77a394 Ajoute Le Jeu de l'Agora : Le Char et Le Gardien du Silence
Build and deploy / deploy (push) Successful in 36s
Page /char (16:9, projetée) pour piloter les deux jeux physiques du
Tribunal : Le Char (2 colonnes de 3 emplacements côte à côte avec un
VS et une illustration de char vu du dessus, sélection en un clic,
duels, compteur et classement des passages) et Le Gardien du Silence
(tirage aléatoire parmi les Citoyens, minuteur avec reroll auto et
manuel). Banque de questions gérée séparément sur /char/questions
(pensée pour être pilotée depuis un téléphone pendant que /char est
projetée depuis un ordinateur).
2026-08-11 18:17:45 +02:00
Valentin ROBIN 4e22001ae0 Ajoute une difficulté progressive au Vol d'Icare
Build and deploy / deploy (push) Successful in 1m36s
À partir du score 10, la vitesse de défilement augmente et l'écart
entre les colonnes se resserre progressivement, jusqu'à un palier à
score 50 (vitesse ×1.6, écart réduit à 75%) pour ne pas devenir
injouable sur une longue partie. Le gap est maintenant stocké par
colonne (plutôt qu'une constante globale) pour que les colonnes déjà
en place ne changent pas de taille rétroactivement.
2026-08-01 22:40:54 +02:00
Valentin ROBIN 7c5ce9dcb9 Peaufine Le Vol d'Icare : animation, overlay, contraste
Build and deploy / deploy (push) Successful in 36s
- Écran de fin (score + Rejouer) déplacé en overlay par-dessus le jeu
  (fond assombri, carte animée, confettis) plutôt qu'en dessous.
- Battement d'ailes repensé : cycle continu en boucle (visible même au
  repos, sans taper) + battement plus ample au tap qui prend le dessus
  brièvement. L'ancienne version ne bougeait qu'au moment du tap et
  retombait trop vite pour être perceptible en jeu réel.
- Corrige une aile qui semblait ne pas bouger : les deux ailes utilisaient
  des teintes différentes et l'une passait partiellement derrière le
  corps ; elles sont maintenant identiques et toutes deux dessinées
  au-dessus du corps. Corrige au passage un signe de rotation inversé.
- Corrige le contraste de plusieurs textes (« Ton record », instructions,
  pied de page) qui utilisaient une couleur prévue pour du texte sur
  marbre alors qu'ils s'affichent sur le fond sombre de la page.
2026-07-30 00:59:15 +02:00
Valentin ROBIN 33d2476ef6 Remplace la Course du Char par Le Vol d'Icare
Build and deploy / deploy (push) Successful in 37s
Après retour d'expérience, la course de char (vue du dessus, piste
générée par jour) laisse place à un Flappy Bird grec plus simple et
plus lisible sur téléphone : Icare vole entre des colonnes de temple,
touche l'écran pour battre des ailes, échec net au premier contact
(score remis à zéro).

Record personnel all-time (plus de piste quotidienne ni de fantômes) :
les scores se figent dès que la date du Tribunal est atteinte, puis les
gloires du top 3 sont attribuées automatiquement via une tâche
planifiée pg_cron, comme pour l'ancienne Course du Char.

schema.sql nettoie explicitement l'ancienne Course du Char (tables,
RPC, tâche planifiée) avant de poser le nouveau schéma, puisqu'elle
avait déjà été appliquée en prod.
2026-07-29 19:14:52 +02:00
Valentin ROBIN 6af56d2ade Ajoute La Course du Char : mini-jeu de course 2D quotidien
Build and deploy / deploy (push) Successful in 37s
Premier mini-jeu compétitif du Tribunal (/course) : piste 2D générée
de façon déterministe à partir de la date du jour (identique pour tout
le monde, jamais stockée côté serveur), pilotage au joystick tactile
virtuel, murs + obstacles qui ralentissent temporairement sans jamais
stopper la course, fantômes du top 3 du jour. Chacun rejoue autant
qu'il veut, seul le meilleur temps compte.

Moteur de jeu maison (src/lib/chariot/) : canvas + requestAnimationFrame,
sans dépendance externe, dans la continuité de l'existant (roulette).

Navigation : nouvelle entrée "La Course du Char" (IconChariot), route
protégée par le proxy comme le reste de l'app.
2026-07-27 18:54:04 +02:00
Valentin ROBIN 9f54b459f3 Généralise Podium et computeRanks au-delà des points
computeRanksBy(items, comparator) remplace la logique de classement
"ex-aequo partagent le rang" en la rendant générique ; computeRanks
devient un simple appel avec le comparateur points desc, sans rien
changer pour l'appelant existant. Podium accepte maintenant un prop
renderValue (+ valueLabel optionnel) à la place du "points/gloires" en
dur, pour pouvoir afficher un classement par temps (Course du Char)
avec le même composant que le classement par points.
2026-07-27 18:53:54 +02:00
Valentin ROBIN 777d9ebaea Ajoute le schéma de La Course du Char (tables, RPC, clôture auto)
- chariot_runs : meilleur temps + tracé fantôme par joueur et par jour,
  verrouillée comme points_log (écriture uniquement via RPC).
- submit_chariot_run() : calcule la date côté serveur, borne le temps,
  n'écrase que si strictement meilleur.
- close_daily_chariot_race() + chariot_race_closes : clôture la journée
  précédente et attribue les gloires du top 3 automatiquement, sans
  intervention d'un Archonte — planifiée via pg_cron (à activer une
  fois côté Dashboard Supabase).
- points_log.judge_id devient nullable (un point auto n'a pas de juge) ;
  Le Crieur affiche "Le Tribunal" pour ces décrets-là.
2026-07-27 18:53:45 +02:00
Valentin ROBIN f462cff8a7 Retire le bouton "Nouveau round" du Conseil des Archontes
Un seul round sur toute la semaine : plus besoin de pouvoir
réinitialiser le repère de classement depuis l'admin. La logique des
flèches de progression (previous_rank, reset_rank_reference) reste en
place, simplement plus rien ne la déclenche.
2026-07-27 18:53:22 +02:00