Traçage et audit

Chaque requête émise par un espace de travail — les appels de l'agent aux fournisseurs de LLM, les téléchargements de paquets, le trafic kubectl et aws, les simples récupérations web — passe par le proxy MITM côté hôte de Bromure Agentic Coding. Comme le proxy se tient déjà sur cette frontière du fil, il peut enregistrer ce qui la traverse : quels hôtes l'agent a contactés, ce qu'il a envoyé, ce qui est revenu, si un identifiant a été échangé ou divulgué, et — pour le trafic IA — l'intégralité de la conversation, les appels d'outils et les commandes shell pilotés par le modèle.

Cet enregistrement constitue la trace de session de l'espace de travail. Il existe pour une seule raison : vous permettre de répondre, après coup, à la question « qu'a réellement fait l'agent ? » — jusqu'au prompt individuel, au rm -rf individuel, à la requête sortante individuelle. Tout est enregistré sur votre Mac, chiffré au repos, et (pour les utilisateurs individuels) ne le quitte jamais.

Ce chapitre couvre l'ensemble du système : ce que capture une trace, comment elle est stockée et purgée, la fenêtre de l'Inspecteur de traces, la ligne de commande bromure-cli trace, comment récupérer les données, et la frontière de confidentialité entre l'audit local et la télémétrie que les Mac inscrits diffusent à une organisation. La référence champ par champ des réglages du volet se trouve dans Réglages de traçage.

Ce qu'enregistre une trace

Le traçage se fait par espace de travail, contrôlé par le sélecteur Trace de session dans le volet Traçage de la fenêtre Modifier l'espace de travail. Il comporte quatre niveaux, chacun étant un sur-ensemble du précédent :

Le volet Traçage de la fenêtre Modifier l'espace de travail, avec le sélecteur Trace de session réglé sur Détails des requêtes IA
NiveauCe qui est enregistré
DésactivéRien.
Activité uniquementUn enregistrement de métadonnées par requête — sans corps.
Détails des requêtes IA (par défaut)Métadonnées de chaque requête, plus les corps complets des requêtes et réponses pour les hôtes LLM connus.
ToutMétadonnées de chaque requête, plus les corps de chaque hôte.

Les nouveaux espaces de travail utilisent par défaut Détails des requêtes IA, de sorte que les conversations de l'agent sont auditables d'emblée sans stocker sur le disque les corps du trafic sans rapport (téléchargements de paquets, pings de télémétrie).

Remarque : l'énumération du niveau de trace prend par défaut la valeur Désactivé dans le format de profil, de sorte qu'un espace de travail dont le JSON stocké est antérieur à ce réglage se décode comme Désactivé. La valeur par défaut Détails des requêtes IA ne s'applique qu'aux espaces de travail créés à partir du modèle actuel. Choisissez le niveau délibérément lorsque l'audit importe.

L'enregistrement de métadonnées

À partir d'Activité uniquement, le proxy écrit un enregistrement de trace par requête. Chaque enregistrement — quel que soit le niveau — porte les métadonnées :

  • Horodatage, hôte, port, méthode HTTP et chemin.
  • Code de statut et latence, mesurés depuis le CONNECT qui a ouvert le tunnel jusqu'à la réponse.
  • Octets de requête (mesurés avant tout échange d'identifiant) et octets de réponse.
  • Le rapport d'échange de jetons — quels identifiants le proxy a substitués à la sortie (voir Échanges et fuites d'identifiants).
  • Avertissements de fuite d'identifiants — jetons de type bearer dans la requête sortante que Bromure n'a pas générés.
  • Sous un routage de modèle local ou hybride, quel backend a servi le tour (voir Modèles locaux).

C'est suffisant pour reconstituer le tableau complet de avec qui l'agent a échangé et quand sans conserver un seul octet de texte de prompt ou de réponse sur le disque. Lorsque vous voulez la piste d'audit — domaines contactés, gestion des identifiants, latence — mais pas le contenu, Activité uniquement est le niveau à choisir.

Corps capturés et conversations analysées

Au niveau Détails des requêtes IA, le proxy stocke en plus les corps complets des requêtes et réponses pour les hôtes LLM connus : Anthropic, OpenAI / ChatGPT, Google, Cohere, Mistral, Perplexity, x.ai / Grok, Groq, Replicate et HuggingFace, ainsi que l'hôte d'inférence locale lorsqu'un espace de travail route vers un modèle local. Au niveau Tout, les corps sont conservés pour tous les hôtes.

Un corps IA capturé n'est pas seulement stocké — il est analysé. L'Inspecteur de traces le restitue sous forme de vue Conversation : le prompt système, chaque tour utilisateur, les réponses de l'assistant et les blocs structurés émis par le modèle. Ces blocs sont exactement ce qui rend utile une trace d'agent de codage :

  • Appels d'outils — chaque bloc tool_use produit par le modèle, avec son entrée.
  • Commandes shell — les appels d'outil Bash / Shell, c'est-à-dire les commandes que l'agent a exécutées dans la VM.
  • Lectures et écritures de fichiers — les appels d'outil Read / View et Write / Edit / MultiEdit, avec les chemins qu'ils ont touchés.

Ainsi, un unique enregistrement de requête IA répond à « qu'a décidé de faire le modèle ce tour-ci » — lire ce fichier, exécuter cette commande, appeler cette API — extrait du corps brut de l'API. La même structure est ce que le tap d'événements en temps réel transforme en événements d'audit sur les Mac inscrits.

Échanges et fuites d'identifiants

Deux faits relatifs à la gestion des identifiants sont enregistrés à chaque requête, et mis en évidence car ce sont ceux qui comptent pour une revue de sécurité :

  • Échanges de jetons. Lorsque le proxy remplace l'identifiant leurre détenu par la VM par le véritable identifiant sur le fil, l'enregistrement le note — sous forme d'aperçus des premiers/derniers caractères des valeurs factice et réelle (sk-a…f9q3), jamais les octets du secret. C'est le cas normal et sain : il confirme que le système d'échange fait son travail.
  • Fuites. Lorsqu'une requête sortante transporte un jeton de type bearer que Bromure n'a pas généré — un véritable secret collé directement dans la VM, contournant le système d'échange — l'enregistrement le signale comme une fuite potentielle, là encore uniquement sous forme d'aperçu, étiqueté avec une classe de suspicion : knownPrefix (un préfixe de secret reconnu que Bromure n'a pas émis) ou opaqueToken (une longue valeur d'authentification opaque). Un signalement de fuite est une invitation à enquêter ; l'intégralité des mécanismes des identifiants leurres et de la détection de compromission se trouve dans Identifiants.

Chiffrement au repos et rétention

Les traces résident sous ~/Library/Application Support/BromureAC/traces/, organisées par jour :

  • Les métadonnées sont ajoutées à raison d'une ligne JSON par requête dans traces/YYYY-MM-DD/<sessionID>.jsonl.
  • Les corps capturés sont stockés à côté sous traces/YYYY-MM-DD/<sessionID>/<recordID>.req.enc et .res.enc — scellés en AES-GCM avec la clé maîtresse SecretsVault, la même clé détenue dans le Keychain qui chiffre les secrets de votre espace de travail. Les permissions de fichier sont 0600.

Avant toute écriture, l'enregistrement est assaini :

  • Les en-têtes sensibles sont expurgés. Authorization, Proxy-Authorization, Cookie, Set-Cookie, x-amz-security-token, api-key, et tout en-tête se terminant par -api-key sont réécrits en <redacted>.
  • Les secrets sont stockés uniquement sous forme d'aperçu. Les échanges de jetons et les fuites suspectées conservent les aperçus des premiers/derniers caractères — les véritables octets d'un secret n'entrent jamais dans un enregistrement de trace, chiffré ou non.

La rétention est automatique et s'exécute paresseusement (une passe de nettoyage tous les 200 ajouts) :

PlafondComportement en cas de dépassement
100 Mo de corps par sessionLes fichiers de corps .enc les plus anciens de cette session sont évincés. Les lignes de métadonnées demeurent — vous conservez la piste d'audit, vous ne perdez que le texte capturé le plus ancien.
5 Go sur l'ensemble du répertoire traces/Les répertoires de jour les plus anciens sont supprimés en premier.

Séparément, l'application conserve les 5 000 derniers enregistrements dans un anneau en mémoire pour la vue en direct ; les enregistrements plus anciens restent sur le disque dans les limites des plafonds ci-dessus.

Avertissement : aux niveaux Détails des requêtes IA et Tout, l'intégralité du texte des prompts et réponses des échanges IA se trouve sur le disque — chiffrée, mais présente. Comme les corps sont scellés avec la clé maîtresse SecretsVault, faire pivoter cette clé rend indéchiffrables les corps précédemment capturés ; l'Inspecteur de traces affiche alors (not captured / decryption failed) là où figurerait le corps.

La fenêtre de l'Inspecteur de traces

L'Inspecteur de traces est le visualiseur en direct et filtrable de chaque échange enregistré à travers tous les espaces de travail. Il lit les mêmes enregistrements que la CLI et se met à jour en temps réel à mesure que de nouvelles requêtes circulent.

Ouverture de la fenêtre

Ouvrez-la depuis WindowTrace Inspector… (⇧⌘I). Elle s'ouvre aussi pré-filtrée sur un espace de travail depuis la barre d'outils d'une fenêtre de session, ce qui vous permet de passer directement d'un agent en cours d'exécution à son propre trafic. À l'ouverture, l'anneau en mémoire est préchauffé depuis le disque — en lisant uniquement les répertoires de jour d'aujourd'hui et d'hier, de sorte qu'un lancement à froid est rapide. Les enregistrements plus anciens restent sur le disque et apparaissent une fois que vous appuyez sur le bouton de rechargement lorsqu'ils sont dans la plage, ou en les lisant avec la CLI.

La liste des requêtes

Le volet de gauche est une liste d'enregistrements, du plus récent au plus ancien. Chaque ligne affiche, de gauche à droite :

  • Un point de statut codé par couleur selon la classe de réponse : vert pour 2xx, bleu pour 3xx, orange pour 4xx, rouge pour 5xx, gris sinon.
  • La méthode et l'hôte (le chemin est affiché en dessous, tronqué au milieu).
  • Des badges, le cas échéant : un triangle d'avertissement orange pour les identifiants non échangés (une fuite potentielle), des flèches d'échange bleues pour les échanges de jetons, et une icône de document lorsqu'un corps a été capturé pour cet enregistrement.
  • Le code de statut et la latence sur la droite.

Le pied de page indique N records (last M in memory) et porte un bouton Recharger depuis le disque (l'icône de flèche circulaire). La liste dispose d'une navigation complète au clavier — ↑ / ↓ pour avancer d'un pas, PgUp / PgDn pour sauter de dix, Home / End pour atteindre les extrémités — la ligne nouvellement sélectionnée étant amenée à la vue par défilement.

Filtrage

Une barre de filtre se trouve au-dessus de la liste :

ContrôleEffet
Sélecteur Espace de travailRestreindre à un espace de travail, ou Tous les espaces de travail.
Fuites uniquementN'afficher que les enregistrements comportant un avertissement d'identifiant non échangé.
Conversations uniquementN'afficher que les enregistrements que le proxy a analysés comme un échange de chat IA.
Filtre d'hôteUne correspondance de sous-chaîne sur l'hôte.

Remarque : Conversations uniquement repose sur un indicateur défini lors de l'écriture de l'enregistrement. Les enregistrements capturés avant l'existence de cet indicateur comptent comme des non-conversations et sont masqués par ce filtre jusqu'à leur ré-enregistrement.

Le volet de détail

La sélection d'une ligne remplit le volet de droite. Son en-tête affiche la méthode, l'URL complète, le statut et une rangée de cellules de métadonnées — Espace de travail, Latence, tailles de Requête et de Réponse, et Heure — plus un bouton segmenté Conversation / Brut.

  • Conversation restitue le chat IA analysé : prompt système, tours, appels d'outils et résultats, mis en forme pour la lecture. Il n'est disponible que lorsqu'un corps a été capturé et que l'échange a été analysé comme une conversation IA ; sinon le bouton bascule de lui-même sur Brut.
  • Brut affiche les composants de l'enregistrement en sections : Identifiants non échangés (fuites potentielles), Échanges de jetons (chacun sous forme d'aperçus factice → réel), Corps de requête et Corps de réponse. Les corps sont déchiffrés à la demande lorsque vous sélectionnez l'enregistrement.

Chaque section de corps dispose d'un bouton de copie qui place le corps complet dans le presse-papiers — le texte intégral même au-delà de la troncature à l'écran, et une chaîne hexadécimale pour les corps binaires. Lorsqu'aucun corps n'a été stocké, ou que la clé maîtresse ne peut plus le déchiffrer, la section indique (not captured / decryption failed).

Sans sélection, le volet affiche un texte indicatif : Choisissez une requête — Sélectionnez une ligne à gauche pour inspecter les en-têtes, les échanges et (si capturés) les corps.

Sessions WebSocket

Les mises à niveau WebSocket de longue durée à travers le proxy — OpenAI Realtime, le responses_websockets de Codex, et similaires — sont tracées comme un enregistrement unique par session WS plutôt que perdues sous forme de binaire opaque. Lorsque le niveau de trace de l'espace de travail capture les corps pour cet hôte, les deux directions sont analysées trame par trame (RFC 6455) : le masquage est retiré, les trames de continuation sont défragmentées, et les charges utiles permessage-deflate (RFC 7692) sont décompressées, de sorte que les trames de texte sont lisibles au lieu d'être du charabia compressé.

À la fermeture, le proxy ajoute une transcription chronologique après la réponse de handshake amont et la stocke comme corps de réponse de l'enregistrement, de sorte que l'Inspecteur de traces la restitue par le chemin de corps ordinaire — vue Conversation comprise lorsqu'elle s'analyse comme un échange IA. Une entrée de transcription ressemble à ceci :

--- WebSocket session transcript ---
>>> [2026-07-13T15:30:05Z] TEXT 1234B
<<< [2026-07-13T15:30:06Z] TEXT 5678B (truncated, total 40000 bytes)

Des limites bornent une session bavarde : 1 Mo conservé par message, 4 096 messages par session, une trame maximale de 64 Mo, et un message décompressé maximal de 32 Mo ; tout ce qui dépasse un plafond est marqué (truncated, total N bytes). Les échecs d'analyse ne dégradent que la transcription — le tunnel en direct pompe les octets bruts et n'est jamais bloqué ni corrompu par le traçage.

La CLI de traçage

Le groupe de commandes bromure-cli trace vous donne les mêmes données de trace dans le terminal. C'est un client léger : il communique avec l'application en cours d'exécution via le socket de contrôle local, de sorte que l'application GUI doit être en cours d'exécution (le client riche fait transiter le protocole identique par SSH pour atteindre une instance distante).

CommandeCe qu'elle fait
bromure-cli trace ls [workspace] [--limit N]Lister les requêtes récentes, de la plus récente à la plus ancienne (50 lignes par défaut). Colonnes : TIME, HOST, METHOD, STATUS, REQ, RESP, LAT, et FLAGS (swap×N, LEAK×N, conv).
bromure-cli trace summary [workspace]Vue agrégée : nombres de requêtes et d'hôtes, octets montants/descendants, un histogramme par classe de statut, nombres d'échanges/fuites/conversations, et le top 10 des hôtes.
bromure-cli trace hostnames [workspace]Chaque hôte distinct contacté, avec le nombre de requêtes.
bromure-cli trace leaks [workspace]Uniquement les requêtes comportant une fuite potentielle d'identifiant — en-tête, aperçu de la valeur et classe de suspicion. Affiche No leaks detected. ✓ lorsqu'il n'y en a aucune.
bromure-cli trace clear [-f]Effacer tout l'historique de traces — l'anneau en mémoire et les fichiers sur disque — après une confirmation y/N (à ignorer avec -f). Rapporte combien d'enregistrements ont été effacés.

L'argument facultatif workspace filtre par id ou par nom. Si le traçage est désactivé pour l'espace de travail (ou si rien n'a encore été enregistré), trace ls affiche No trace records. (Tracing is per-workspace — enable it in the workspace's settings.) ; si l'application n'est pas en cours d'exécution, chaque sous-commande affiche No bromure-cli agent running. La CLI complète est documentée dans Automatisation et CLI.

Exporter une trace

Il n'y a pas de bouton « Exporter » unique — les données de trace quittent l'inspecteur par les chemins qui préservent l'intégrité de la frontière de chiffrement :

  • Depuis l'Inspecteur de traces. En mode Brut, le bouton de copie du Corps de requête ou du Corps de réponse copie le corps déchiffré complet dans le presse-papiers, au-delà de toute troncature à l'écran. L'URL dans l'en-tête est un texte sélectionnable. C'est la façon d'extraire un échange — une paire prompt/réponse complète — pour un rapport ou un signalement de bogue.
  • Depuis la CLI. Redirigez n'importe quelle sous-commande trace vers un fichier, par exemple bromure-cli trace summary my-workspace > audit.txt ou bromure-cli trace ls my-workspace --limit 500 > requests.txt. C'est la façon de capturer la piste de métadonnées de nombreuses requêtes à la fois.
  • Depuis le disque. Le JSONL de métadonnées sous traces/YYYY-MM-DD/ est du texte brut (avec les secrets déjà expurgés en aperçus) et peut être lu directement. Les fichiers de corps .enc sont scellés en AES-GCM avec la clé maîtresse SecretsVault et ne sont déchiffrables qu'à l'intérieur de l'application — copiez-les depuis l'inspecteur, pas depuis le disque.

Ce qui ne quitte jamais votre Mac

Pour une installation individuelle et non gérée, le traçage est entièrement local :

  • Les traces sont écrites dans le répertoire Application Support de votre Mac et chiffrées avec une clé détenue dans votre Keychain de session.
  • Aucun enregistrement de trace, corps ou résumé n'est téléversé où que ce soit. Le proxy n'a aucun point de terminaison d'analytique câblé pour les utilisateurs individuels.
  • Les classificateurs d'injection de prompt qui alimentent aussi le Journal de sécurité s'exécutent sur l'appareil ; voir Détection d'injection de prompt et garde-fous. Rien de votre trafic n'est envoyé à un service cloud pour analyse.

Les règles d'expurgation et d'aperçu ci-dessus font que même les données au repos ne contiennent jamais un secret utilisable. Le traçage est un journal d'audit privé, pas un appel maison.

Mode privé et télémétrie d'entreprise

Le seul cas où des données dérivées des traces quittent la machine est un Mac inscrit auprès d'un espace de travail bromure.io. L'inscription transforme le journal d'audit local en un journal visible par l'organisation — et vous donne un interrupteur pour en désengager un espace de travail individuel. Ce que voient les administrateurs, et comment fonctionne l'inscription, est couvert dans Entreprise ; cette section décrit la frontière du côté du traçage.

Le flux d'événements

Sur un Mac inscrit, les sessions diffusent des événements cloud structurés vers l'espace de travail d'administration de l'organisation, extraits du même trafic IA que capture le traçage :

  • llm.request — par échange : fournisseur, hôte, chemin, statut, latence, modèle, nombres de jetons d'entrée/sortie, et les deux compteurs de cache d'Anthropic (cache_creation_input_tokens, cache_read_input_tokens, analysés même à partir des flux SSE ; le cached_tokens d'OpenAI est également pris en charge).
  • tool.use — chaque appel d'outil, avec un résumé de l'entrée plafonné à 240 caractères.
  • file.read / file.write — le chemin extrait et le nom de l'outil.
  • command.run — la commande shell, plafonnée à 500 caractères.
  • credential.token_swap — un par échange sur le fil, aperçus uniquement.
  • prompt_injection.detection — transmis lorsqu'un détecteur se déclenche, portant l'intégralité de l'extrait signalé (plafonné à 20 Ko), contrairement à l'aperçu de 160 caractères du Journal de sécurité local.

Seul le tour d'assistant le plus récent est parcouru, de sorte que l'historique renvoyé n'est jamais compté deux fois, et les prompts bruts ne sont jamais émis — la télémétrie répond à « ce que l'IA a fait », pas à « ce que l'utilisateur a demandé ».

Le tap d'événements en temps réel

Pour les sessions WebSocket de longue durée, attendre la fermeture du socket pour extraire les événements aveuglerait un administrateur pendant toute la session. À la place, un tap d'événements en temps réel surveille les trames du serveur et émet les mêmes événements llm.request / tool.use / file.read / file.write / command.run à chaque response.completed, de sorte qu'une session Realtime en cours rend compte au fil de l'eau (l'extraction au moment de la fermeture est alors ignorée pour éviter le double comptage). Le tap ne s'attache que lorsque le niveau de trace de l'espace de travail capture déjà les corps pour cet hôte — il chevauche le même chemin de capture de corps que tout le reste de ce chapitre, et n'a pas d'interface propre.

Mode privé

Le mode privé est un interrupteur par espace de travail sur le volet Traçage, affiché uniquement sur les Mac inscrits. Lorsqu'il est activé, cet espace de travail cesse de diffuser les métadonnées de session et les événements ci-dessus vers l'espace de travail bromure.io — ni l'indicateur de la barre de titre ni la liste de sessions de l'administrateur n'en voient quoi que ce soit. Le traçage local et l'Inspecteur de traces ne sont pas affectés : vous conservez la trace chiffrée complète sur votre propre machine.

Il existe précisément pour le cas où l'audit local et la télémétrie organisationnelle devraient diverger — par exemple, un espace de travail où vous utilisez une clé API personnelle et ne voulez pas que cette activité figure dans les tableaux de bord de votre organisation. Sur un Mac non inscrit, rien n'est diffusé, donc l'interrupteur est entièrement masqué.

Remarque : le mode privé supprime aussi les événements prompt_injection.detection, de sorte que sur un espace de travail privé une injection est toujours enregistrée localement dans le Journal de sécurité (et appliquée selon votre action de détection) mais n'est pas transmise à votre organisation. Voir Réglages de traçage pour l'interrupteur lui-même et Entreprise pour ce que diffuse l'inscription.