Concevoir un logiciel de suivi d'échantillons cliniques : chaîne de traçabilité, journal d'audit et envois confirmés par les deux parties

Notre conception du suivi d'échantillons cliniques d'une société de biosciences : statuts liés aux envois, double confirmation, journal d'audit, accès cloisonnés.

Points clés

  • Dans le suivi d'échantillons cliniques, le statut de transport d'un échantillon doit découler de son envoi, jamais d'une saisie manuelle. Cette seule règle supprime l'essentiel des « mais où est cet échantillon ? ».
  • Un envoi implique deux parties : le laboratoire demande une confirmation, le site expéditeur confirme, et toute modification ultérieure de l'envoi annule automatiquement cette confirmation.
  • Chaque modification est inscrite dans un journal d'audit non modifiable, dans la même transaction que la modification elle-même, et les données métier sont désactivées, jamais supprimées. C'est ce qu'attendent des textes comme la 21 CFR Part 11 en matière de piste d'audit.
  • Les accès sont limités par étude et par centre clinique, décidés par des fonctions de politique pures, avec un test unitaire pour chaque rôle.
  • L'API d'intégration appelle les mêmes services que l'application web : aucun client ne peut contourner une règle métier.

En octobre 2026, nous avons livré une plateforme de suivi d'échantillons cliniques à une société de biosciences. Les centres cliniques qui participent aux études du client prélèvent des échantillons et les envoient au client, qui les traite et met les résultats à disposition. Avant la plateforme, ce circuit reposait sur des tableurs et des fils d'e-mails.

Cet article présente les décisions de conception qui ont le plus compté. Il décrit des principes, pas les processus internes ni la configuration du client, et ces principes valent pour la plupart des systèmes où des objets physiques circulent entre organisations et où chaque étape doit pouvoir être expliquée après coup.


Que doit vraiment faire un logiciel de suivi d'échantillons cliniques ?

Un système de suivi d'échantillons doit répondre à tout moment à trois questions : où est cet échantillon, qui en est responsable, et comment le sait-on ? Tout le reste (tableaux de bord, notifications, exports) repose sur ces réponses.

Pour une étude multicentrique, cela se traduit par des exigences concrètes :

  • Plusieurs organisations utilisent le même système : les équipes du promoteur ou du laboratoire, les coordinateurs d'études, les administrateurs de chaque centre clinique et parfois des tiers.
  • Chacun ne doit voir que les études et les sites qui le concernent.
  • L'historique d'un échantillon doit être complet. Si un statut a été corrigé, la valeur d'origine et le motif doivent rester visibles.
  • Les envois franchissent les frontières entre organisations : les deux côtés doivent s'accorder sur ce qui a été envoyé.
  • Rien de ce qui touche à la vie privée des patients ne doit se retrouver là où ce n'est pas nécessaire, par exemple dans les notifications par e-mail.

Aucune de ces exigences n'est exotique. Ce qui les rend difficiles, c'est qu'elles doivent tenir sur chaque point d'entrée du système : l'interface web, les imports de tableurs et les intégrations machine.


Le modèle de données : pourquoi le « centre d'étude » est l'unité de cloisonnement

Le modèle repose sur trois entités : une étude, un centre clinique, et le centre d'étude qui les associe. Un centre clinique peut participer à plusieurs études ; une étude se déroule dans de nombreux centres. Échantillons et envois appartiennent toujours à un centre d'étude, jamais directement à une étude ou à un centre.

Ce rattachement est la décision de modélisation la plus importante du système. Il permet que :

  • un code de site soit unique au sein d'une étude sans l'être globalement ;
  • l'accès d'un administrateur de centre soit accordé sur le rattachement : administrer un centre dans une étude ne donne aucun accès à ses échantillons dans une autre ;
  • chaque requête de liste puisse être filtrée par un ensemble d'identifiants de centres d'étude, ce qui garde le cloisonnement simple et rapide.

Les rôles suivent la même structure. Il existe des rôles globaux pour les équipes du laboratoire, des rôles d'étude pour les coordinateurs et les tiers, et des rôles de centre pour les administrateurs de site. L'accès d'un utilisateur correspond à ce que lui accordent ces rattachements, et rien de plus.


Comment le statut d'un échantillon doit-il évoluer ?

Le cycle de vie est linéaire : prélevé → expédié → reçu → en cours de traitement → résultats disponibles. La vraie question est de savoir qui peut le faire passer d'un statut au suivant.

Les statuts de transport appartiennent à l'envoi

Les trois premiers statuts décrivent un trajet physique : nous les avons donc rattachés aux envois. Personne ne peut marquer directement un échantillon comme « expédié ». Il le devient quand l'envoi auquel il appartient est expédié, et « reçu » quand cet envoi est reçu. Annuler un envoi remet ses échantillons à l'état « prélevé ».

C'est une contrainte, et elle est voulue. Dans un suivi par tableur, l'incohérence la plus fréquente est un échantillon marqué comme expédié qui ne figure sur aucun envoi, ou un envoi reçu dont les échantillons sont encore « prélevés ». Dériver l'un de l'autre rend ces états impossibles, et pas seulement déconseillés.

Les statuts de laboratoire sont directs, mais réservés au laboratoire

Les deux dernières transitions, de reçu à en cours de traitement puis à résultats disponibles, ont lieu dans le laboratoire. Seules ses équipes (ou ses intégrations internes) peuvent les effectuer, et seulement sur des échantillons qui ne sont plus sur un envoi actif.

Les corrections sont une action distincte

Les erreurs arrivent : un administrateur peut donc corriger un statut postérieur au transport. Une correction n'est pas une modification : elle est enregistrée comme un type d'événement à part, avec un motif, à côté de l'original. L'historique montre à la fois ce qui s'est passé et ce qui a été rectifié.

Les données d'enregistrement sont immuables

Les champs d'enregistrement d'un échantillon (son code, son site, ses références, sa date de prélèvement) ne peuvent pas être modifiés après sa création, ni sur le web ni par l'API. Si on pouvait les modifier librement, le journal d'audit enregistrerait bien les changements, mais l'identité même de l'échantillon deviendrait négociable. Corriger une vraie erreur d'enregistrement demande un circuit de correction dédié et audité, pas un simple formulaire d'édition.


Des envois confirmés par les deux parties

Un envoi passe par les états brouillon → prêt → expédié → reçu, et peut être annulé tant qu'il est brouillon ou prêt. L'étape qui a demandé le plus de réflexion se situe entre « prêt » et « expédié ».

Le laboratoire sait ce qu'il s'attend à recevoir ; le site sait ce qu'il envoie réellement. Nous voulions que les deux soient d'accord avant que quoi que ce soit ne parte :

  1. Un utilisateur du laboratoire marque l'envoi comme prêt et demande une confirmation au site.
  2. L'administrateur du site reçoit une notification et confirme ou refuse l'envoi.
  3. L'envoi ne peut passer à « expédié » qu'une fois confirmé.
  4. Si quelqu'un modifie l'envoi après confirmation (ajout ou retrait d'un échantillon, changement des informations de suivi) ou l'annule, la confirmation devient périmée et un événement d'invalidation est enregistré. Le site doit confirmer à nouveau.

C'est le point 4 qui donne son sens à la confirmation. Une confirmation qui survit aux modifications ultérieures prouve seulement que le site a validé une version de l'envoi. L'invalider à chaque changement pertinent la lie exactement à ce qui a été envoyé.

Chaque envoi peut aussi produire des manifestes PDF. Plutôt que de stocker des fichiers générés, chaque version de manifeste enregistre un instantané JSON figé de l'envoi et de ses échantillons à ce moment-là, et le PDF est produit à partir de cet instantané au téléchargement. Un manifeste généré le mardi montre toujours les données du mardi, même si l'envoi a changé le mercredi.


Un journal d'audit impossible à contourner

Les environnements réglementés attendent des pistes d'audit. Le texte américain sur les enregistrements électroniques, la 21 CFR 11.10(e), demande des pistes d'audit « sécurisées, générées par ordinateur et horodatées » des saisies et actions des opérateurs, et exige que les modifications ne masquent pas les informations enregistrées auparavant. Valider un système relève toujours de l'organisation qui l'utilise, mais ces contrôles doivent d'abord exister dans le logiciel : nous les avons donc prévus dès le départ.

Trois décisions font l'essentiel du travail :

  • Même transaction. Chaque modification métier écrit son événement d'audit (auteur, origine, valeurs avant et après, champs modifiés, identifiant de requête) dans la même transaction que la modification. Si la modification est validée, la ligne d'audit existe ; sinon, aucune des deux n'existe. Il n'y a aucun moment où un changement aurait eu lieu sans être enregistré.
  • Historiques en ajout seul. Les événements d'audit, de statut d'échantillon et de confirmation d'envoi sont uniquement insérés. Aucun chemin de code ne les modifie ni ne les supprime.
  • Aucune suppression définitive. Études, centres, utilisateurs et échantillons sont désactivés, jamais supprimés. Les deux liens qui peuvent être retirés (un rôle révoqué, un échantillon sorti d'un envoi en brouillon) sont eux-mêmes audités.

Nous utilisons aussi un contrôle de concurrence optimiste sur chaque enregistrement modifiable : chacun porte un numéro de version, et une mise à jour ne s'applique que si la version n'a pas changé depuis la lecture. Deux coordinateurs qui modifient le même envoi ne peuvent pas s'écraser mutuellement en silence ; le second reçoit un conflit et voit l'état actuel.


Le contrôle d'accès : une seule décision, testée pour chaque rôle

Avec cinq rôles répartis sur trois niveaux, des vérifications de droits au cas par cas auraient divergé en quelques semaines. Nous avons repris la structure décrite dans notre article sur la structuration de l'autorisation :

  • Un contexte d'accès est chargé une fois par requête : l'utilisateur local, ses rôles globaux et ses rattachements actifs aux études et aux centres.
  • Les politiques sont des fonctions pures. Une vérification comme canConfirmShipment(context, shipment) renvoie vrai ou faux ; getListScope(context) renvoie « tout », « soi », « rien » ou l'ensemble des études et centres visibles.
  • Les services appellent les politiques et appliquent le résultat. Les pages, les actions de formulaire et les routes d'API ne décident jamais elles-mêmes des accès.

Comme les politiques sont des fonctions pures, elles se testent facilement. Chacune est testée sur un jeu commun de profils couvrant chaque rôle, y compris des utilisateurs désactivés, et les règles explicites du type personne ne peut supprimer un échantillon sont testées elles aussi. À la passation, la suite comptait plus de 180 tests unitaires, tous exécutés en intégration continue.

Une inscription sur invitation uniquement

Personne ne peut s'inscrire et obtenir un accès de lui-même. Un administrateur du laboratoire invite une personne avec exactement les rôles qu'elle doit recevoir ; l'invitation n'est rattachée à son compte que si l'adresse invitée y est vérifiée. Une inscription sans invitation correspondante donne un compte sans aucun accès. Désactiver un utilisateur dans l'application le bloque dès sa requête suivante, même si sa session de connexion est encore valide.


Les mêmes règles pour l'application web et l'API

Les systèmes internes du client doivent enregistrer des échantillons et mettre à jour des envois de façon automatisée : la plateforme inclut donc une API machine authentifiée, avec des identifiants à périmètre limité.

La règle que nous avons tenue : une écriture par l'API passe par le même service que l'action web équivalente. Même validation, mêmes vérifications de politique, mêmes événements d'audit, mêmes notifications. Une intégration ne peut pas créer un échantillon directement « expédié », ni modifier des champs d'enregistrement, ni se passer de la confirmation du site, parce que le code qui le permettrait n'existe pas.

Il est tentant d'écrire des routes d'API qui parlent directement à la base de données, parce que c'est plus rapide à développer. Cela crée aussi une seconde implémentation, légèrement différente, de chaque règle métier, et les deux finissent par diverger. Notre propre audit avant la passation a repéré exactement ce type d'écart dans une première version des routes d'échantillons ; les faire passer par les services partagés l'a corrigé durablement.


Des notifications sans données patient

Les coordinateurs et les administrateurs de site reçoivent des notifications par e-mail aux étapes qui les concernent : échantillon enregistré, statut modifié, résultats disponibles, envoi en attente de confirmation, confirmé, refusé, expédié ou reçu.

Deux choix les ont façonnées :

  • Les messages contiennent des identifiants, pas des personnes. Les notifications indiquent les codes d'échantillons et d'envois, les noms d'études et de centres, les statuts et les informations de suivi. Elles ne contiennent jamais de données patient et omettent la référence libre qu'un site peut utiliser en interne. C'est le principe du RGPD selon lequel les données personnelles doivent être « limitées à ce qui est nécessaire » (article 5, paragraphe 1, point c).
  • Une modification métier n'échoue jamais à cause de l'e-mail. Les notifications sont écrites dans une table d'outbox, dans la même transaction que la modification, puis envoyées ensuite avec des relances. Nous détaillons ce modèle dans L'outbox transactionnelle en pratique.

La passation : la documentation comme livrable

Le client dispose de sa propre équipe technique, et la plateforme a toujours été destinée à être exploitée par elle. La dernière phase du projet n'a donc pas été un lancement, mais une passation :

  • Un audit de notre propre code, chaque constat étant qualifié de confirmé, probable ou simple suggestion, puis corrigé ou explicitement accepté.
  • Quatorze documents couvrant l'installation, l'architecture, le modèle de données, la sécurité et la matrice des rôles, l'exploitation, l'API et les services tiers.
  • Un registre de décisions d'architecture comptant 25 décisions consignées, chacune avec son contexte et ses conséquences.
  • Un journal des modifications et une feuille de route priorisée, pour que le prochain développeur sache ce qui est prévu et pourquoi.

C'est la partie d'un projet la plus facile à sacrifier et la plus coûteuse à manquer. Être propriétaire du code ne veut pas dire grand-chose si ceux qui le possèdent ne peuvent pas le modifier sans risque. Nous abordons le volet contractuel dans À qui appartient le code ?.


Questions fréquentes

Une plateforme de suivi d'échantillons sur mesure remplace-t-elle un LIMS ?

En général, non. Un LIMS gère le travail à l'intérieur du laboratoire : instruments, analyses, résultats. Une plateforme de suivi comme celle-ci gère ce qui se passe entre les organisations : quels sites envoient quoi, qui l'a confirmé et qui doit être prévenu. Les deux s'intègrent plus souvent qu'ils ne se concurrencent.

Un tel système peut-il être conforme à la 21 CFR Part 11 ?

Un logiciel peut fournir les contrôles techniques attendus par la Part 11 : pistes d'audit, comptes nominatifs, accès limité aux personnes autorisées. La conformité elle-même dépend de la façon dont le système est validé et utilisé dans le système qualité de l'organisation : aucun éditeur ne peut la certifier seul.

Quelle pile technique avez-vous utilisée ?

TypeScript et Next.js pour l'application, PostgreSQL avec Prisma pour les données, un fournisseur d'identité managé pour la connexion, et une image Docker construite par l'intégration continue. Le modèle d'autorisation vit dans la base de données de l'application : le fournisseur d'identité peut être remplacé sans toucher aux règles d'accès.

Combien de temps dure un projet de ce type ?

Cela dépend du nombre de parcours et d'intégrations. Une plateforme de cette ampleur se compte généralement en mois avec une petite équipe senior, pas en semaines. Une phase de cadrage payante permet d'en tirer une estimation ferme pour votre projet ; voir comment commander un logiciel sur mesure.


Si vous suivez des échantillons, des prélèvements ou d'autres objets physiques entre plusieurs sites et que le tableur montre ses limites, lisez l'étude de cas complète, découvrez notre travail dans les sciences de la vie ou parlez-nous de votre projet.