Confrontation Audit -- ulias-org
Date : 15-02-2026 05:00
Status : IMPLEMENTEE
Auditeur senior : Claude Opus 4.6 (confrontation des 3 passes)
Methode : Lecture integrale des 3 rapports d'audit + verification croisee sur le code source pour arbitrer les contradictions
Resume executif
| Metrique |
Nombre |
| Findings CONFIRMES (2-3 passes concordantes) |
17 |
| Findings UNIQUES (1 seule passe) |
13 |
| Faux positifs elimines |
5 |
| Contradictions resolues |
4 |
Les 3 passes convergent fortement sur les problemes majeurs : la logique de briefing inversee, le lifecycle WS defaillant, le pipeline runner sans AbortSignal, le mecanisme onDecision jamais branche, et les fallbacks IP/port hardcodes. Les divergences portent principalement sur les niveaux de severite (ex: CONNECTORS_API_URL fallback classe "FAUX POSITIF" par P1 mais "BUG CERTAIN" par P3) et sur quelques findings de niche identifies par une seule passe.
Findings CONFIRMES (2-3 passes concordantes)
C-01 : Briefing processAnswer -- logique de skip inversee
- Confirme par : Pass 1 (1.1) + Pass 2 (P2-17) + Pass 3 (F-05)
- Severite definitive : BUG CERTAIN
- Description consolidee : La condition
!currentQ.required || !skipWords.includes(answer) fait que les questions required=false enregistrent TOUJOURS la reponse (meme "passer") car le || court-circuite. De plus, Pass 2 apporte un eclairage supplementaire : currentQuestionIndex++ se fait APRES le if, donc pour les questions required=true, la reponse "passer" n'est pas enregistree MAIS la question avance quand meme -- permettant de skipper les questions obligatoires.
- Impact : Double bug : (1) les questions optionnelles ne sont jamais skippables, (2) les questions obligatoires sont skippables sans erreur. Le briefing genere des prompts incomplets ou pollues.
- Priorite de correction : CRITIQUE
C-02 : WS deconnexion -- reference morte et ws.send() sur socket ferme
- Confirme par : Pass 1 (1.3) + Pass 2 (P2-01, P2-02) + Pass 3 (F-03)
- Severite definitive : BUG CERTAIN
- Description consolidee : Les 3 passes identifient le meme probleme sous des angles differents. Pass 1 identifie les chemins de ws.send() sans guard (generateConversationTitle, generateConversationSummary, onEvent). Pass 2 ajoute l'analyse structurelle : le close handler ne peut pas identifier la session associee au WS (pas de ws.data, et l'objet ws change entre handlers -- bug connu Elysia/Bun documente dans MEMORY.md). Pass 3 confirme que session.ws n'est jamais mis a undefined. Les 3 passes convergent : apres deconnexion, les fire-and-forget continuent a envoyer sur un WS mort pendant potentiellement 10 minutes (timeout agent).
- Impact : Exceptions silencieuses sur ws.send(), jobs LLM inutiles, logs pollues. Pas de data loss grace aux catch, mais gaspillage de ressources GPU.
- Priorite de correction : HAUTE
C-03 : Pipeline runner ne passe pas l'AbortSignal
- Confirme par : Pass 2 (P2-16) + verification directe du code source
- Severite definitive : BUG CERTAIN
- Description consolidee :
Director.handleMessage() cree un AbortController (L273) et le passe a handleSingleStep() et handleMultiStep(), mais quand un pipeline est utilise (L281), pipelineRunner.runSequential() est appele SANS signal. Le code de PipelineRunner.runSequential() (L181) appelle runner.run(agentConfig, task, onEvent) sans le 4eme argument (signal). Verifie sur le code source : runSequential n'a meme pas de parametre signal dans sa signature (L123-131).
- Impact : Le cancel d'un objectif pipeline (create_frontend, create_fullstack, verification_chain) est completement inefficace. L'agent continue jusqu'a completion naturelle ou timeout 10 min.
- Priorite de correction : HAUTE
C-04 : onDecision callback jamais branche -- agents requiresApproval casses
- Confirme par : Pass 2 (P2-11, P2-20) -- verifie sur le code source
- Severite definitive : BUG CERTAIN
- Description consolidee :
Director.handleSingleStep() appelle runner.run(agentConfig, task, onEvent, undefined, signal) -- le 4eme argument (onDecision) est toujours undefined. Le code de requestDecision() (agent-runner L371-374) auto-deny si !onDecision. De plus, pendingDecisions Map (index.ts L143) n'est jamais alimentee (set() non appele). Resultat : les agents deployer, incident, infra, patcher, strategist, gitlab-dev ne peuvent JAMAIS executer les outils marques requiresApproval (dockerRestart, gitPush, exec pour patcher, gitlabCreateProject, gitlabTriggerPipeline).
- Impact : 6 agents sont fonctionnellement casses pour leurs operations critiques. Le patcher ne peut executer AUCUN de ses outils.
- Priorite de correction : CRITIQUE
C-05 : CALLBACK_BASE_URL hardcode sans env var definie
- Confirme par : Pass 1 (2.1) + Pass 2 (P2-23) + Pass 3 (F-02)
- Severite definitive : BUG PROBABLE
- Description consolidee :
CALLBACK_BASE = process.env.CALLBACK_BASE_URL || 'http://192.168.1.12:5515'. L'env var n'est definie ni dans conf.prod.gouroubleu.yml ni dans .env.deploy. Le fallback hardcode fonctionne en pratique (ai-orchestrator sur win11 peut atteindre prod-portainer sur 192.168.1.12), sinon tout le systeme LLM serait casse. Mais c'est fragile : tout changement d'IP, de port, ou de topologie reseau cassera les callbacks silencieusement.
- Impact : Fonctionne en pratique mais non-resilient. Un changement d'infra casserait les callbacks LLM avec un fallback sur le poll timeout (5 min de latence inutile).
- Priorite de correction : HAUTE
C-06 : CONNECTORS_API_URL fallback port 5400 au lieu de 5403
- Confirme par : Pass 1 (2.2) + Pass 2 (P2-22) + Pass 3 (F-06)
- Severite definitive : BUG PROBABLE (dev uniquement)
- Description consolidee : Le fallback dans index.ts est
http://192.168.1.12:5400 mais connectors-api ecoute sur 5403 (derriere wireguard sidecar). En prod, l'env var est correctement injectee via conf.prod.gouroubleu.yml (http://192.168.1.12:5403), donc le fallback n'est jamais utilise. C'est un piege en dev local uniquement.
- Impact : Zero en production. Erreur de connexion uniquement en dev local sans .env.
- Priorite de correction : BASSE
- Note sur la contradiction : Pass 3 classe ce finding "BUG CERTAIN" tandis que Pass 1 le classe "FAUX POSITIF en prod". L'arbitrage retient "BUG PROBABLE" car le fallback est objectivement faux (mauvais port), mais l'impact est limite au dev local. Ce n'est ni un faux positif (le fallback est factuellement incorrect) ni un bug certain (il ne se manifeste pas en prod).
C-07 : Cache hash trop faible -- troncature 200 chars + DJB2 32-bit
- Confirme par : Pass 1 (2.3) + Pass 2 (P2-06) + Pass 3 (F-21)
- Severite definitive : BUG PROBABLE
- Description consolidee : Les 3 passes identifient le meme probleme : hash DJB2 32-bit sur
model + systemPrompt[:200] + lastUserMessage. Deux agents avec des prompts differant apres les 200 premiers chars et recevant le meme message utilisateur obtiendraient la meme entree cache. Le cache est limite a 50 entrees et 5 min TTL, et ne s'applique qu'a l'iteration 1.
- Impact : Collision improbable en pratique car les 200 premiers chars des prompts sont generalement distinctifs entre agents. Mais le design est fragile.
- Priorite de correction : BASSE
C-08 : Circuit breaker et response cache globaux partages entre sessions
- Confirme par : Pass 1 (10.5, 10.19) + Pass 2 (P2-03) + Pass 3 (F-08)
- Severite definitive : RISQUE THEORIQUE
- Description consolidee :
toolCircuitBreaker et responseCache sont declares au niveau module (singletons). Si un outil echoue 3x pour un utilisateur, le circuit s'ouvre pour TOUS les utilisateurs. Le cache de reponses est partage entre sessions. En mono-utilisateur, c'est un feature. En multi-utilisateur, c'est un defaut d'isolation.
- Impact : Nul en mono-utilisateur. Blocage inter-sessions et fuite d'information potentielle en multi-tenant.
- Priorite de correction : BASSE (mono-utilisateur actuel)
C-09 : Prompt overrides globaux, pas par session/user
- Confirme par : Pass 1 (5.1) + Pass 2 (P2-08) + Pass 3 (F-17)
- Severite definitive : RISQUE THEORIQUE
- Description consolidee :
promptOverrides est un Map global dans registry.ts. Le dernier utilisateur a se connecter ecrase les overrides de tous les autres. Les 3 passes convergent : nul en mono-utilisateur, bombe a retardement en multi-tenant.
- Impact : Nul en mono-utilisateur actuel.
- Priorite de correction : BASSE
C-10 : Pas de validation d'ownership sur les endpoints REST
- Confirme par : Pass 1 (6.3) + Pass 2 (P2-09)
- Severite definitive : RISQUE THEORIQUE
- Description consolidee : DELETE /api/objectives/:id, POST /api/objectives/:id/cancel, DELETE /api/conversations/:id, PATCH messages, GET export, POST fork -- aucun ne verifie que l'objet appartient au user authentifie. L'authentification est verifiee mais pas l'ownership. Vulnerability IDOR en multi-tenant.
- Impact : Nul en mono-utilisateur. Critique en multi-tenant.
- Priorite de correction : BASSE (mono-utilisateur actuel)
C-11 : Injection commande SSH via les agents LLM
- Confirme par : Pass 1 (3.3) + Pass 2 (P2-10) + Pass 3 (F-20)
- Severite definitive : RISQUE THEORIQUE
- Description consolidee : Les commandes SSH sont passees telles quelles depuis le LLM. Pass 1 et Pass 3 identifient le risque specifique du heredoc
ULIAS_EOF dans writeFile (si le contenu contient ce pattern, le heredoc se ferme prematurement). Pass 2 ajoute le vecteur d'injection via $() et backticks dans le contenu. Le seul chemin est via les agents LLM, qui sont declenches par des messages authentifies. C'est de l'execution de commande "by design" pour un utilisateur qui est proprietaire des machines.
- Impact : En mono-utilisateur, l'utilisateur execute ses propres commandes. Le risque ULIAS_EOF est reel mais improbable en pratique.
- Priorite de correction : BASSE
C-12 : Traduction automatique systematique gaspille latence et tokens
- Confirme par : Pass 1 (5.3) + Pass 2 (P2-07) + Pass 3 (F-18)
- Severite definitive : BUG PROBABLE
- Description consolidee :
translateOutput() appele pour CHAQUE reponse agent, meme si deja en francais. Ajoute ~2-10s de latence et un job GPU supplementaire par requete. Pass 2 ajoute le risque de corruption de donnees techniques (JSON, IPs, UUIDs, code). Les 3 passes convergent que c'est un choix delibere mais sous-optimal.
- Impact : Double latence systematique. Risque de corruption de donnees techniques. Consommation GPU inutile.
- Priorite de correction : MOYENNE
C-13 : API key stockee en clair dans Supabase
- Confirme par : Pass 1 (6.2) + Pass 2 (P2-14) + Pass 3 (F-13)
- Severite definitive : RISQUE THEORIQUE
- Description consolidee : L'API key connectors-api est stockee en clair dans
ceo_profile.preferences.connector_api_key. Les 3 passes convergent : en mono-utilisateur self-hosted, le risque est faible. En multi-tenant ou si Supabase est compromis, toutes les API keys sont exposees.
- Impact : Faible en contexte actuel. Critique si le service evolue vers du multi-tenant.
- Priorite de correction : BASSE
C-14 : editFile ne remplace que la premiere occurrence
- Confirme par : Pass 1 (10.8) + Pass 2 (P2-15) + Pass 3 (F-07)
- Severite definitive : RISQUE THEORIQUE
- Description consolidee :
content.replace(oldString, newString) ne remplace que la premiere occurrence. Les 3 passes notent que c'est probablement intentionnel (meme comportement que Claude Code pour eviter les effets de bord), mais non documente dans la tool description. L'agent LLM ne sait pas qu'il doit faire plusieurs appels si le pattern apparait plusieurs fois.
- Impact : Edits partiels potentiels si le LLM ne sait pas. Faible car le comportement est standard.
- Priorite de correction : BASSE (documenter dans la description du tool)
C-15 : message_count increment non-atomique (read-modify-write)
- Confirme par : Pass 1 (2.4) + Pass 2 (P2-21)
- Severite definitive : BUG PROBABLE
- Description consolidee : Pattern classique read-then-write sans transaction. En cas de messages concurrents, le compteur peut etre incorrect, affectant l'auto-title et l'auto-summary.
- Impact : Tres faible en mono-utilisateur (un seul message a la fois en pratique). Le message_count ne sert qu'a declencher auto-title (a 0) et auto-summary (tous les 10).
- Priorite de correction : BASSE
C-16 : GITLAB_TOKEN en clair dans les fichiers versionnes
- Confirme par : Pass 1 (3.2, 10.16) + Pass 3 (implicitement via F-06/.env.deploy)
- Severite definitive : RISQUE THEORIQUE
- Description consolidee : Le token GitLab personnel
glpat-yaowLwWBJhXfzJEC8UBC est en clair dans conf.prod.gouroubleu.yml et .env.deploy, les deux versionnes dans le repo GitLab. Ce token est deja dans CLAUDE.md et utilise partout dans l'infra.
- Impact : En contexte prive (GitLab self-hosted, single user), le risque est la propagation accidentelle si le repo est rendu public. Bonne pratique serait Docker secrets.
- Priorite de correction : BASSE
C-17 : Endpoints /internal/* et /api/agents sans authentification + nginx non private
- Confirme par : Pass 1 (3.1, 6.1, 10.18) + Pass 3 (F-09)
- Severite definitive : BUG CERTAIN
- Description consolidee : Le endpoint
/api/agents lit le header x-api-key mais ne le verifie JAMAIS. N'importe qui peut GET /api/agents et obtenir tous les prompts systeme (contenant des IPs internes, noms de machines, ports). Les endpoints /internal/job-callback et /internal/pending-jobs ne verifient aucune auth. Combine avec le fait que conf.prod.gouroubleu.yml ne contient PAS private: true dans la section nginx (verifie sur le fichier source), le service est accessible publiquement sur Internet via ulias-org.33800.nowhere84.com. C'est la combinaison de ces findings qui eleve la severite.
- Impact : Information disclosure (IPs internes, architecture, prompts complets des 24 agents) a toute personne connaissant ou decouvrant le domaine.
- Priorite de correction : CRITIQUE
Findings UNIQUES (1 seule passe)
U-01 : CLI default server URL pointe vers le mauvais port (5510 au lieu de 5515)
- Source : Pass 1 (1.2)
- Severite : BUG CERTAIN
- Pourquoi les autres passes ne l'ont pas trouve : Pass 2 et Pass 3 se concentraient sur le code serveur. Le fichier CLI (
packages/cli/bin/ulias.ts) est un package separe que les passes 2 et 3 n'ont pas couvert.
- Verdict : CONFIRME -- le port 5510 est factuellement celui de claude-memory, pas d'ulias-org. Le mode par defaut du CLI est casse.
U-02 : NotificationService definie mais jamais importee
- Source : Pass 1 (2.5), mentionne par Pass 2 (P2-24) comme FAUX POSITIF
- Severite : CODE MORT
- Pourquoi les autres passes ne l'ont pas trouve : Pass 2 le mentionne mais le classe "faux positif" car c'est du code preparatoire. Pass 3 ne le mentionne pas.
- Verdict : CODE MORT -- c'est du code mort factuel (jamais importe, jamais appele). Pas un bug fonctionnel mais un indicateur d'architecture inachevee. Pas un faux positif non plus : le code existe et n'est pas utilise, c'est un fait.
U-03 : git-workflow.ts -- status '??' teste deux fois, 'untracked' jamais assigne
- Source : Pass 1 (10.3)
- Severite : BUG CERTAIN
- Pourquoi les autres passes ne l'ont pas trouve : Le fichier git-workflow.ts est du code mort (non importe -- Pass 1 10.4 le documente). Les passes 2 et 3 se sont concentrees sur le code actif.
- Verdict : CONFIRME mais BASSE priorite -- le bug est reel (logique morte, '??' classe comme 'added' au lieu de 'untracked'), mais le fichier entier est du code mort. Le fix serait utile si le module est integre dans le futur.
U-04 : Upload base64 decode en UTF-8 corrompt les binaires
- Source : Pass 1 (10.21)
- Severite : BUG CERTAIN
- Pourquoi les autres passes ne l'ont pas trouve : Le endpoint
/api/upload est un endpoint secondaire, pas sur le chemin principal du message flow. Les passes 2 et 3 se concentraient sur les flux principaux (WS, agents, sessions).
- Verdict : CONFIRME --
Buffer.from(content, 'base64').toString('utf-8') corrompt effectivement les donnees binaires. Tout upload non-texte (images, PDF) est corrompu. Le chemin est rarement utilise mais le bug est reel.
U-05 : storageGetPublicUrl avec IP hardcodee en fallback
- Source : Pass 1 (10.7)
- Severite : BUG PROBABLE (chemin quasi-mort)
- Pourquoi les autres passes ne l'ont pas trouve : La fonction est dans un chemin de code rarement utilise (storage tools non assignes a un agent actif, voir Pass 1 10.6).
- Verdict : CONFIRME mais BASSE priorite -- IP hardcodee dans un chemin de code quasi-mort.
U-06 : compactToolResult et translateOutput -- num_ctx passe dans les options est ignore
- Source : Pass 1 (7.1, 10.10)
- Severite : BUG PROBABLE
- Pourquoi les autres passes ne l'ont pas trouve : Necessite une analyse detaillee de l'interface LLMOptions et de la methode llmChat pour comprendre que le champ
num_ctx est silencieusement ignore. Les passes 2 et 3 ont vu le num_ctx mais n'ont pas verifie s'il etait effectivement utilise.
- Verdict : CONFIRME -- le num_ctx passe dans les options LLM est ignore. La valeur est toujours 16384 (hardcode dans llmChat). Ce n'est pas grave fonctionnellement (16384 suffit), mais le code est trompeur.
U-07 : consecutiveErrors semantique incorrecte en executions paralleles
- Source : Pass 1 (10.11)
- Severite : BUG PROBABLE (impact faible)
- Pourquoi les autres passes ne l'ont pas trouve : Necessite une analyse fine des interactions entre
Promise.all et la variable partagee consecutiveErrors. Les passes 2 et 3 ont identifie la concurrence des messages mais pas ce point specifique dans la boucle agent.
- Verdict : CONFIRME -- la semantique de "consecutive" n'a pas de sens en execution parallele. L'impact est faible car c'est un garde-fou secondaire.
U-08 : userId fallback fragile (apiKey[:8])
- Source : Pass 1 (10.20)
- Severite : BUG PROBABLE
- Pourquoi les autres passes ne l'ont pas trouve : Detail d'implementation dans auth.ts que les passes 2 et 3 n'ont pas examine en profondeur a cet endroit precis.
- Verdict : CONFIRME -- le fallback est fragile (collision possible sur les 8 premiers chars). En pratique, connectors-api renvoie toujours un user_id, donc le fallback n'est quasi jamais utilise.
U-09 : forkConversation charge 10000 messages en memoire + inserts sequentiels
- Source : Pass 1 (10.14, 10.15)
- Severite : PROBLEME ARCHITECTURAL
- Pourquoi les autres passes ne l'ont pas trouve : Detail d'implementation dans db/index.ts que les passes orientees "architecture" et "integration" n'ont pas priorise.
- Verdict : CONFIRME -- probleme de performance reel pour les longues conversations. Optimisation possible via batch insert ou RPC PostgreSQL.
U-10 : Incoherence instance parameter (id vs name) dans connectorFetch
- Source : Pass 3 (F-01)
- Severite : BUG PROBABLE
- Pourquoi les autres passes ne l'ont pas trouve : Pass 3 avait un angle specifique "integration inter-services" qui a permis de comparer systematiquement les appels connectorFetch. Les passes 1 et 2 examinaient les appels individuellement sans comparer la convention.
- Verdict : CONFIRME -- l'incoherence est factuelle : Supabase/ntfy/loki utilisent
.id, AI-orchestrator/GitLab/mailjet utilisent .name. Si connectors-api accepte les deux, ca fonctionne. Mais c'est un contrat fragile.
U-11 : auth.ts hardcode le nom 'Supabase' vs client.ts utilise .id dynamique
- Source : Pass 3 (F-16)
- Severite : BUG PROBABLE
- Pourquoi les autres passes ne l'ont pas trouve : Similaire a U-10, necessite une comparaison entre auth.ts et client.ts que les passes 1 et 2 n'ont pas faite explicitement.
- Verdict : CONFIRME --
auth.ts hardcode instance: 'Supabase' (string literal) tandis que client.ts utilise sbInstance.id (dynamique). Si l'instance est renommee, l'auth se cassera silencieusement.
U-12 : dbInsert/dbUpdate retour undefined non gere
- Source : Pass 3 (F-14)
- Severite : BUG PROBABLE
- Pourquoi les autres passes ne l'ont pas trouve : Detail d'implementation dans db/index.ts que les passes 1 et 2 n'ont pas examine sous cet angle (retour silencieux).
- Verdict : CONFIRME -- si Supabase ne retourne pas d'ID (GRANT manquant, erreur PostgREST), les operations en aval echouent silencieusement avec des IDs undefined.
U-13 : Nudge agent injecte un message 'user' qui fausse l'historique
- Source : Pass 3 (F-11)
- Severite : RISQUE THEORIQUE
- Pourquoi les autres passes ne l'ont pas trouve : Detail subtil dans la boucle ReAct du runner. Les passes 1 et 2 ont decrit la boucle sans examiner ce comportement de nudge specifique.
- Verdict : A VERIFIER -- le risque est theoriquement valide (le LLM peut interpreter le nudge comme une instruction utilisateur), mais le nudge ne se produit que sur les reponses vides ce qui est un cas marginal. Impact faible.
Contradictions resolues
Contradiction 1 : Severite de CONNECTORS_API_URL fallback port 5400
- Pass 1 : Classe "FAUX POSITIF en prod" (4.2) + "BUG PROBABLE en dev" (2.2)
- Pass 2 : Classe "FAUX POSITIF en contexte" (P2-22)
- Pass 3 : Classe "BUG CERTAIN" (F-06)
- Resolution : Pass 3 a tort de classifier "BUG CERTAIN" car en production l'env var est correctement injectee et le fallback n'est jamais utilise. Cependant, Pass 1 a raison de noter que le fallback est factuellement incorrect -- ce n'est donc pas un "faux positif" pur. Le verdict est BUG PROBABLE : le code est faux (port 5400 au lieu de 5403) mais l'impact est limite au dev local.
Contradiction 2 : NotificationService -- code mort ou code preparatoire ?
- Pass 1 : Classe "BUG PROBABLE" (2.5) -- code mort, architecture inachevee
- Pass 2 : Classe "FAUX POSITIF" (P2-24) -- design intent, pas du dead code problematique
- Resolution : Pass 2 a une meilleure nuance. C'est objectivement du code non-utilise, mais le classifier "BUG PROBABLE" est excessif. Le verdict est CODE MORT -- ni un bug ni un faux positif. C'est une opportunite de nettoyage ou d'integration.
Contradiction 3 : nginx private: true -- est-ce le cas ou non ?
- Pass 1 : Affirme "conf.prod.gouroubleu.yml ne specifie pas private: true" (10.18) -- le service est PUBLIC
- Pass 3 : Affirme dans F-19 "Le service est marque private: true dans nginx" -- le service est PRIVE
- Resolution : Verification directe du fichier conf.prod.gouroubleu.yml : la section nginx contient
enabled: true, domain, ssl: true, websocket: true. Il n'y a PAS de private: true. Pass 1 a raison, Pass 3 a tort. Le service est accessible publiquement. Cela eleve la severite du finding sur les endpoints sans auth (C-17).
Contradiction 4 : Pas de protection contre messages concurrents -- BUG ou RISQUE ?
- Pass 2 : Classe "BUG PROBABLE" (P2-12) -- race condition reelle
- Pass 3 : Classe "BUG PROBABLE" (F-10) -- empilement d'agents possible
- Pass 1 : Ne le mentionne pas directement (sauf message_count en 2.4)
- Resolution : Les passes 2 et 3 ont raison. En l'absence de semaphore par session, un utilisateur peut lancer plusieurs agents en parallele en spammant des messages. C'est un BUG PROBABLE en mono-utilisateur (l'utilisateur peut accidentellement lancer des agents en parallele) et un probleme plus grave en multi-utilisateur.
Faux positifs elimines
FP-01 : HTTP status codes manquants sur les endpoints REST
- Source : Pass 1 (4.1)
- Justification : Choix architectural delibere. Le frontend et le CLI verifient le champ
error dans le JSON, pas le status HTTP. Ce n'est pas un bug -- c'est un pattern courant pour les APIs internes. Les 3 passes convergent implicitement sur ce point.
FP-02 : toolCallsCount non-thread-safe dans Promise.all
- Source : Pass 1 (10.9)
- Justification : JavaScript single-thread garantit l'atomicite de
++. Il n'y a pas de preemption entre les callbacks de Promise.all. Chaque callback s'execute atomiquement entre les await. Pass 1 l'avait deja correctement identifie comme faux positif.
FP-03 : Agents avec toolSet vide
- Source : Pass 2 (P2-19)
- Justification : Pass 2 l'avait deja correctement identifie comme faux positif. L'agent
simplifier a un toolSet vide [] intentionnellement (text processing pur). Le code gere correctement ce cas (config.tools.length > 0 ? config.tools : undefined).
FP-04 : Rate limiting manquant (reclassifie)
- Source : Pass 3 (F-19)
- Justification : Pass 3 dit "Le service est marque private: true dans nginx, ce qui limite l'exposition" -- mais cette affirmation est FAUSSE (voir Contradiction 3). Neanmoins, l'absence de rate limiting n'est pas un "bug" -- c'est une amelioration de securite. En contexte mono-utilisateur, le rate limiting n'est pas critique. Reclassifie de BUG en RISQUE THEORIQUE, mais note que l'absence de nginx private eleve le risque reel.
FP-05 : Pending jobs memory leak (reclassifie)
- Source : Pass 3 (F-04)
- Justification : Chaque pending job a un
setTimeout qui nettoie l'entree apres le timeout. Pass 2 (P2-05) note correctement que c'est un "RISQUE THEORIQUE, pas un leak". Si le process crash, toute la memoire est liberee de toute facon. Si un agent est annule via AbortSignal, le pending job reste en memoire jusqu'au timeout (5 min max), puis est nettoye. Ce n'est pas un leak indefini. Reclassifie de BUG PROBABLE en RISQUE THEORIQUE.
Top 10 actions prioritaires
| Rang |
Finding |
Severite |
Correction |
| 1 |
C-17 : Ajouter private: true dans nginx OU ajouter auth sur /api/agents et /internal/* |
BUG CERTAIN |
Modifier conf.prod.gouroubleu.yml section nginx, ajouter private: true. Alternative : ajouter verification x-api-key sur /api/agents et un token partage sur /internal/*. |
| 2 |
C-04 : Brancher le mecanisme onDecision |
BUG CERTAIN |
Passer le callback onDecision depuis Director vers runner.run(). Implementer le flow decision_request/decision_response via WS et pendingDecisions Map. |
| 3 |
C-01 : Corriger la logique de skip du briefing |
BUG CERTAIN |
Reformuler la condition : const isSkip = skipWords.includes(answer); if (isSkip && !currentQ.required) { /* ne pas enregistrer, avancer */ } else if (isSkip && currentQ.required) { /* refuser de skipper, redemander */ } else { session.answers.set(currentQ.id, answer); } |
| 4 |
C-02 : Corriger le lifecycle WS (close handler + guard ws.send) |
BUG CERTAIN |
Stocker l'apiKey dans ws.data lors de l'auth. Dans close handler, retrouver la session et mettre session.ws = undefined. Ajouter if (ws.readyState === 1) avant chaque ws.send(). |
| 5 |
C-03 : Passer l'AbortSignal au pipeline runner |
BUG CERTAIN |
Ajouter signal?: AbortSignal a la signature de runSequential/runParallel. Propager aux appels runner.run(). |
| 6 |
C-05 : Ajouter CALLBACK_BASE_URL dans conf.prod.gouroubleu.yml |
BUG PROBABLE |
Ajouter CALLBACK_BASE_URL: "http://192.168.1.12:5515" dans la section env de conf.prod.gouroubleu.yml. |
| 7 |
U-04 : Corriger l'upload binaire (decode base64 sans conversion UTF-8) |
BUG CERTAIN |
Envoyer le Buffer directement au lieu de .toString('utf-8'). Adapter storageUpload pour accepter un Buffer. |
| 8 |
U-01 : Corriger le port CLI par defaut (5510 -> 5515) |
BUG CERTAIN |
Modifier packages/cli/bin/ulias.ts : changer ws://localhost:5510/ws/cli en ws://localhost:5515/ws/cli. |
| 9 |
C-12 : Optimiser la traduction (heuristique avant appel LLM) |
BUG PROBABLE |
Ajouter une detection de langue simple (proportion de mots francais) avant d'appeler translateOutput. Exclure les outputs contenant du JSON/code. |
| 10 |
C-16 : Deplacer GITLAB_TOKEN vers Docker secrets |
RISQUE THEORIQUE |
Remplacer le token en clair par une reference a un secret Docker dans conf.prod.gouroubleu.yml. Supprimer le token de .env.deploy. |
Annexe : Matrice de correspondance complete entre passes
| Sujet |
Pass 1 |
Pass 2 |
Pass 3 |
Verdict final |
| Briefing skip logic |
1.1 BUG CERTAIN |
P2-17 BUG PROBABLE |
F-05 BUG CERTAIN |
C-01 BUG CERTAIN |
| CLI port 5510 |
1.2 BUG CERTAIN |
-- |
-- |
U-01 BUG CERTAIN |
| WS send apres deconnexion |
1.3 BUG CERTAIN |
P2-01/02 BUG CERTAIN |
F-03 BUG CERTAIN |
C-02 BUG CERTAIN |
| CALLBACK_BASE_URL hardcode |
2.1 BUG PROBABLE |
P2-23 RISQUE |
F-02 BUG PROBABLE |
C-05 BUG PROBABLE |
| CONNECTORS_API_URL fallback |
2.2 BUG PROBABLE |
P2-22 FAUX POSITIF |
F-06 BUG CERTAIN |
C-06 BUG PROBABLE |
| Cache hash faible |
2.3 BUG PROBABLE |
P2-06 BUG PROBABLE |
F-21 RISQUE |
C-07 BUG PROBABLE |
| message_count non-atomique |
2.4 BUG PROBABLE |
P2-21 RISQUE |
-- |
C-15 BUG PROBABLE |
| NotificationService inutilisee |
2.5 BUG PROBABLE |
P2-24 FAUX POSITIF |
-- |
FP/CODE MORT |
| /api/agents sans auth |
3.1 RISQUE |
-- |
F-09 RISQUE |
C-17 BUG CERTAIN (combine avec nginx non-private) |
| GITLAB_TOKEN en clair |
3.2 RISQUE |
-- |
-- |
C-16 RISQUE THEORIQUE |
| Injection heredoc |
3.3 RISQUE |
P2-10 RISQUE |
F-20 BUG PROBABLE |
C-11 RISQUE THEORIQUE |
| Limite taille WS |
3.4 RISQUE |
-- |
-- |
Non retenu (faible, mono-user) |
| Prompt overrides globaux |
5.1 ARCHI |
P2-08 BUG PROBABLE |
F-17 RISQUE |
C-09 RISQUE THEORIQUE |
| Session cleanup sans ws.close |
5.2 ARCHI |
P2-01 BUG PROBABLE |
F-15 BUG PROBABLE |
Couvert par C-02 |
| Traduction systematique |
5.3 ARCHI |
P2-07 BUG PROBABLE |
F-18 RISQUE |
C-12 BUG PROBABLE |
| fetchRelevantLessons latence |
5.4 ARCHI |
-- |
-- |
Non retenu (choix design) |
| Ownership REST |
6.3 RISQUE |
P2-09 RISQUE |
-- |
C-10 RISQUE THEORIQUE |
| API key en clair |
6.2 RISQUE |
P2-14 RISQUE |
F-13 RISQUE |
C-13 RISQUE THEORIQUE |
| git-workflow '??' |
10.3 BUG CERTAIN |
-- |
-- |
U-03 BUG CERTAIN (code mort) |
| git-workflow code mort |
10.4 CODE MORT |
-- |
-- |
U-03 (meme) |
| Circuit breaker global |
10.5 RISQUE |
P2-03 BUG PROBABLE |
F-08 RISQUE |
C-08 RISQUE THEORIQUE |
| TOOL_SETS storage-dev mort |
10.6 CODE MORT |
-- |
-- |
CODE MORT |
| storageGetPublicUrl IP |
10.7 BUG PROBABLE |
-- |
-- |
U-05 BUG PROBABLE |
| editFile premiere occurrence |
10.8 QUALITE |
P2-15 RISQUE |
F-07 BUG PROBABLE |
C-14 RISQUE THEORIQUE |
| consecutiveErrors parallele |
10.11 BUG PROBABLE |
-- |
-- |
U-07 BUG PROBABLE |
| Upload binaire corrompu |
10.21 BUG CERTAIN |
-- |
-- |
U-04 BUG CERTAIN |
| nginx non private |
10.18 RISQUE |
-- |
(F-19 dit private=true, FAUX) |
C-17 BUG CERTAIN |
| onDecision jamais branche |
-- |
P2-11 BUG CERTAIN |
-- |
C-04 BUG CERTAIN |
| Pipeline sans AbortSignal |
-- |
P2-16 BUG CERTAIN |
-- |
C-03 BUG CERTAIN |
| Messages concurrents |
-- |
P2-12 BUG PROBABLE |
F-10 BUG PROBABLE |
BUG PROBABLE (couvert par C-02/C-04 en partie) |
| Context overflow runner |
-- |
P2-13 RISQUE |
-- |
Non retenu (num_ctx est le garde-fou) |
| Cancel n'annule pas GPU jobs |
-- |
P2-04 RISQUE |
-- |
Non retenu (design choice) |
| Incoherence id vs name |
-- |
-- |
F-01 BUG PROBABLE |
U-10 BUG PROBABLE |
| auth.ts hardcode 'Supabase' |
-- |
-- |
F-16 BUG CERTAIN |
U-11 BUG PROBABLE |
| dbInsert retour undefined |
-- |
-- |
F-14 BUG PROBABLE |
U-12 BUG PROBABLE |
| Nudge injecte comme 'user' |
-- |
-- |
F-11 RISQUE |
U-13 RISQUE THEORIQUE |
| searchConversations ilike |
10.13 RISQUE |
P2-18 RISQUE |
F-12 BUG PROBABLE |
RISQUE THEORIQUE (PostgREST parametrise) |
| num_ctx ignore |
7.1/10.10 QUALITE |
-- |
-- |
U-06 BUG PROBABLE |
| userId fallback fragile |
10.20 BUG PROBABLE |
-- |
-- |
U-08 BUG PROBABLE |
| HTTP status codes |
4.1 FAUX POSITIF |
-- |
-- |
FP-01 |
| toolCallsCount thread-safe |
10.9 FAUX POSITIF |
-- |
-- |
FP-02 |
| Agents toolSet vide |
-- |
P2-19 FAUX POSITIF |
-- |
FP-03 |
Confrontation realisee le 15-02-2026 par lecture integrale des 3 rapports d'audit (Pass 1 : 1079 lignes, Pass 2 : 594 lignes, Pass 3 : 443 lignes) avec verification croisee sur le code source pour les contradictions identifiees. Total : 17 findings confirmes, 13 uniques, 5 faux positifs elimines, 4 contradictions resolues.