Revue des correctifs d'audit — TERMINÉE
Date : 15/02/2026
Methode : Revue un par un avec validation utilisateur avant chaque action
Rapport source : ~/propositions/15-02-2026-10-10-audit-rapport-final-verifie.md
Progression
- [x] connectors-api (22/22 valides)
- [x] ai-orchestrator (33/33 valides)
- [x] ulias-org (30/30 valides)
- [x] ulias-org-web (25/25 valides)
- [x] dashboard (36/36 valides)
Total : 146/146 findings revus et valides
Implémentation des correctifs — Progression
Migration DNS Pi-hole — TERMINÉE
- 8 records
*.internal.nowhere84.com ajoutés dans /mnt/stock_8to/33800-stack/docker/stacks/pihole/etc-dnsmasq.d/02-local-domains.conf
misc.etc_dnsmasq_d activé à true dans pihole.toml (était false → dnsmasq.d jamais chargé !)
01-pihole-local.conf renommé en .bak (legacy v5, conflit avec FTL v6)
- Découverte : le split-DNS wildcard
*.33800.nowhere84.com ne marchait PAS avant — seuls les 18 records individuels pihole.toml fonctionnaient. Maintenant wildcard + .local + .internal fonctionnent
- Tous les tests OK (8 records internal + wildcard + .local + résolution système Python)
connectors-api — TERMINÉ (20/22 correctifs)
- Commit
010702a — Pipeline #1079 SUCCESS
- Commit
a0f1aa7 — Pipeline #1084 (C-10 + C-17 deferred)
- C-01: HMAC-SHA256 JWT signature verification
- C-02/C-06: Suppression fallbacks hardcodés (Supabase URL + key)
- C-03/C-09: getUserFromRequest supprimé, requireAuth async partout
- C-04: Auth onBeforeHandle global (allowlist routes publiques)
- C-05: Rate limiting login/register (5 req/min/IP)
- C-07: Global error handler (404/422/401/500)
- C-08: Register password minLength 8
- C-11: OAuth state CSRF (nonce stocké + vérifié one-time)
- C-12: Soft-delete instances (deleted_at) + migration SQL appliquée
- C-14: Auth failure logging
- C-19: Pagination instances + all_tags global
- C-20: CORS regex *.nowhere84.com
- C-21: Security headers (nosniff, DENY, HSTS, CSP)
- C-22: Health check dépendances (DB + WireGuard, 503 si degraded)
- C-16/C-17/C-18: Déjà implémentés (API keys hashées, SSH chiffré, timeout configurable)
- C-10: FAIT — Suppression NODE_TLS_REJECT_UNAUTHORIZED=0 (bypass ciblé déjà dans fetch.ts)
- C-13: N/A — Validation schema → smart-deploy
- C-15: N/A — JWT stateless, pas de sessions en mémoire
- Tests POST-DEPLOY : health OK, auth OK, headers OK
ai-orchestrator — TERMINÉ (33/33 correctifs)
- Commit
50b6e0d — Pipeline #1080 SUCCESS (552s)
- Commit
2f8786c — Pipeline #1083 (U-10 + C-17 deferred)
- C-01: Anthropic semaphore (max 5 concurrent) + active_anthropic_tasks tracking
- C-02: Budget TOCTOU reservation (reserve before API call, release after)
- C-03: Credentials env vars (REDIS_HOST/PASSWORD, POSTGRES_HOST/USER/PASSWORD, no fallback)
- C-05: CORS restrict to *.nowhere84.com
- C-06: Local GPU cost tracking (watts × duration × kWh price)
- C-07: Dynamic concurrent limits via GPU_CONFIG (already implemented)
- C-08: httpx retry on batch polling connection errors (max 5 retries)
- C-09: SadTalker process cleanup (kill+wait in finally)
- C-10: Job claim pattern (LMOVE Redis to processing list, confirm after DB)
- C-11: queue_sync at startup (resync Redis from DB pending jobs)
- C-12: Retry counter MAX_RETRIES=3, requeue_with_retry helper
- C-13: SSH proc.kill on timeout + subprocess_exec (no shell)
- C-14: Watchdog N/A handling (skip, continue)
- C-15: 13 bare except → except Exception
- C-16: Upload size limit MAX_UPLOAD_SIZE_MB (streaming chunks)
- C-17: Auth middleware ACTIVÉ (API_KEY uncommented + 4 clients mis à jour: connectors-api, needfinder, qwik-interface-generator, ulias-org)
- C-18: costs_summary datetime.now() defaults
- C-19: tools_state periodic resync (60s background task)
- C-20: Path traversal realpath + startswith check (5 endpoints)
- C-21: face_swapper_model/enhancer whitelist
- U-01: WIN11_HOST required env var
- U-03: VRAM sum distinct models (not max)
- U-04: Upload unique filenames (timestamp suffix)
- U-05: init.py created
- U-06: StrictHostKeyChecking removed
- U-07: 13 local imports moved to module top
- U-08: Seed limits clamped per tool (ComfyUI 2^32, Fooocus 2^63)
- U-09: SadTalker job_id UUID validation + preprocess whitelist
- U-12: Health crash protection (503 degraded)
- U-13: stop_tool cloud skip
- U-14: Batch JSONL result type verification
- C-22: FAUX POSITIF — confirmé
- U-10: FAIT — Applio _build_applio_params() wrapper avec 60 named arguments
- U-11: schema.sql créé — pas de migrations auto (trop risqué monolithe)
- conf.prod.gouroubleu.yml mis à jour (env vars Redis/Postgres/API_KEY)
- AI_ORCHESTRATOR_API_KEY ajouté dans prod.env
- Tests POST-DEPLOY : health OK, Redis connected, Postgres connected, worker actif
ulias-org — TERMINÉ (31/30 correctifs → 30/30 + C-13 encryption bonus)
- Commit
4328a53 — Pipeline #1081 SUCCESS
- Commit
9cfc758 — Pipeline #1085 (C-04 + C-09 + C-13 deferred)
- C-01: Fix briefing processAnswer logic inversion (required vs optional)
- C-02: WS close handlers clean session.ws (dead socket protection)
- C-03: AbortSignal passé au pipeline runner pour cancellation propre
- C-05: CALLBACK_BASE_URL env var ajouté, fallback hardcodé supprimé
- C-06: CONNECTORS_API_URL fallback supprimé (port 5400 incorrect)
- C-07: DJB2 hash → SHA-256 via Bun.CryptoHasher
- C-08: Cache renommé defaultResponseCache (TODO: per-session injection)
- C-10: IDOR — getObjective/getConversation filtrent par userId
- C-11: Heredoc delimiter aléatoire (crypto.randomUUID)
- C-12: Translation configurable — skip si output déjà en français (4+ marqueurs)
- C-14: editFile option replaceAll ajoutée
- C-15: incrementMessageCount méthode DB (read-increment-write)
- C-16: GITLAB_TOKEN → @GITLAB_TOKEN (référence secrets prod.env)
- C-17: Auth sur /api/agents + UUID validation sur /internal/job-callback
- U-01: CLI port 5510 → 5515
- U-02: Suppression dead code (notifications/index.ts)
- U-03: git-workflow duplicate '??' → 'untracked' avant 'added'
- U-04: Upload base64 sans decode UTF-8 (corruption binaires)
- U-05: storageGetPublicUrl throw si pas d'URL (plus de fallback IP)
- U-06: num_ctx respecte le paramètre LLMOptions (default 16384)
- U-07: Sliding window error tracking (4/6 seuil vs consécutif)
- U-08: userId throw si absent (plus de fallback apiKey[:8])
- U-09: forkConversation batch loading (100 au lieu de 10000)
- U-11: SUPABASE_INSTANCE_NAME constante (remplace hardcoded strings)
- U-12: Vérification retour dbInsert (throw si pas d'ID)
- U-13: Nudge role 'user' → 'system' dans agent-runner
- C-04: FAIT — onDecision callback wiring (WS decision_request/response + 2min timeout)
- C-09: FAIT — Prompt overrides per-session (module-level singleton → per-session Map)
- C-13: FAIT — API key encryption AES-256-GCM (format enc:iv:tag:ciphertext, backward-compatible)
- U-10: VÉRIFIÉ OK — exec() résout nom→id, design cohérent
- Tests POST-DEPLOY : health OK, service up, 1 session active
ulias-org-web — TERMINÉ (21/25 correctifs)
- Commit
4fbdea4 — Pipeline #1082 SUCCESS (897s total)
- C-02: XSS sanitize markdown URLs (whitelist http/https/mailto)
- C-01: Suppression stale archive polling interval
- C-03: SPA nav() au lieu de window.location.href pour retry
- C-04: loadLastConversation après auth_success (pas setTimeout 500ms)
- C-05: X-API-Key ajouté sur /api/teams fetch
- C-06: console.error sur catch blocks critiques
- C-07: Vérification res.ok AVANT mise à jour état UI
- C-08: confirm() avant suppression conversations/objectifs
- C-09: WS reconnexion infinie (5 rapides + backoff lent 30s/60s/2min)
- C-11/U-06: Types TypeScript events complétés (routing, thinking, tool_result, subtask)
- U-01: searchTimerRef cleanup on unmount
- U-02: ARIA role="status" sur ConnectionBadge
- U-03: aria-label sur boutons icon-only
- U-04: span onClick$ → button elements (accessibilité)
- U-05: aria-live="polite" + aria-busy sur streaming indicator
- U-07: Fix dead code event.data?.title (propriétés directes, pas .data)
- U-08: originalMessage ajouté aux types events
- U-09: WS /ws/cli → /ws/webui
- U-11: revokeObjectURL délai 1000ms
- U-12: requestAnimationFrame au lieu de setTimeout(500) pour template
- C-10: REPORTÉ — API key par message WS nécessite changement serveur
- C-12: NON NÉCESSAIRE — useStore fonctionne dans useVisibleTask$ (scope correct)
- U-13: NON NÉCESSAIRE — 9 signaux EventCard indépendants, pas de bénéfice à grouper
- U-10: VÉRIFIÉ OK — Login gère déjà 401 correctement
- Tests POST-DEPLOY : container healthy, HTTP 200 (via port interne)
Ordre d'implémentation global — BILAN :
Migration DNS Pi-hole FAIT
connectors-api FAIT (20/22 — C-13 N/A, C-15 N/A)
ai-orchestrator FAIT (33/33 — tous correctifs implémentés)
ulias-org FAIT (30/30 — tous correctifs implémentés)
ulias-org-web FAIT (21/25 — C-10 reporté serveur, C-12/U-13 non nécessaires, U-10 vérifié OK)
Correctifs reportés FAIT (6/6 implémentés — commit 2f8786c, a0f1aa7, 9cfc758, c1f4e15, 22cb3a0)
- Dashboard migration (nouveau projet) ← PROCHAIN
Decisions transversales
Migration DNS Pi-hole (VALIDÉE)
- Proposition :
~/propositions/15-02-2026-12-00-migration-ip-vers-dns-pihole.md
- Pattern :
<nom>.internal.nowhere84.com pour les hosts internes
- Pi-hole Local DNS Records, résolution depuis prod-portainer/containers Docker
- nginx reste en IP (DNS Freebox, pas Pi-hole)
Migration dashboard projet GitLab (VALIDÉE)
- Proposition :
~/propositions/15-02-2026-13-30-dashboard-projet-gitlab-complet.md
- API backend (Bun/Elysia sur prod-portainer) + SPA frontend (O2switch)
- CI/CD GitLab → smart-deploy full automatisé
- 28 findings dashboard absorbés par la migration, 8 intégrés comme exigences
- Dépend des correctifs auth/health/CORS/DNS sur les autres projets
Health check réel (VALIDÉE — tous projets)
- Chaque service vérifie ses dépendances ET ses sidecars Docker
- Retour structuré :
{ status, dependencies: { ... } }
- Degraded (503) si dépendance down, jamais crash le process
CORS *.nowhere84.com (VALIDÉE — tous projets)
- Vérifier dynamiquement l'origin via endsWith('.nowhere84.com')
- Pas de liste de sous-domaines à maintenir
Auth API key interne (VALIDÉE — tous services internes)
- ai-orchestrator, ulias-org, dashboard-api : auth par API key
- Clé dans conf.prod.gouroubleu.yml comme env var
Zéro fallback hardcodé (VALIDÉE — tous projets)
- Pas de fallback IP, URL, credential dans le code
- Si config manque → erreur explicite au démarrage
Coût estimé IA locale (VALIDÉE)
- Calcul basé sur durée job × consommation GPU × prix kWh
- electricity_cost_kwh configurable dans conf.prod.gouroubleu.yml
- Stocké avec flag cost_type: 'cloud' | 'local_estimated'
Decisions validees — connectors-api (22)
C-01 : verifyJWT() ne verifie pas la signature HMAC
Decision : VALIDE
Correctif : Implementer verification HMAC-SHA256 avec crypto.createHmac('sha256', SUPABASE_JWT_SECRET). ~10 lignes dans verifyJWT().
C-02 : Fallback Supabase URL hardcode
Decision : VALIDE
Correctif : Supprimer le fallback. Throw erreur explicite si URL non configuree dans l'instance.
C-03 : getUserFromRequest() sync ne gere pas les API keys
Decision : VALIDE — Simplification du code
Correctif : Supprimer getUserFromRequest() completement. Tout migrer vers getAuthFromRequest() (un seul chemin d'auth). PAS de doublon de code.
C-04 : onRequest hook bypass pour routes hors /api/
Decision : VALIDE — Securite par ergonomie
Correctif : Inverser la logique. Auth sur TOUTES les routes par defaut. Allowlist explicite pour les routes publiques : const PUBLIC_ROUTES = ['/health', '/api/oauth/callback']
C-05 : Pas de rate limiting sur login/register
Decision : VALIDE
Correctif : Rate limiter simple sur login/register. Max 5 tentatives par IP par minute. Compteur en memoire avec Map<ip, {count, timestamp}>.
C-06 : Mot de passe Supabase en fallback hardcode
Decision : VALIDE
Correctif : Supprimer le fallback. Throw erreur si variable d'env manque. Credential uniquement via conf.prod.gouroubleu.yml.
C-07 : Error handler 404 catch les erreurs applicatives
Decision : VALIDE
Correctif : Separer les handlers : 404 pour routes inexistantes, 500 pour erreurs applicatives avec log de l'erreur reelle.
C-08 : Pas de validation body sur register
Decision : VALIDE
Correctif : Validation via t.Object() d'Elysia. Email : present, non vide, format valide. Password : present, min 8 caracteres. Retour 422 si invalide.
C-09 : getUserFromRequest retourne null au lieu de throw
Decision : VALIDE — Lie a C-03
Correctif : getAuthFromRequest() (le seul chemin d'auth apres C-03) doit THROW 401 quand l'auth echoue, pas retourner null. Si le code s'execute, l'utilisateur est authentifie.
C-10 : NODE_TLS_REJECT_UNAUTHORIZED=0 en production
Decision : VALIDE
Correctif : Identifier le service avec cert problematique (probablement GitLab local). Ajouter le cert comme CA trusted via NODE_EXTRA_CA_CERTS. Retirer NODE_TLS_REJECT_UNAUTHORIZED=0.
C-11 : OAuth state non verifie apres callback
Decision : VALIDE
Correctif : Generer state aleatoire a l'initiation OAuth, stocker en memoire avec TTL court. Verifier au callback que le state recu correspond. Rejeter sinon.
C-12 : Deletion complete au lieu de soft-delete pour instances
Decision : VALIDE
Correctif : Ajouter champ deleted_at (timestamp nullable). DELETE met deleted_at = now(). GET filtre WHERE deleted_at IS NULL. Optionnel : endpoint restore/purge.
C-13 : Pas de validation schema sur conf.prod.gouroubleu.yml
Decision : VALIDE
Correctif : Validation dans smart-deploy (pas dans connectors-api). Verifier champs obligatoires, types, warning env vars manquantes. Refuser deploiement si schema invalide.
C-14 : Logging insuffisant sur les erreurs d'auth
Decision : VALIDE
Correctif : console.warn() sur chaque echec d'auth avec : raison (token expire, signature invalide, API key inconnue), endpoint appele, timestamp.
C-15 : Session cleanup inexistant pour sessions expirees
Decision : VALIDE — Utiliser Redis
Correctif : Remplacer Map en memoire par Redis. Cles session:{apiKey} avec EXPIRE = duree de vie JWT (ou 24h). Auto-expiration sans cron. Ajouter URL Redis dans conf.prod.gouroubleu.yml pour connectors-api.
C-16 : API keys stockees en clair dans Supabase
Decision : VALIDE
Correctif : Hasher (SHA-256) avant stockage. Retourner la cle en clair UNE SEULE FOIS a la creation. Auth : hasher la cle recue et comparer. Migration : regenerer les API keys existantes.
C-17 : SSH connector password en clair dans config instance
Decision : VALIDE — ATTENTION : ne pas perdre la cle de chiffrement
Correctif : Chiffrer credentials sensibles (AES-256-GCM) avec cle serveur (env var ENCRYPTION_KEY). Dechiffrer au moment de l'utilisation. Ne JAMAIS retourner les mots de passe dans les reponses API GET. Backup obligatoire de la cle de chiffrement dans un endroit separe (credentials.md + fichier protege PVE).
C-18 : Timeout SSH fixe 30s sans configuration
Decision : VALIDE
Correctif : Garder 30s comme defaut. Utiliser le parametre timeout optionnel deja prevu dans le schema de /api/ssh/execute. S'assurer qu'il est bien passe a l'execution SSH reelle.
C-19 : Pas de pagination sur GET /api/user/instances
Decision : VALIDE — Tags globaux obligatoires
Correctif : Query params ?limit=50&offset=0. Retourner { instances, total, limit, offset, all_tags }. all_tags = liste dedupliquee de TOUS les tags de TOUTES les instances (pas seulement la page courante).
C-20 : CORS allow_origin=* en production
Decision : VALIDE — Pattern *.nowhere84.com
Correctif : Verifier dynamiquement origin.endsWith('.nowhere84.com'). Pas de liste de sous-domaines a maintenir.
C-21 : Pas de Content-Security-Policy header
Decision : VALIDE
Correctif : Middleware global : X-Content-Type-Options: nosniff, X-Frame-Options: DENY, HSTS, CSP: default-src 'none'. ~5 lignes dans onAfterHandle.
C-22 : Health endpoint sans check de dependances
Decision : VALIDE — Pattern transversal tous projets + sidecars Docker
Correctif : /health verifie Supabase + Redis + sidecars (wireguard, browser). Retour structuré { status, dependencies }. Timeout 2-3s par check. 503 si degraded, jamais crash.
Decisions validees — ai-orchestrator (33)
C-01 : Cloud tasks Anthropic sans tracking
Correctif : Set active_tasks, Semaphore(max_concurrent=5), cleanup au shutdown.
C-02 : TOCTOU budget Anthropic
Correctif : Reservation cout estime au demarrage job, ajustement au reel en fin de job, transaction atomique.
C-03 : Credentials Redis/Postgres hardcodes
Correctif : Env vars dans conf.prod.gouroubleu.yml, pas de fallback, erreur au demarrage si manque.
C-04 : Mode generate Ollama sans num_ctx
Correctif : Passer num_ctx dans generate aussi, defaut 8192.
C-05 : CORS allow_origins=["*"] + allow_credentials=True
Correctif : Pattern *.nowhere84.com (transversal).
C-06 : is_cloud calcule deux fois + cout IA locale
Correctif : Calculer is_cloud une seule fois. Ajouter calcul cout estime local (GPU watts × duree × prix kWh). Flag cost_type cloud/local_estimated.
C-07 : Docstring dit 1-5, code fait min(10)
Correctif : Approfondir — bornes dynamiques par GPU et modele. Supprimer valeurs magiques.
C-08 : httpx client reutilise 2h
Correctif : Classifier erreurs transitoires (retry backoff) vs fatales (fail immediat). Recreer client apres erreur connexion.
C-09 : SadTalker cleanup process SSH
Correctif : await process.wait() dans finally. process.kill() en cas d'annulation. Stocker ref process pour cleanup shutdown.
C-10 : Job poppe de Redis puis DB echoue = perdu
Correctif : Pattern claim : deplacer dans liste processing Redis avant pop. Ecrire DB. Retirer de processing apres confirmation.
C-11 : queue_sync jamais appele au demarrage
Correctif : Appeler queue_sync() au demarrage avant de traiter des jobs. Re-queuer les jobs orphelins.
C-12 : Requeue sans compteur retry
Correctif : Incrementer retry_count a chaque requeue. MAX_RETRIES=3, au-dela → failed definitif.
C-13 : run_ssh_command timeout sans proc.kill()
Correctif : process.kill() + await process.wait() au timeout. Timeout configurable par job (defaut 60s). Pattern try/finally systematique.
C-14 : Watchdog parse "N/A" → desactive
Correctif : Verifier si valeur est "N/A" avant conversion. Skip metrique, continuer watchdog. Logger warning. Jamais desactiver watchdog a cause d'un parsing.
C-15 : 13 bare except
Correctif : Remplacer par except Exception: (exclut CancelledError, SystemExit). Idealement typer chaque except. Logger warning dans chaque bloc.
C-16 : Upload file.read() sans limite
Correctif : Verifier Content-Length, MAX_UPLOAD_SIZE_MB configurable (defaut 500), lire en streaming par chunks, 413 si depasse.
C-17 : Aucune authentification
Correctif : Auth API key via env var API_KEY. Header Authorization: Bearer. Pattern transversal services internes.
C-18 : costs_summary year/month hardcodes
Correctif : datetime.now().year/month comme defaut. Garder params pour historique.
C-19 : tools_state sans resync periodique
Correctif : Resync toutes les 60s, ping chaque outil, mettre a jour state. Independant du watchdog.
C-20 : Path traversal startswith("/")
Correctif : os.path.realpath() + verifier resolved.startswith(allowed_base_dir). 403 si hors repertoire. 5 fonctions.
C-21 : SSH injection face_swapper_model
Correctif : Whitelist modeles connus. shlex.quote() sur TOUS les parametres SSH. Pattern defensif systematique.
C-22 : FAUX POSITIF (nginx IP-restreint malgre absence private:true dans yml)
U-01 : WIN11_HOST hardcode
Correctif : Utiliser DNS Pi-hole win11.internal.nowhere84.com. Env var dans conf.prod.gouroubleu.yml.
U-02 : Race condition pop Redis (= C-10)
Correctif : Couvert par C-10.
U-03 : VRAM estimation max au lieu de sum
Correctif : sum() des VRAM quand multi-modeles sur meme GPU. Prendre en compte modeles deja charges.
U-04 : Upload ecrase fichiers existants
Correctif : Suffixe unique (timestamp/UUID court) ou 409 Conflict si existe. Logger upload.
U-05 : Pas de init.py
Correctif : Ajouter init.py vide dans app/.
U-06 : StrictHostKeyChecking=no sur 2 commandes
Correctif : Ajouter cle host win11 dans known_hosts du container. Retirer StrictHostKeyChecking=no.
U-07 : 13 imports locaux repetes
Correctif : Deplacer imports en haut du fichier.
U-08 : Fooocus seed 2^63 vs ComfyUI 2^32
Correctif : Aligner limites seed par outil. ComfyUI: 2^32-1, Fooocus: 2^63-1.
U-09 : SadTalker job_id sans sanitisation
Correctif : shlex.quote() par principe defensif (meme si UUID interne).
U-10 : Applio 60 parametres positionnels
Correctif : Named arguments ou script wrapper sur win11 qui traduit named → positionnels.
U-11 : Pas de schema.sql ni migrations
Correctif : Exporter schema.sql, dossier migrations/ avec fichiers SQL numerotes, appliquer au demarrage.
U-12 : /health crash si Redis down → boucle restart
Correctif : Catch erreurs dependances dans /health. Retourner 503 degraded, jamais crash.
U-13 : stop_tool("anthropic") SSH inutile
Correctif : Supprimer code mort stop SSH pour Anthropic (service cloud).
U-14 : Batch JSONL result.type pas verifie
Correctif : Verifier result.type, compter succes/echecs, ne pas traiter erreurs comme resultats valides.
Decisions validees — ulias-org (30)
C-01 : Briefing processAnswer logique inversee
Correctif : Inverser la condition (! manquant ou en trop).
C-02 : WS deconnexion session.ws jamais nettoye
Correctif : session.ws = null dans handler close. Verifier ws non null avant send. Cleanup session apres delai.
C-03 : Pipeline runner ne passe pas AbortSignal
Correctif : Passer signal a chaque etape. Verifier signal.aborted avant chaque appel LLM/tool.
C-04 : onDecision callback jamais branche
Correctif : Brancher sur WS. Envoyer question au client, attendre reponse approve/reject. Timeout → auto-reject.
C-05 : CALLBACK_BASE_URL hardcode
Correctif : Env var dans conf.prod.gouroubleu.yml, pas de fallback.
C-06 : CONNECTORS_API_URL fallback port 5400 au lieu de 5403
Correctif : Supprimer fallback. Env var. Utiliser domaine HTTPS avec migration DNS.
C-07 : Cache hash DJB2 32-bit + troncature
Correctif : Remplacer par SHA-256, supprimer troncature.
C-08 : Circuit breaker et cache globaux partages
Correctif : Circuit breaker reste global (logique). Cache isole par session (cle inclut session ID).
C-09 : Prompt overrides globaux
Correctif : Stocker overrides par session, pas en global.
C-10 : Pas de validation ownership (IDOR)
Correctif : Verifier resource.user_id === authenticated_user.id. WHERE id=? AND user_id=? dans SQL.
C-11 : Injection SSH via heredoc ULIAS_EOF
Correctif : Delimiteur dynamique/aleatoire a chaque appel. Valider/limiter commandes par agent.
C-12 : Traduction automatique systematique
Correctif : Configurable par agent/session. Detecter langue, skip si deja langue cible. Cacher langue user.
C-13 : API key en clair dans Supabase
Correctif : Hash SHA-256 (meme pattern que connectors-api C-16). Transversal.
C-14 : editFile ne remplace que premiere occurrence
Correctif : replaceAll() ou regex /g. Option replace_all: boolean (defaut false).
C-15 : message_count increment non-atomique
Correctif : UPDATE SET message_count = message_count + 1 (atomique SQL).
C-16 : GITLAB_TOKEN en clair dans conf.prod
Correctif : Sortir dans fichier secrets non versionne ou variables CI/CD. Regenerer token.
C-17 : /api/agents et /internal/* sans auth
Correctif : Auth API key/JWT sur /api/. API key partagee pour /internal/. Pattern transversal.
U-01 : CLI default port 5510 au lieu de 5515
Correctif : Corriger port. Utiliser domaine HTTPS avec migration DNS.
U-02 : NotificationService code mort
Correctif : Supprimer (notifications via outils connecteur).
U-03 : git-workflow.ts status '??' teste 2 fois
Correctif : Supprimer test duplique.
U-04 : Upload base64 toString('utf-8') corrompt binaires
Correctif : Ecrire buffer directement sans conversion UTF-8.
U-05 : storageGetPublicUrl IP hardcodee
Correctif : Supprimer fallback IP. Env var + DNS.
U-06 : num_ctx ecrase par hardcode 16384
Correctif : Respecter num_ctx passe en parametre. 16384 = defaut si non specifie. Adapter au GPU/modele.
U-07 : consecutiveErrors semantique incorrecte en parallele
Correctif : Fenetre glissante (X erreurs sur Y derniers appels) au lieu de compteur consecutif strict.
U-08 : userId fallback apiKey[:8]
Correctif : Supprimer fallback. Auth doit toujours resoudre un userId. Erreur si pas de userId.
U-09 : forkConversation charge 10000 messages
Correctif : Charger par batches (100). INSERT batch au lieu de N inserts sequentiels.
U-10 : Incoherence instance parameter id vs name
Correctif : Standardiser sur id (UUID). Resoudre nom→id une seule fois.
U-11 : auth.ts hardcode 'Supabase' vs client.ts .id
Correctif : Constante ou env var SUPABASE_INSTANCE_ID utilisee par les deux.
U-12 : dbInsert/dbUpdate retour undefined
Correctif : Verifier retour. Throw si undefined/erreur. Idealement dbInsert/dbUpdate throw eux-memes.
U-13 : Nudge agent injecte message 'user'
Correctif : Role 'system' ou flag is_system. Ne pas persister dans historique visible.
Decisions validees — ulias-org-web (25)
C-01 : setInterval archive polling closure figee
Correctif : Lire valeur courante a chaque tick. Ou pattern reactif Qwik. Cleanup interval.
C-02 : XSS javascript: URI dans Markdown
Correctif : Sanitiser URLs (whitelist http/https/mailto). DOMPurify sur HTML genere.
C-03 : retryObjective window.location.href detruit WS
Correctif : Attendre confirmation envoi WS avant naviguer. Ou update etat local (SPA).
C-04 : Race condition setTimeout(500ms) loadLastConversation
Correctif : Attendre event WS onopen, pas setTimeout.
C-05 : /api/teams fetch sans X-API-Key
Correctif : Ajouter header. Centraliser dans wrapper fetch qui ajoute auth auto.
C-06 : Erreurs reseau silencieuses (catch vides)
Correctif : Supprimer catch vides. Wrapper fetch centralise (toast + log). Gerer erreurs au bon niveau.
C-07 : Etat local desynchronise apres delete/archive echoue
Correctif : Verifier res.ok AVANT de mettre a jour UI. Si echec → erreur, ne pas toucher etat.
C-08 : Suppression sans confirmation
Correctif : Dialogue confirmation avant suppression (confirm() ou modal).
C-09 : Reconnexion WS limitee 5 tentatives
Correctif : Apres 5 rapides → backoff exponentiel (30s, 60s, 120s). Bandeau "connexion perdue" + bouton reconnecter.
C-10 : API key dans chaque message WS
Correctif : Envoyer API key uniquement au premier message (auth). Session WS deja authentifiee.
C-11 : Types TypeScript incomplets events serveur
Correctif : Union type ServerEvent. Typer chaque event.
C-12 : useStore mute dans handler vanilla JS
Correctif : useSignal pour flags simples. Fonction $() pour mutations complexes.
U-01 : searchTimerRef jamais nettoye
Correctif : clearTimeout dans cleanup composant.
U-02 : Modal sans role/aria/focus trap
Correctif : role="dialog", aria-modal="true", focus trap, Escape ferme.
U-03 : Boutons SVG sans aria-label
Correctif : Ajouter aria-label descriptif.
U-04 : div onClick$ sans role/tabIndex
Correctif : Remplacer par <button> natif. Sinon role="button" + tabIndex={0} + onKeyDown$.
U-05 : Pas de live region streaming
Correctif : aria-live="polite" sur zone reponse. aria-busy pendant streaming.
U-06 : 14 types events custom sans typage
Correctif : Enum/union type pour events. Se fait avec C-11.
U-07 : event.data?.title code mort
Correctif : Verifier si vestige → supprimer. Ou corriger mapping.
U-08 : originalMessage absent → retry/edit caches
Correctif : Backend inclure originalMessage. Ou frontend afficher retry/edit sans condition.
U-09 : WS connecte /ws/cli au lieu de /ws/webui
Correctif : Connecter sur /ws/webui.
U-10 : /api/status ne verifie pas API key
Correctif : Backend ajouter auth sur /api/status. Frontend afficher "API key invalide" si 401.
U-11 : revokeObjectURL trop tot
Correctif : Revoquer apres setTimeout(1000ms).
U-12 : setTimeout(500ms) template message
Correctif : Meme fix que C-04 — event au lieu de timer.
U-13 : 9 signaux Qwik par EventCard
Correctif : Regrouper en 1 useStore. Ou calculer a la volee. Attention .sort() dans render.
Decisions validees — dashboard (36)
NOTE : 28 findings sont absorbes par la migration dashboard vers projet GitLab (voir proposition ~/propositions/15-02-2026-13-30-dashboard-projet-gitlab-complet.md). 8 findings sont integres comme exigences du nouveau projet.
Absorbes par la migration (pas de patch sur le vieux code)
C-01, C-02, C-03, C-04, C-05, C-06, C-08, C-09, C-10, C-11, C-12, C-14, C-15, C-16, C-17, C-18, U-01, U-02, U-04, U-06, U-07, U-08, U-10, U-14, U-15, U-16 (faux probleme), U-17, U-18
Exigences pour le nouveau dashboard
- C-07 : Echappement HTML → framework avec echappement auto
- C-13 : Polling → visibilitychange pause/resume
- U-03 : Injection jq → valider inputs dans API backend
- U-05 : XSS inject_json → pas d'injection JSON dans script tags, utiliser fetch
- U-09 : XSS innerHTML → textContent ou framework avec echappement
- U-11 : IP PVE inconsistante → DNS Pi-hole
- U-12 : Port browser-connector faux → sous-domaines HTTPS (plus de ports)
- U-13 : Port connectors-api faux → sous-domaines HTTPS
Prochaine etape : Implementation
Ordre recommande :
- Migration DNS Pi-hole (prerequis pour plusieurs fixes)
- connectors-api (22 correctifs — projet le plus critique en securite)
- ai-orchestrator (33 correctifs — stabilite GPU + securite)
- ulias-org (30 correctifs — IDOR + isolation sessions)
- ulias-org-web (25 correctifs — XSS + UX)
- Dashboard migration (nouveau projet — depend des fixes 1-5)