Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,39 @@

---

## 🖥️ 24 septembre 2026 — Le terminal dit enfin ce que la leçon enseigne (THI-353)

*PR #385 · #386 · #387 · test permanent `lessonFidelity` · 2558 tests · exercices « validés malgré une erreur » : 44 → 3*

Le Grand Check-up de l'été avait trouvé un défaut de fond : pour valider un exercice, Terminal Learning regardait la commande tapée, jamais ce que le terminal répondait. Mesuré sur les 66 leçons × 3 environnements : **44 exercices se validaient alors que le terminal affichait une erreur en rouge.** L'élève tapait exactement ce que la leçon demandait, lisait `fatal: not a git repository`, et recevait quand même ses félicitations. On a corrigé par le moteur d'abord, groupe par groupe.

- **Chaque leçon démarre dans l'état qu'elle enseigne (#385).** Les leçons Git s'ouvrent dans `~/projets` avec le dépôt, la branche ou le dépôt distant dont elles ont besoin ; la leçon de sécurité dispose d'un `~/.ssh` simulé avec les permissions 700 / 600 / 644 qu'elle explique. Les 33 cas Git sont corrigés d'un coup. Au passage, la sortie du terminal garde son indentation (`git branch`, `git status`) et le markdown brut (accents graves, `**`) n'apparaît plus dans les consignes.
- **Les scripts s'exécutent vraiment (#387).** `./script.sh`, `bash script.sh` et `.\script.sh` sous Windows lisent le fichier ligne par ligne. Lancé avec `./`, il faut le droit d'exécution — sinon `Permission denied`, exactement ce qu'enseigne la leçon `chmod`. Comme un vrai sous-shell, un script garde les fichiers qu'il écrit mais pas ses `cd` ni ses variables. Un script qui s'appelle lui-même ne peut plus bloquer l'onglet (profondeur 3, 500 lignes au plus par commande).
- **PowerShell rattrape son retard (#387).** `$PROFILE`, `cat $PROFILE` (la leçon dispose désormais d'un vrai fichier de profil), `(Get-Content fichier).Count` et `Set-ExecutionPolicy` fonctionnent.
- **Un vieux bug de `chmod`, débusqué par les nouveaux tests (#387).** `chmod +x` écrivait le droit une position trop loin : le fichier ne devenait jamais exécutable pour son propriétaire. Corrigé, avec tous les modes octaux et les formes symboliques (`u+x`, `go-w`, `a=r`).
- **Le tiret qui « disparaissait » (#386).** Signalé par Thierry : en tapant `git merge --no-ff`, un des deux tirets s'effaçait à l'espace et revenait à la validation. Les touches enregistrées prouvaient que les caractères étaient intacts : c'était la police, JetBrains Mono, qui dessine `--` d'un seul trait (ligature). Les ligatures sont désactivées sur tout le texte monospace. **Vérifié sur un vrai iPhone** (THI-354).
- **Un garde-fou permanent.** Un test rejoue, pour chaque leçon et chaque environnement, la commande que la leçon demande de taper, et exige qu'elle se valide **sans aucune ligne d'erreur**. Les 3 cas restants (la redirection `2>`) sont listés explicitement, et cette liste ne peut que rétrécir.

Ce qui reste, et c'est dit : les redirections (`2>`, `>` pour toutes les commandes, `tee`) arrivent dans la prochaine livraison ; ensuite seulement, un exercice refusera de se valider si le terminal a affiché une erreur.

---

## 🔧 23 septembre 2026 — Reprise après la pause : dépendances corrigées, et une preuve d'âge qui ne se perd plus (THI-340)

*PR #383 · #384 · npm audit 41 → 24 (critique 1 → 0) · +16 tests*

Première journée de reprise après l'été et le Grand Check-up (sécurité, dépendances, marché, contenu, conformité). Les deux corrections prioritaires sont passées en premier.

- **Dépendances (#383).** `react-router` 7.13 → 7.18.4 (avis de sécurité XSS / redirection ouverte), `vite` 6.4.3, et les correctifs compatibles des dépendances indirectes, dont `tar` (critique). Aucune version majeure changée. Les deux paquets dont la seule « correction » proposée était une rétrogradation (`@lhci/cli`, `@vercel/node`, de l'outillage absent du site servi) restent tels quels, en connaissance de cause.
- **La preuve d'âge se perdait sur un chemin précis (#384).** Un élève qui ouvrait le lien d'invitation de son professeur, puis se connectait avec GitHub ou Google, passait bien l'écran d'âge — mais la redirection partait avant l'enregistrement de l'horodatage. La population la plus susceptible d'être mineure se retrouvait précisément sans trace. L'horodatage est désormais posé avant toute redirection.
- **Les échecs se voient.** Un enregistrement raté est signalé à Sentry avec son seul code d'erreur — aucun identifiant, aucun message.
- **`/privacy` dit exactement ce que fait le code** pour un visiteur refusé : la date d'éligibilité reste sur l'appareil et s'efface à la première visite après ce jour-là.
- **Accessibilité de l'écran d'âge** : le refus est annoncé aux lecteurs d'écran et reçoit le focus, l'erreur est liée au champ, le sélecteur de date suit le thème sombre.

Contrôles : `security-auditor` (0 critique, 0 élevé, avec une relecture de l'écran d'âge d'origine), `ui-auditor`, `feature-dev:code-reviewer` (SHIP). Chaque nouveau test a été vérifié rouge sur l'ancien code.

---

## 🚸 19 août 2026 — La page promettait, le produit applique enfin : garde-fou d'âge à la création de compte (THI-340)

*PR #380 · migration 035 · `ageGate.ts` + `AgeGateStep` · 36 tests · RGPD Art. 8 — Belgique = 13 ans*
Expand All @@ -23,6 +56,16 @@ Ce qui n'est **pas** fermé, et c'est dit : une déclaration reste une déclarat

---

## 🛡️ 18-19 août 2026 — Deux correctifs en base et une page `/privacy` qui dit enfin la vérité

*PR #377 [HOTFIX] · #378 · #379*

- **Fermer un ticket de support fonctionne à nouveau (#377).** Passer un signalement en « résolu » violait une contrainte de cohérence en base : le panneau d'administration ne pouvait plus clôturer un ticket. Correctif d'urgence.
- **Moins de surface en base (#378).** Des fonctions `SECURITY DEFINER` réservées aux déclencheurs restaient exécutables par les rôles de l'API ; ce droit est retiré (avertissements 0028 / 0029 de l'analyseur de sécurité Supabase).
- **`/privacy` corrigée (#379).** La page affirmait « aucune donnée personnelle collectée » — faux depuis l'arrivée des comptes. Elle distingue maintenant l'usage anonyme (rien ne quitte l'appareil) du compte optionnel (email, profil, progression chez Supabase), déclare Supabase et Vercel avec leurs garanties de transfert, et ajoute une note sur les mineurs et l'AI Act.

---

## 🔍 6 juin 2026 — Audit complet avant la pause : on vérifie que tout tient avant de couper (THI-342)

*PR #375 · security-auditor 9.4/10 · content-auditor · mobile-responsive-auditor · route-attack-auditor · Sentry · e2e Chrome*
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ No account required. No setup. Just open it and start learning.

- 🖥️ **Interactive terminal** — type real commands, get real feedback (not just theory)
- 🌍 **Multi-environment** — learn on Linux, macOS, or Windows — the interface adapts
- 🔒 **Progressive curriculum** — 11 modules, 66 lessons, 1000+ unit tests
- 🔒 **Progressive curriculum** — 11 modules, 66 lessons, 2500+ unit tests
- 🤖 **AI as a dev tool** — dedicated module on using AI professionally (prompts, validation, limits)
- 💾 **Progress saved automatically** — locally, or synced to the cloud with a free account
- 📖 **Contextual help** — `help <command>` returns usage and examples for your environment
Expand Down Expand Up @@ -116,7 +116,7 @@ Full security policy and vulnerability reporting: [SECURITY.md](SECURITY.md). In
| **Phase 2** | ✅ Done | Vercel Analytics + Sentry error monitoring + source maps |
| **Phase 3** | ✅ Done | Supabase Auth + user progress sync |
| **Phase 4** | ✅ Done | Curriculum v2 + multi-environment selection + terminal profiles |
| **Phase 5** | 🔄 In progress | Curriculum expansion: 11 modules, 66 lessons, 1000+ unit tests + 176 E2E |
| **Phase 5** | 🔄 In progress | Curriculum expansion: 11 modules, 66 lessons, 2500+ unit tests + 176 E2E |
| **Phase 5.5** | ✅ Done | Terminal Sentinel — automated security & content audit agents |
| **Phase 7** | ✅ Done | RBAC — student / teacher / institution_admin / super_admin roles |
| **Phase 7b** | ✅ Done | AI Tutor V1 — optional BYOK contextual tutor (OpenRouter / Anthropic / OpenAI / Gemini), client-side keys, live in production |
Expand Down
12 changes: 12 additions & 0 deletions STORY.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ Ce projet a été construit avec l'aide de Claude — l'IA d'Anthropic, des mod

---

## Le bug était dans la police, et 44 exercices qui mentaient poliment (23-24 septembre 2026)

Le Grand Check-up de l'été avait posé un diagnostic que je n'aimais pas : pour décider qu'un exercice était réussi, Terminal Learning lisait la commande tapée — et jamais ce que le terminal répondait. J'ai rejoué la solution de chaque exercice, dans chaque environnement, et compté. Sur 198 cas, 44 se validaient alors que l'écran affichait une erreur en rouge. Un élève tapait `git status` comme on le lui demandait, lisait `fatal: not a git repository`, et recevait des félicitations juste en dessous. Un mensonge poli, mais un mensonge : l'outil disait « bravo » à quelqu'un qui venait de voir que ça ne marchait pas.

La correction évidente aurait été de refuser la validation dès qu'une erreur s'affiche. Je ne l'ai pas faite en premier, et c'est la décision de ces deux jours que je défendrais le plus volontiers. Dans ces 44 cas, la faute n'était pas à l'élève mais au simulateur : les leçons Git s'ouvraient sans dépôt, les scripts ne s'exécutaient pas, PowerShell ignorait `$PROFILE`. Durcir la validation d'abord, c'était bloquer des élèves sur nos propres trous. On a donc réparé le moteur, groupe par groupe, en gardant un compteur honnête : un test qui liste explicitement les cas encore faux, et qui échoue si l'un d'eux se met à passer sans qu'on l'ait retiré de la liste. La liste ne peut que rétrécir. Elle est passée de 44 à 9, puis à 3.

Au milieu de ce chantier, Thierry a signalé un bug d'apparence banale : en tapant `git merge --no-ff`, un tiret s'effaçait à l'espace et revenait à la validation. Il avait dû copier-coller la commande pour finir l'exercice. Mon premier réflexe allait vers la saisie — un gestionnaire de touches qui avalerait un caractère. J'ai préféré regarder avant de corriger : j'ai enregistré chaque événement clavier. Le champ contenait bien deux tirets et un espace, intacts. Rien n'était effacé. C'était la police, JetBrains Mono, qui dessine `--` en un seul trait continu : une ligature, jolie dans un éditeur de code, désastreuse dans un cours dont le sujet est précisément de taper `--`. Un correctif « de saisie » aurait été du code faux pour un bug d'affichage. Trois lignes de CSS ont suffi, et Thierry les a vérifiées sur son iPhone, là où je n'étais pas sûr que Safari obéisse.

Le dernier épisode est celui qui m'a le plus appris. En faisant enfin exécuter les scripts, les tests ont révélé que `chmod +x` n'avait jamais fonctionné : il écrivait le droit une position trop loin, et le fichier ne devenait jamais exécutable pour son propriétaire. Le bug dormait depuis des mois, invisible, parce que rien ne lançait jamais le fichier. Un simulateur qui n'exécute pas ne peut pas découvrir qu'une permission est fausse. La leçon, je crois, dépasse le terminal : **un test qui regarde le résultat attrape des bugs que personne ne cherchait ; un test qui ne regarde que l'intention n'attrape que ceux qu'on avait déjà imaginés.**

---

## Écrire une règle le matin, devoir la tenir le soir (19 août 2026)

Le matin du 19 août, j'ai réparé la page `/privacy` parce qu'elle mentait. Elle affirmait que Terminal Learning ne collectait aucune donnée personnelle, alors que créer un compte envoie bel et bien une adresse email chez Supabase. On a réécrit la page, déclaré les sous-traitants, ajouté un encadré « Mineurs » avec une phrase parfaitement exacte en droit : en dessous de 13 ans, la création d'un compte requiert le consentement d'un parent. PR mergée, prod vérifiée, satisfaction légitime.
Expand Down
Loading
Loading