Stoodi
Un réseau social étudiant à identité vérifiée combinant messagerie temps réel, mise en relation, groupes et événements. J’ai conçu et construit l’architecture métier backend, la vérification d’identité, le pipeline de confiance et sécurité, et les frontières imposées par la CI qui le gardent maintenable en croissance.
Le code source est privé. L’étude de cas se concentre sur les frontières de domaines, la confiance identitaire et le contrat d’architecture imposé par la CI plutôt que sur les données utilisateurs.
- Modèle produit
- Réseau social étudiant vérifié
- Public
- Étudiants universitaires
- Période
- 2025
- Mon rôle
- Architecte backend & ingénieur plateforme
- Contexte
- Produit commercial privé
- Périmètre
- Architecture métier · temps réel · confiance & sécurité · CI/CD
01
Surfaces produit
Surfaces produit
Des surfaces distinctes rendaient visibles les responsabilités école, association et campus avant même de regarder l’architecture.
Parcours de vérification étudiante
Déclaration d’inscription, rapprochement registre et parcours de relance avant l’accès complet.
Découverte & messagerie temps réel
Mise en relation et conversations directes/groupe livrées via des connexions WebSocket authentifiées.
Opérations confiance & sécurité
Revue des signalements, sanctions et appels opérant sur la même identité vérifiée que le graphe social.
02
Problème et contraintes
Problème et contraintes
Un produit social étudiant ne peut pas reposer sur une inscription déclarée, et ne peut pas laisser 11 domaines fonctionnels en croissance — identité, découverte, messagerie, groupes, événements, modération et facturation — s’emmêler en imports directs. Confiance et architecture devaient être imposées, pas supposées.
Déclarations d’identité invérifiables
Une déclaration d’école auto-rapportée ne donne aucun signal de confiance réel pour un produit construit autour d’étudiants vérifiés.
La messagerie temps réel exige sa propre frontière d’authentification
Un identifiant HTTP longue durée ne convient pas à une connexion socket persistante.
Pression de croissance des domaines
Onze domaines fonctionnels partageant un même code tendent à éroder l’isolation sous la pression de livraison, sauf si les frontières sont imposées mécaniquement.
La sécurité ne peut pas être purement réactive
Certains risques, comme les utilisateurs mineurs, exigent une détection et un confinement automatiques plutôt que d’attendre un signalement manuel.
03
Mon périmètre exact
Mon périmètre exact
J’ai conçu
- L’architecture métier complète : 11 domaines délimités, chacun derrière services, sélecteurs et adaptateurs, composés via des ports explicites plutôt que des imports directs.
- Le modèle de confiance reliant inscription déclarée, vérification registre et modération en un cycle d’identité cohérent.
- L’approche de mise en relation et de classement déterministe pour la découverte, ainsi que le modèle d’authentification temps réel par ticket.
J’ai implémenté
- Les 11 domaines Django, leurs APIs, tâches de fond, et le pattern d’adaptateur piloté par ADR câblé à la racine de composition.
- Le pipeline de vérification face au jeu de données ouvert ESR, le pipeline de modération et sanctions, et la détection automatisée de mineurs.
- Le pipeline CI en 12 étapes : lint, typage strict, import-linter, scan de sécurité, seuils de couverture, contrôle des migrations et détection de rupture OpenAPI.
J’ai collaboré sur
- Le comportement produit du client Flutter consommant ces APIs, et la façon dont les états temps réel et de vérification s’affichent aux utilisateurs.
- Les décisions de politique de confiance et sécurité traduites dans les règles du domaine modération.
03
Objectifs
Objectifs
Confiance
Rattacher l’accès produit à une inscription vérifiée face à un registre externe faisant autorité.
Frontières
Garder 11 domaines testables indépendamment et imposer l’isolation comme un contrat vérifié en CI.
Temps réel
Livrer la messagerie sur des sockets persistants sans exposer d’identifiants longue durée à la connexion.
Sécurité
Combiner modération manuelle et détection automatisée pour les cas à plus haut risque.
04
Architecture système
Architecture système
Flutter · iOS · Android
DRF · Channels/WebSockets · auth par ticket
11 domaines délimités · services · ports
PostgreSQL/PostGIS · Redis · Celery · ESR · RevenueCat
Le client Flutter, les APIs temps réel et requête, le cœur à 11 domaines et les services externes restent séparés afin qu’aucune couche n’ait besoin de connaître les détails internes d’une autre.
Stack technique
Application
Django 5 · Django REST Framework · drf-spectacular · ASGI/Daphne
Temps réel & asynchrone
Channels · channels-redis · Celery · Redis
Données & stockage
PostgreSQL · PostGIS · S3-compatible storage
Intégrations & exploitation
RevenueCat · Sentry · Prometheus · structlog · ESR open dataset
05
Modèle métier
Modèle métier
Le modèle de données garde distincts l’identité vérifiée, le graphe social et la couche de sécurité. Une école est validée face à un registre externe avant de pouvoir ancrer une vérification, les connexions et conversations dépendent de cette identité vérifiée, et la modération agit sur la même identité sans se mêler aux tables produit.
École (vérifiée registre)
Synchronisée depuis le jeu de données ouvert ESR et rapprochée par similarité de nom normalisé.
Compte & vérification
Identité locale plus un enregistrement et un état de vérification d’inscription indépendants.
Profil & disponibilité découverte
Média, localisation approximative et conditions de visibilité avant l’entrée en mise en relation.
Connexion
Demandes d’ami et blocages rattachés à des comptes vérifiés.
Conversation & message
Messagerie directe et de groupe livrée via des sockets temps réel authentifiés.
Communauté & événement
Groupes avec rôles, et événements avec participation rattachée à l’appartenance.
Dossier de modération
Signalements, preuves, sanctions et appels se rattachent à l’identité vérifiée, pas à une ligne utilisateur générique.
06
Modèle d’états
Modèle d’états
Vérification et confiance forment un seul cycle : une inscription déclarée ne devient un accès qu’après une preuve externe, et les événements de sécurité ultérieurs agissent sur cette même identité vérifiée plutôt que sur un concept de compte séparé.
Inscription déclarée
L’utilisateur soumet une école et une déclaration d’identité.
Registre rapproché
La déclaration est normalisée et rapprochée du catalogue école ESR.
Vérifié
Le compte obtient un accès complet une fois l’inscription confirmée.
Confiance maintenue
Signalements et sanctions se rattachent ensuite à cette même identité vérifiée.
Transitions alternatives
Incohérence de vérification
Une incohérence registre est orientée vers une revue plutôt qu’acceptée ou rejetée silencieusement.
Mineur détecté
Le compte est auto-suspendu et les sessions révoquées en attente de revue, indépendamment de la modération manuelle.
Vérification et confiance forment un seul cycle : l’accès suit une preuve externe, et les événements de sécurité agissent sur cette même identité vérifiée plutôt que sur un concept parallèle.
07
Défis d’ingénierie
Défis d’ingénierie
Vérifier de vrais étudiants sans devenir une autorité de registre
Une inscription auto-rapportée ne donne aucun signal de confiance défendable, mais la plateforme ne peut pas posséder elle-même un registre étudiant faisant autorité.
Synchroniser et normaliser le jeu de données ouvert du Ministère de l’Enseignement Supérieur, rapprocher les déclarations par similarité de nom, et orienter les incohérences vers une revue et une relance plutôt qu’une décision automatique.
La vérification dépend de la fraîcheur des données externes et d’une revue manuelle occasionnelle, mais l’accès repose sur une preuve défendable plutôt que sur la seule confiance en l’utilisateur.
Si l’inscription n’est que déclarée, la promesse d’identité vérifiée s’effondre et des acteurs malveillants peuvent se faire passer pour des étudiants librement.
Des frontières de domaines qui survivent à la croissance
Onze domaines partageant un même code sont à un import pratique de s’emmêler à mesure que les fonctionnalités s’accumulent.
Imposer des contrats import-linter en CI, documenter chaque exception inter-domaines légitime comme un adaptateur justifié par ADR enregistré à une racine de composition unique, et faire transiter les faits inter-domaines par un outbox transactionnel.
Chaque interaction inter-domaines coûte plus de cérémonie qu’un appel direct, mais les domaines restent testables et remplaçables indépendamment.
Sans imposition, la pression de livraison érode les frontières import par import jusqu’à ce que les domaines ne puissent plus évoluer indépendamment.
Messagerie temps réel sans identifiant longue durée sur le socket
Exposer un token d’accès standard directement à une connexion WebSocket persistante étend sa fenêtre d’exposition bien au-delà d’une requête normale.
Échanger un ticket temps réel de courte durée pour la poignée de main socket, et suivre les sessions au niveau appareil indépendamment de l’authentification HTTP.
Le client a besoin d’un aller-retour supplémentaire pour obtenir un ticket avant de se connecter, en échange d’un identifiant borné sur le socket.
Un token longue durée compromis donnerait sinon un accès prolongé à un flux de conversation en direct plutôt qu’une fenêtre courte et révocable.
08
Modes d’échec & mitigation
Modes d’échec & mitigation
Incohérence de registre pendant la vérification
Une incohérence de nom normalisé est orientée vers une revue et une relance plutôt qu’acceptée ou rejetée silencieusement.
Utilisateur mineur détecté
Le compte est automatiquement suspendu et ses sessions révoquées en attente de revue, indépendamment de la file de modération manuelle.
Événement inter-domaines non encore livré
L’outbox transactionnel persiste le fait durablement et permet un rejeu plutôt que de le perdre en cas d’échec en aval.
Ticket temps réel invalide ou expiré
La connexion socket est rejetée explicitement, forçant un nouvel échange de ticket plutôt qu’une dégradation silencieuse.
09
Décisions techniques
Décisions techniques
Des ports, pas des imports, entre domaines
Les lectures inter-domaines passent par des adaptateurs enregistrés à la racine de composition, import-linter imposant la frontière comme un contrat vérifié en CI plutôt qu’une convention.
Un outbox transactionnel pour les faits inter-domaines
Les événements de domaine sont persistés durablement et rejouables plutôt qu’émis puis oubliés, afin qu’un domaine en aval ne manque jamais un fait silencieusement.
Une confiance fondée sur une preuve externe
L’inscription est vérifiée face au registre ESR plutôt que d’accepter une déclaration, les incohérences étant orientées vers une revue plutôt qu’acceptées ou rejetées silencieusement.
10
Sécurité & exploitation
Sécurité & exploitation
Frontières d’architecture imposées par la CI
Les contrats import-linter et les exceptions documentées par ADR conditionnent chaque fusion, au-delà de la seule discipline de revue.
Configuration production fail-fast
La validation au démarrage refuse le mode debug, les hôtes joker, les cookies non sécurisés et les secrets par défaut au lieu de les accepter silencieusement.
Rotation de clés et secrets chiffrés
Les clés de signature JWT tournent avec plusieurs clés de vérification acceptées, et les secrets OTP sont chiffrés Fernet au repos.
Webhooks de facturation vérifiés
Les webhooks RevenueCat sont validés par signature HMAC avant l’octroi de tout droit d’accès.
- Seuils de couverture 85% lignes et 80% branches imposés en CI.
- Un pipeline en 12 étapes couvrant scan de sécurité, fraîcheur des migrations et détection de rupture OpenAPI.
- Logs structurés, Sentry et métriques Prometheus pour la visibilité opérationnelle.
11
Résultat livré
Résultat livré
Résultats d’implémentation — aucune métrique commerciale non vérifiée.
Une frontière de confiance défendable
L’accès repose sur une inscription vérifiée au registre plutôt que sur une simple déclaration.
Une isolation imposée, pas supposée
11 domaines restent testables indépendamment car c’est la CI, et non la convention, qui impose leurs frontières.
Un pipeline de sécurité auditable
Signalements, sanctions et appels opèrent sur la même identité vérifiée avec des parcours manuels et automatiques.
Du temps réel sans perdre le contrôle de session
La messagerie s’exécute sur des sockets persistants tandis que les identifiants restent courts et révocables.
Ce que j’en retiens
“Les frontières d’architecture ne tiennent que si la CI les impose mécaniquement — les conventions seules s’érodent sous la pression de livraison. Et la confiance dans un produit social doit reposer sur une preuve externe, pas une simple déclaration.”