Qui a demandé cela à l’assistant
Une fiche d’audit dit qui a fait quoi et quand, sans garder le texte privé. Elle compte, car lorsqu’un problème survient, il faut reconstituer ce qui s’est passé sans avoir copié les messages de tout le monde.
Un outil refuse une demande étrange le mardi. Le vendredi, quelqu’un demande pourquoi. Une fiche avec un identifiant, un nom d’outil, un résultat et une heure répond. Une copie de la discussion répondrait aussi, et deviendrait un risque.
À la fin de cette leçon
Remarque
Je peux écrire des fiches d’audit sans contenu privé et les supprimer quand leur durée de conservation s’achève.
Mots clés
| Mot | Ce que ça veut dire | Exemple |
|---|---|---|
| Fiche d’audit | une note de qui a fait quoi, quand et avec quel résultat | |
| Conservation | la durée pendant laquelle on garde une fiche | |
| Purge | supprimer les fiches qui ont dépassé leur durée | |
| Horloge simulée | une heure que votre code fixe, pour qu’un test maîtrise le temps | |
| Identifiant | un code qui représente une personne sans la nommer | u-17 |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Notez qui, quoi et quand
Écrivez une petite fiche pour chaque chose que la fonction a faite. Tenez-vous à une liste fixe de champs. Tout le reste, comme un prompt ou une réponse, est abandonné avant l’enregistrement.
Employez un identifiant pour la personne, pas un nom. Ajoutez des fiches sans jamais les modifier, pour que le journal reste digne de confiance.
Exemple : une fiche d’audit
| Champ | Exemple | Pourquoi il est là |
|---|---|---|
| quand | une heure | Quand c’est arrivé |
| utilisateur | u-17 | Qui a demandé, sans nom |
| action | lire_note | Ce que la fonction a fait |
| resultat | autorisé | Ce que les contrôles ont décidé |
| jetons | 120 | Ce que cela a coûté, en nombre |
| (non gardé) | le texte du prompt | Il peut contenir des données personnelles |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Gardez les fiches tant qu’elles servent
Chaque fiche a une raison, et cette raison finit. Choisissez une durée de conservation par genre : courte pour le texte des discussions, plus longue pour les fiches d’audit. Supprimez ensuite ce qui est plus ancien.
Les obligations légales varient selon le pays et le domaine : vérifiez celles qui vous concernent avant de choisir un nombre.
Écrire le script d’audit, partie 1
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'const JOUR = 24 * 60 * 60 * 1000;' 'let maintenant = Date.UTC(2026, 0, 1);' 'const autorises = [\"utilisateur\", \"action\", \"resultat\", \"jetons\"];' 'const journal = [];' '' '// Une fiche d’audit contient qui, quoi et quand. Jamais le texte.' 'function enregistrer(champs) {' ' const propre = { quand: maintenant, id: journal.length + 1 };' ' for (const cle of autorises) {' ' if (cle in champs) propre[cle] = champs[cle];' ' }' ' journal.push(propre);' ' return propre;' '}' > journal.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script d’audit, partie 2
docker exec -w /home/node/project agent sh -c "printf '%s\n' 'enregistrer({ utilisateur: \"u-17\", action: \"lire_note\", resultat: \"autorisé\", jetons: 120, prompt: \"Bonjour je suis Camille\" });' 'maintenant = maintenant + 20 * JOUR;' 'enregistrer({ utilisateur: \"u-18\", action: \"lancer_commande\", resultat: \"refusé\", jetons: 0 });' 'maintenant = maintenant + 20 * JOUR;' 'enregistrer({ utilisateur: \"u-17\", action: \"additionner\", resultat: \"autorisé\", jetons: 60 });' 'console.log(\"Champs gardés : \" + Object.keys(journal[0]).join(\", \"));' 'console.log(\"Prompt stocké : \" + (\"prompt\" in journal[0]));' >> journal.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Écrire le script d’audit, partie 3
docker exec -w /home/node/project agent sh -c "printf '%s\n' '// Conservation : garder une fiche 30 jours, puis la supprimer.' 'const GARDER = 30 * JOUR;' 'function purger(liste, instant) {' ' return liste.filter(function (fiche) { return instant - fiche.quand <= GARDER; });' '}' 'const restantes = purger(journal, maintenant);' 'console.log(\"Avant : \" + journal.length + \", après : \" + restantes.length);' 'console.log(\"Identifiants gardés : \" + restantes.map(function (fiche) { return fiche.id; }).join(\", \"));' >> journal.js"Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Lancer le script d’audit
docker exec -w /home/node/project agent node journal.jsAffichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.
Ce que le script affiche
| Ligne | Ce qu’elle montre |
|---|---|
| Champs gardés : quand, id, utilisateur, action, resultat, jetons | Le champ prompt a été abandonné |
| Prompt stocké : false | Rien de privé n’est arrivé dans le journal |
| Avant : 3, après : 2 | La première fiche a 40 jours et la limite est de 30 |
| Identifiants gardés : 2, 3 | Les deux fiches récentes restent |
Les cellules que les étudiants remplissent restent vides dans cet aperçu.
Une liste remplace un vrai stockage
Le script garde son journal dans un tableau et avance une horloge simulée à la main. Un vrai système emploie une base de données, avec sauvegardes et contrôle d’accès, et une tâche planifiée qui purge.
Les sauvegardes comptent aussi. Une fiche supprimée de la base reste dans la sauvegarde du mois dernier, sauf si la sauvegarde expire aussi.
Une erreur fréquente
Attention
Beaucoup pensent que journaliser davantage est toujours plus sûr. Un journal qui garde chaque prompt est lui-même un stock de données personnelles, et il faut le protéger et le purger comme tel. Journalisez les champs dont vous aurez besoin pour répondre à une question, et pas plus.