Sortir le personnel de WhatsApp : pourquoi et comment j’ai construit la messagerie d’OptiServ
Dans beaucoup d'établissements, le personnel s'organise sur WhatsApp. Remplacer cet outil ne se joue pas sur la conformité, mais sur la ressemblance. Retour sur le pourquoi, puis sur les choix techniques.
Le problème : un outil pratique, au mauvais endroit
Un groupe WhatsApp « Vie scolaire », un autre « Profs de 2nde », un troisième pour tout l'établissement. C'est rapide, tout le monde l'a déjà sur son téléphone, et ça marche. C'est justement pour ça que le problème passe inaperçu.
Dans ces groupes circulent des noms d'élèves, des absences, parfois une situation familiale ou un souci de santé. Ces données sortent de l'établissement et vivent chez un éditeur grand public, sur le téléphone personnel de chacun.
Trois difficultés en découlent, et aucune n'est technique.
- Personne ne maîtrise la conservation. Combien de temps ces messages restent-ils ? Sur quels appareils ? Personne ne peut répondre, alors que le RGPD demande précisément de le savoir.
- L'historique part avec la personne. Quand un salarié quitte l'établissement, il garde tout sur son téléphone, et l'équipe perd ce qui s'y est dit.
- Rien n'est administrable. Personne ne peut retirer quelqu'un d'un groupe à son départ s'il en était l'administrateur, ni intervenir quand un échange dérape.
Ce que je voulais construire
Une messagerie interne, intégrée à OptiServ, qui règle ces trois points sans demander d'effort au personnel :
- une conversation par service, et une pour tout l'établissement, sans rien à paramétrer ;
- des conversations privées et des groupes, comme sur WhatsApp ;
- des notifications sur le téléphone ;
- une durée de conservation fixée par l'établissement ;
- une installation possible sur les serveurs de l'établissement, pour que les données restent chez lui.
Et une contrainte au-dessus des autres : elle devait ressembler à WhatsApp. On demande aux gens d'abandonner un outil qu'ils maîtrisent. Si le nouveau se lit comme un journal d'événements, tout le monde y retourne en une semaine, quelles que soient les garanties de confidentialité. La conformité ne se plaide pas contre une habitude.
Les choix techniques
OptiServ repose sur Kotlin et Spring Boot côté serveur, PostgreSQL pour les données, Vue 3 et Quasar pour l'interface, et Keycloak pour l'authentification. La messagerie s'y intègre comme un module.
Les conversations de service suivent l'organigramme. Je ne stocke pas la liste de leurs membres : elle se calcule à partir de l'organigramme du module RH. Une personne voit la conversation de son service et celles des services au-dessus d'elle ; un responsable voit celles de ses équipes. Quand quelqu'un change de service, il change de conversation sans que personne n'y touche. Stocker la liste aurait demandé une synchronisation, et donc une famille entière de bugs.
L'écriture passe par l'API, le temps réel ne fait que diffuser. Un message s'enregistre par un appel REST classique. Le WebSocket (STOMP) ne sert qu'à prévenir les autres participants et à afficher « en train d'écrire ». Pour la diffusion entre serveurs, j'utilise le NOTIFY de PostgreSQL, émis dans la même transaction que l'enregistrement : PostgreSQL ne délivre la notification qu'au moment du commit, et rien du tout en cas d'échec. Un message n'est donc jamais annoncé sans être enregistré, ni enregistré sans être annoncé. La notification ne porte que des identifiants ; chaque serveur relit le message en base.
Les notifications ne transportent rien par défaut. C'est le point qui demande le plus d'honnêteté. Une notification sur téléphone passe forcément par les services de Google ou d'Apple : c'est ainsi que fonctionnent les téléphones. Par défaut, OptiServ n'y met que « Nouveau message », sans aperçu du contenu. L'établissement peut activer l'aperçu, en sachant qu'une notification s'affiche aussi sur un écran verrouillé, devant qui passe. Une plage « ne pas déranger » s'applique par personne, le soir et le week-end, dans son propre fuseau horaire.
Un responsable ne lit pas les conversations privées. Le rôle d'administrateur règle la conservation et ouvre les conversations de service, mais il n'ouvre pas la lecture d'un échange privé. Ce qu'un responsable peut voir, c'est ce qu'un membre lui a signalé : la personne qui signale choisit de montrer un message qu'elle a reçu. Chaque consultation de la modération est tracée et visible des autres administrateurs. La seule exception assumée est l'export des messages d'une personne, pour répondre à une demande RGPD : il exige un motif écrit, il est réservé au propriétaire du compte, et il apparaît dans le journal d'activité.
La conservation est réelle. L'établissement choisit une durée entre 1 et 60 mois (12 par défaut). Chaque nuit, une purge efface les messages plus anciens, pièces jointes comprises. Si le stockage des fichiers ne répond pas, l'effacement en base a lieu quand même : c'est l'exigence réglementaire qui prime.
Les pièces jointes sont reconnues à leur contenu. Images et PDF seulement, 10 Mo au plus, identifiés par leur signature plutôt que par leur extension. Le SVG est refusé, parce qu'il peut contenir du script.
Rien ne dépend d'Internet. Même le sélecteur d'emojis est embarqué dans l'application. Les bibliothèques courantes chargent leurs données depuis un serveur externe : sur une installation sans sortie Internet, il n'y aurait simplement aucun emoji, sans message d'erreur.
Ce qui fait vraiment la différence : les détails de WhatsApp
La moitié du travail a porté sur des choses qui paraissent cosmétiques et ne le sont pas :
- les messages d'une même personne, envoyés à moins de cinq minutes d'écart, regroupés sous un seul nom ;
- l'heure dans la bulle, en bas à droite ;
- les coches « remis » et « lu » — mais seulement dans les conversations privées et les groupes, là où l'on peut vraiment le constater. Afficher « lu par tous » dans une conversation de service serait un mensonge ;
- les réponses à un message, les réactions, les mentions
@prenom.nom; - un téléphone qui sonne même quand la messagerie est ouverte sur l'ordinateur du bureau.
Ce dernier point m'a occupé plus longtemps que prévu. Au départ, une personne « en ligne » ne recevait pas de notification. Mais un onglet resté ouvert au bureau suffisait pour qu'elle soit considérée en ligne, et son téléphone ne recevait plus rien. La présence se suit maintenant par type d'appareil, comme sur WhatsApp.
Une leçon de débogage
Pendant une semaine, les messages arrivaient, mais plus aucune notification ne partait, sans la moindre erreur dans les journaux. La cause : en ajoutant une fonction, je l'avais insérée entre le commentaire d'une autre fonction et sa signature. En Kotlin, une annotation s'applique à la déclaration qui la suit : @Transactional avait glissé sur la mauvaise fonction. Or l'envoi de la notification attend la fin de la transaction, et Spring ignore sans un mot un événement publié hors transaction. Un test vérifie désormais la présence de l'annotation.
Où en est le module
La messagerie fonctionne dans OptiServ, sur navigateur et sur l'application mobile. Elle reste un outil récent : son adoption se mesure dans la durée, et c'est l'usage, plus que le code, qui dira si le pari de la ressemblance est gagné.
Et vous, comment s'organisent les échanges du personnel dans votre structure ?