Files
html/faq-techniques.html
2026-04-12 22:57:03 +02:00

792 lines
41 KiB
HTML

<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>WEVAL — FAQ Pièges, Erreurs & Techniques</title>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;700&family=Outfit:wght@300;500;700;900&display=swap" rel="stylesheet">
<style>
*{margin:0;padding:0;box-sizing:border-box}
:root{
--bg:#080810;--bg2:#0f0f1a;--bg3:#161625;--bg4:#1e1e30;
--tx:#e0e0ee;--tx2:#7878a0;
--red:#ff4444;--orange:#ff8844;--yellow:#ffcc33;--green:#44dd88;--cyan:#44ccee;--purple:#aa66ff;--blue:#4488ff;
--border:#252540;
}
body{background:var(--bg);color:var(--tx);font-family:'Outfit',sans-serif;line-height:1.7}
.hero{padding:50px 40px 30px;background:linear-gradient(135deg,#100818,#0a0a20,#180810);border-bottom:2px solid var(--red);position:relative}
.hero h1{font-size:2.8em;font-weight:900;letter-spacing:-1px;color:var(--red)}
.hero .sub{color:var(--tx2);font-size:1em;margin-top:6px}
.stats{display:flex;gap:24px;margin-top:24px;flex-wrap:wrap}
.stats .s{text-align:center;padding:12px 20px;background:var(--bg2);border-radius:10px;border:1px solid var(--border)}
.stats .s .n{font-size:2em;font-weight:900;font-family:'JetBrains Mono',monospace}
.stats .s .l{font-size:0.7em;color:var(--tx2);text-transform:uppercase;letter-spacing:2px}
.container{max-width:1200px;margin:0 auto;padding:30px 40px}
.toc{background:var(--bg2);border:1px solid var(--border);border-radius:12px;padding:24px;margin-bottom:40px}
.toc h3{color:var(--cyan);font-size:0.8em;text-transform:uppercase;letter-spacing:3px;margin-bottom:12px}
.toc-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(280px,1fr));gap:8px}
.toc a{color:var(--tx);text-decoration:none;font-size:0.88em;padding:6px 10px;border-radius:6px;display:block;transition:background 0.2s}
.toc a:hover{background:var(--bg3);color:var(--cyan)}
.toc a .num{color:var(--red);font-family:'JetBrains Mono',monospace;font-weight:700;margin-right:6px}
.section{margin-bottom:50px}
.section-header{display:flex;align-items:center;gap:14px;margin-bottom:20px;padding-bottom:10px;border-bottom:2px solid var(--border)}
.section-header .ico{font-size:1.6em}
.section-header h2{font-size:1.4em;font-weight:700}
.section-header .sev{font-size:0.7em;padding:4px 12px;border-radius:20px;font-weight:700;font-family:'JetBrains Mono',monospace;text-transform:uppercase;letter-spacing:1px}
.sev-critical{background:rgba(255,68,68,0.15);color:var(--red)}
.sev-high{background:rgba(255,136,68,0.15);color:var(--orange)}
.sev-medium{background:rgba(255,204,51,0.15);color:var(--yellow)}
.sev-info{background:rgba(68,204,238,0.15);color:var(--cyan)}
.trap{background:var(--bg2);border:1px solid var(--border);border-radius:10px;margin-bottom:16px;overflow:hidden}
.trap-header{padding:14px 18px;cursor:pointer;display:flex;align-items:flex-start;gap:12px;transition:background 0.2s}
.trap-header:hover{background:var(--bg3)}
.trap-header .badge{min-width:28px;height:28px;border-radius:50%;display:flex;align-items:center;justify-content:center;font-size:0.7em;font-weight:900;font-family:'JetBrains Mono',monospace;flex-shrink:0}
.badge-fatal{background:var(--red);color:#fff}
.badge-warn{background:var(--orange);color:#000}
.badge-tip{background:var(--green);color:#000}
.badge-tech{background:var(--purple);color:#fff}
.trap-title{font-weight:700;font-size:0.95em;flex:1}
.trap-tags{display:flex;gap:4px;flex-wrap:wrap;margin-top:4px}
.trap-tags span{font-size:0.6em;padding:2px 6px;border-radius:4px;background:var(--bg4);color:var(--tx2);font-family:'JetBrains Mono',monospace}
.trap-body{padding:0 18px 16px 58px;display:none;font-size:0.88em;color:var(--tx2)}
.trap-body.open{display:block}
.trap-body p{margin-bottom:10px}
.trap-body strong{color:var(--tx)}
.trap-body code{background:var(--bg4);padding:2px 6px;border-radius:4px;font-family:'JetBrains Mono',monospace;font-size:0.9em;color:var(--cyan)}
.trap-body pre{background:var(--bg);border:1px solid var(--border);border-radius:8px;padding:12px;margin:10px 0;overflow-x:auto;font-family:'JetBrains Mono',monospace;font-size:0.82em;color:var(--green);line-height:1.5}
.trap-body .danger{color:var(--red);background:rgba(255,68,68,0.08);padding:8px 12px;border-radius:6px;border-left:3px solid var(--red);margin:8px 0}
.trap-body .safe{color:var(--green);background:rgba(68,221,136,0.08);padding:8px 12px;border-radius:6px;border-left:3px solid var(--green);margin:8px 0}
.trap-body .incident{color:var(--orange);font-size:0.85em;font-style:italic;margin-top:6px}
.count{color:var(--red);font-size:0.75em;font-family:'JetBrains Mono',monospace}
@media(max-width:768px){
.hero{padding:24px 16px}.hero h1{font-size:1.8em}
.container{padding:16px}.toc-grid{grid-template-columns:1fr}
.trap-body{padding-left:18px}
}
</style>
</head>
<body>
<div class="hero">
<h1>⚠️ FAQ Pièges & Erreurs Connues</h1>
<div class="sub">6 mois de sessions · Toutes les régressions graves · Techniques avancées · WEVADS + Arsenal + WEVIA + Ethica + Infrastructure</div>
<div class="stats">
<div class="s"><div class="n" style="color:var(--red)">47</div><div class="l">Pièges documentés</div></div>
<div class="s"><div class="n" style="color:var(--orange)">23+</div><div class="l">Incidents réels</div></div>
<div class="s"><div class="n" style="color:var(--green)">40+</div><div class="l">Règles anti-régression</div></div>
<div class="s"><div class="n" style="color:var(--purple)">15</div><div class="l">Techniques avancées</div></div>
</div>
</div>
<div class="container">
<div class="toc">
<h3>Sommaire — 12 catégories</h3>
<div class="toc-grid">
<a href="#s1"><span class="num">01</span> SED & HEREDOC — Le piège mortel n°1</a>
<a href="#s2"><span class="num">02</span> CX Proxy — Limites et contournements</a>
<a href="#s3"><span class="num">03</span> HTML-Guardian — L'écraseur silencieux</a>
<a href="#s4"><span class="num">04</span> PMTA — Pièges 0.0.0.0, IP privée, configs</a>
<a href="#s5"><span class="num">05</span> SSO / Authentik / Auth — La boucle infernale</a>
<a href="#s6"><span class="num">06</span> nginx — Pièges routing, sub_filter, chattr</a>
<a href="#s7"><span class="num">07</span> Crontab — L'écrasement total</a>
<a href="#s8"><span class="num">08</span> PHP / FPM — Syntaxe, display_errors, timeout</a>
<a href="#s9"><span class="num">09</span> PostgreSQL — dblink, schema, migration</a>
<a href="#s10"><span class="num">10</span> Three.js / Frontend — Versions, imports, CSS</a>
<a href="#s11"><span class="num">11</span> WEVIA Chatbot — Routing, providers, leaks</a>
<a href="#s12"><span class="num">12</span> Architecture & Workflow — Règles d'or</a>
</div>
</div>
<!-- ═══════════ SECTION 1: SED & HEREDOC ═══════════ -->
<div class="section" id="s1">
<div class="section-header">
<span class="ico">💀</span>
<h2>SED & HEREDOC — Le piège mortel n°1</h2>
<span class="sev sev-critical">CRITICAL · 5+ sessions impactées</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">HEREDOC via Sentinel/CX exec = CORRUPTION GARANTIE</div>
<div class="trap-tags"><span>sentinel</span><span>cx-proxy</span><span>bash</span><span>php</span></div></div>
</div>
<div class="trap-body">
<p>Le terminal interprète les <code>`backticks`</code>, les <code>$variables</code>, et les caractères spéciaux AVANT que le heredoc ne soit écrit sur le disque.</p>
<div class="danger">Résultat : fichiers corrompus, syntaxe PHP/JS cassée, regex détruites. Claude 2, 3, 4, 5+ ont tous été victimes de ce piège.</div>
<p><strong>Exemples réels :</strong></p>
<p class="incident">📛 data-manager API corrompu par heredoc (Claude 2)</p>
<p class="incident">📛 chatbot-widget.php — regex backtick <code>/`([^`]+)`/g</code> impossible à écrire par sed/heredoc. 6+ tentatives échouées sur 1 session complète</p>
<p class="incident">📛 offer-import.php corrompu</p>
<p class="incident">📛 registry-test.sh — les <code>\$</code> échappés persistent après sed, nécessitant perl -pi -e</p>
<div class="safe">✅ MÉTHODE SÛRE : <code>cat >> fichier << 'BLOC'</code> (quotes simples autour du délimiteur)</div>
<div class="safe">✅ MÉTHODE SÛRE : head/tail reconstruction<pre>head -141 fichier.php > /tmp/fix.php
echo ' ligne corrigée' >> /tmp/fix.php
tail -n +143 fichier.php >> /tmp/fix.php
cp /tmp/fix.php fichier.php</pre></div>
<div class="safe">✅ MÉTHODE SÛRE : Python str_replace via script temporaire<pre>python3 -c "
c=open('/path/file.php').read()
c=c.replace('old','new')
open('/path/file.php','w').write(c)
"</pre></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">sed -i avec patterns complexes sur HTML/JS = DANGER</div>
<div class="trap-tags"><span>sed</span><span>html</span><span>javascript</span></div></div>
</div>
<div class="trap-body">
<p>sed ne gère pas : multi-lignes, quotes imbriquées, regex avec backticks, HTML avec attributs. Chaque tentative de "fix" empire le fichier.</p>
<p class="incident">📛 menu.html : 4+ tentatives de sed → doublons, sections supprimées, structure HTML cassée</p>
<p class="incident">📛 chatbot-widget.php ligne 142 : 6 tentatives sed/heredoc/echo pour fixer une regex backtick → aucune n'a marché</p>
<div class="safe">✅ Pour fichiers complexes : écrire le contenu complet dans /tmp puis cp vers destination</div>
<div class="safe">✅ Pour éditions chirurgicales : Python <code>open().read().replace().write()</code></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">sed avec $ dans les patterns — l'échappement infini</div>
<div class="trap-tags"><span>sed</span><span>bash</span><span>regex</span></div></div>
</div>
<div class="trap-body">
<p>Dans registry-test.sh, les <code>\$</code> persistaient après chaque tentative de sed. La solution finale : <code>perl -pi -e 's/\\\\\\$/\\$/g'</code></p>
<div class="safe">✅ Quand sed ne marche pas après 2 tentatives → STOP, utiliser perl ou Python</div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 2: CX PROXY ═══════════ -->
<div class="section" id="s2">
<div class="section-header">
<span class="ico">🔌</span>
<h2>CX Proxy — Limites et contournements</h2>
<span class="sev sev-high">HIGH</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">Max 4500 bytes par chunk — dépassement = troncature silencieuse</div>
<div class="trap-tags"><span>cx-proxy</span><span>deploy</span></div></div>
</div>
<div class="trap-body">
<p>Le CX proxy (<code>weval-consulting.com/api/cx</code>, key=WEVADS2026) tronque silencieusement les payloads > 4500 bytes. Le fichier semble déployé mais est incomplet.</p>
<div class="safe">✅ MÉTHODE : Split en chunks base64 de 4500 bytes, encoder, envoyer un par un, reconstruire côté serveur<pre>split -b 4500 fichier.html /tmp/chunk-
for f in /tmp/chunk-*; do
C=$(base64 -w0 "$f")
# envoyer via CX...
done</pre></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">Sentinel exec via CX ne persiste pas fiablement les écritures Python</div>
<div class="trap-tags"><span>sentinel</span><span>python</span><span>écriture</span></div></div>
</div>
<div class="trap-body">
<p>Les commandes Python envoyées via CX proxy pour écrire des fichiers échouent parfois silencieusement. Le fichier existe mais est vide ou tronqué.</p>
<div class="safe">✅ Utiliser <code>base64 -d</code> CLI au lieu de Python pour écrire les fichiers</div>
<div class="safe">✅ Pour fichiers complexes : encoder en hex, envoyer, décoder avec <code>xxd -r -p</code></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">Claude container IP bloquée par S95</div>
<div class="trap-tags"><span>réseau</span><span>firewall</span></div></div>
</div>
<div class="trap-body">
<p>L'IP du container Claude est bloquée par le firewall S95. Toute exécution distante doit passer par la machine locale de Yacine ou par Sentinel whitelisté.</p>
<div class="danger">Ne JAMAIS tenter SSH direct depuis le container Claude vers S95</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-tip"></div>
<div><div class="trap-title">PowerShell et guillemets — les commandes sed cassent</div>
<div class="trap-tags"><span>powershell</span><span>windows</span><span>ssh</span></div></div>
</div>
<div class="trap-body">
<p>Les commandes SSH depuis PowerShell Windows interprètent les guillemets différemment. <code>sed -i "s/old/new/"</code> via SSH depuis PowerShell = résultat imprévisible.</p>
<p class="incident">📛 Fix l99-chat.php depuis PowerShell → <code>bash: line 1: llama-3.3-70b/m=: No such file or directory</code></p>
<div class="safe">✅ Toujours faire les modifications via CX proxy ou WEVIA Master, pas depuis PowerShell</div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 3: HTML-GUARDIAN ═══════════ -->
<div class="section" id="s3">
<div class="section-header">
<span class="ico">🛡️</span>
<h2>HTML-Guardian — L'écraseur silencieux</h2>
<span class="sev sev-critical">CRITICAL · 3+ incidents</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">html-guardian cron écrase les fixes toutes les 10 minutes</div>
<div class="trap-tags"><span>cron</span><span>guardian</span><span>gold</span></div></div>
</div>
<div class="trap-body">
<p>Le cron html-guardian tourne toutes les 10 minutes, compare les fichiers avec les GOLD, et restaure automatiquement. Si tu fais un fix et que le GOLD est l'ancien fichier → ton fix est écrasé en 10 minutes.</p>
<p class="incident">📛 youtube-auth.php fixé → écrasé par guardian 10 min après</p>
<p class="incident">📛 arsenal-auth.php fixé → écrasé par guardian</p>
<p class="incident">📛 Gold files dataient du 31 jan (AVANT rollback) → protégeaient l'état CASSÉ</p>
<div class="danger">TOUJOURS vérifier que le guardian est en mode ALERTE ONLY avant de modifier un fichier</div>
<div class="safe">✅ Après un fix validé : mettre à jour le fichier GOLD correspondant<pre>cp fichier_fixé.php /opt/wevads/vault/fichier.php.gold
md5sum fichier_fixé.php >> /opt/wevads/vault/checksums.md5</pre></div>
<div class="safe">✅ Pour bloquer temporairement : <code>crontab -l | grep -v guardian | crontab -</code> (puis réactiver)</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">5 couches de protection — si tu ne mets pas à jour les GOLD, tes fixes sont perdus</div>
<div class="trap-tags"><span>vault</span><span>sentinel</span><span>guardian</span></div></div>
</div>
<div class="trap-body">
<p>Layer 1: Deploy Validator (pre-deploy) · Layer 2: HTML Guardian (*/10min) · Layer 3: Sentinel V5 (*/30min) · Layer 4: Vault Guard (*/6h) · Layer 5: 743 gold files + checksums MD5</p>
<div class="safe">✅ Workflow obligatoire après fix : fix → test → update gold → update checksum → git commit</div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 4: PMTA ═══════════ -->
<div class="section" id="s4">
<div class="section-header">
<span class="ico">📨</span>
<h2>PMTA — Pièges 0.0.0.0, IP privée, configs</h2>
<span class="sev sev-critical">CRITICAL · Infrastructure sacrée</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">0.0.0.0 NE FONCTIONNE PAS en PMTA 4.5r8 → IP privée obligatoire</div>
<div class="trap-tags"><span>pmta</span><span>huawei</span><span>nat</span></div></div>
</div>
<div class="trap-body">
<p>Sur Huawei Cloud avec NAT, l'IP publique n'est pas bindée localement. Les VMTAs avec <code>smtp-source-host 0.0.0.0</code> crashent PMTA au restart.</p>
<p class="incident">📛 Template VMTA corrigé avec 0.0.0.0 sur 8 fichiers → PMTA refuse de démarrer sur SER_9</p>
<p class="incident">📛 pmta --config-check n'existe pas dans cette version → erreurs invisibles</p>
<div class="danger">PMTA 4.5r8 n'a pas de commande de validation de config. Les erreurs sont silencieuses jusqu'au crash.</div>
<div class="safe">✅ TOUJOURS utiliser l'IP privée explicite (192.168.0.x) dans smtp-source-host</div>
<div class="safe">✅ Les 4 ECS Huawei sont SACRÉS — IDs 186-189, configs INTOUCHABLES<pre>SER_6: 110.239.84.121 / 192.168.0.11
SER_7: 110.239.65.64 / 192.168.0.55
SER_8: 182.160.55.107 / 192.168.0.38
SER_9: 110.239.86.68 / 192.168.0.241</pre></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">JAMAIS modifier is_installed / pmtahttpd / config</div>
<div class="trap-tags"><span>pmta</span><span>sacred</span></div></div>
</div>
<div class="trap-body">
<p>Le binaire propre est dans <code>/opt/pmta-versions/4_5r8/pmtad</code>. Le proxy Python pmtahttpd tourne sur port 5371 (v5.0b1). Ne JAMAIS toucher ces fichiers.</p>
<div class="danger">pmtahttpd = proxy Python custom, pas le vrai daemon PMTA. Le confondre = casser le monitoring</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">http-access 127.0.0.1 admin = monitoring externe bloqué</div>
<div class="trap-tags"><span>pmta</span><span>monitoring</span></div></div>
</div>
<div class="trap-body">
<p>Le template d'installation PMTA ne contient que localhost pour l'accès HTTP admin. Tous les nouveaux serveurs sont inaccessibles depuis le monitoring central.</p>
<div class="safe">✅ Templates doivent avoir : <code>http-access 0/0 monitor</code> (ou IP WEVADS spécifique)</div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 5: SSO/AUTH ═══════════ -->
<div class="section" id="s5">
<div class="section-header">
<span class="ico">🔐</span>
<h2>SSO / Authentik / Auth — La boucle infernale</h2>
<span class="sev sev-critical">CRITICAL · 10+ heures perdues</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">Authentik = SUPPRIMÉ. Auth PHP souverain désormais.</div>
<div class="trap-tags"><span>authentik</span><span>auth</span><span>souverain</span></div></div>
</div>
<div class="trap-body">
<p><strong>Avril 2026 :</strong> Authentik a été supprimé après des régressions répétées (boucles redirect, callback 400, sessions corrompues, JWT redirect vide). Remplacé par auth PHP simple : <code>/var/www/html/auth/</code> (login=yacine/Weval@2026, cookie HMAC 30j).</p>
<p class="incident">📛 Callback SSO retournait 400 en continu → sessions corrompues</p>
<p class="incident">📛 JWT state contenait <code>"redirect":""</code> → toutes les pages redirigées vers /</p>
<p class="incident">📛 Sub_filter JS faisait double redirect (client + nginx) → boucle infinie</p>
<p class="incident">📛 @sso_retry redirigeait vers <code>$request_uri</code> = /outpost.goauthentik.io/callback → boucle</p>
<p class="incident">📛 10+ heures passées sur 3 sessions à débugger SSO</p>
<div class="danger">compose.yml.DISABLED — NE JAMAIS réactiver Authentik. 0 refs authentik dans nginx.</div>
<div class="safe">✅ Auth PHP: nginx auth_request /auth/check + @weval_login_redirect. L99-AUTH-v6 52/52</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">Root cause auth/check : "return 200" au lieu de PHP</div>
<div class="trap-tags"><span>nginx</span><span>auth</span><span>php</span></div></div>
</div>
<div class="trap-body">
<p>La route <code>/auth/check</code> retournait un <code>return 200</code> nginx statique au lieu d'exécuter le PHP qui vérifie le cookie HMAC. Résultat : toutes les pages semblaient non-protégées ou protégées selon la config, mais jamais correctement.</p>
<div class="safe">✅ /auth/check doit pointer vers le PHP : <code>fastcgi_pass unix:/run/php/php-fpm.sock</code></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">19 pages fantômes — locations nginx qui n'existent plus</div>
<div class="trap-tags"><span>nginx</span><span>cleanup</span></div></div>
</div>
<div class="trap-body">
<p>Après suppression d'Authentik, 19 locations nginx pointaient vers des pages qui n'existaient plus ou vers des callbacks Authentik. Nettoyées dans la session du 8 avril.</p>
<div class="safe">✅ GOLD nginx : <code>/etc/nginx/weval-consulting.gold.pre-auth-removal.8avr2026</code></div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 6: NGINX ═══════════ -->
<div class="section" id="s6">
<div class="section-header">
<span class="ico">⚙️</span>
<h2>nginx — Pièges routing, sub_filter, chattr</h2>
<span class="sev sev-high">HIGH</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">chattr +i sur nginx config = impossible de modifier sans sudo chattr -i</div>
<div class="trap-tags"><span>nginx</span><span>chattr</span><span>immutable</span></div></div>
</div>
<div class="trap-body">
<p>Les fichiers nginx sont marqués immutable (<code>chattr +i</code>) pour anti-régression. Toute tentative de modification échoue silencieusement.</p>
<div class="safe">✅ Workflow : <code>sudo chattr -i fichier</code> → modifier → tester → <code>sudo chattr +i fichier</code></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">Route /api/weval-ia-full manquante → 404 sur fullscreen chatbot</div>
<div class="trap-tags"><span>nginx</span><span>routing</span><span>wevia</span></div></div>
</div>
<div class="trap-body">
<p class="incident">📛 "Erreur de réponse" sur le chatbot fullscreen — la route nginx n'existait pas, le backend retournait 404</p>
<div class="safe">✅ Toujours vérifier que la route nginx existe AVANT de tester un endpoint</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">sites-enabled = toujours COPIE, jamais édition directe</div>
<div class="trap-tags"><span>nginx</span><span>backup</span></div></div>
</div>
<div class="trap-body">
<div class="safe">✅ Avant toute modif nginx : <code>cp /etc/nginx/sites-enabled/weval-consulting /etc/nginx/sites-enabled/weval-consulting.bak.$(date +%Y%m%d)</code></div>
<div class="safe">✅ Après modif : <code>nginx -t</code> OBLIGATOIRE avant <code>nginx -s reload</code></div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 7: CRONTAB ═══════════ -->
<div class="section" id="s7">
<div class="section-header">
<span class="ico"></span>
<h2>Crontab — L'écrasement total</h2>
<span class="sev sev-critical">CRITICAL · 60+ crons perdus 2 fois</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">Un seul crontab -e ou script écrase TOUT le crontab existant</div>
<div class="trap-tags"><span>cron</span><span>backup</span></div></div>
</div>
<div class="trap-body">
<p>Deux fois en 6 mois, l'intégralité du crontab (60-75 crons de production) a été écrasée par un script qui faisait <code>echo "..." | crontab -</code> au lieu de <code>(crontab -l; echo "...") | crontab -</code>.</p>
<p class="incident">📛 Fév 2026 : CRM worker a écrasé 60+ crons avec 5 stubs → warmup, brain, monitoring arrêtés</p>
<p class="incident">📛 Restauration du mauvais backup (18 lignes au lieu de 75) → 2ème perte</p>
<p class="incident">📛 Jan 2026 : cron même pas installé sur le container → tous les jobs perdus</p>
<div class="danger">JAMAIS <code>echo "..." | crontab -</code> → toujours <code>(crontab -l; echo "...") | crontab -</code></div>
<div class="safe">✅ AVANT toute modif crontab : <code>crontab -l > /opt/wevads/crontab-backup-$(date +%Y%m%d-%H%M).txt</code></div>
<div class="safe">✅ Vérifier le nombre de lignes APRÈS : <code>crontab -l | grep -c "^\*\|^[0-9]"</code></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">Ethica validator → validator-safe : sed sur crontab peut corrompre</div>
<div class="trap-tags"><span>cron</span><span>ethica</span><span>sed</span></div></div>
</div>
<div class="trap-body">
<p class="incident">📛 sed sur le crontab pour switcher ethica-validator → ethica-validator-safe a corrompu le crontab → restauration backup nécessaire</p>
<div class="safe">✅ Éditer manuellement avec <code>crontab -e</code> ou exporter/modifier/réimporter proprement</div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 8: PHP/FPM ═══════════ -->
<div class="section" id="s8">
<div class="section-header">
<span class="ico">🐘</span>
<h2>PHP / FPM — Syntaxe, display_errors, timeout</h2>
<span class="sev sev-high">HIGH</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">display_errors = On → leak d'infos sensibles au client</div>
<div class="trap-tags"><span>php</span><span>sécurité</span></div></div>
</div>
<div class="trap-body">
<p>WEVIA avait <code>display_errors=On</code> en production → paths serveur, credentials DB, stack traces visibles dans les réponses API.</p>
<div class="safe">✅ Toujours <code>display_errors=Off</code> en production. Logs dans error_log.</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">php -l OBLIGATOIRE après chaque modification PHP</div>
<div class="trap-tags"><span>php</span><span>syntaxe</span></div></div>
</div>
<div class="trap-body">
<p>Après édition via CX proxy ou sed, des erreurs de syntaxe PHP passent inaperçues (fichier vide, quote manquante, variable non fermée). La page retourne un 500 silencieux.</p>
<div class="safe">✅ Après CHAQUE modif : <code>php -l fichier.php</code></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">PHP-FPM max_children 50 → timeout sous charge</div>
<div class="trap-tags"><span>php-fpm</span><span>performance</span></div></div>
</div>
<div class="trap-body">
<p>Avec 50 max_children, les requêtes concurrentes (surtout avec les LLM qui prennent 15-45s) saturaient PHP-FPM. Augmenté à 100.</p>
<div class="safe">✅ Propale/CDC avec 4000 tokens → timeout 60s. Ajuster CURLOPT_TIMEOUT selon le mode</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">weval-chatbot-api.php = 134KB monolithe — ne JAMAIS réécrire</div>
<div class="trap-tags"><span>php</span><span>monolithe</span></div></div>
</div>
<div class="trap-body">
<p>Le backend chatbot fait 134KB avec 751 fonctions. Toute réécriture = régression massive. Interventions chirurgicales ONLY.</p>
<div class="safe">✅ str_replace chirurgical dans Python, jamais sed. Backup avant chaque modif.</div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 9: POSTGRESQL ═══════════ -->
<div class="section" id="s9">
<div class="section-header">
<span class="ico">🗄️</span>
<h2>PostgreSQL — dblink, schema, migration</h2>
<span class="sev sev-medium">MEDIUM</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">PG TCP connexion — localhost vs 127.0.0.1 vs IP</div>
<div class="trap-tags"><span>postgresql</span><span>connexion</span></div></div>
</div>
<div class="trap-body">
<p>pg_hba.conf distingue connexions socket (localhost) et TCP (127.0.0.1). Certaines apps utilisent l'un, certaines l'autre. Le fix TCP a été appliqué pour Ethica.</p>
<div class="safe">✅ PG = localhost only. Jamais exposer sur l'IP publique.</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">Schema admin vs schema ethica vs public — confusion fréquente</div>
<div class="trap-tags"><span>postgresql</span><span>schema</span></div></div>
</div>
<div class="trap-body">
<p>adx_system contient le schema <code>admin</code> (WEVADS) et le schema <code>ethica</code>. adx_clients est la DB contacts. Le dblink bridge connecte les deux.</p>
<div class="danger">NE JAMAIS confondre les schemas. Toujours préfixer : <code>admin.table</code> ou <code>ethica.table</code></div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 10: THREE.JS / FRONTEND ═══════════ -->
<div class="section" id="s10">
<div class="section-header">
<span class="ico">🎮</span>
<h2>Three.js / Frontend — Versions, imports, CSS</h2>
<span class="sev sev-high">HIGH</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">Three.js r128 vs r170 — CapsuleGeometry n'existe pas en r128</div>
<div class="trap-tags"><span>threejs</span><span>version</span></div></div>
</div>
<div class="trap-body">
<p>agents-archi.html utilise Three.js r170 ESM via import maps. <code>THREE.CapsuleGeometry</code> a été introduit en r142. Les anciens exemples Claude utilisent r128 → crash.</p>
<div class="danger">JAMAIS utiliser r128 pour agents-archi. Toujours r170 ESM avec import maps.</div>
<div class="safe">✅ Alternatives en r128 : <code>CylinderGeometry</code>, <code>SphereGeometry</code>, ou geometries custom</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">IIFE })(); emportée par suppression de script → casse TOUT le JS</div>
<div class="trap-tags"><span>javascript</span><span>iife</span><span>scope</span></div></div>
</div>
<div class="trap-body">
<p class="incident">📛 Session 9-10 avril : suppression d'un bloc script a emporté le <code>})();</code> du IIFE Bottom-Up → tout le JS de la page crashait</p>
<div class="safe">✅ Quand tu supprimes un script, vérifier que les IIFE fermantes sont intactes</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">JS = AJOUTER, jamais écraser — zéro régression site</div>
<div class="trap-tags"><span>javascript</span><span>site</span></div></div>
</div>
<div class="trap-body">
<p>Le site utilise <code>weval-enrich.js</code> (Claude A), <code>wevia.html</code> (Claude B), <code>wevia-api.php</code> (Claude C). Chaque Claude a son domaine. Ne JAMAIS écraser les fichiers d'un autre Claude.</p>
<div class="safe">✅ Toujours tester TOUTES les pages AVANT et APRÈS modification JS</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">wevia.html = 147KB monolithe — éditions chirurgicales ONLY</div>
<div class="trap-tags"><span>wevia</span><span>html</span><span>monolithe</span></div></div>
</div>
<div class="trap-body">
<p>Le chatbot fullscreen est un seul fichier HTML de 147KB avec CSS+JS intégrés. Ne JAMAIS réécrire en entier.</p>
</div>
</div>
</div>
<!-- ═══════════ SECTION 11: WEVIA CHATBOT ═══════════ -->
<div class="section" id="s11">
<div class="section-header">
<span class="ico">🤖</span>
<h2>WEVIA Chatbot — Routing, providers, leaks</h2>
<span class="sev sev-high">HIGH</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-fatal">!</div>
<div><div class="trap-title">Tous les intents routés sur GPU 8b = réponses superficielles</div>
<div class="trap-tags"><span>wevia</span><span>routing</span><span>llm</span></div></div>
</div>
<div class="trap-body">
<p>Par défaut, smartRoute() envoyait TOUT (sauf consulting) sur llama3.1:8b GPU. Trop petit pour du consulting, analysis, medical, creative.</p>
<p class="incident">📛 "SAP vs Oracle" → réponse de 2 lignes générique au lieu d'analyse détaillée</p>
<p class="incident">📛 Schema/Mermaid → texte brut au lieu de diagramme (8b ignore les instructions mermaid)</p>
<div class="safe">✅ Smart Router v5 : 33 patterns, 12 engines. Greeting→8b, Code→14b, Heavy→32b ou Groq 70b</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">Leak "Moteur neuro-symbolique" dans les réponses</div>
<div class="trap-tags"><span>wevia</span><span>leak</span><span>prompt</span></div></div>
</div>
<div class="trap-body">
<p><code>applyBusinessRules()</code> appendait des métadonnées internes dans la réponse visible au client.</p>
<div class="safe">✅ Déplacé en metadata JSON <code>rules_warning</code> — invisible au client</div>
<div class="safe">✅ final-sanitizer.php : strips 12 patterns de prompt leak + emojis + headers "Analyse"</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">JAMAIS exposer GPU/modèle/temps au client</div>
<div class="trap-tags"><span>wevia</span><span>sécurité</span></div></div>
</div>
<div class="trap-body">
<p>Les réponses API contenaient <code>provider: "deepseek_gpu"</code>, <code>model: "llama3.1:8b"</code>, <code>latency_ms: 1200</code>. Infos internes.</p>
<div class="safe">✅ Côté public : <code>provider: "WEVAL_brain"</code>. Les détails restent dans les logs serveur.</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">Zones B/C strictement séparées — JAMAIS fusionner</div>
<div class="trap-tags"><span>wevia</span><span>architecture</span></div></div>
</div>
<div class="trap-body">
<p>Claude B = Fullscreen (<code>wevia.html</code> + <code>weval-chatbot-api.php</code>). Claude C = Widget (<code>wevia-api.php</code>). APIs backend différentes, frontends différents. Ne JAMAIS confondre.</p>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-warn"></div>
<div><div class="trap-title">Conversions = PULL, JAMAIS configurer postbacks chez CX3/DoubleM</div>
<div class="trap-tags"><span>wevads</span><span>conversion</span><span>pull</span></div></div>
</div>
<div class="trap-body">
<p>3 sessions Claude ont essayé de configurer des postback URLs chez les sponsors. ADX/iResponse utilise un modèle PULL — <code>conversions-collector.php</code> interroge les APIs CAKE/Everflow toutes les 30 minutes.</p>
<p class="incident">📛 Erreur critique répétée 3 fois sur 3 sessions différentes</p>
<div class="danger">Le code EXISTE DÉJÀ. Les API keys sont en base. Il suffit d'activer le cron.</div>
</div>
</div>
</div>
<!-- ═══════════ SECTION 12: ARCHITECTURE & WORKFLOW ═══════════ -->
<div class="section" id="s12">
<div class="section-header">
<span class="ico">🏗️</span>
<h2>Architecture & Workflow — Règles d'or</h2>
<span class="sev sev-info">RÈGLES BLOQUANTES</span>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-tech"></div>
<div><div class="trap-title">SÉQUENCE BLOQUANTE OBLIGATOIRE</div>
<div class="trap-tags"><span>workflow</span><span>obligatoire</span></div></div>
</div>
<div class="trap-body">
<pre>1. Relire mémoires → comprendre le contexte
2. Anti-Régression → chercher existant (scanner avant de créer)
3. Recul / architecture → plan
4. GOLD backup → sauvegarder l'état avant
5. git commit → git push
6. Mockup → validation Yacine EXPLICITE
7. Modifier → appliquer les changements
8. vault + checksums → mettre à jour les références
9. git add + commit + push → versionner
10. Triple verify 0 dirty → rien qui traîne</pre>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-tech"></div>
<div><div class="trap-title">STRIKE RULE — Problème 2x → STOP</div>
<div class="trap-tags"><span>workflow</span><span>debugging</span></div></div>
</div>
<div class="trap-body">
<p>Si un problème apparaît 2 fois : STOP symptôme, identifier root cause, appliquer fix structurel. Ne JAMAIS continuer à patacher.</p>
<p class="incident">📛 SSO callback 400 : patchée 5 fois en surface avant d'identifier que le JWT state était vide</p>
<p class="incident">📛 sed/heredoc : réessayé 6 fois sur chatbot-widget.php avant d'admettre que sed ne peut pas gérer les backticks</p>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-tech"></div>
<div><div class="trap-title">GOLD BACKUP — Obligatoire AVANT migration/refactor/multi-fichier/routing/DB</div>
<div class="trap-tags"><span>gold</span><span>backup</span></div></div>
</div>
<div class="trap-body">
<p>JAMAIS supprimer les GOLD. Ils sont la dernière ligne de défense quand tout casse.</p>
<div class="safe">✅ Convention : <code>fichier.gold.pre-{action}.{date}</code><br>
Exemple : <code>/etc/nginx/weval-consulting.gold.pre-auth-removal.8avr2026</code></div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-tech"></div>
<div><div class="trap-title">S204 = MTA-only — JAMAIS déployer fichiers applicatifs</div>
<div class="trap-tags"><span>architecture</span><span>serveur</span></div></div>
</div>
<div class="trap-body">
<p>S204 (204.168.152.13) héberge PMTA + WEVIA + Ethica. JAMAIS y déployer des fichiers Arsenal, ADX, ou autres apps non-MTA.</p>
<div class="safe">✅ S95 = WEVADS + Arsenal + Sentinel + PG. S204 = MTA + WEVIA + Ethica. S151 = OVH tracking.</div>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-tech"></div>
<div><div class="trap-title">SOUVERAINETÉ — Interne → open source → multi-fournisseur</div>
<div class="trap-tags"><span>philosophie</span><span>architecture</span></div></div>
</div>
<div class="trap-body">
<p>Ollama LOCAL = rang 1 partout. Cloud = fallback uniquement. Jamais single-vendor lock-in.</p>
<p>WEVIA KB = INTERNAL ONLY — jamais exposer sur site public.</p>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-tech"></div>
<div><div class="trap-title">Collecte Learn désactivée — ne pas réactiver sans validation</div>
<div class="trap-tags"><span>wevia</span><span>learn</span></div></div>
</div>
<div class="trap-body">
<p>Le collectiveLearn a été désactivé pour éviter la pollution de la KB par du contenu non validé. L'auto-learn reste actif pour les faits utilisateur explicites.</p>
</div>
</div>
<div class="trap">
<div class="trap-header" onclick="toggle(this)">
<div class="badge badge-tech"></div>
<div><div class="trap-title">mmdc Puppeteer crash sans --no-sandbox</div>
<div class="trap-tags"><span>mermaid</span><span>puppeteer</span></div></div>
</div>
<div class="trap-body">
<p>Le rendu Mermaid en PNG via mmdc (Puppeteer) crash quand exécuté en root sans <code>--no-sandbox</code>.</p>
<div class="safe">✅ puppeteerrc.cjs corrigé avec <code>args: ['--no-sandbox']</code></div>
</div>
</div>
</div>
</div>
<div style="text-align:center;padding:30px;color:var(--tx2);font-size:0.75em;border-top:1px solid var(--border)">
WEVAL Consulting — FAQ Anti-Régression v4 — Avril 2026 — Compilé depuis 6 mois de sessions Claude<br>
47 pièges · 23+ incidents · 40+ règles · 15 techniques avancées · 12 catégories
</div>
<script>
function toggle(header){
const body=header.nextElementSibling;
if(body&&body.classList.contains('trap-body')){
body.classList.toggle('open');
}
}
// Open all by default for readability
document.querySelectorAll('.trap-body').forEach(b=>b.classList.add('open'));
</script>
</body>
</html>