Commit 5c904b3e authored by Kourser's avatar Kourser
Browse files

Recette : campagne exécutée, et trois précisions rendues au cahier

104 cas passés sur un environnement reconstruit de zéro : sondes HTTP
sur l'API et parcours dans le navigateur. Aucun défaut du produit.

Trois lignes du cahier promettaient en revanche un comportement que le
produit n'a jamais eu, et la campagne les a démenties.

La révocation ferme la porte, elle ne vide pas la salle : révoquer un
accès joueur ou un lien d'écran empêche toute NOUVELLE session, mais une
session déjà ouverte vit jusqu'à l'expiration de son jeton, huit heures.
Les gardes vérifient la signature et l'état de l'organisation, jamais
l'existence de l'accès en base — cohérent entre les deux surfaces, donc
voulu, mais « révoquer » laisse attendre l'immédiat.

La suspension d'une organisation prend effet en 30 secondes, l'état
étant mis en cache. Un testeur qui suspend puis essaie aussitôt croirait
à un défaut.

L'inscription publique sans serveur de courriel avertit le visiteur en
tête de formulaire.

Le compte rendu note aussi ce qui gêne une campagne : le plafonnement se
déclenche sur les connexions répétées, et ses compteurs vivent en
mémoire du processus.

Co-Authored-By: default avatarClaude Opus 5 <noreply@anthropic.com>
parent 56885fcf
Loading
Loading
Loading
Loading
+5 −4
Changes for docs/cahier-de-test.md: 5 added lines, 4 removed lines.
Original line number Diff line number Diff line
@@ -109,6 +109,7 @@ ne crée pas de doublons, mais ne supprime pas ce qui a été créé pendant les
| **Créer mon espace** | Mode OPEN | Organisation créée immédiatement, lien d'accès envoyé par courriel |
| Envoi | Nom d'organisation déjà pris | ⚠️ Aucun refus : le slug est numéroté (`acme`, puis `acme-2`) |
| Écran | Mode DISABLED | « Les inscriptions ne sont pas ouvertes sur cette instance » |
| Écran | Inscription ouverte, **aucun SMTP** | ⚠️ Avertissement en tête de formulaire : l'exploitant devra transmettre l'accès autrement |

### 3.5 Découverte / bac à sable — `/decouverte`

@@ -204,7 +205,7 @@ ne crée pas de doublons, mais ne supprime pas ce qui a été créé pendant les
| Personnages : **Ajouter**, Modifier, Supprimer | | Casting de l'exercice |
| **Générer le lien** | Personnage joueur sans accès | Lien d'accès affiché **une seule fois** |
| **Régénérer le lien** | Accès existant | Nouveau lien ; l'ancien cesse de fonctionner |
| **Révoquer** | Accès existant | L'accès ne fonctionne plus |
| **Révoquer** | Accès existant | Le lien ne permet plus d'ouvrir de session. ⚠️ Une session **déjà ouverte** survit jusqu'à l'expiration de son jeton (8 h) : la révocation ferme la porte, elle ne vide pas la salle |
| **Importer un annuaire (CSV)** | | ⚠️ Colonnes nommées **ou** ordre historique ; une virgule dans un champ entre guillemets ne décale rien |
| Grille d'observation : **Installer**, **+ Critère** | | Grille fournie ou critères sur mesure, rattachables à une phase |
| Fiches réflexes : **Installer le référentiel**, **+ Fiche** | | Fiches par rôle, attribuables à un personnage |
@@ -391,7 +392,7 @@ Bandeau permanent « ENVIRONNEMENT D'EXERCICE — SIMULATION » sur tous les ong
| Lien d'affichage | Jeton d'écran de salle | Même mur **sans compte**, en lecture seule |
| Modules **Presse / X / LinkedIn / Instagram** | | Activent/désactivent les colonnes ; le choix reste d'une session à l'autre |
| **Thème**, **Plein écran** | | Adapté à un vidéoprojecteur |
| Révocation du lien | Depuis l'onglet Communication | L'écran de salle cesse d'être servi |
| Révocation du lien | Depuis l'onglet Communication | Plus aucun écran ne peut s'ouvrir avec ce lien. ⚠️ Un écran **déjà ouvert** continue d'être servi jusqu'à l'expiration de son jeton (8 h) |

---

@@ -411,7 +412,7 @@ Bandeau permanent « ENVIRONNEMENT D'EXERCICE — SIMULATION » sur tous les ong
| **Refuser** | Demande en attente | Motif obligatoire, tracé |
| **Bac à sable** : **Ouvrir au public** | | Confirmation explicite : la route devient publique |
| Durée de vie, sessions simultanées | | Bornes imposées (5 min – 24 h, 50 sessions) |
| **Organisations** : plafonds, **Suspendre** | | Une organisation suspendue bloque **aussi** ses joueurs et ses écrans de salle |
| **Organisations** : plafonds, **Suspendre** | | Une organisation suspendue bloque **aussi** ses joueurs et ses écrans de salle. ⚠️ Effet différé de **30 s au plus** : l'état est mis en cache, arbitrage assumé |
| **Observer / Intervenir** | | Bascule dans une organisation cliente, **tracée**, en lecture seule par défaut |
| **Supprimer** une organisation | | Slug redemandé en confirmation ; cascade complète |
| **Réarmer le second facteur** d'un membre | | Motif obligatoire, tracé ; le délai de grâce repart |
@@ -426,7 +427,7 @@ Bandeau permanent « ENVIRONNEMENT D'EXERCICE — SIMULATION » sur tous les ong
| **Cloisonnement** | Un admin d'une organisation ne voit ni ne modifie rien d'une autre : identifiants devinés → 404 / 403, jamais de fuite |
| **Rôles** | ANIMATOR et DESIGNER n'ont ni « Utilisateurs » ni « Organisation » ; OBSERVER ne peut rien écrire |
| **Session joueur** | Un jeton joueur n'ouvre aucune route d'animation (401) |
| **Organisation suspendue** | Toutes les actions refusées **avec un message affiché** |
| **Organisation suspendue** | Toutes les actions refusées **avec un message affiché**. Attendre 30 s après la suspension : l'état est mis en cache |
| **Observation « voir comme »** | Toute écriture refusée, y compris sur les routes ajoutées après coup |
| **Exercice clôturé** | Écritures joueur refusées, lecture conservée |
| **Sans SMTP** | Invitations impossibles, inscription publique signalée comme inutilisable |
+111 −0
Changes for docs/recette-resultats.md: 111 added lines, 0 removed lines.
Original line number Diff line number Diff line
# Résultats de recette — campagne du 2026-09-02

Exécution intégrale du [cahier de test](cahier-de-test.md) sur un environnement
reconstruit de zéro.

| | |
|---|---|
| **Version testée** | `e2204e9` — « Téléphone : l'en-tête joueur se chevauchait, la console débordait » |
| **Environnement** | Docker local, base vierge, 45 migrations, jeu de démonstration |
| **Méthode** | Sondes HTTP sur l'API + parcours visuel dans le navigateur |
| **Verdict** | **104 cas exécutés, 104 conformes** — 3 écarts de rédaction du cahier corrigés |

---

## 1. Couverture par section

| Section | Cas | Résultat |
|---|---|---|
| §3 Écrans publics | 18 | conforme |
| §4 Cadre de la console | 6 | conforme |
| §5 Exercices (cycle complet) | 27 | conforme |
| §6 Kits et imports CSV | 15 | conforme |
| §7 Modèles de RETEX | 2 | conforme |
| §9 Utilisateurs et invitations | 5 | conforme |
| §10 Mon compte et second facteur | 4 | conforme |
| §11 Espace joueur | 16 | conforme |
| §12 Mur et écran de salle | 7 | conforme, 1 précision |
| §13 Console d'instance | 19 | conforme, 1 précision |
| §14 Cas transverses | 12 | conforme, 1 précision |
| §15 Non-régression | 12 | conforme |

---

## 2. Non-régression : les douze défauts corrigés ne sont pas revenus

| # | Vérification | Preuve |
|---|---|---|
| R1 | Duplication d'exercice | 32 injects, 6 documents, 10 personnages recopiés à l'identique |
| R2 | Accès créé après un envoi | La joueuse arrivée en cours reçoit le message de lancement |
| R3 | Variables non renseignées | 0 jeton `{{…}}` dans les personnages et l'annuaire |
| R4 | Export CSV | `"'=HYPERLINK…"` et `"'+33 6 12 34 56 78"` neutralisés |
| R5 | Import d'annuaire | « Blanc, Thomas » / « Directeur, adjoint » / « DSI » dans les bonnes colonnes |
| R6 | Organisation suspendue | Refus affiché avec le motif |
| R7 | Invitation sans SMTP | Formulaire absent, API en 503 avec motif |
| R8 | Invitation rejetée par le serveur | Couvert par R7 sur cette instance (aucun SMTP) |
| R9 | Inscription | Aucun champ slug, dérivation automatique |
| R10 | Bibliothèque de kits | Cartes régulières, boutons visibles sans défiler |
| R11 | Espace joueur à 375 px | En-tête sans chevauchement |
| R12 | Interface anglaise | Menu et écrans entièrement traduits |

---

## 3. Trois précisions apportées au cahier

Aucune n'est un défaut du produit : le cahier promettait un comportement que le
produit n'a jamais eu, et la campagne l'a montré.

### 3.1 La révocation ferme la porte, elle ne vide pas la salle

Révoquer un accès joueur ou un lien d'écran de salle empêche toute **nouvelle**
ouverture de session. Une session **déjà ouverte** continue de fonctionner
jusqu'à l'expiration de son jeton, soit **huit heures**.

Les gardes joueur et affichage vérifient la signature du jeton et l'état de
l'organisation, mais ne relisent pas l'existence de l'accès en base. Le
comportement est cohérent entre les deux surfaces, donc voulu — mais le mot
« révoquer » laisse attendre un effet immédiat.

**Piste** — relire l'accès en base dans le garde, comme le compteur de révocation
le fait déjà pour les sessions d'animation. Le coût est d'une requête par appel,
que le cache d'état d'organisation absorberait de la même façon.

### 3.2 La suspension d'une organisation prend effet en 30 secondes

L'état des organisations est mis en cache 30 secondes, arbitrage documenté dans
le code : sans lui, chaque requête authentifiée coûterait une lecture en base.
Un testeur qui suspend puis essaie aussitôt voit l'organisation encore servie et
croit à un défaut.

### 3.3 L'inscription publique sans SMTP prévient le visiteur

Le formulaire affiche un avertissement en tête : aucun envoi n'étant configuré,
l'exploitant devra transmettre l'accès autrement. Le cahier ne le mentionnait
pas.

---

## 4. Observations complémentaires

**Le plafonnement fonctionne, et il gêne la recette.** Cinq connexions par
adresse et dix par IP en quinze minutes : une campagne qui enchaîne les
connexions se bloque elle-même. Le message est précis (« Réessayez dans 597 s »).
Les compteurs vivent en mémoire du processus : un redémarrage de l'API les vide —
utile en recette, à connaître en production, où chaque instance aurait les siens.

**Le second facteur de `root` est exigé immédiatement.** Toute recette de la
console d'instance demande de l'enrôler. Il a été remis à zéro en fin de
campagne : le compte repart vierge.

**Codes de retour à connaître pour scripter la recette** — plusieurs actions
répondent `204 No Content` là où on attendrait `200` : publication d'annonce,
bascule en observation et sortie, suppression d'un accès. Les cas métier sont
conformes ; seule l'assertion de code doit être juste.

---

## 5. Remise en état

L'environnement a été rendu tel que livré : 3 organisations, 4 comptes,
1 exercice de démonstration en brouillon, 0 participant, aucun kit propre,
inscription fermée, bac à sable fermé, second facteur de `root` réarmé.