33800 Docs

← Retour

Audit approfondi - Dashboard 33800

Date : 15/02/2026 Status : IMPLEMENTEE Auditeur : Claude Opus 4.6 Projet : dashboard-33800 (/stock_8to/33800-stack/monitoring/) Scope : generate.d/.sh, assets/, config.json


Resume executif

Le projet dashboard-33800 est un ensemble de scripts bash generant des pages HTML statiques deployees sur O2switch (https://dashboard.nowhere84.com). L'audit a revele 42 findings repartis en 5 categories : navigation inconstante, CSS fragmente, variables CSS manquantes, hardcoding et problemes JavaScript.

Le probleme principal est l'absence de systeme de navigation unifie : il existe 4 mecanismes de navigation differents cohabitant dans le projet, chacun avec sa propre liste de liens, ce qui garantit des incoherences permanentes a chaque ajout de page.


1. NAVIGATION --- Desynchronisations multiples (CRITIQUE)

Finding 1.1 : 4 systemes de navigation coexistent

Le projet contient 4 sources de verite pour la navigation, toutes differentes :

Source Fichier Pages listees
A gen_header() _common.sh (L88-114) 14 liens
B _gen_header() 01-index.sh (L17-57) 17 liens
C nav.js assets/nav.js (L3-23) 18 liens
D Inline hardcode Chaque module (.sh) Variable

Detail des divergences :

Page _common.sh (A) 01-index.sh (B) nav.js (C) 02-alerts.sh 13-models.sh 18-ai-tools.sh 19-ai-orchestrator.sh 20-ai-jobs.sh
Dashboard oui oui oui oui oui oui oui oui
Alertes oui -- oui oui (active) oui oui -- oui
Liens oui -- oui oui oui oui -- --
Montages oui oui oui oui oui oui -- --
Nginx oui oui oui oui oui oui -- --
API oui oui oui oui oui oui oui oui
Archi oui -- -- -- -- -- oui --
Doc oui oui oui oui oui oui oui --
Modeles oui oui oui oui oui (active) oui oui --
AI Tools -- oui oui -- -- oui (active) oui --
AI Orchestrator -- oui oui -- -- -- -- --
AI Jobs oui -- oui -- -- oui oui (active) oui (active)
Secrets oui oui oui oui oui oui -- --
Crons oui oui oui oui oui oui -- oui
RAIDZ oui oui oui oui oui oui -- oui
Services oui oui oui oui oui oui -- oui
Syncthing -- oui oui -- -- -- -- --
LinkedIn -- oui oui -- -- -- -- --
Schema -- oui oui -- -- -- -- --
O2switch -- oui oui -- -- -- -- --
Claude oui -- -- -- -- -- -- --

Finding 1.2 : nav.js jamais utilise

Le fichier assets/nav.js (L1-44) fournit un systeme de navigation centralisee via JavaScript (cherche un element #main-nav). Mais aucun module ne genere de <nav id="main-nav">. Ce fichier n'est jamais inclus dans le <script> des pages generees. Il est donc mort.

Finding 1.3 : La page architecture.html est dans certaines navs mais absente d'autres

La page architecture.html est referencee dans :

Finding 1.4 : La page claude.html est uniquement dans _common.sh

La page claude.html est generee par 26-claude.sh et apparait uniquement dans la nav _common.sh gen_header (L109). Elle est absente de nav.js, de 01-index.sh, et de toutes les navigations inline des autres modules.

Finding 1.5 : shortlinks.html referencee mais generation non trouvee dans generate.d/

Le lien shortlinks.html figure dans la plupart des navigations, mais aucun fichier *shortlinks*.sh n'existe dans generate.d/. La page est peut-etre generee dans le generate.sh principal ou deploye manuellement. Le deploiement SCP dans 01-index.sh (L1372-1374) copie shortlinks.html depuis MONITORING_DIR si existant.


2. CSS --- Double fichier, variables manquantes (MAJEUR)

Finding 2.1 : Deux fichiers CSS identiques (95%) avec divergences

Les 689 premieres lignes de style.css sont identiques a dashboard.css. Puis style.css ajoute ~520 lignes supplementaires (sections 21-30 : metrics, info-rows, VM lists, ZFS pools, crons, etc.).

Probleme : Les pages referent assets/style.css. dashboard.css semble etre un vestige ou une version anterieure non nettoyee.

Finding 2.2 : style.css vs dashboard.css -- divergences mineures dans la partie commune

Dans la partie commune (sections 1-20), style.css contient quelques differences :

Cela suggere que style.css est la version active/evoluee et dashboard.css est obsolete.

Finding 2.3 : Variables CSS manquantes dans certains modules

Plusieurs modules utilisent des variables CSS qui n'existent PAS dans style.css :

Variable utilisee Module(s) Existe dans style.css ?
--bg-secondary 18-ai-tools.sh (L26), 13-models.sh NON
--bg-tertiary 18-ai-tools.sh (L77), 13-models.sh NON
--border-color 18-ai-tools.sh (L30,38), 13-models.sh NON
--text-primary 18-ai-tools.sh (L42) NON
--text-secondary 13-models.sh (L26,41,56) NON
--accent-blue 18-ai-tools.sh (L89), 13-models.sh (L37) NON
--accent-green 18-ai-tools.sh (L66), 13-models.sh NON
--accent-orange 18-ai-tools.sh (L60), 13-models.sh NON
--accent-red 18-ai-tools.sh (L144) NON
--bg-hover 26-claude.sh (L98) NON
--bg-main 26-claude.sh (L129,153) NON
--text-dim 20-ai-jobs.sh (L339,461) NON
--card-bg 01-index.sh (L730) NON

Les variables definies dans style.css sont : --bg-dark, --bg-card, --bg-card-hover, --bg-input, --border, --border-hover, --text, --text-muted, --text-bright, --green, --yellow, --red, --blue, --purple, --orange, --cyan, --space-*, --radius-*, --shadow-*, --header-height.

Consequence : Les proprietes utilisant ces variables non definies sont ignorees par le navigateur, causant un rendu inconsistant (fond transparent, texte invisible, bordures manquantes).

Finding 2.4 : 25-services.sh a son propre design systeme complet

Le module 25-services.sh ne charge PAS assets/style.css. Il integre un design systeme entierement different et autonome (L49-240), avec :

Cette page a un look totalement different de toutes les autres.


3. HARDCODING --- IPs et modeles en dur (MAJEUR)

Finding 3.1 : IP hardcodee dans 19-ai-orchestrator.sh

# Ligne 13
local API_URL="http://192.168.1.12:5501"

Devrait utiliser get_host_ip "prod-portainer" et get_config ".services.ai-orchestrator.port".

Finding 3.2 : IPs hardcodees dans 18-ai-tools.sh (page entiere)

Toute la page ai-tools.html est un heredoc statique, y compris :

Contrairement a 13-models.sh qui applique un sed post-generation pour remplacer les IPs (L246-249), 18-ai-tools.sh ne fait aucune substitution.

Finding 3.3 : IPs dans les footers hardcodes

Les modules suivants ont des footers avec IPs en dur au lieu d'utiliser gen_footer_full() :

Finding 3.4 : Modeles Ollama listes en dur

13-models.sh contient une table HTML statique de modeles (llama3.2, mistral, qwen2.5:7b, etc.) directement dans le heredoc (L112-137). Ces modeles sont figes au moment de l'ecriture du script. Aucune mise a jour dynamique.

Egalement dans 01-index.sh : la recommendation dans le texte (L143-166, qwen3:4b) ne correspond pas aux modeles de la table de 13-models.sh.

Finding 3.5 : Port browser-connector hardcode

15-linkedin.sh (L16) hardcode BROWSER_PORT=5401. Ce port devrait etre lu depuis config.json. Nota : config.json liste browser-connector sur le port 5401, mais le CLAUDE.md mentionne que le port reel est 5404, pas 5401. Inconsistance potentielle.


4. JAVASCRIPT --- Problemes de polling et API calls (MOYEN)

Finding 4.1 : 19-ai-orchestrator.sh -- polling agressif de 15 secondes

// Ligne 650
setInterval(refreshAll, 15000);

La page effectue un refreshAll() toutes les 15s, qui fait 2 appels API a chaque fois (/api/gpu et /api/tools/refresh). Cela represente ~11520 appels/jour pour un utilisateur qui laisse l'onglet ouvert. Le polling devrait idealement utiliser document.visibilityState pour se desactiver quand l'onglet n'est pas visible.

Finding 4.2 : 20-ai-jobs.sh -- pas de polling JS malgre le commentaire

Ligne 49 du heredoc :

<!-- Auto-refresh disabled - using JS polling instead to preserve modal state -->

Mais je n'ai pas trouve de setInterval ou equivalent dans la partie JS de la page (la partie JS est injectee plus loin dans le fichier, au-dela de la ligne 1400 que je n'ai pas lue integralement). Le meta-refresh est desactive mais si aucun polling n'est present, la page est statique apres chargement initial sauf pour le refresh GPU live.

Finding 4.3 : 20-ai-jobs.sh -- variable CSS --orange non definie utilisee dans le CSS

Ligne 523 :

background: linear-gradient(135deg, var(--yellow), var(--orange, #f97316));

La notation var(--orange, #f97316) fournit un fallback, ce qui est correct. Cependant, --orange EST definie dans style.css comme #f0883e, donc le fallback est inutile mais pas nuisible.

Finding 4.4 : data-loader.js jamais utilise

Le fichier assets/data-loader.js (L1-142) est un systeme generique de chargement de donnees via data/current.json avec data-binding sur le DOM. Mais aucune page ne l'inclut en <script>. Il utilise des conventions (data-bind, data-format) qu'aucune page n'emploie. Ce fichier est mort.

Finding 4.5 : 01-index.sh -- updateAlertsBadge() reference un element inexistant

// Ligne 1239
var badge = document.getElementById('alerts-badge');

Mais aucun element avec id="alerts-badge" n'est genere dans le HTML de 01-index.sh. La fonction countAlerts() est appelee mais le badge n'est jamais mis a jour car l'element n'existe pas.


5. ARCHITECTURE & DEPLOIEMENT (MOYEN)

Finding 5.1 : Double deploiement contradictoire dans 01-index.sh

Le module 01-index.sh fait :

  1. deploy_page "$OUTPUT_FILE" "index.html" (L1363) -- copie dans le repo git pour O2switch
  2. scp direct vers nginx (L1373-1378) -- deploiement de shortlinks.html et assets/

Cela signifie que la page index va vers O2switch mais que les assets et shortlinks sont aussi pousses vers le nginx local. Ce double deploiement est inconsistant avec le principe "dashboard = O2switch uniquement".

Finding 5.2 : gen_footer_full() dans _common.sh non utilise

La fonction gen_footer_full() (L124-180) de _common.sh genere un footer dynamique depuis config.json. Mais les modules n'utilisent pas cette fonction :

Finding 5.3 : gen_html_head() dans _common.sh partiellement utilisee

La fonction gen_html_head() genere un <head> standard avec assets/style.css?v=$(date +%s). Mais la plupart des modules utilisent leur propre heredoc sans appeler cette fonction, avec des timestamps figes (?v=1767876396) ou sans cache-buster du tout.

Finding 5.4 : 25-services.sh -- ne deploie pas avec deploy_page()

Le module 25-services.sh ne contient aucun appel a deploy_page() a la fin de sa fonction generate_services(). La page est generee dans $OUTPUT_DIR mais jamais copiee vers le repo git. Elle depend du script parent pour etre deployee.

Finding 5.5 : Fichiers non generes mais references


6. PROBLEMES MINEURS

Finding 6.1 : style.css version parameter hardcode

Plusieurs modules utilisent ?v=1767876396 comme cache-buster (L22 de 02-alerts.sh, 04-secrets.sh, 05-endpoints.sh, etc.) au lieu de ?v=$(date +%s) que la fonction gen_html_head() genererait dynamiquement. Le timestamp 1767876396 correspond a environ juin 2026, donc c'est un timestamp futur force.

Finding 6.2 : 02-alerts.sh -- nameMap hardcode

Ligne 84 de 02-alerts.sh :

const nameMap = { 'pve': 'PVE', 'proxmox1': 'Proxmox', 'docker-prod': 'prod-portainer', ... };

Contrairement a 01-index.sh qui genere le nameMap depuis CONFIG.hosts dynamiquement, 02-alerts.sh le hardcode.

Finding 6.3 : Template HTML non unifie

Le <body> HTML commence differemment selon les modules :

Finding 6.4 : 20-ai-jobs.sh -- taille disproportionnee

Le module 20-ai-jobs.sh fait plus de 1500 lignes. Il contient le CSS (770+ lignes), le HTML statique, la generation bash des job cards, le JavaScript complet, et les formulaires pour tous les outils. Ce fichier devrait etre decoupe.

Finding 6.5 : 14-syncthing.sh -- Device ID potentiellement expose

Ligne 18 :

local device_id=$(ssh ... || echo "SRJERHI-YFX33A4-EOSJJZZ-P37FO7P-JXSA7X7-P3FBPWR-QNWJT4Z-NLBZ5AO")

Le device ID Syncthing est hardcode en fallback. Ce n'est pas un secret (les device IDs sont conçus pour etre partages), mais le hardcoder signifie qu'un changement de device ne se reflete pas dans la page si SSH echoue.


7. RECAPITULATIF PAR SEVERITE

CRITIQUE (a corriger en priorite)

# Finding Impact
1.1 4 systemes de navigation differents Pages inaccessibles, liens manquants, UX cassee
2.3 14+ variables CSS non definies Rendu visuel casse sur ai-tools, models, claude, ai-jobs

MAJEUR (a corriger)

# Finding Impact
1.2 nav.js jamais utilise Code mort
1.4 claude.html absent de presque toutes les navs Page orpheline
2.1 Deux fichiers CSS (dashboard.css = obsolete) Confusion maintenance
2.4 services.html design totalement different Rupture visuelle
3.1 IP hardcodee dans ai-orchestrator.sh Cassera si IP change
3.2 IPs hardcodees dans ai-tools.sh Cassera si IP change

MOYEN (a ameliorer)

# Finding Impact
4.1 Polling 15s sans check visibilite onglet Charge API inutile
4.4 data-loader.js jamais utilise Code mort
4.5 updateAlertsBadge reference element inexistant Fonctionnalite silencieusement cassee
5.1 Double deploiement (O2switch + SCP nginx) Confusion deploiement
5.2 gen_footer_full() jamais utilisee Code mort, footers inconsistants
5.3 gen_html_head() rarement utilisee Cache-busters figes

MINEUR (nice to have)

# Finding Impact
6.1 Cache-buster fige ?v=1767876396 Cache navigateur pas invalide
6.2 nameMap hardcode dans alerts.sh Maintenance manuelle
6.3 Template HTML non unifie Qualite code
6.4 20-ai-jobs.sh > 1500 lignes Maintenabilite

8. RECOMMANDATIONS (par ordre de priorite)

R1 : Unifier la navigation (CRITIQUE)

Choisir UNE SEULE source de verite pour la navigation. Deux options :

Supprimer les navigations inline hardcodees dans chaque module.

R2 : Definir les variables CSS manquantes (CRITIQUE)

Ajouter dans style.css les aliases manquants :

:root {
    --bg-secondary: var(--bg-card);
    --bg-tertiary: var(--bg-input);
    --bg-hover: var(--bg-card-hover);
    --bg-main: var(--bg-dark);
    --border-color: var(--border);
    --text-primary: var(--text-bright);
    --text-secondary: var(--text-muted);
    --text-dim: var(--text-muted);
    --accent-blue: var(--blue);
    --accent-green: var(--green);
    --accent-orange: var(--orange);
    --accent-red: var(--red);
    --accent: var(--cyan);
    --card-bg: var(--bg-card);
}

R3 : Supprimer dashboard.css (MAJEUR)

Verifier qu'aucune page ne le reference, puis le supprimer.

R4 : Eliminer les IPs hardcodees (MAJEUR)

Remplacer les IPs en dur dans 18-ai-tools.sh et 19-ai-orchestrator.sh par les fonctions get_host_ip() / get_config().

R5 : Supprimer les fichiers morts (MOYEN)

R6 : Aligner 25-services.sh sur le design commun (MOYEN)

Ajouter <link rel="stylesheet" href="assets/style.css"> et utiliser les classes standard.

R7 : Ajouter visibilitychange au polling (MINEUR)

document.addEventListener('visibilitychange', () => {
    if (document.hidden) clearInterval(pollInterval);
    else pollInterval = setInterval(refreshAll, 15000);
});

Annexe : Liste des fichiers audites

Fichier Lignes Lu en entier
generate.d/_common.sh 196 oui
generate.d/01-index.sh 1393 oui
generate.d/02-alerts.sh 139 oui
generate.d/03-doc.sh ~800 partiel (30 lignes)
generate.d/04-secrets.sh ~400 partiel (30 lignes)
generate.d/05-endpoints.sh ~500 partiel (30 lignes)
generate.d/06-montages.sh ~300 partiel (30 lignes)
generate.d/07-nginx.sh ~400 partiel (30 lignes)
generate.d/08-crons.sh ~300 partiel (30 lignes)
generate.d/09-architecture.sh ~500 partiel (30 lignes)
generate.d/12-raidz.sh ~300 partiel (30 lignes)
generate.d/13-models.sh 272 oui
generate.d/14-syncthing.sh 433 oui
generate.d/15-linkedin.sh ~400 partiel (50 lignes)
generate.d/16-o2switch.sh ~300 partiel (50 lignes)
generate.d/17-schema.sh ~200 partiel (50 lignes)
generate.d/18-ai-tools.sh 1052 oui
generate.d/19-ai-orchestrator.sh 663 oui
generate.d/20-ai-jobs.sh ~1500+ partiel (1400 lignes)
generate.d/25-services.sh 625 oui
generate.d/26-claude.sh 323 oui
assets/style.css 1210 oui
assets/dashboard.css 689 oui
assets/nav.js 44 oui
assets/data-loader.js 142 oui
config.json 229 oui

Total : 26 fichiers audites, ~11000 lignes lues.