Skip to content

OctoGuard 2, livraison 3a : la colonne, la vue d'ensemble, mes règles, le bac à sable - #942

Merged
Pokled merged 5 commits into
mainfrom
feat/octoguard-ui-3a
Nov 3, 2026
Merged

Pokled merged 5 commits into
mainfrom
feat/octoguard-ui-3a

Conversation

@Pokled

@Pokled Pokled commented Nov 3, 2026

Copy link
Copy Markdown
Owner

Première partie de l'interface d'OctoGuard 2 (CDC NODYX_OCTOGUARD_V2_CDC.md, E4c), d'après la maquette validée le 03/11. Frontend seul : aucun changement du cœur.

Ce qui change

La colonne. En entrant dans OctoGuard, la colonne de l'admin affiche le menu d'OctoGuard à la place du sien (même largeur, aucune place perdue). « Administration » en tête la fait revenir sans quitter la page. Les anciens onglets disparaissent.

Vue d'ensemble (/admin/octoguard) : l'état en une phrase, les chiffres de la semaine (pris, auraient été pris, annulés, signalements), « À regarder » (dont « Passer au cran » d'un clic pour une règle observée qui a pris des messages), les dernières actions racontées en phrases, des raccourcis illustrés, la santé du moteur.

Mes règles (/admin/octoguard/rules) :

  • cartes de catégories en tête, puis un bloc par catégorie : Mots et insultes, Liens et spam, Nouveaux comptes, Contenu illisible, Sur mesure ;
  • une carte par règle : interrupteur, cran (icône + couleur, identiques partout), phrase qui dit ce qui se passe, chiffres de la semaine, endroits, équipe exemptée ;
  • « Comprendre les crans » : ce qui arrive au message, à l'auteur, à l'équipe ;
  • panneau de réglages : seuils propres à chaque type, endroits, rôles exemptés, derniers déclenchements, suppression avec confirmation.

Mots interdits : trois cases (mot entier, début de mot, n'importe où) et « Toujours autorisés », avec un exemple concret par case, une alerte quand un mot ratisse trop large (« débil » prendrait « débilitant ») corrigeable d'un clic, des lots prêts à l'emploi et un essai en direct qui surligne le texte tel que tapé. La syntaxe stockée ne change pas (mot, mot*, *mot*).

Bac à sable (/admin/octoguard/sandbox) : branché sur le vrai moteur (POST /admin/octoguard/sandbox, sans effet de bord), avec la raison quand une règle ne s'applique pas (endroit, rôle exempté, compte non visé).

Volontairement pas dans cette PR

  • Retenir (5e cran), barème, bouclier, charte, rejouer 30 jours : lots du cœur (E4e/E4f), à valider à part. Le sélecteur montre 4 crans.
  • Modèles, journal avec Annuler, bienvenue, commandes, webhook, sourdines sur le kit : livraison 3b. Ces pages restent servies telles quelles, dans leur cadre sombre.

Vérifications

  • Moteur et navigateur d'accord : la reconnaissance des mots est une copie fidèle de matchers2.ts. Parité vérifiée sur 40 cas en appelant les deux (déguisements, mots épelés avec points ou espaces, exceptions, HTML, traits d'union).
  • Tests : 18 nouveaux (keywords.test.ts, rules.test.ts) ; suite frontend 400/400.
  • npm run check : 0 erreur, aucun avertissement dans les fichiers touchés.
  • i18n : les 5 portes au vert ; 289 clés og2.* en fr et en ; les 109 clés construites dynamiquement vérifiées une à une.
  • Navigateur (Playwright, serveur de dev local branché en lecture seule sur nodyx.org, compte de test) : 31/31. Couvre la bascule de la colonne, les blocs et filtres, la recherche, l'éditeur de mots (alerte, essai, Annuler), le panneau (ouverture, Échap), le bac à sable, l'ancienne page Bienvenue, aucun défilement horizontal à 1440 et 390 px, clair et sombre, aucune erreur JS, aucune écriture OctoGuard envoyée. Ce parcours a trouvé un bug (le panneau plantait à l'ouverture), corrigé.

…e, mes règles, le bac à sable

L'interface d'OctoGuard 2, première partie, telle que validée sur la maquette.

- La colonne de l'admin bascule sur le menu d'OctoGuard au lieu de s'y ajouter
  (même largeur ; « Administration » en tête pour revenir sans changer de page).
- Vue d'ensemble : état en une phrase, chiffres de la semaine, « À regarder »
  (dont « passer au cran » d'un clic pour une règle observée), dernières
  actions racontées en phrases, raccourcis illustrés, santé du moteur.
- Mes règles : catégories en tête (Mots et insultes, Liens et spam, Nouveaux
  comptes, Contenu illisible, Sur mesure), un bloc par catégorie, une carte par
  règle avec interrupteur, cran, phrase, chiffres de la semaine. Tableau
  « Comprendre les crans » (message, auteur, équipe). Panneau de réglages :
  seuils, endroits, rôles exemptés, derniers déclenchements, suppression.
- Mots interdits en trois cases (mot entier, début de mot, n'importe où) +
  « Toujours autorisés », alerte quand un mot ratisse trop large, lots prêts à
  l'emploi, essai en direct. Copie fidèle du moteur (parité vérifiée sur 40 cas
  avec matchers2.ts), même syntaxe stockée : aucun changement du cœur.
- Bac à sable branché sur le vrai moteur (POST /sandbox, sans effet de bord).

Quatre crans affichés (Observer, Signaler, Avertir, Supprimer) : « Retenir »
arrivera avec le lot du cœur qui le rend possible. Bienvenue, commandes,
webhook, journal et sourdines gardent leur page actuelle jusqu'à la 3b.

i18n : 289 clés og2.* en fr et en, dont 109 clés dynamiques vérifiées une à une.
- Réglages : n'envoyer que les champs réellement modifiés. Enregistrer sans
  rien changer envoyait tout le formulaire, et le serveur marquait alors une
  règle du profil de base « personnalisée » (elle ne recevait plus les mises
  à jour du profil). Sans changement, plus aucune requête.
- Mots interdits : basculer l'interrupteur ou le cran de la carte effaçait la
  saisie en cours. L'éditeur ne se remet à zéro que si la version enregistrée
  change vraiment.
- Essai en direct : vider le champ le remplissait aussitôt avec l'exemple.
- Panneau : le focus clavier se pose dans le panneau à l'ouverture.

Prouvé dans le navigateur, écritures interceptées (rien n'atteint le
serveur) : 12/12 avec le correctif, et les mêmes tests échouent sur
l'ancien code.
@Pokled

Pokled commented Nov 3, 2026

Copy link
Copy Markdown
Owner Author

Passe de vérification avant fusion : quatre défauts trouvés à la relecture du code, corrigés dans 1037b4c.

  1. Réglages → Enregistrer sans rien changer envoyait tout le formulaire. Le serveur marquait alors la règle « personnalisée », et elle ne recevait plus les mises à jour du profil de base. Désormais, seuls les champs modifiés partent, et rien du tout s'il n'y a pas de changement.
  2. Mots interdits : basculer l'interrupteur ou le cran de la carte effaçait la saisie non enregistrée.
  3. Essai en direct : vider le champ le remplissait aussitôt avec l'exemple.
  4. Panneau : le focus clavier n'y entrait pas à l'ouverture.

Preuve : un test navigateur avec les écritures OctoGuard interceptées (rien n'atteint le serveur) passe 12/12 avec le correctif. Les mêmes tests échouent sur l'ancien code (7 échecs, aux endroits annoncés).

Re-vérifié ensuite : npm run check 0 erreur, les 5 portes i18n, vitest 400/400, parcours complet 31/31, aucune erreur JS.

Le serveur accepte les réglages d'une règle tels quels (RuleParams en
passthrough). Le moteur se protège d'une valeur vide (retour au défaut),
pas d'une valeur absurde : Inondation à 1 répétition, -1 lien, 1 % de
capitales feraient prendre TOUS les messages.

- Réglages : chaque seuil doit être un entier dans ses bornes, avec des
  planchers volontaires (Majuscules : 5 lettres, 50 %) ; sites bien formés,
  enregistrés en minuscules, au moins un. Sinon rien ne part et le panneau
  dit pourquoi.
- Mots interdits : au-delà de 500 mots (ce que le moteur lit), Enregistrer
  est bloqué avec un message, au lieu d'ignorer la fin sans bruit.
- Test des droits du menu (admin, gardien OctoGuard, modérateur, équipe sans
  droit de modération).

Navigateur, écritures interceptées : 11/11 (seuils absurdes, site mal
formé, échec serveur qui fait revenir cran et interrupteur, 501 mots).
Sur l'ancien code, le panneau acceptait « 1 répétition » sans un mot.
@Pokled

Pokled commented Nov 3, 2026

Copy link
Copy Markdown
Owner Author

Deuxième passe de vérification, corrigée dans f9b3e8d.

Trouvé : le serveur accepte les réglages d'une règle tels quels (RuleParams en passthrough). Le moteur se protège d'une valeur vide (il retombe sur la valeur par défaut), mais pas d'une valeur absurde : Inondation à 1 répétition, -1 lien ou 1 % de capitales feraient prendre tous les messages. Le panneau de la 3a l'acceptait sans un mot, prouvé sur l'ancien code.

Corrigé côté écran (le cœur reste intact) :

  • chaque seuil doit être un entier dans ses bornes, avec des planchers volontaires (Majuscules : 5 lettres, 50 %) ;
  • les sites doivent être bien formés, sont enregistrés en minuscules, et il en faut au moins un ;
  • au-delà de 500 mots (ce que lit le moteur), Enregistrer est bloqué avec un message ;
  • sinon rien ne part, et le panneau dit pourquoi.

Vérifié aussi :

  • échec du serveur : le cran et l'interrupteur reviennent à leur état, et la carte affiche le message ;
  • droits du menu : test unitaire couvrant admin, gardien OctoGuard, modérateur des membres (signalements et sourdines seulement) et équipe sans droit de modération (rien).

Batterie complète sur le code final :

  • npm run check : 0 erreur ;
  • les 5 portes i18n ;
  • vitest 404/404 ;
  • parité moteur/navigateur 40/40 ;
  • parcours 31/31, correctifs 12/12, validation et échecs 11/11 ;
  • aucune erreur JS. Toutes les écritures OctoGuard ont été interceptées, aucune n'a atteint nodyx.org.

Non couvert en navigateur : le bouton « Passer au cran » de la Vue d'ensemble, absent faute de règle observée ayant pris des messages cette semaine. Il envoie {dry_run:false}, vérifié à la lecture du code.

…/invite)

La validation des sites ajoutée dans f9b3e8d n'acceptait que les noms de
domaine nus. Or la règle « Invitations vers d'autres serveurs » du profil de
base contient discord.com/invite et discordapp.com/invite : ses réglages ne
pouvaient plus être enregistrés du tout (prouvé sur ce code-là).

Même expression que le cœur (services/octoguard/params.ts, PR à part) :
domaine, *.domaine, domaine/chemin. Un lien collé (https://discord.gg/) est
ramené au site au lieu d'être refusé. Aide mise à jour (fr, en).
@Pokled

Pokled commented Nov 3, 2026

Copy link
Copy Markdown
Owner Author

Troisième passe : le bouton « Passer au cran » est testé en vrai. Un relais local injecte des prises fictives dans /stats uniquement, et l'écriture est interceptée. Résultat : 5 suggestions affichées, un seul PUT au corps exactement {"dry_run":false}, et la suggestion disparaît. Défaut trouvé et corrigé (dd57ae8) : la validation des sites refusait discord.com/invite, donc la règle « Invitations » du profil de base ne pouvait plus être enregistrée, prouvé sur le code d'avant. Elle reprend maintenant l'expression du cœur (#943). Batterie : check 0 erreur, i18n 5/5, vitest 404/404, navigateur 31+12+11+2+3 sans échec, aucune erreur JS.

@Pokled
Pokled merged commit 44dbc90 into main Nov 3, 2026
10 checks passed
@Pokled
Pokled deleted the feat/octoguard-ui-3a branch November 3, 2026 21:26
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant