# Pistes d'audit : qui les écrit ?

> La séparation des tâches appliquée à la preuve : pourquoi les équipes produit ne doivent jamais être les seules autrices de leurs propres enregistrements d'audit, et comment un proxy Kafka, le CDC et la réconciliation y remédient.

Source: https://www.bluewise.fr/fr/audit-trails-who-writes-them  
Author: Marc Morel  
Published: 2026-06-01  
Category: Architecture  
Series: Audit trails, part 3

Jusqu'ici, cette série a porté sur l'enregistrement lui-même : ce qui en fait une preuve dans la [partie 1](https://www.bluewise.fr/audit-trails-logs-are-not-enough), et comment le garder assez sobre pour être sûr dans la [partie 2](https://www.bluewise.fr/audit-trails-not-a-data-lake). J'ai gardé une question pour un article à part, parce que c'est celle que la plupart des conceptions éludent discrètement : qui écrit réellement la piste d'audit ?

Dans la plupart des systèmes, la réponse honnête est l'équipe qui a construit la fonctionnalité. Les développeurs qui implémentent un flux de paiement écrivent aussi la ligne de code qui l'enregistre. Personne n'y met de mauvaise intention ; c'est simplement la voie de moindre résistance. Mais cela revient à demander à une fonctionnalité de témoigner sur elle-même, et cela nous ramène tout droit au point de départ de la série. Une déclaration qu'un système fait sur lui-même prouve très peu, aussi soigneusement qu'elle soit stockée ensuite.

## Personne n'audite son propre travail

La séparation des tâches est l'un des plus anciens contrôles de la finance. La personne qui initie un paiement ne l'approuve pas ; celle qui tient les comptes ne compte pas la caisse. Elle figure parmi les contrôles d'ISO 27001, et elle traverse toutes les attentes des superviseurs en matière de risque informatique. Appliquée aux pistes d'audit, elle nous donne un principe qui paraît presque évident une fois écrit :

> Les personnes qui construisent et exploitent une fonctionnalité ne doivent jamais être les seules autrices de la preuve de ce que fait cette fonctionnalité.

Les mots « seules autrices » portent beaucoup de poids ici, et délibérément. Une version plus stricte, comme « les développeurs ne doivent jamais toucher aux entrées d'audit », ne survit pas au contact de la réalité : le code d'une fonctionnalité émettra toujours quelque chose, que ce soit un événement métier, un statut ou un identifiant de corrélation. La version qui tient devant un auditeur repose sur trois règles.

1. **Les équipes produit peuvent déclarer, mais jamais attester seules.** Ce qu'elles enregistrent est une affirmation, à corroborer.
2. **La capture se fait dans des couches qu'elles ne possèdent ni ne déploient.** Les composants qui observent, transforment et stockent la preuve appartiennent à une équipe distincte, avec un code, un pipeline et des identifiants distincts.
3. **Leur coopération est vérifiée, pas présumée.** Quand une équipe oublie sa part du contrat, le système le remarque.

## Le vrai risque, c'est la défaillance de mode commun

Je veux être prudent ici, parce que cet article ne consiste pas à soupçonner les ingénieurs. La fraude par un développeur existe, mais elle est rare. Le risque quotidien est bien plus banal : un chemin d'exception qui retourne avant l'appel d'audit, un refactoring qui fait disparaître un champ, un feature flag qui contourne le handler habituel, un hotfix à deux heures du matin qui écrit directement dans une table.

Dans chacun de ces cas, le code qui échoue est aussi le code qui était censé signaler l'échec. Les ingénieurs fiabilité ont un nom pour cela : la défaillance de mode commun, quand un moniteur partage un mode de défaillance avec ce qu'il surveille. Une piste d'audit écrite uniquement par la fonctionnalité a exactement cette propriété. La séparation des tâches rompt ce couplage. Si une couche indépendante observe la requête entrer et les données changer, une défaillance silencieuse dans le code de la fonctionnalité devient un trou visible.

## Faits déclarés et faits observés

La distinction qui rend cela praticable est celle entre ce qu'une fonctionnalité **déclare** et ce qu'une couche indépendante **observe**. Dans une architecture événementielle, il existe trois sources naturelles, chacune bonne pour une question et aveugle aux autres.

| Source           | Capturé par                                         | Appartient à                                                   | Vous dit                                                 | Ne peut pas vous dire                        |
| ---------------- | --------------------------------------------------- | ---------------------------------------------------------- | --------------------------------------------------------- | -------------------------------------- |
| Fait déclaré    | Une ligne d'outbox écrite par le service, transportée par le CDC | Écrit par l'équipe produit, transporté par la plateforme d'audit | Le sens métier : action, finalité, contexte                | Si cela s'est passé comme déclaré        |
| Intention observée  | Le filtre d'audit du proxy Kafka, le plugin de l'API gateway | La plateforme d'audit                                         | Qui a demandé quoi, quand, sous quelle identité authentifiée | Si la requête a été exécutée       |
| Résultat observé | Le CDC qui lit le write-ahead log de la base de données            | La plateforme d'audit                                         | Ce qui a réellement changé dans les données, dans quelle transaction   | Qui a demandé, et pourquoi                     |

Aucune des trois ne suffit seule. Ensemble, elles se corroborent mutuellement, ce qui est précisément ce qu'un auditeur, un superviseur ou un tribunal entend par preuve.

Le cadre est volontairement ordinaire. Quatre services, pour les clients, les bénéficiaires, les cartes et les paiements, possèdent chacun leur base de données et échangent commandes et événements via Kafka. Ce qui change, c'est la couleur des boîtes. Tout ce qui est en bleu appartient à une équipe plateforme d'audit avec son propre code, son propre pipeline de déploiement et ses propres identifiants. Les équipes produit gardent l'entière maîtrise de leurs services et de leurs schémas, mais elles ne détiennent aucun identifiant sur le cluster d'audit et ne peuvent redéployer rien de ce qui capture, transforme ou stocke la preuve.

La suite de cet article suit le schéma de haut en bas.

## Capturer l'intention à la périphérie

Un proxy Kafka parle le protocole réseau de Kafka. Les clients s'y connectent comme s'il s'agissait du cluster, et il transmet leur trafic aux vrais brokers. Des projets open source comme [Kroxylicious](https://kroxylicious.io), ainsi que plusieurs gateways commerciales, permettent de brancher des filtres sur ce trafic. Un filtre d'audit sur les requêtes de production vers les topics de commandes enregistre, pour chaque commande :

- le topic, la clé et les en-têtes, y compris l'identifiant de corrélation ;
- le principal authentifié du client, issu de mTLS ou de SASL ;
- le moment où la requête a atteint la périphérie ;
- une copie minimisée du payload.

Tout cela se produit avant que la moindre logique métier ne s'exécute, dans du code que l'équipe produit ne possède pas. Comme le proxy se trouve devant chaque client, il voit aussi les commandes de service à service, pas seulement celles qui viennent du monde extérieur.

Deux conditions rendent cette capture digne de confiance.

- **Le proxy doit être le seul point d'entrée.** Si un service peut atteindre les brokers directement, le filtre devient optionnel. Imposez le chemin au niveau réseau, et configurez les ACL des brokers pour n'accepter que les connexions provenant de l'identité du proxy.
- **Les appels synchrones ont besoin du même traitement.** Toutes les intentions ne transitent pas par Kafka. L'API gateway, qui attribue aussi l'identifiant de corrélation, embarque un plugin d'audit appartenant à la même équipe plateforme et écrivant des enregistrements de même forme.

Le proxy se trouve aussi sur le chemin critique, donc son comportement en cas de défaillance mérite une décision délibérée. Pour les commandes ayant un impact financier ou réglementaire, je choisirais l'échec fermé : si l'intention ne peut pas être enregistrée, la commande n'est pas acceptée. C'est la conséquence naturelle du principe de la partie 1 selon lequel un enregistrement manquant est un incident. Pour les topics à moindre enjeu, l'échec ouvert avec une alerte peut être acceptable. Dans tous les cas, consignez le choix par classe de topic, et exploitez le proxy avec les mêmes objectifs de disponibilité que les brokers eux-mêmes.

Ce que la capture d'intention ne peut pas vous dire, c'est si quelque chose s'est passé ensuite. C'est le rôle de la base de données.

## Capturer les résultats dans la base de données

Le change data capture lit le propre write-ahead log de la base de données : chaque insertion, mise à jour et suppression validée, avec les images avant et après, l'identifiant de transaction et la position dans le log. Dans les écosystèmes Kafka, [Debezium](https://debezium.io/documentation/) est l'implémentation de référence. Pour notre propos, sa propriété la plus précieuse est que le code applicatif ne peut pas le contourner. Si une modification a été validée, elle est dans le log, qu'elle vienne du service, d'un script de migration, d'un hotfix ou d'une console de DBA.

Les faits déclarés empruntent la même route. Chaque service écrit ses lignes d'audit déclarées dans une table d'outbox, dans la même transaction que la modification métier, et l'outbox router du connecteur CDC les publie vers le cluster d'audit. L'équipe produit écrit la ligne, mais ne touche jamais au tuyau qui la transporte, et ne peut pas modifier discrètement une ligne validée : la modification apparaîtrait aussi dans le log.

### L'identifiant de transaction est le chaînon manquant

C'est la partie de la conception que je trouve la plus élégante. Avec les métadonnées de transaction activées, Debezium marque chaque événement de modification avec la transaction qui l'a produit. La ligne d'outbox est écrite dans la même transaction que les lignes métier, et elle porte l'identifiant de corrélation. Elle relie donc l'intention, via l'identifiant de corrélation, aux modifications de lignes, via l'identifiant de transaction. Inutile d'ajouter des colonnes de corrélation aux tables métier.

### Trois précautions

- **Minimiser dès la capture.** Le CDC émet des images de ligne complètes, ce qui est exactement l'accumulation contre laquelle la partie 2 met en garde. Des transformations dans le pipeline du connecteur pseudonymisent, hachent ou suppriment des champs et chiffrent ce qui doit être conservé, avant que quoi que ce soit n'atteigne le cluster d'audit. Les hachages à clé gardent les valeurs comparables pour la réconciliation sans les exposer.
- **S'accorder sur les tables pertinentes pour l'audit.** Les modifications physiques incluent des caches, des projections et des tables purement techniques. L'équipe plateforme et chaque équipe produit conviennent de la liste, et ses modifications passent par la revue de l'équipe plateforme.
- **Appliquer aussi la séparation des tâches à la base de données.** Le slot de réplication, la publication et les identifiants du connecteur appartiennent à l'équipe plateforme. Les administrateurs de bases de données, qui pourraient sinon à la fois modifier les données et reconfigurer leur capture, ne doivent pas pouvoir faire les deux.

## La réconciliation : là où les enregistrements deviennent des preuves

Capturer trois enregistrements indépendants ne représente que la moitié de la valeur. L'autre moitié vient de leur confrontation.

[![Deux scénarios. Dans le chemin normal, une intention capturée au proxy Kafka, une ligne d'outbox déclarée et une modification de ligne issue du write-ahead log sont jointes sur l'identifiant de corrélation et l'identifiant de transaction, et concordent. Dans le second, un DBA modifie la table directement : la modification de ligne n'a ni intention ni ligne d'outbox correspondante, et la réconciliation lève un constat.](https://www.bluewise.fr/images/blog/who-writes-the-audit-trail/audit-trail-reconciliation-join.svg)](https://www.bluewise.fr/images/blog/who-writes-the-audit-trail/audit-trail-reconciliation-join.svg)

Un moteur de réconciliation, appartenant à l'équipe plateforme d'audit, joint les trois flux et classe chaque cas.

| Constat                                | Ce que cela signifie généralement                                               | Réponse                                                        |
| -------------------------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------- |
| Intention, déclaration et résultat concordent  | Le chemin normal                                                     | Scellé, rien à faire                                           |
| Intention sans résultat                 | Une commande rejetée ou en échec                                        | Attendu quand un rejet est déclaré ; à investiguer sinon    |
| Résultat sans intention                 | Un accès direct à la base, un batch non déclaré, une porte dérobée ou un bug   | Alerter immédiatement la deuxième ligne                               |
| Déclaration et résultat divergent       | Un défaut de logique ou une falsification : un montant différent, un bénéficiaire différent | Ouvrir un dossier                                                     |
| Identifiant de corrélation manquant                 | Une équipe a cassé la propagation                                            | Constat qualité pour cette équipe : détecté, jamais perdu en silence    |

La dernière ligne est celle que je trouve la plus satisfaisante. Les équipes produit doivent toujours propager l'identifiant de corrélation et écrire leurs lignes d'outbox. Si elles ne le font pas, la réconciliation le remarque. Leur coopération est vérifiée plutôt que présumée, ce qui est exactement la troisième règle.

Quelques aspects pratiques font la différence entre une démo et un contrôle.

- **Travailler par fenêtres, pas par instants.** Dans un système événementiel, un résultat peut arriver quelques secondes après son intention. La réconciliation s'exécute sur des fenêtres définies par flux, et une fenêtre qui se ferme sans sa contrepartie est elle-même un constat.
- **Comparer des valeurs sans les révéler.** Parce que les valeurs ont été minimisées avec des hachages à clé sous la même clé de personne, la réconciliation peut confirmer que l'IBAN déclaré correspond à l'IBAN validé sans jamais voir ni l'un ni l'autre.
- **Traiter aussi les constats comme des preuves.** Ils sont publiés sur leur propre topic d'audit, puis chaînés et scellés comme tout autre enregistrement. La deuxième ligne les examine via l'interface de requête masquée de la partie 2, avec la même discipline de finalité.

Si vous avez travaillé dans la banque, vous reconnaîtrez le schéma. C'est le rapprochement comptable appliqué au comportement des systèmes : deux livres indépendants doivent concorder, et chaque écart doit être expliqué.

## Ce qu'aucun des points de capture ne voit

Dans l'esprit de cette série, voici les limites.

- **Les lectures.** Le CDC voit les écritures, et le proxy voit les commandes. Les lectures de données sensibles nécessitent leurs propres contrôles : le broker d'accès d'urgence et l'interface de requête masquée des parties 1 et 2 pour les personnes, et un audit au niveau de la base comme [pgAudit](https://www.pgaudit.org) pour les quelques tables où les lectures des services comptent aussi.
- **La véracité de l'intention.** Le proxy prouve quel identifiant a fait la demande. Il ne peut pas prouver que la personne derrière l'identifiant le voulait. L'authentification forte et l'exigence d'attribution de la partie 1 restent essentielles.

## Qui audite les auditeurs ? Trois tortues suffisent peut-être

Dans un article précédent, [Three turtles might be enough](https://www.bluewise.fr/three-turtles-might-be-enough), j'expliquais que la sécurité ne se termine jamais sur une racine de confiance inconditionnelle : elle s'arrête là où la couche suivante cesse d'être rentable. Cet article appliquait l'idée aux clés SSH sur un Mac. La séparation des tâches soulève ici la même régression. Si la plateforme d'audit surveille les équipes produit, qui surveille la plateforme d'audit ? Et qui surveille ceux-là ?

Ici aussi, trois tortues suffisent peut-être, à condition que la dernière se trouve en dehors de votre organisation.

1. **Les équipes produit déclarent.** Elles écrivent des lignes d'outbox et propagent l'identifiant de corrélation. Ce qu'elles produisent est une affirmation, jamais une preuve à elle seule.
2. **La plateforme d'audit observe et réconcilie.** Elle capture intentions et résultats indépendamment des équipes produit et les confronte aux déclarations. Elle ne peut pas non plus réécrire discrètement ce qu'elle détient : chaque enregistrement est chaîné par hachage, les modifications de son propre pipeline nécessitent un second regard, et l'accès de ses ingénieurs à la piste est audité comme celui de n'importe qui.
3. **Des tiers indépendants scellent et vérifient.** Un prestataire de services de confiance qualifié horodate les racines de Merkle, sous la supervision d'un organisme national. Un auditeur externe vérifie les preuves d'inclusion et de cohérence avec un vérificateur qui ne dépend pas de vos systèmes. Une fois qu'une racine a été horodatée hors de l'organisation, même la plateforme d'audit ne peut pas modifier l'historique sans que cela se voie.

La régression s'arrête à la troisième tortue pour une raison simple. Ses incitations et sa responsabilité ne dépendent pas des vôtres : elle est régulée, auditée pour son propre compte et responsable de ce qu'elle atteste. Une quatrième tortue à l'intérieur de l'entreprise ajouterait du coût et des processus, mais aucune indépendance. Davantage de tortues à l'intérieur de la maison n'aident pas ; une tortue à l'extérieur, si.

## Ce que cela demande à chaque équipe

| Équipe                    | Responsabilités                                                                                   | Ne doit pas                                                                |
| ----------------------- | -------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------- |
| Équipes produit           | Propager l'identifiant de corrélation, écrire les lignes d'outbox dans la transaction métier, garder les schémas enregistrés | Détenir des identifiants sur le cluster d'audit, ni déployer un composant de capture  |
| Équipe plateforme d'audit     | Posséder le filtre du proxy, le plugin de gateway, les connecteurs CDC, la minimisation, la réconciliation et le stockage     | Implémenter de la logique métier, ni modifier des enregistrements scellés                       |
| Deuxième ligne             | Trier les constats, examiner les sessions d'accès d'urgence                                                       | Modifier la configuration de capture                                            |
| Administrateurs de bases de données | Exploiter et optimiser les bases de données                                                                     | Configurer la capture CDC, ni approuver leurs propres modifications directes              |

Rien de tout cela ne ralentit les équipes produit en pratique. Leur contrat est petit et explicite, et en échange elles sont déchargées de quelque chose qu'elles n'ont jamais été bien placées pour faire : se porter garantes de leur propre travail.

## Ce qui change

Une preuve devient crédible quand elle est corroborée par des parties qui n'ont rien à y gagner. Avec des intentions capturées à la périphérie, des résultats capturés dans la base de données, un moteur de réconciliation n'appartenant à aucune des deux parties, et une dernière tortue en dehors de l'organisation, la piste d'audit cesse d'être le récit qu'une fonctionnalité fait d'elle-même et devient un enregistrement indépendant de ce qui s'est passé.

Nous avons maintenant toutes les pièces : les propriétés probantes de la partie 1, la discipline de divulgation de la partie 2, et la séparation des tâches décrite ici. [La partie 4, « Audit Trail Reference Architecture »](https://www.bluewise.fr/audit-trails-reference-architecture), les assemble en une seule conception, rédigée sous forme d'architecture decision record.
