secubox-openwrt/docs-fr/development-guidelines.md
CyberMind-FR ccfb58124c docs: Add trilingual documentation (French and Chinese translations)
Add complete French (fr) and Chinese (zh) translations for all documentation:

- Root files: README, CHANGELOG, SECURITY, BETA-RELEASE
- docs/: All 16 core documentation files
- DOCS/: All 19 deep-dive documents including embedded/ and archive/
- package/secubox/: All 123+ package READMEs
- Misc: secubox-tools/, scripts/, EXAMPLES/, config-backups/, streamlit-apps/

Total: 346 translation files created

Each file includes language switcher links for easy navigation between
English, French, and Chinese versions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-20 10:00:18 +01:00

51 KiB

SecuBox & System Hub - Guide de Développement

Langues disponibles: English | Français | 中文

Version: 1.0.0 Dernière mise à jour: 2025-12-28 Statut: Actif Audience: Développeurs, assistants IA, mainteneurs

Ce document définit les standards, bonnes pratiques et validations obligatoires pour le développement de modules SecuBox et System Hub dans l'écosystème OpenWrt LuCI.


Table des matières

  1. Design System & Directives UI
  2. Architecture & Conventions de nommage
  3. Bonnes pratiques RPCD & ubus
  4. ACL & Permissions
  5. Patterns JavaScript
  6. Standards CSS/Styles
  7. Erreurs courantes & Solutions
  8. Liste de vérification
  9. Procédures de déploiement
  10. Fichiers contextuels pour assistants IA

Design System & Directives UI

Palette de couleurs (inspirée de la démo)

IMPORTANT: Toujours utiliser la palette définie dans system-hub/common.css

Mode sombre (Principal - Recommandé)

--sh-text-primary: #fafafa;
--sh-text-secondary: #a0a0b0;
--sh-bg-primary: #0a0a0f;      /* Fond principal (noir profond) */
--sh-bg-secondary: #12121a;     /* Fond cartes/sections */
--sh-bg-tertiary: #1a1a24;      /* Fond survol/actif */
--sh-bg-card: #12121a;
--sh-border: #2a2a35;
--sh-primary: #6366f1;          /* Indigo */
--sh-primary-end: #8b5cf6;      /* Violet (pour dégradés) */
--sh-success: #22c55e;          /* Vert */
--sh-danger: #ef4444;           /* Rouge */
--sh-warning: #f59e0b;          /* Orange */

Mode clair (Secondaire)

--sh-text-primary: #0f172a;
--sh-text-secondary: #475569;
--sh-bg-primary: #ffffff;
--sh-bg-secondary: #f8fafc;
--sh-bg-tertiary: #f1f5f9;
--sh-bg-card: #ffffff;
--sh-border: #e2e8f0;

TOUJOURS utiliser les variables CSS - Ne JAMAIS coder les couleurs en dur.

Typographie

Pile de polices

/* Texte général */
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;

/* Valeurs numériques, IDs, code */
font-family: 'JetBrains Mono', 'Courier New', monospace;

Import requis (ajouté dans common.css):

@import url('https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600;700&family=Inter:wght@400;500;600;700&display=swap');

Tailles de police

/* Titres */
--sh-title-xl: 28px;    /* Titres de page */
--sh-title-lg: 20px;    /* Titres de carte */
--sh-title-md: 16px;    /* En-têtes de section */

/* Texte */
--sh-text-base: 14px;   /* Corps du texte */
--sh-text-sm: 13px;     /* Labels, méta */
--sh-text-xs: 11px;     /* Labels majuscules */

/* Valeurs */
--sh-value-xl: 40px;    /* Grandes métriques */
--sh-value-lg: 32px;    /* Aperçu statistiques */
--sh-value-md: 28px;    /* Badges */

Patterns de composants

Hiérarchie des composants

Le diagramme suivant montre la structure standard de page et les relations entre composants:

graph TB
    PAGE[Page Container<br/>.module-dashboard] --> HEADER[sh-page-header]
    PAGE --> CONTENT[sh-content]

    HEADER --> TITLE_SECTION[Title Section<br/>div]
    HEADER --> STATS[sh-stats-grid]

    TITLE_SECTION --> TITLE[sh-page-title<br/>gradient text]
    TITLE_SECTION --> SUBTITLE[sh-page-subtitle]

    STATS --> BADGE1[sh-stat-badge]
    STATS --> BADGE2[sh-stat-badge]
    STATS --> BADGE3[...]

    BADGE1 --> VALUE1[sh-stat-value<br/>monospace font]
    BADGE1 --> LABEL1[sh-stat-label<br/>uppercase]

    CONTENT --> TABS[sh-filter-tabs]
    CONTENT --> CARD_GRID[Card Grid<br/>grid layout]

    TABS --> TAB1[sh-filter-tab<br/>active]
    TABS --> TAB2[sh-filter-tab]

    CARD_GRID --> CARD1[sh-card]
    CARD_GRID --> CARD2[sh-card-success]
    CARD_GRID --> CARD3[sh-card-danger]

    CARD1 --> CH1[sh-card-header]
    CARD1 --> CB1[sh-card-body]

    CH1 --> CT1[sh-card-title]
    CT1 --> ICON1[sh-card-title-icon]

    CB1 --> BUTTONS[Button Group]
    CB1 --> INFO[Info Rows]

    BUTTONS --> BTN1[sh-btn<br/>sh-btn-primary]
    BUTTONS --> BTN2[sh-btn<br/>sh-btn-secondary]

    style PAGE fill:#0a0a0f,color:#fafafa,stroke:#6366f1,stroke-width:3px
    style HEADER fill:#12121a,color:#fafafa,stroke:#6366f1,stroke-width:2px
    style CONTENT fill:#12121a,color:#fafafa,stroke:#6366f1,stroke-width:2px
    style CARD1 fill:#12121a,color:#fafafa,stroke:#6366f1,stroke-width:2px
    style CARD2 fill:#12121a,color:#fafafa,stroke:#22c55e,stroke-width:2px
    style CARD3 fill:#12121a,color:#fafafa,stroke:#ef4444,stroke-width:2px
    style TITLE fill:#6366f1,color:#fff
    style BTN1 fill:#6366f1,color:#fff
    style VALUE1 fill:#8b5cf6,color:#fff

Catégories de composants:

  1. Conteneurs de mise en page: Wrapper de page, en-tête, sections de contenu
  2. Typographie: Titres avec effets dégradés, sous-titres, labels
  3. Affichage de données: Badges de stats avec valeurs monospace, cartes avec bordures
  4. Navigation: Onglets filtres, onglets navigation (sticky)
  5. Interactif: Boutons avec dégradés et effets de survol

Règles de style:

  • Cartes: Bordure supérieure 3px (dégradé au survol, ou colorée pour le statut)
  • Badges stats: Largeur minimum 130px, police monospace pour les valeurs
  • Boutons: Fonds en dégradé, ombre au survol, transitions douces
  • Onglets: État actif avec fond en dégradé et lueur
  • Grilles: Auto-fit avec minimums (130px, 240px, ou 300px)

1. En-tête de page (Standard)

EXIGENCE: Chaque vue de module DOIT commencer avec ce .sh-page-header compact. N'introduisez pas de sections hero personnalisées ou de bannières surdimensionnées; l'en-tête garde une hauteur prévisible (titre + sous-titre à gauche, stats à droite) et garantit la cohérence entre les tableaux de bord SecuBox. Si aucune stat n'est nécessaire, gardez le conteneur mais fournissez un .sh-stats-grid vide pour les métriques futures.

Variante slim: Quand la page n'a besoin que de 2-3 métriques, utilisez .sh-page-header-lite + .sh-header-chip (voir luci-app-vhost-manager et les paramètres luci-app-secubox). Les chips portent un emoji/icône, un petit label, et la valeur; les couleurs (.success, .danger, .warn) communiquent l'état. Cette variante remplace les blocs hero volumineux des anciennes démos.

Chip de version: Exposez toujours la version du package depuis le backend RPC (lu depuis /usr/lib/opkg/info/<pkg>.control) et affichez-la comme premier chip (icon: ). Cela maintient l'UI et PKG_VERSION synchronisés sans chercher des chaînes codées en dur.

Structure HTML:

E('div', { 'class': 'sh-page-header' }, [
    E('div', {}, [
        E('h2', { 'class': 'sh-page-title' }, [
            E('span', { 'class': 'sh-page-title-icon' }, '🎯'),
            'Titre de la page'
        ]),
        E('p', { 'class': 'sh-page-subtitle' }, 'Description de la page')
    ]),
    E('div', { 'class': 'sh-stats-grid' }, [
        // Badges de stats ici
    ])
])

Classes CSS:

  • .sh-page-header - Conteneur avec mise en page flex
  • .sh-page-title - Effet texte en dégradé
  • .sh-page-title-icon - Icône (sans dégradé)
  • .sh-page-subtitle - Texte secondaire
  • .sh-stats-grid - Grille pour badges (130px min)

2. Badges de statistiques

RÈGLE: Minimum 130px, police monospace pour les valeurs

E('div', { 'class': 'sh-stat-badge' }, [
    E('div', { 'class': 'sh-stat-value' }, '92'),
    E('div', { 'class': 'sh-stat-label' }, 'CPU %')
])

Mise en page grille:

.sh-stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
    gap: 12px;
}

3. Cartes avec bordure colorée

OBLIGATOIRE: Toutes les cartes doivent avoir une bordure supérieure de 3px

E('div', { 'class': 'sh-card sh-card-success' }, [
    E('div', { 'class': 'sh-card-header' }, [
        E('h3', { 'class': 'sh-card-title' }, [
            E('span', { 'class': 'sh-card-title-icon' }, '⚙️'),
            'Titre de la carte'
        ])
    ]),
    E('div', { 'class': 'sh-card-body' }, [
        // Contenu
    ])
])

Variantes de bordure:

  • .sh-card - Bordure en dégradé (visible au survol)
  • .sh-card-success - Bordure verte permanente
  • .sh-card-danger - Bordure rouge permanente
  • .sh-card-warning - Bordure orange permanente

4. Boutons

Boutons en dégradé (préférés):

E('button', { 'class': 'sh-btn sh-btn-primary' }, 'Action principale')
E('button', { 'class': 'sh-btn sh-btn-success' }, 'Action réussie')
E('button', { 'class': 'sh-btn sh-btn-danger' }, 'Action dangereuse')
E('button', { 'class': 'sh-btn sh-btn-secondary' }, 'Action secondaire')

Tous les boutons doivent avoir:

  • Effet d'ombre (déjà dans CSS)
  • Animation au survol (translateY(-2px))
  • Transition douce (0.3s cubic-bezier)

5. Onglets de filtre

E('div', { 'class': 'sh-filter-tabs' }, [
    E('div', {
        'class': 'sh-filter-tab active',
        'data-filter': 'all'
    }, [
        E('span', { 'class': 'sh-tab-icon' }, '📋'),
        E('span', { 'class': 'sh-tab-label' }, 'Tous')
    ])
])

Style de l'onglet actif:

  • Fond: dégradé indigo-violet
  • Couleur: blanc
  • Box-shadow avec lueur

Systèmes de grille

Aperçu stats (Compact)

grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
gap: 16px;

Cartes métriques (Moyen)

grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 20px;

Cartes info (Grand)

grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;

Effets de dégradé

Texte en dégradé (Titres)

background: linear-gradient(135deg, var(--sh-primary), var(--sh-primary-end));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;

Utiliser: la classe .sh-gradient-text ou .sh-page-title

Fonds en dégradé (Boutons, Badges)

background: linear-gradient(135deg, var(--sh-primary), var(--sh-primary-end));

Bordures en dégradé (Haut)

/* Bordure supérieure 3px avec dégradé */
.element::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--sh-primary), var(--sh-primary-end));
}

Standards d'animation

Effets de survol

transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
transform: translateY(-3px);  /* Cartes */
transform: translateY(-2px);  /* Boutons, badges */

Progression des ombres

/* Par défaut */
box-shadow: none;

/* Survol - Subtil */
box-shadow: 0 8px 20px var(--sh-shadow);

/* Survol - Prononcé */
box-shadow: 0 12px 28px var(--sh-hover-shadow);

/* Survol bouton */
box-shadow: 0 8px 20px rgba(99, 102, 241, 0.5);

Architecture & Conventions de nommage

Vue d'ensemble de l'architecture système

Le diagramme suivant illustre le flux de données complet du JavaScript navigateur au backend système:

graph TB
    subgraph "Navigateur"
        UI[Vue JavaScript<br/>view/module/overview.js]
        API[Module API<br/>module/api.js]
    end

    subgraph "Framework LuCI"
        RPC[Couche RPC<br/>L.rpc.declare]
        UHTTPD[uhttpd<br/>Serveur Web]
    end

    subgraph "Services Backend"
        RPCD[Daemon RPCD]
        SCRIPT[Script RPCD<br/>/usr/libexec/rpcd/luci.module-name]
        UBUS[Bus de messages ubus]
    end

    subgraph "Couche Système"
        UCI[Configuration UCI]
        SYS[Services Système<br/>scripts init.d]
        FS[Système de fichiers<br/>proc, sys, etc]
    end

    UI -->|"API.getStatus()"| API
    API -->|"rpc.declare({ object: 'luci.module' })"| RPC
    RPC -->|"HTTP POST /ubus"| UHTTPD
    UHTTPD -->|"appel méthode"| RPCD
    RPCD -->|"exécute script"| SCRIPT
    SCRIPT -->|"ubus call"| UBUS
    UBUS -->|"lecture/écriture"| UCI
    UBUS -->|"contrôle"| SYS
    SCRIPT -->|"lecture métriques"| FS

    style UI fill:#6366f1,color:#fff,stroke:#4f46e5
    style API fill:#8b5cf6,color:#fff,stroke:#7c3aed
    style SCRIPT fill:#22c55e,color:#fff,stroke:#16a34a
    style RPCD fill:#f59e0b,color:#fff,stroke:#d97706
    style UCI fill:#ef4444,color:#fff,stroke:#dc2626

Composants clés:

  1. Couche navigateur: Les vues JavaScript et modules API gèrent l'UI et les requêtes de données
  2. Framework LuCI: La couche RPC traduit les appels JavaScript en protocole ubus
  3. Services backend: RPCD exécute les scripts shell via le bus de messages ubus
  4. Couche système: Les configs UCI, services système et système de fichiers fournissent les données

Règle de nommage critique: Le nom du script RPCD DOIT correspondre au paramètre object dans le rpc.declare() JavaScript.


CRITIQUE: Nommage des scripts RPCD

RÈGLE ABSOLUE: Le nom du fichier RPCD DOIT correspondre EXACTEMENT au nom de l'objet ubus dans JavaScript.

CORRECT:

JavaScript:

var callStatus = rpc.declare({
    object: 'luci.system-hub',  // ← Nom objet
    method: 'getHealth'
});

Fichier RPCD:

root/usr/libexec/rpcd/luci.system-hub  # ← CORRESPONDANCE EXACTE

INCORRECT (Causes d'erreur -32000):

# Mauvais - manque le préfixe
root/usr/libexec/rpcd/system-hub

# Mauvais - underscore au lieu de tiret
root/usr/libexec/rpcd/luci.system_hub

# Mauvais - nom différent
root/usr/libexec/rpcd/systemhub

Conventions de chemin de menu

RÈGLE: Les chemins dans menu.d/*.json doivent correspondre EXACTEMENT aux fichiers de vue.

CORRECT:

JSON du menu:

{
    "action": {
        "type": "view",
        "path": "system-hub/overview"
    }
}

Fichier de vue:

htdocs/luci-static/resources/view/system-hub/overview.js

INCORRECT (Cause erreur 404):

Menu: "path": "system-hub/overview" mais fichier: view/systemhub/overview.js

Préfixes standards

Type Préfixe Exemple
Objets ubus luci. luci.system-hub
Classes CSS sh- (System Hub) ou sb- (SecuBox) .sh-page-header
Variables CSS --sh- --sh-primary
Modules JavaScript Nom du module system-hub/api.js

Template de structure de fichiers

luci-app-<module-name>/
├── Makefile
├── README.md
├── htdocs/luci-static/resources/
│   ├── view/<module-name>/
│   │   ├── overview.js         # Page principale
│   │   ├── settings.js         # Configuration
│   │   └── *.js                # Autres vues
│   └── <module-name>/
│       ├── api.js              # Client RPC
│       ├── theme.js            # Helpers de thème (optionnel)
│       ├── common.css          # Styles partagés
│       └── *.css               # Styles spécifiques
└── root/
    ├── usr/
    │   ├── libexec/rpcd/
    │   │   └── luci.<module-name>    # DOIT correspondre à l'objet ubus
    │   └── share/
    │       ├── luci/menu.d/
    │       │   └── luci-app-<module-name>.json
    │       └── rpcd/acl.d/
    │           └── luci-app-<module-name>.json
    └── etc/config/<module-name> (optionnel)

Bonnes pratiques RPCD & ubus

Template de script RPCD (Shell)

Fichier: root/usr/libexec/rpcd/luci.<module-name>

#!/bin/sh
# Backend RPCD pour <module-name>
# objet ubus: luci.<module-name>

case "$1" in
    list)
        # Liste des méthodes disponibles
        echo '{
            "getStatus": {},
            "getHealth": {},
            "getServices": {}
        }'
        ;;
    call)
        case "$2" in
            getStatus)
                # TOUJOURS retourner du JSON valide
                printf '{"enabled": true, "version": "1.0.0"}\n'
                ;;
            getHealth)
                # Lire les métriques système
                cpu_usage=$(top -bn1 | grep "CPU:" | awk '{print $2}' | sed 's/%//')
                mem_total=$(free | grep Mem | awk '{print $2}')
                mem_used=$(free | grep Mem | awk '{print $3}')

                printf '{
                    "cpu": {"usage": %s},
                    "memory": {"total_kb": %s, "used_kb": %s}
                }\n' "$cpu_usage" "$mem_total" "$mem_used"
                ;;
            getServices)
                # Exemple avec services
                services='[]'
                for service in /etc/init.d/*; do
                    # Construire tableau JSON
                    :
                done
                echo "$services"
                ;;
            *)
                echo '{"error": "Méthode non trouvée"}'
                exit 1
                ;;
        esac
        ;;
esac

Validation des scripts RPCD

CHECKLIST OBLIGATOIRE:

  1. Fichier exécutable: chmod +x root/usr/libexec/rpcd/luci.<module-name>
  2. Shebang présent: #!/bin/sh
  3. Structure case/esac correcte
  4. Méthode list retourne JSON avec toutes les méthodes
  5. Méthode call gère tous les cas
  6. Toujours retourner du JSON valide
  7. Pas de echo de debug (commentés en prod)
  8. Gestion d'erreur pour méthodes inconnues

Test des scripts RPCD

Sur le routeur:

# Test direct
/usr/libexec/rpcd/luci.system-hub list

# Via ubus
ubus list luci.system-hub
ubus call luci.system-hub getStatus

# Redémarrer RPCD après modification
/etc/init.d/rpcd restart

Erreurs RPCD courantes

Erreur: "Object not found" (-32000)

Cause: Nom du fichier RPCD ne correspond pas à l'objet ubus

Solution:

# Vérifier le nom dans JS
grep -r "object:" htdocs/luci-static/resources/view/ --include="*.js"

# Renommer le fichier RPCD pour correspondre
mv root/usr/libexec/rpcd/wrong-name root/usr/libexec/rpcd/luci.correct-name

Erreur: "Method not found" (-32601)

Cause: Méthode non déclarée dans list ou non implémentée dans call

Solution:

# Vérifier que la méthode est dans les deux blocs
grep "getStatus" root/usr/libexec/rpcd/luci.*

Erreur: JSON invalide retourné

Cause: Sortie RPCD n'est pas du JSON valide

Solution:

# Tester le JSON
/usr/libexec/rpcd/luci.module-name call getStatus | jsonlint

# Utiliser printf au lieu de echo pour le JSON
printf '{"key": "%s"}\n' "$value"

ACL & Permissions

Template de fichier ACL

Fichier: root/usr/share/rpcd/acl.d/luci-app-<module-name>.json

{
    "luci-app-<module-name>": {
        "description": "Accorder l'accès à <Module Name>",
        "read": {
            "ubus": {
                "luci.<module-name>": [
                    "getStatus",
                    "getHealth",
                    "getServices"
                ]
            },
            "uci": [
                "<module-name>"
            ]
        },
        "write": {
            "ubus": {
                "luci.<module-name>": [
                    "setConfig",
                    "restartService"
                ]
            },
            "uci": [
                "<module-name>"
            ]
        }
    }
}

Bonnes pratiques ACL

  1. Séparation lecture/écriture: Ne donnez que les permissions nécessaires
  2. Liste explicite: Listez toutes les méthodes ubus utilisées
  3. Accès UCI: Ajoutez les configs UCI dans read et write
  4. Validation JSON: Toujours valider avec jsonlint

Erreurs ACL courantes

Erreur: "Access denied"

Cause: Méthode ubus pas dans ACL

Solution:

{
    "read": {
        "ubus": {
            "luci.system-hub": [
                "getHealth"  // ← Ajouter la méthode manquante
            ]
        }
    }
}

Erreur: "UCI config not accessible"

Cause: Config UCI pas dans ACL

Solution:

{
    "read": {
        "uci": [
            "system-hub"  // ← Ajouter la config
        ]
    }
}

Patterns JavaScript

Template de module API

Fichier: htdocs/luci-static/resources/<module-name>/api.js

'use strict';
'require rpc';
'require uci';

return L.Class.extend({
    // Déclarer les appels RPC
    callGetStatus: rpc.declare({
        object: 'luci.<module-name>',
        method: 'getStatus',
        expect: { }
    }),

    callGetHealth: rpc.declare({
        object: 'luci.<module-name>',
        method: 'getHealth',
        expect: { }
    }),

    // Méthodes wrapper avec gestion d'erreur
    getStatus: function() {
        return this.callGetStatus().catch(function(err) {
            console.error('Échec de récupération du statut:', err);
            return { enabled: false, error: err.message };
        });
    },

    getHealth: function() {
        return this.callGetHealth().catch(function(err) {
            console.error('Échec de récupération de la santé:', err);
            return {
                cpu: { usage: 0 },
                memory: { usage: 0 },
                error: err.message
            };
        });
    },

    // Utilitaires
    formatBytes: function(bytes) {
        if (bytes === 0) return '0 B';
        var k = 1024;
        var sizes = ['B', 'KB', 'MB', 'GB'];
        var i = Math.floor(Math.log(bytes) / Math.log(k));
        return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
    }
});

Template de vue

Fichier: htdocs/luci-static/resources/view/<module-name>/overview.js

'use strict';
'require view';
'require ui';
'require dom';
'require poll';
'require <module-name>/api as API';

return view.extend({
    // État
    healthData: null,
    sysInfo: null,

    // Charger les données
    load: function() {
        return Promise.all([
            API.getStatus(),
            API.getHealth()
        ]);
    },

    // Rendre l'UI
    render: function(data) {
        var self = this;
        this.sysInfo = data[0] || {};
        this.healthData = data[1] || {};

        var container = E('div', { 'class': '<module>-dashboard' }, [
            // Lier les fichiers CSS
            E('link', { 'rel': 'stylesheet', 'href': L.resource('<module>/common.css') }),
            E('link', { 'rel': 'stylesheet', 'href': L.resource('<module>/overview.css') }),

            // En-tête
            this.renderHeader(),

            // Contenu
            this.renderContent()
        ]);

        // Configurer le rafraîchissement automatique
        poll.add(L.bind(function() {
            return Promise.all([
                API.getStatus(),
                API.getHealth()
            ]).then(L.bind(function(refreshData) {
                this.sysInfo = refreshData[0] || {};
                this.healthData = refreshData[1] || {};
                this.updateDashboard();
            }, this));
        }, this), 30); // Rafraîchir toutes les 30s

        return container;
    },

    renderHeader: function() {
        return E('div', { 'class': 'sh-page-header' }, [
            // Contenu de l'en-tête
        ]);
    },

    renderContent: function() {
        return E('div', { 'class': 'sh-content' }, [
            // Contenu principal
        ]);
    },

    updateDashboard: function() {
        // Mettre à jour les éléments DOM existants
        var element = document.querySelector('.my-element');
        if (element) {
            dom.content(element, this.renderContent());
        }
    },

    // Stubs requis pour LuCI
    handleSaveApply: null,
    handleSave: null,
    handleReset: null
});

Pattern de gestion des événements

// CORRECT: Lier les événements après le rendu
render: function(data) {
    var container = E('div', {}, [
        E('button', {
            'id': 'my-button',
            'class': 'sh-btn sh-btn-primary'
        }, 'Cliquez-moi')
    ]);

    // Ajouter l'événement après la création du conteneur
    container.addEventListener('click', function(ev) {
        if (ev.target && ev.target.id === 'my-button') {
            self.handleButtonClick();
        }
    });

    return container;
},

handleButtonClick: function() {
    ui.addNotification(null, E('p', 'Bouton cliqué!'), 'info');
}

Erreurs JavaScript courantes

Erreur: "[object HTMLButtonElement]" affiché

Cause: Array imbriqué quand E() attend un array simple

// INCORRECT
E('div', {}, [
    this.renderButtons()  // renderButtons retourne déjà un array
])

// CORRECT
E('div', {},
    this.renderButtons()  // Pas de [ ] supplémentaire
)

Erreur: "Cannot read property of undefined"

Cause: Données API non disponibles

// INCORRECT
var cpuUsage = this.healthData.cpu.usage;

// CORRECT (avec optional chaining)
var cpuUsage = (this.healthData.cpu && this.healthData.cpu.usage) || 0;
// ou
var cpuUsage = this.healthData.cpu?.usage || 0; // ES2020

Erreur: "poll callback failed"

Cause: Promise non retournée dans poll.add

// INCORRECT
poll.add(function() {
    API.getHealth(); // Pas de return!
}, 30);

// CORRECT
poll.add(function() {
    return API.getHealth().then(function(data) {
        // Mettre à jour l'UI
    });
}, 30);

Standards CSS/Styles

Organisation des fichiers

<module-name>/
├── common.css       # Composants partagés (en-têtes, boutons, cartes, onglets)
├── overview.css     # Spécifique à la page aperçu
├── services.css     # Spécifique à la page services
└── *.css            # Autres styles spécifiques aux pages

Template de fichier CSS

/**
 * Nom du module - Styles de page/composant
 * Description de ce que ce fichier stylise
 * Version: X.Y.Z
 */

/* === Importer les styles partagés (si nécessaire) === */
/* Non requis si chargé dans le HTML */

/* === Variables spécifiques à la page (si nécessaire) === */
:root {
    --page-specific-var: value;
}

/* === Mise en page === */
.module-page-container {
    /* Styles de mise en page */
}

/* === Composants === */
.module-component {
    /* Styles de composant */
}

/* === Responsive === */
@media (max-width: 768px) {
    /* Styles mobile */
}

/* === Surcharges mode sombre === */
[data-theme="dark"] .module-component {
    /* Spécifique au mode sombre */
}

Bonnes pratiques CSS

1. TOUJOURS utiliser les variables CSS

/* INCORRECT */
.my-card {
    background: #12121a;
    color: #fafafa;
}

/* CORRECT */
.my-card {
    background: var(--sh-bg-card);
    color: var(--sh-text-primary);
}

2. Préfixer les classes par module

/* System Hub */
.sh-page-header { }
.sh-card { }
.sh-btn { }

/* SecuBox */
.sb-module-grid { }
.sb-dashboard { }

/* Module spécifique */
.netdata-chart { }
.crowdsec-alert { }

3. Transitions cohérentes

/* Transition standard */
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

/* Transition rapide (états de survol) */
transition: all 0.2s ease;

/* Transition douce (grands mouvements) */
transition: all 0.5s ease;

4. Points de rupture responsive

/* Mobile */
@media (max-width: 768px) {
    .sh-stats-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

/* Tablette */
@media (min-width: 769px) and (max-width: 1024px) {
    /* Spécifique tablette */
}

/* Bureau */
@media (min-width: 1025px) {
    /* Spécifique bureau */
}

5. Mode sombre OBLIGATOIRE

Toujours fournir des styles mode sombre:

/* Mode clair (par défaut) */
.my-component {
    background: var(--sh-bg-card);
    border: 1px solid var(--sh-border);
}

/* Surcharge mode sombre */
[data-theme="dark"] .my-component {
    background: var(--sh-bg-card);
    border-color: var(--sh-border);
}

Échelle z-index

Respecter cette échelle:

--z-base: 0;
--z-dropdown: 100;
--z-sticky: 200;
--z-fixed: 300;
--z-modal-backdrop: 400;
--z-modal: 500;
--z-popover: 600;
--z-tooltip: 700;

Erreurs courantes & Solutions

1. Objet RPCD non trouvé (-32000)

Erreur complète:

RPC call to luci.system-hub/getHealth failed with error -32000: Object not found

Diagnostic:

# 1. Vérifier que le fichier RPCD existe
ls -la /usr/libexec/rpcd/luci.system-hub

# 2. Vérifier qu'il est exécutable
chmod +x /usr/libexec/rpcd/luci.system-hub

# 3. Lister les objets ubus
ubus list | grep system-hub

# 4. Si absent, redémarrer RPCD
/etc/init.d/rpcd restart
ubus list | grep system-hub

Solutions:

  1. Renommer le fichier RPCD pour correspondre exactement
  2. Vérifier les permissions (755 ou rwxr-xr-x)
  3. Redémarrer rpcd

2. Vue non trouvée (404)

Erreur:

HTTP error 404 while loading class file '/luci-static/resources/view/system-hub/overview.js'

Diagnostic:

# 1. Vérifier que le fichier existe
ls -la /www/luci-static/resources/view/system-hub/overview.js

# 2. Vérifier le chemin dans menu.d
grep "path" /usr/share/luci/menu.d/luci-app-system-hub.json

Solutions:

  1. Vérifier que le chemin dans le JSON du menu correspond au fichier
  2. Vérifier les permissions du fichier (644)
  3. Nettoyer le cache: rm -f /tmp/luci-indexcache /tmp/luci-modulecache/*

3. CSS non chargé (403 Forbidden)

Erreur:

GET /luci-static/resources/system-hub/common.css 403 Forbidden

Diagnostic:

# Vérifier les permissions
ls -la /www/luci-static/resources/system-hub/common.css

Solution:

# Corriger les permissions
chmod 644 /www/luci-static/resources/system-hub/*.css

4. JSON invalide depuis RPCD

Erreur dans la console navigateur:

SyntaxError: Unexpected token in JSON at position X

Diagnostic:

# Tester le JSON directement
/usr/libexec/rpcd/luci.system-hub call getHealth | jsonlint

# Ou avec jq
/usr/libexec/rpcd/luci.system-hub call getHealth | jq .

Solutions courantes:

# INCORRECT - Quote simple non échappée
echo '{"error": "can't process"}'

# CORRECT - Utiliser printf et doubles quotes
printf '{"error": "cannot process"}\n'

# INCORRECT - Variable non quotée
echo "{\"value\": $var}"

# CORRECT - Variable quotée
printf '{"value": "%s"}\n' "$var"

5. Problèmes de cache navigateur

Symptômes:

  • Changements CSS/JS non visibles
  • Anciennes données affichées
  • Code mis à jour mais interface identique

Solutions:

# 1. Côté serveur - nettoyer le cache LuCI
ssh root@router "rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* && /etc/init.d/uhttpd restart"

# 2. Côté client - actualisation forcée
Ctrl + Shift + R (Chrome/Firefox)
Ctrl + F5 (Windows)
Cmd + Shift + R (Mac)

# 3. Mode privé/incognito pour test
Ctrl + Shift + N (Chrome)
Ctrl + Shift + P (Firefox)

6. Accès ACL refusé

Erreur:

Access to path '/admin/secubox/system/system-hub' denied

Diagnostic:

# Vérifier l'ACL
cat /usr/share/rpcd/acl.d/luci-app-system-hub.json | jq .

# Vérifier que les méthodes ubus sont listées
grep "getHealth" /usr/share/rpcd/acl.d/luci-app-system-hub.json

Solution: Ajouter la méthode manquante dans l'ACL et redémarrer rpcd.


Liste de vérification

Checklist pré-commit

Avant chaque commit, vérifier:

  • Script RPCD:

    • Nom du fichier correspond à l'objet ubus
    • Exécutable (chmod +x)
    • Structure list/call correcte
    • Retourne du JSON valide
    • Toutes les méthodes implémentées
  • Menu & ACL:

    • Chemin du menu correspond au fichier vue
    • L'ACL liste toutes les méthodes ubus
    • JSON valide (jsonlint)
  • JavaScript:

    • 'use strict' en première ligne
    • Imports requis présents
    • Pas de console.log en prod
    • Gestion d'erreur sur les appels API
    • Gestionnaires d'événements liés correctement
  • CSS:

    • Variables CSS utilisées (pas de valeurs codées en dur)
    • Classes préfixées (sh-, sb-, module-)
    • Mode sombre supporté
    • Responsive (max-width: 768px)
    • Transitions cohérentes
  • Makefile:

    • PKG_VERSION incrémenté
    • LUCI_DEPENDS correct
    • Chemin d'inclusion correct (../../luci.mk)

Checklist pré-déploiement

Avant le déploiement sur le routeur:

  • Scripts de validation:

    ./secubox-tools/validate-modules.sh
    
  • Test RPCD local:

    /usr/libexec/rpcd/luci.module-name list
    /usr/libexec/rpcd/luci.module-name call getStatus
    
  • Test JSON:

    find . -name "*.json" -exec jsonlint {} \;
    
  • Shellcheck:

    shellcheck root/usr/libexec/rpcd/*
    
  • Permissions:

    # Scripts RPCD
    chmod 755 root/usr/libexec/rpcd/*
    
    # Fichiers CSS/JS
    chmod 644 htdocs/luci-static/resources/**/*
    

Checklist post-déploiement

Après le déploiement:

  • Services:

    /etc/init.d/rpcd status
    /etc/init.d/uhttpd status
    
  • Objets ubus:

    ubus list | grep luci.module-name
    
  • Fichiers présents:

    ls -la /www/luci-static/resources/view/module-name/
    ls -la /www/luci-static/resources/module-name/
    
  • Permissions correctes:

    ls -la /usr/libexec/rpcd/luci.module-name
    ls -la /www/luci-static/resources/module-name/*.css
    
  • Test navigateur:

    • Ouvrir en mode privé
    • Vérifier la console (F12) - pas d'erreurs
    • Vérifier l'onglet Network - tous les fichiers chargent (200)
    • Tester le mode sombre/clair
    • Tester le responsive (vue mobile)

Procédures de déploiement

Workflow de déploiement

Le diagramme suivant illustre le processus de déploiement complet avec les points de contrôle de validation:

flowchart TD
    START([Démarrer le déploiement]) --> LOCAL_VAL{Validation locale<br/>réussie?}
    LOCAL_VAL -->|Non| FIX_LOCAL[Corriger les problèmes localement]
    FIX_LOCAL --> LOCAL_VAL
    LOCAL_VAL -->|Oui| CHECK_DISK{Espace disque<br/>< 90%?}

    CHECK_DISK -->|Non| CLEAN_DISK[Nettoyer les fichiers temp<br/>& anciens backups]
    CLEAN_DISK --> CHECK_DISK
    CHECK_DISK -->|Oui| FIX_PERM_LOCAL[Corriger les permissions<br/>source locale]

    FIX_PERM_LOCAL --> COPY[Copier les fichiers vers le routeur<br/>scp JS/CSS/RPCD]
    COPY --> FIX_PERM_REMOTE[Corriger les permissions<br/>fichiers distants<br/>755 RPCD / 644 CSS-JS]
    FIX_PERM_REMOTE --> CLEAR[Vider le cache LuCI<br/>/tmp/luci-*]
    CLEAR --> RESTART[Redémarrer les services<br/>rpcd + uhttpd]

    RESTART --> V1{Objet ubus<br/>disponible?}
    V1 -->|Non| DEBUG1[Déboguer le script RPCD<br/>Vérifier le nommage et les permissions]
    DEBUG1 --> FIX_PERM_REMOTE

    V1 -->|Oui| V2{Fichiers<br/>accessibles?}
    V2 -->|Erreur 403| DEBUG2[Corriger les permissions fichiers<br/>chmod 644]
    DEBUG2 --> FIX_PERM_REMOTE

    V2 -->|Oui| V3{Chemin menu<br/>correspond à la vue?}
    V3 -->|Erreur 404| DEBUG3[Corriger le chemin JSON du menu]
    DEBUG3 --> COPY

    V3 -->|Oui| V4{L'UI charge<br/>correctement?}
    V4 -->|Erreurs| DEBUG4[Vérifier la console navigateur<br/>Corriger les erreurs JavaScript]
    DEBUG4 --> COPY

    V4 -->|Oui| TEST[Test navigateur<br/>Mode privé<br/>Mode sombre/clair<br/>Responsive]
    TEST --> SUCCESS([Déploiement réussi])

    style START fill:#6366f1,color:#fff,stroke:#4f46e5
    style SUCCESS fill:#22c55e,color:#fff,stroke:#16a34a
    style DEBUG1 fill:#ef4444,color:#fff,stroke:#dc2626
    style DEBUG2 fill:#ef4444,color:#fff,stroke:#dc2626
    style DEBUG3 fill:#ef4444,color:#fff,stroke:#dc2626
    style DEBUG4 fill:#ef4444,color:#fff,stroke:#dc2626
    style CHECK_DISK fill:#f59e0b,color:#fff,stroke:#d97706
    style LOCAL_VAL fill:#8b5cf6,color:#fff,stroke:#7c3aed

Étapes de déploiement:

  1. Validation locale: Exécuter validate-modules.sh et fix-permissions.sh --local
  2. Vérifications préalables: Espace disque et vérification des permissions
  3. Transfert de fichiers: Copier JavaScript, CSS et scripts RPCD
  4. Configuration distante: Corriger les permissions et vider les caches
  5. Redémarrage des services: Recharger les daemons rpcd et uhttpd
  6. Validation: Vérification multi-étapes (ubus, fichiers, menu, UI)
  7. Tests: Tests navigateur en mode privé

Chemins de récupération d'erreur courants:

  • Objet non trouvé (-32000): Vérifier le nommage et les permissions du script RPCD
  • 403 Forbidden: Corriger les permissions des fichiers à 644 pour CSS/JS
  • 404 Not Found: Vérifier que le chemin du menu correspond à l'emplacement du fichier vue
  • Erreurs JavaScript: Vérifier la console navigateur et corriger les problèmes de code

Vérifications pré-déploiement (CRITIQUE)

TOUJOURS exécuter ces vérifications AVANT tout déploiement:

1. Vérification de l'espace disque

# Sur le routeur cible
ssh root@192.168.8.191 "df -h | grep overlay"

# Vérifier que l'utilisation est < 90%
# Exemple OK:
# /dev/loop0    98.8M    45.2M    53.6M   46% /overlay

# Exemple CRITIQUE (ARRÊTER le déploiement):
# /dev/loop0    98.8M    98.8M       0  100% /overlay  ← PLEIN!

Si l'overlay est plein (≥95%):

# Libérer de l'espace avant le déploiement
ssh root@192.168.8.191 << 'EOF'
# Supprimer les fichiers temporaires
rm -rf /tmp/*.ipk /tmp/luci-* 2>/dev/null

# Supprimer les anciens backups (>7 jours)
find /root -name '*.backup-*' -type f -mtime +7 -delete 2>/dev/null

# Vérifier les packages inutilisés
opkg list-installed | grep -E 'netdata|unused'

# Après nettoyage, vérifier l'espace libéré
df -h | grep overlay
EOF

Tailles typiques à surveiller:

  • UI web Netdata: ~22MB (considérer la suppression si non utilisé)
  • Modules LuCI: ~1-2MB chacun
  • Fichiers CSS/JS: ~10-50KB chacun

2. Vérification des permissions (Critique pour éviter les erreurs 403)

Permissions OBLIGATOIRES:

Type Permission Octal Raison
Scripts RPCD rwxr-xr-x 755 Exécutable par le système
Fichiers CSS rw-r--r-- 644 Lecture serveur web
Fichiers JS rw-r--r-- 644 Lecture serveur web
Fichiers JSON rw-r--r-- 644 Lecture rpcd

Erreur courante: Fichiers créés avec 600 (rw-------) au lieu de 644

Symptôme: HTTP 403 Forbidden lors du chargement de fichiers JS/CSS

Exemple d'erreur:

NetworkError: HTTP error 403 while loading class file
"/luci-static/resources/view/netdata-dashboard/dashboard.js"

Diagnostic rapide:

# Vérifier les permissions des fichiers déployés
ssh root@192.168.8.191 "ls -la /www/luci-static/resources/view/MODULE_NAME/"

# Chercher les fichiers avec des permissions incorrectes (600)
ssh root@192.168.8.191 "find /www/luci-static/resources/view/ -type f -name '*.js' -perm 600"

# MAUVAIS (cause 403):
# -rw-------  1 root root  9763 dashboard.js  ← 600 = pas lisible par le web!

# BON:
# -rw-r--r--  1 root root  9763 dashboard.js  ← 644 = OK

Correction immédiate:

# Corriger TOUS les fichiers CSS/JS
ssh root@192.168.8.191 << 'EOF'
find /www/luci-static/resources/ -name '*.css' -exec chmod 644 {} \;
find /www/luci-static/resources/ -name '*.js' -exec chmod 644 {} \;
find /usr/libexec/rpcd/ -name 'luci.*' -exec chmod 755 {} \;
EOF

Correction automatique (Recommandé):

Utiliser le script automatique qui vérifie et corrige toutes les permissions:

# Corriger les permissions locales (code source)
./secubox-tools/fix-permissions.sh --local

# Corriger les permissions sur le routeur
./secubox-tools/fix-permissions.sh --remote

# Corriger les deux (local + distant)
./secubox-tools/fix-permissions.sh

Le script fix-permissions.sh effectue automatiquement:

  • Fixe tous les scripts RPCD à 755
  • Fixe tous les CSS à 644
  • Fixe tous les JS à 644
  • Vérifie qu'aucun fichier 600 ne reste
  • Vide le cache et redémarre les services (mode distant)
  • Affiche un rapport complet des changements

Validation automatique des permissions:

Le script validate-modules.sh inclut maintenant un Check 7 qui vérifie automatiquement les permissions:

./secubox-tools/validate-modules.sh

# Le Check 7 validera:
# ✓ Tous les RPCD sont 755
# ✓ Tous les CSS sont 644
# ✓ Tous les JS sont 644
# ✗ Affichera des erreurs si les permissions sont incorrectes

Workflow recommandé:

  1. Développer/modifier le code
  2. ./secubox-tools/fix-permissions.sh --local (avant commit)
  3. ./secubox-tools/validate-modules.sh (tout vérifier)
  4. Commit & push
  5. Déployer sur le routeur
  6. ./secubox-tools/fix-permissions.sh --remote (après déploiement)

3. Vérification post-déploiement

Checklist après déploiement:

#!/bin/bash
ROUTER="root@192.168.8.191"
MODULE="module-name"

echo "Vérification post-déploiement"
echo ""

# 1. Vérifier l'espace disque
echo "1. Espace disque restant:"
ssh "$ROUTER" "df -h | grep overlay | awk '{print \$5}'" || echo "ÉCHEC"

# 2. Vérifier les permissions CSS/JS
echo "2. Permissions CSS/JS:"
ssh "$ROUTER" "find /www/luci-static/resources/$MODULE -type f \( -name '*.css' -o -name '*.js' \) ! -perm 644" | \
    if [ -z "$(cat)" ]; then echo "OK"; else echo "ÉCHEC - Permissions incorrectes"; fi

# 3. Vérifier les permissions RPCD
echo "3. Permissions RPCD:"
ssh "$ROUTER" "ls -l /usr/libexec/rpcd/luci.$MODULE | grep -q rwxr-xr-x" && echo "OK" || echo "ÉCHEC"

# 4. Vérifier l'objet ubus
echo "4. Objet ubus disponible:"
ssh "$ROUTER" "ubus list | grep -q luci.$MODULE" && echo "OK" || echo "ÉCHEC"

# 5. Vérifier que les fichiers sont accessibles (HTTP)
echo "5. Fichiers web accessibles:"
ssh "$ROUTER" "test -r /www/luci-static/resources/$MODULE/common.css" && echo "OK" || echo "common.css non trouvé"

# 6. Vérifier que le cache est vidé
echo "6. Cache LuCI vidé:"
ssh "$ROUTER" "test ! -f /tmp/luci-indexcache" && echo "OK" || echo "Cache encore présent"

echo ""
echo "Vérification terminée"

4. Erreurs de déploiement courantes

Erreur Cause Solution rapide
HTTP 403 Forbidden Permissions 600 au lieu de 644 chmod 644 *.js *.css
No space left on device Overlay plein Nettoyer /tmp, supprimer les anciens backups
Object not found -32000 RPCD pas exécutable ou mal nommé chmod 755 rpcd/luci.* + vérifier le nom
Module n'apparaît pas Cache LuCI non vidé rm /tmp/luci-* + redémarrer les services
Changements non visibles Cache navigateur Mode privé + Ctrl+Shift+R

5. Récupération d'urgence de l'espace disque

Si le déploiement échoue avec "No space left on device":

#!/bin/bash
ROUTER="root@192.168.8.191"

echo "Récupération d'urgence de l'espace disque"
echo ""

# 1. Analyser l'utilisation
echo "Top 10 consommateurs:"
ssh "$ROUTER" "du -k /overlay/upper 2>/dev/null | sort -rn | head -10"

# 2. Nettoyer les fichiers temporaires
echo ""
echo "Nettoyage des fichiers temporaires..."
ssh "$ROUTER" "rm -rf /tmp/*.ipk /tmp/luci-* /root/*.ipk 2>/dev/null"

# 3. Supprimer les anciens backups
echo "Suppression des anciens backups (>7 jours)..."
ssh "$ROUTER" "find /root -name '*.backup-*' -mtime +7 -delete 2>/dev/null"

# 4. Option: Supprimer l'UI web Netdata (libère ~22MB)
echo ""
echo "Option: Supprimer l'UI web Netdata (économise ~22MB)?"
read -p "Continuer? (o/N) " -n 1 -r
if [[ $REPLY =~ ^[Oo]$ ]]; then
    ssh "$ROUTER" "opkg remove netdata-web 2>/dev/null || rm -rf /usr/share/netdata/web/*"
fi

# 5. Vérifier l'espace libéré
echo ""
echo "Espace après nettoyage:"
ssh "$ROUTER" "df -h | grep overlay"

Template de script de déploiement standard

#!/bin/bash
# Déployer <Nom du module>

ROUTER="root@192.168.8.191"
MODULE="<module-name>"
LOCAL_DIR="/path/to/luci-app-$MODULE/htdocs/luci-static/resources"
REMOTE_DIR="/www/luci-static/resources"

echo "Déploiement $MODULE"
echo ""

# 1. Déployer les fichiers JS
echo "1. Copie des fichiers JS..."
scp "$LOCAL_DIR/view/$MODULE/"*.js "$ROUTER:$REMOTE_DIR/view/$MODULE/"
scp "$LOCAL_DIR/$MODULE/api.js" "$ROUTER:$REMOTE_DIR/$MODULE/"

# 2. Déployer les fichiers CSS
echo "2. Copie des fichiers CSS..."
scp "$LOCAL_DIR/$MODULE/"*.css "$ROUTER:$REMOTE_DIR/$MODULE/"

# 3. Déployer le backend RPCD
echo "3. Copie du backend RPCD..."
scp "root/usr/libexec/rpcd/luci.$MODULE" "$ROUTER:/usr/libexec/rpcd/"

# 4. Corriger les permissions
echo "4. Correction des permissions..."
ssh "$ROUTER" "chmod 755 /usr/libexec/rpcd/luci.$MODULE"
ssh "$ROUTER" "chmod 644 $REMOTE_DIR/$MODULE/*.css"
ssh "$ROUTER" "chmod 644 $REMOTE_DIR/view/$MODULE/*.js"

# 5. Vider le cache
echo "5. Nettoyage du cache..."
ssh "$ROUTER" "rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* 2>/dev/null"

# 6. Redémarrer les services
echo "6. Redémarrage des services..."
ssh "$ROUTER" "/etc/init.d/rpcd restart"
ssh "$ROUTER" "/etc/init.d/uhttpd restart"

# 7. Vérifier
echo ""
echo "7. Vérification..."
ssh "$ROUTER" "ubus list | grep luci.$MODULE"

echo ""
echo "Déploiement terminé!"
echo ""
echo "Testez (mode privé):"
echo "   https://192.168.8.191/cgi-bin/luci/admin/secubox/path/to/$MODULE"

Procédure de rollback

En cas de problème:

#!/bin/bash
# Revenir à la version précédente

ROUTER="root@192.168.8.191"
BACKUP_DIR="/root/luci-backups/$(date +%Y%m%d)"

# 1. Créer un backup avant le déploiement
ssh "$ROUTER" "mkdir -p $BACKUP_DIR"
ssh "$ROUTER" "cp -r /www/luci-static/resources/module-name $BACKUP_DIR/"
ssh "$ROUTER" "cp /usr/libexec/rpcd/luci.module-name $BACKUP_DIR/"

# 2. En cas de problème, restaurer
ssh "$ROUTER" "cp -r $BACKUP_DIR/module-name /www/luci-static/resources/"
ssh "$ROUTER" "cp $BACKUP_DIR/luci.module-name /usr/libexec/rpcd/"
ssh "$ROUTER" "/etc/init.d/rpcd restart && /etc/init.d/uhttpd restart"

Contrôle de version

Toujours incrémenter les versions:

# Makefile
PKG_VERSION:=0.3.0
PKG_RELEASE:=1
/* Fichiers CSS */
/**
 * Module - Styles
 * Version: 0.3.0
 */
// JavaScript
// Version: 0.3.0

Versioning sémantique:

  • MAJOR.MINOR.PATCH (1.2.3)
  • MAJOR: Changements cassants
  • MINOR: Nouvelles fonctionnalités (rétrocompatible)
  • PATCH: Corrections de bugs

Référence rapide

Commandes essentielles

# Validation
./secubox-tools/validate-modules.sh

# Build (local)
./secubox-tools/local-build.sh build luci-app-module-name

# Déployer les fichiers
scp file.js root@router:/www/luci-static/resources/

# Corriger les permissions
ssh root@router "chmod 644 /www/luci-static/resources/**/*.css"
ssh root@router "chmod 755 /usr/libexec/rpcd/luci.*"

# Vider le cache
ssh root@router "rm -f /tmp/luci-indexcache /tmp/luci-modulecache/*"

# Redémarrer les services
ssh root@router "/etc/init.d/rpcd restart && /etc/init.d/uhttpd restart"

# Tester ubus
ssh root@router "ubus list | grep luci"
ssh root@router "ubus call luci.module-name getStatus"

# Valider le JSON
jsonlint file.json
jq . file.json

Référence rapide des classes CSS

/* Mise en page */
.sh-page-header          /* Conteneur d'en-tête de page */
.sh-page-title           /* Titre de page (texte en dégradé) */
.sh-page-subtitle        /* Sous-titre de page */

/* Stats */
.sh-stats-grid           /* Grille pour les badges de stats (130px min) */
.sh-stat-badge           /* Conteneur de badge de stat */
.sh-stat-value           /* Valeur de stat (monospace) */
.sh-stat-label           /* Label de stat (majuscules) */

/* Cartes */
.sh-card                 /* Conteneur de carte (avec bordure en dégradé au survol) */
.sh-card-success         /* Carte avec bordure verte */
.sh-card-danger          /* Carte avec bordure rouge */
.sh-card-warning         /* Carte avec bordure orange */
.sh-card-header          /* En-tête de carte */
.sh-card-title           /* Titre de carte */
.sh-card-body            /* Contenu de carte */

/* Boutons */
.sh-btn                  /* Bouton de base */
.sh-btn-primary          /* Bouton principal (dégradé) */
.sh-btn-success          /* Bouton succès (vert) */
.sh-btn-danger           /* Bouton danger (rouge) */
.sh-btn-secondary        /* Bouton secondaire (contour) */

/* Onglets */
.sh-filter-tabs          /* Conteneur d'onglets de filtre */
.sh-filter-tab           /* Onglet de filtre */
.sh-filter-tab.active    /* Onglet de filtre actif (dégradé) */
.sh-nav-tabs             /* Onglets de navigation (sticky) */
.sh-nav-tab              /* Onglet de navigation */
.sh-nav-tab.active       /* Onglet de nav actif (souligné) */

/* Utilitaires */
.sh-gradient-text        /* Effet de texte en dégradé */
.sh-id-display           /* Affichage d'ID monospace */
.sh-empty-state          /* Placeholder d'état vide */

Référence rapide des variables de couleur

/* Texte */
var(--sh-text-primary)      /* Texte principal */
var(--sh-text-secondary)    /* Texte secondaire */

/* Fonds */
var(--sh-bg-primary)        /* Fond principal */
var(--sh-bg-secondary)      /* Fond secondaire */
var(--sh-bg-tertiary)       /* Fond tertiaire */
var(--sh-bg-card)           /* Fond de carte */

/* Bordures */
var(--sh-border)            /* Couleur de bordure */

/* Couleurs */
var(--sh-primary)           /* Indigo #6366f1 */
var(--sh-primary-end)       /* Violet #8b5cf6 */
var(--sh-success)           /* Vert #22c55e */
var(--sh-danger)            /* Rouge #ef4444 */
var(--sh-warning)           /* Orange #f59e0b */

/* Effets */
var(--sh-shadow)            /* Ombre de boîte */
var(--sh-hover-shadow)      /* Ombre au survol */
var(--sh-hover-bg)          /* Fond au survol */

Fichiers contextuels pour assistants IA

Le travail SecuBox est partagé entre les assistants Claude et Codex. Gardez les dossiers de contexte synchronisés pour qu'un agent puisse reprendre le travail rapidement:

Répertoire Fichier Usage
.claude/ HISTORY.md Journal chronologique des changements UI/thème et déploiements majeurs
.claude/ TODO.md Backlog de haut niveau (polish UX, docs, idées d'automatisation)
.claude/ WIP.md Tâches actives, risques et prochaines étapes immédiates
.codex/ HISTORY.md Miroir de la timeline de développement pour les sessions Codex
.codex/ TODO.md Tâches orientées outillage (linting, scripts, automatisation de build)
.codex/ WIP.md Traqueur de statut pour les efforts Codex en cours

Règles de maintenance

  1. Mettre à jour après chaque session: En terminant le travail, ajoutez un court point à HISTORY et ajustez WIP/TODO pour refléter le nouvel état.
  2. Référencer les scripts de déploiement: Notez quel script secubox-tools/*.sh a été utilisé (dashboard vs full deploy) pour que l'assistant suivant sache comment le reproduire.
  3. Garder des entrées concises: Un seul paragraphe ou point par mise à jour suffit; les spécifications détaillées restent dans DOCS.
  4. Vérifier avant les gros changements: Lisez les deux dossiers avant de commencer le travail pour éviter les conflits ou efforts dupliqués.

Traitez ces fichiers comme des notes de passage vivantes - s'ils dérivent, l'intégration d'une nouvelle IA/coéquipier devient significativement plus lente.


Conclusion

Ce guide doit être consulté AVANT de:

  1. Créer un nouveau module
  2. Modifier des styles existants
  3. Ajouter des méthodes RPCD
  4. Déployer sur un routeur
  5. Déboguer des erreurs

En cas de doute, TOUJOURS:

  1. Consulter ce guide
  2. Exécuter validate-modules.sh
  3. Tester en mode privé
  4. Vérifier la console navigateur (F12)

Ressources supplémentaires:

  • CLAUDE.md - Architecture et build
  • secubox-tools/validate-modules.sh - Validation automatique
  • Templates/ - Templates de code

Dernière mise à jour: 2025-12-26 Maintenu par: CyberMind Studio Version du guide: 1.0.0