13 oct. 2026
5 min de lecture
- Open Source
- NestJS
- MongoDB
- Next.js
- Security
- Community
SOS Academy aide les débutants à apprendre en travaillant sur de vrais projets open source, avec un mentor. Pourquoi l'idée fonctionne, les fonctionnalités que j'ai construites, et ce que j'ai appris.

Le projet
En une phrase : Shinobi Open Source Academy (« SOS Academy ») est une communauté gratuite qui aide les développeurs débutants à apprendre en travaillant sur de vrais logiciels open source, avec un mentor à leurs côtés.
Beaucoup de gens apprennent à coder avec des vidéos et des tutoriels, puis se heurtent à un mur : ils connaissent les bases, mais n'ont jamais travaillé sur un vrai projet avec de vraies revues de code. Les entreprises demandent de l'expérience ; les débutants ne peuvent pas en acquérir. SOS Academy propose un passage : les apprenants rejoignent de petits groupes (« squads ») menés par un développeur expérimenté, choisissent de vraies tâches dans de vrais projets open source sur GitHub, et sont accompagnés jusqu'à ce que leur travail soit accepté.
La plateforme web de l'académie — le site, l'administration, le blog et le tableau de bord des apprenants — est elle-même open source, et c'est à elle que j'ai contribué.
Ce qui le rend innovant
- Du vrai travail au lieu d'exercices. Les apprenants règlent de vrais problèmes dans de vrais projets : leur travail finit dans des logiciels utilisés — et sur leur profil public.
- Un mentor qui vous suit vraiment. Avec de petits groupes, un mentor voit la vraie progression de chaque apprenant.
- Une progression suivie automatiquement. Quand le travail d'un apprenant est proposé, relu ou accepté sur GitHub, la plateforme se met à jour toute seule.
- Les apprenants peuvent aussi améliorer la plateforme. Elle est open source : contribuer à l'académie est déjà une vraie première contribution.
En bref : ma contribution et ce que j'en retiens
Ma part : j'ai construit des fonctionnalités de la plateforme : les groupes de mentorat (qui encadre qui, avec une limite de places qui tient même quand beaucoup de gens s'inscrivent à la même seconde), le suivi de la tâche de chaque apprenant de « réservée » à « acceptée », mis à jour automatiquement depuis GitHub, et plusieurs corrections de sécurité — dont un système de connexion qui aurait pu accepter d'anciennes clés, et des pages de gestion des utilisateurs ouvertes à tous. La première partie est acceptée ; le reste est en relecture, dont deux parties déjà approuvées.
Ce que j'en retiens : quand beaucoup de gens agissent au même moment, les règles doivent être appliquées par le système lui-même, pas en espérant que les demandes arrivent une par une. Et construire pour une communauté, c'est discuter, découper le travail en étapes et écouter les relecteurs.
La suite de l'article entre dans les détails techniques, pour les développeurs.
Sous le capot
Un monorepo TypeScript — API NestJS + MongoDB, apps Next.js (site, admin, blog, portail des apprenants), une librairie partagée, déployé avec Docker et Vercel.
En détail : ce que j'ai apporté
Ma contribution en chiffres : 14 pull requests. Le modèle Squad est mergé ; les autres sont ouvertes, dont deux déjà approuvées. Contrairement aux autres projets, il s'agit surtout de nouvelles fonctionnalités plutôt que de correctifs.
Les squads
La première PR (#221, mergée) définit le modèle Squad : un mentor, une communauté, des membres et une capacité, avec des règles comme « un mentor doit vraiment être mentor » et « un mentor ne peut pas être membre de sa propre squad ». Les suivantes ajoutent les endpoints d'administration et la page qui montre à un mentor les membres de sa squad.
La partie intéressante, c'est la concurrence. La capacité est vérifiée dans la mise à jour elle-même : trois personnes qui rejoignent une squad d'une place au même moment donnent exactement un succès. « Une seule squad active par apprenant » est garanti par un index unique partiel — sans le filtre partiel, chaque squad vide entrerait en collision avec toutes les autres.
Le cycle de vie d'un ticket en machine à états
Chaque ticket passe par des statuts — réservé, en cours, PR ouverte, modifications demandées, mergé… — déclarés dans une seule table de transitions. Chaque changement est un compare-and-set qui écrit aussi son entrée d'historique :
findOneAndUpdate(
{ _id: id, status: current },
{ $set: { status: next }, $push: { statusHistory: entry } },
)
Cinq personnes qui réservent le même ticket au même moment : une seule gagne, les autres reçoivent un 409 clair. Un job de synchronisation lit ensuite la timeline GitHub de chaque ticket, trouve la pull request ouverte par la personne assignée et fait avancer le ticket. Pour passer de « en cours » à « mergé », il cherche un chemin dans le graphe des transitions (parcours en largeur) : même les sauts déclenchés par la synchronisation passent par des étapes légales et enregistrées. Il respecte les limites de l'API GitHub et ne fait rien quand rien n'a changé.
Authentification et sécurité
/auth/refreshéchouait toujours : le parseur de cookies n'était pas enregistré. Le corriger a révélé un problème subtil — bcrypt ne lit que les 72 premiers octets, et les tokens de rafraîchissement d'un utilisateur partagent leurs 72 premiers octets : d'anciens tokens auraient été acceptés. Ils sont maintenant hachés en SHA-256.- Les routes de gestion des utilisateurs, dont
DELETE /users/:id, étaient ouvertes à tous. Elles exigent maintenant une session admin ou l'utilisateur lui-même, et un utilisateur ne peut pas changer son propre rôle. pnpm auditest passé de 232 alertes (dont 5 critiques) à 5 modérées, et l'audit en CI peut désormais vraiment bloquer un build.
Les leçons techniques
- Laisser la base de données faire respecter les règles. Vérifier la capacité dans le service puis mettre à jour laisse un trou dans lequel deux requêtes peuvent passer. Une mise à jour conditionnelle ou un index le ferme pour de bon.
- Une machine à états rend les états illégaux impossibles. Une seule table de transitions a répondu à des questions qui, sinon, seraient éparpillées dans des
if— et a rendu la synchronisation GitHub simple à raisonner. - Connaître les limites de sa crypto. bcrypt est le bon outil pour les mots de passe, et le mauvais pour de longs tokens aux préfixes identiques. Le bug n'est apparu que parce que j'avais corrigé celui qui le précédait.
- La dette de sécurité se cache dans les routes « internes ». Des endpoints de gestion des utilisateurs ouverts, c'est le genre de chose que personne ne remarque, jusqu'au jour où quelqu'un le fait.
- Contribuer à une communauté, ce n'est pas seulement corriger des bugs. Les fonctionnalités m'ont demandé de discuter du périmètre, d'empiler des PR qui dépendent les unes des autres, et de répondre aux relecteurs comme CREDO23 — dont la remarque sur l'héritage des rôles a rendu le guard correct.