33800 Docs

← Retour

Proposition - Ajouter audit logs pour les appels internes proxyFetch

Date : 02/02/2026 Projet : connectors-api Statut : En attente de validation


Probleme

Les instances AI (ai-orchestrator, web-search, web-scraper, yolo) n'ont aucun log dans l'onglet Logs de l'instance.

Cause : L'audit log fetch.execute est uniquement dans le handler HTTP POST /api/fetch (index.ts:245). Les services internes (ai.ts, intentExecutor.ts) appellent proxyFetch.execute() directement, contournant le handler HTTP et donc l'audit.

Frontend (chat) → intentExecutor → proxyFetch.execute() → API externe
                                    ↑ pas d'audit log ici

Requete directe → POST /api/fetch → proxyFetch.execute() → API externe
                   ↑ audit log ici (index.ts:245)

Modifications (Option 2 : audit chirurgical)

1. src/services/audit.ts — Ajouter les types manquants

// AuditAction : ajouter
| 'ai.submit_job'
| 'ai.job_complete'
| 'yolo.detect'

// AuditResource : ajouter (si pas deja fait)
| 'ai'    // deja present via ai.suggest_command

'ai' est deja utilise comme resource par ai.suggest_command (ai.ts:250), donc pas de modif pour AuditResource.

2. src/services/ai.ts — Audit dans submitJob()

Apres proxyFetch.execute() reussit (ligne 57-63), ajouter un log ai.submit_job :

// Apres ligne 63: const jobId = res.data?.job_id || res.data?.id;
audit.log({
  userId: userId || undefined,
  action: 'ai.submit_job',
  resource: 'ai',
  resourceId: jobId,
  details: {
    instance: fetchReq.instance,
    tool_id: jobData.tool_id,
    job_type: jobData.job_type,
  }
});

Note : Ne PAS loguer dans pollJobResult() — c'est du polling repetitif (potentiellement 45 appels GET par job), ca spammerait les logs.

3. src/services/intentExecutor.ts — Audit dans executeFetchIntent()

Ajouter import { audit } from './audit'; en haut du fichier.

Dans doFetch() (ligne 102-111), apres un fetch reussi, ajouter un log fetch.execute :

const doFetch = async (path: string, body?: Record<string, any>) => {
  const fetchReq: any = { connector, method: endpoint.method, path };
  if (intent.instanceName) fetchReq.instance = intent.instanceName;
  if (body) fetchReq.body = body;
  const result = await proxyFetch.execute(fetchReq, userId);
  if (!result.success) {
    return { success: false, error: `API error: ${result.status} - ${result.error || 'failed'}` };
  }

  // Audit log pour appels internes (chat)
  audit.log({
    userId,
    action: 'fetch.execute',
    resource: 'fetch',
    resourceId: `${endpoint.method} ${path}`,
    details: {
      connector,
      instance: intent.instanceName,
      method: endpoint.method,
      path,
      success: true,
      source: 'chat'
    }
  });

  return { success: true, data: result.data };
};

4. src/services/intentExecutor.ts — Audit dans executeYoloIntent()

Apres la detection YOLO reussie (ligne 255-259), ajouter un log yolo.detect :

const result = await yoloResponse.json();

// Audit log pour detection YOLO
audit.log({
  userId,
  action: 'yolo.detect',
  resource: 'fetch',
  resourceId: imageUrl || 'attachment',
  details: {
    instance: intent.instanceName || 'yolo',
    connector: 'yolo',
    detections: result.count || result.detections?.length || 0,
    source: 'chat'
  }
});

return { success: true, data: result, ... };

Fichiers modifies (3)

Fichier Modification
src/services/audit.ts +3 action types
src/services/ai.ts +8 lignes dans submitJob()
src/services/intentExecutor.ts +1 import, +10 lignes dans doFetch(), +10 lignes dans executeYoloIntent()

Ce que ca resout

Instance Avant Apres
ai-orchestrator 0 logs ai.submit_job a chaque job soumis
web-search 0 logs fetch.execute a chaque recherche via chat
web-scraper 0 logs fetch.execute a chaque scrape via chat
yolo 0 logs yolo.detect a chaque detection
jellyfin (via chat) 0 logs fetch.execute a chaque recherche media via chat

Le champ details.instance est present dans tous les logs, donc le filtre frontend existant (log.details?.instance === instance.value.name) les affichera automatiquement.

Le champ details.source: 'chat' permet de distinguer les appels venant du chat des appels directs via /api/fetch.


Ce qu'on ne logue PAS (volontairement)


Verification

  1. Ouvrir le chat AI et poser une question web-search → verifier le log fetch.execute dans l'instance web-search
  2. Demander une detection YOLO → verifier le log yolo.detect dans l'instance yolo
  3. Demander une suggestion de commande SSH (declenche ai-orchestrator) → verifier le log ai.submit_job
  4. Verifier dans Loki/Grafana que les logs JSON sont bien emis