# SecuBox & System Hub - Development Guidelines

**Version:** 1.0.0  
**Last Updated:** 2025-12-28  
**Status:** Active  
**Audience:** Développeurs, IA assistants, 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 & UI Guidelines](#design-system-ui-guidelines)
2. [Architecture & Naming Conventions](#architecture-naming-conventions)
3. [RPCD & ubus Best Practices](#rpcd-ubus-best-practices)
4. [ACL & Permissions](#acl-permissions)
5. [JavaScript Patterns](#javascript-patterns)
6. [CSS/Styling Standards](#cssstyling-standards)
7. [Common Errors & Solutions](#common-errors-solutions)
8. [Validation Checklist](#validation-checklist)
9. [Deployment Procedures](#deployment-procedures)
10. [AI Assistant Context Files](#ai-assistant-context-files)

---

## Design System & UI Guidelines

### Color Palette (Demo-inspired)

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

#### Dark Mode (Primary - Recommended)
```css
--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 hover/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 */
```

#### Light Mode (Secondary)
```css
--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 CSS variables** - Ne JAMAIS hardcoder les couleurs.

### Typography

#### Fonts Stack
```css
/* 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):
```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');
```

#### Font Sizes
```css
/* Titres */
--sh-title-xl: 28px;    /* Page titles */
--sh-title-lg: 20px;    /* Card titles */
--sh-title-md: 16px;    /* Section headers */

/* Texte */
--sh-text-base: 14px;   /* Body text */
--sh-text-sm: 13px;     /* Labels, meta */
--sh-text-xs: 11px;     /* Uppercase labels */

/* Valeurs */
--sh-value-xl: 40px;    /* Large metrics */
--sh-value-lg: 32px;    /* Stats overview */
--sh-value-md: 28px;    /* Badges */
```

### Component Patterns

#### Component Hierarchy

The following diagram shows the standard page structure and component relationships:

```mermaid
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
```

**Component Categories:**
1. **Layout Containers:** Page wrapper, header, content sections
2. **Typography:** Titles with gradient effects, subtitles, labels
3. **Data Display:** Stat badges with monospace values, cards with borders
4. **Navigation:** Filter tabs, nav tabs (sticky)
5. **Interactive:** Buttons with gradients and hover effects

**Styling Rules:**
- **Cards:** 3px top border (gradient on hover, or colored for status)
- **Stat Badges:** Minimum 130px width, monospace font for values
- **Buttons:** Gradient backgrounds, shadow on hover, smooth transitions
- **Tabs:** Active state with gradient background and glow
- **Grid Layouts:** Auto-fit with minimums (130px, 240px, or 300px)

---

#### 1. Page Header (Standard)

**REQUIREMENT:** Every module view MUST begin with this compact `.sh-page-header`. Do not introduce bespoke hero sections or oversized banners; the header keeps height predictable (title + subtitle on the left, stats on the right) and guarantees consistency across SecuBox dashboards. If no stats are needed, keep the container but supply an empty `.sh-stats-grid` for future metrics.

**Slim variant:** When the page only needs 2‑3 metrics, use `.sh-page-header-lite` + `.sh-header-chip` (see `luci-app-vhost-manager` and `luci-app-secubox` settings). Chips carry an emoji/icon, a tiny label, and the value; colors (`.success`, `.danger`, `.warn`) communicate state. This variant replaces the bulky hero blocks from older demos.

**Version chip:** Always expose the package version from the RPC backend (read from `/usr/lib/opkg/info/<pkg>.control`) and display it as the first chip (`icon: 🏷️`). That keeps the UI and `PKG_VERSION` in sync without hunting for hard-coded strings.

**HTML Structure:**
```javascript
E('div', { 'class': 'sh-page-header' }, [
    E('div', {}, [
        E('h2', { 'class': 'sh-page-title' }, [
            E('span', { 'class': 'sh-page-title-icon' }, '🎯'),
            'Page Title'
        ]),
        E('p', { 'class': 'sh-page-subtitle' }, 'Description of the page')
    ]),
    E('div', { 'class': 'sh-stats-grid' }, [
        // Stats badges here
    ])
])
```

**CSS Classes:**
- `.sh-page-header` - Container with flex layout
- `.sh-page-title` - Gradient text effect
- `.sh-page-title-icon` - Icon (no gradient)
- `.sh-page-subtitle` - Secondary text
- `.sh-stats-grid` - Grid pour badges (130px min)

#### 2. Stats Badges

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

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

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

#### 3. Cards avec bordure colorée

**OBLIGATOIRE:** Toutes les cards doivent avoir une bordure top de 3px

```javascript
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' }, '⚙️'),
            'Card Title'
        ])
    ]),
    E('div', { 'class': 'sh-card-body' }, [
        // Content
    ])
])
```

**Variants de bordure:**
- `.sh-card` - Bordure gradient (visible au hover)
- `.sh-card-success` - Bordure verte permanente
- `.sh-card-danger` - Bordure rouge permanente
- `.sh-card-warning` - Bordure orange permanente

#### 4. Buttons

**Gradient buttons (preferred):**
```javascript
E('button', { 'class': 'sh-btn sh-btn-primary' }, 'Primary Action')
E('button', { 'class': 'sh-btn sh-btn-success' }, 'Success Action')
E('button', { 'class': 'sh-btn sh-btn-danger' }, 'Danger Action')
E('button', { 'class': 'sh-btn sh-btn-secondary' }, 'Secondary Action')
```

**Tous les buttons doivent avoir:**
- Shadow effect (déjà dans CSS)
- Hover animation (translateY(-2px))
- Transition smooth (0.3s cubic-bezier)

#### 5. Filter Tabs

```javascript
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' }, 'All')
    ])
])
```

**Active tab styling:**
- Background: gradient indigo-violet
- Color: white
- Box-shadow avec glow

### Grid Systems

#### Stats Overview (Compact)
```css
grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
gap: 16px;
```

#### Metric Cards (Medium)
```css
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
gap: 20px;
```

#### Info Cards (Large)
```css
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
gap: 20px;
```

### Gradient Effects

#### Gradient Text (Titles)
```css
background: linear-gradient(135deg, var(--sh-primary), var(--sh-primary-end));
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-clip: text;
```

**Utiliser:** `.sh-gradient-text` class ou `.sh-page-title`

#### Gradient Backgrounds (Buttons, Badges)
```css
background: linear-gradient(135deg, var(--sh-primary), var(--sh-primary-end));
```

#### Gradient Borders (Top)
```css
/* 3px top border 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));
}
```

### Animation Standards

#### Hover Effects
```css
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
transform: translateY(-3px);  /* Cards */
transform: translateY(-2px);  /* Buttons, badges */
```

#### Shadow Progression
```css
/* Default */
box-shadow: none;

/* Hover - Subtle */
box-shadow: 0 8px 20px var(--sh-shadow);

/* Hover - Pronounced */
box-shadow: 0 12px 28px var(--sh-hover-shadow);

/* Button Hover */
box-shadow: 0 8px 20px rgba(99, 102, 241, 0.5);
```

---

## Architecture & Naming Conventions

### System Architecture Overview

The following diagram illustrates the complete data flow from browser JavaScript to system backend:

```mermaid
graph TB
    subgraph "Browser"
        UI[JavaScript View<br/>view/module/overview.js]
        API[API Module<br/>module/api.js]
    end

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

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

    subgraph "System Layer"
        UCI[UCI Configuration]
        SYS[System Services<br/>init.d scripts]
        FS[Filesystem<br/>proc, sys, etc]
    end

    UI -->|"API.getStatus()"| API
    API -->|"rpc.declare({ object: 'luci.module' })"| RPC
    RPC -->|"HTTP POST /ubus"| UHTTPD
    UHTTPD -->|"call method"| RPCD
    RPCD -->|"execute script"| SCRIPT
    SCRIPT -->|"ubus call"| UBUS
    UBUS -->|"read/write"| UCI
    UBUS -->|"control"| SYS
    SCRIPT -->|"read metrics"| 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
```

**Key Components:**
1. **Browser Layer:** JavaScript views and API modules handle UI and data requests
2. **LuCI Framework:** RPC layer translates JavaScript calls to ubus protocol
3. **Backend Services:** RPCD executes shell scripts via ubus message bus
4. **System Layer:** UCI configs, system services, and filesystem provide data

**Critical Naming Rule:** The RPCD script name **MUST** match the `object` parameter in JavaScript's `rpc.declare()`.

---

### CRITICAL: RPCD Script Naming

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

#### ✅ CORRECT:

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

**Fichier RPCD:**
```bash
root/usr/libexec/rpcd/luci.system-hub  # ← EXACT MATCH
```

#### ❌ INCORRECT (Causes d'erreur -32000):

```bash
# 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
```

### Menu Path Conventions

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

#### ✅ CORRECT:

**Menu JSON:**
```json
{
    "action": {
        "type": "view",
        "path": "system-hub/overview"
    }
}
```

**Fichier de vue:**
```bash
htdocs/luci-static/resources/view/system-hub/overview.js
```

#### ❌ INCORRECT (Causes 404):

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

### Prefixes Standards

| Type | Prefix | Exemple |
|------|--------|---------|
| ubus objects | `luci.` | `luci.system-hub` |
| CSS classes | `sh-` (System Hub) ou `sb-` (SecuBox) | `.sh-page-header` |
| CSS variables | `--sh-` | `--sh-primary` |
| JavaScript modules | Nom du module | `system-hub/api.js` |

### File Structure Template

```
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              # RPC client
│       ├── theme.js            # Theme helpers (optionnel)
│       ├── common.css          # Styles partagés
│       └── *.css               # Styles spécifiques
└── root/
    ├── usr/
    │   ├── libexec/rpcd/
    │   │   └── luci.<module-name>    # ⚠️ MUST match ubus object
    │   └── share/
    │       ├── luci/menu.d/
    │       │   └── luci-app-<module-name>.json
    │       └── rpcd/acl.d/
    │           └── luci-app-<module-name>.json
    └── etc/config/<module-name> (optionnel)
```

---

## RPCD & ubus Best Practices

### RPCD Script Template (Shell)

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

```bash
#!/bin/sh
# RPCD backend for <module-name>
# ubus object: 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
                    # Build JSON array
                    :
                done
                echo "$services"
                ;;
            *)
                echo '{"error": "Method not found"}'
                exit 1
                ;;
        esac
        ;;
esac
```

### RPCD Script Validation

**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

### Testing RPCD Scripts

**Sur le routeur:**

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

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

# Restart RPCD après modification
/etc/init.d/rpcd restart
```

### Common RPCD Errors

#### Error: "Object not found" (-32000)

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

**Solution:**
```bash
# 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
```

#### Error: "Method not found" (-32601)

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

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

#### Error: Invalid JSON returned

**Cause:** Output RPCD n'est pas du JSON valide

**Solution:**
```bash
# 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

### ACL File Template

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

```json
{
    "luci-app-<module-name>": {
        "description": "Grant access to <Module Name>",
        "read": {
            "ubus": {
                "luci.<module-name>": [
                    "getStatus",
                    "getHealth",
                    "getServices"
                ]
            },
            "uci": [
                "<module-name>"
            ]
        },
        "write": {
            "ubus": {
                "luci.<module-name>": [
                    "setConfig",
                    "restartService"
                ]
            },
            "uci": [
                "<module-name>"
            ]
        }
    }
}
```

### ACL Best Practices

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

### Common ACL Errors

#### Error: "Access denied"

**Cause:** Méthode ubus pas dans ACL

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

#### Error: "UCI config not accessible"

**Cause:** Config UCI pas dans ACL

**Solution:**
```json
{
    "read": {
        "uci": [
            "system-hub"  // ← Ajouter le config
        ]
    }
}
```

---

## JavaScript Patterns

### API Module Template

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

```javascript
'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('Failed to get status:', err);
            return { enabled: false, error: err.message };
        });
    },

    getHealth: function() {
        return this.callGetHealth().catch(function(err) {
            console.error('Failed to get health:', 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];
    }
});
```

### View Template

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

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

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

    // Load data
    load: function() {
        return Promise.all([
            API.getStatus(),
            API.getHealth()
        ]);
    },

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

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

            // Header
            this.renderHeader(),

            // Content
            this.renderContent()
        ]);

        // Setup auto-refresh
        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); // Refresh every 30s

        return container;
    },

    renderHeader: function() {
        return E('div', { 'class': 'sh-page-header' }, [
            // Header content
        ]);
    },

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

    updateDashboard: function() {
        // Update existing DOM elements
        var element = document.querySelector('.my-element');
        if (element) {
            dom.content(element, this.renderContent());
        }
    },

    // Required stubs for LuCI
    handleSaveApply: null,
    handleSave: null,
    handleReset: null
});
```

### Event Handling Pattern

```javascript
// ✅ CORRECT: Bind events après render
render: function(data) {
    var container = E('div', {}, [
        E('button', {
            'id': 'my-button',
            'class': 'sh-btn sh-btn-primary'
        }, 'Click Me')
    ]);

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

    return container;
},

handleButtonClick: function() {
    ui.addNotification(null, E('p', 'Button clicked!'), 'info');
}
```

### Common JavaScript Errors

#### Error: "[object HTMLButtonElement]" affiché

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

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

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

#### Error: "Cannot read property of undefined"

**Cause:** Données API non disponibles

```javascript
// ❌ 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
```

#### Error: "poll callback failed"

**Cause:** Promise non retournée dans poll.add

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

// ✅ CORRECT
poll.add(function() {
    return API.getHealth().then(function(data) {
        // Update UI
    });
}, 30);
```

---

## CSS/Styling Standards

### File Organization

```
<module-name>/
├── common.css       # Shared components (headers, buttons, cards, tabs)
├── overview.css     # Overview page specific
├── services.css     # Services page specific
└── *.css            # Other page-specific styles
```

### CSS File Template

```css
/**
 * Module Name - Page/Component Styles
 * Description of what this file styles
 * Version: X.Y.Z
 */

/* === Import shared styles (if needed) === */
/* Not required if loaded in HTML */

/* === Page-specific variables (if needed) === */
:root {
    --page-specific-var: value;
}

/* === Layout === */
.module-page-container {
    /* Layout styles */
}

/* === Components === */
.module-component {
    /* Component styles */
}

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

/* === Dark Mode Overrides === */
[data-theme="dark"] .module-component {
    /* Dark mode specific */
}
```

### CSS Best Practices

#### 1. TOUJOURS utiliser les variables CSS

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

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

#### 2. Prefix classes par module

```css
/* 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

```css
/* Standard transition */
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);

/* Quick transition (hover states) */
transition: all 0.2s ease;

/* Smooth transition (large movements) */
transition: all 0.5s ease;
```

#### 4. Responsive breakpoints

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

/* Tablet */
@media (min-width: 769px) and (max-width: 1024px) {
    /* Tablet specific */
}

/* Desktop */
@media (min-width: 1025px) {
    /* Desktop specific */
}
```

#### 5. Dark mode OBLIGATOIRE

**Toujours fournir des styles dark mode:**

```css
/* Light mode (default) */
.my-component {
    background: var(--sh-bg-card);
    border: 1px solid var(--sh-border);
}

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

### Z-index Scale

**Respecter cette échelle:**

```css
--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;
```

---

## Common Errors & Solutions

### 1. RPCD Object Not Found (-32000)

**Erreur complète:**
```
RPC call to luci.system-hub/getHealth failed with error -32000: Object not found
```

**Diagnostic:**
```bash
# 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 permissions (755 ou rwxr-xr-x)
3. Redémarrer rpcd

### 2. View Not Found (404)

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

**Diagnostic:**
```bash
# 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 path dans menu JSON correspond au fichier
2. Vérifier permissions du fichier (644)
3. Nettoyer cache: `rm -f /tmp/luci-indexcache /tmp/luci-modulecache/*`

### 3. CSS Not Loading (403 Forbidden)

**Erreur:**
```
GET /luci-static/resources/system-hub/common.css 403 Forbidden
```

**Diagnostic:**
```bash
# Vérifier permissions
ls -la /www/luci-static/resources/system-hub/common.css
```

**Solution:**
```bash
# Corriger permissions
chmod 644 /www/luci-static/resources/system-hub/*.css
```

### 4. Invalid JSON from RPCD

**Erreur dans browser console:**
```
SyntaxError: Unexpected token in JSON at position X
```

**Diagnostic:**
```bash
# 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:**
```bash
# ❌ 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. Browser Cache Issues

**Symptômes:**
- Changements CSS/JS non visibles
- Anciennes données affichées
- Code mis à jour mais interface identique

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

# 2. Côté client - hard refresh
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. ACL Access Denied

**Erreur:**
```
Access to path '/admin/secubox/system/system-hub' denied
```

**Diagnostic:**
```bash
# Vérifier ACL
cat /usr/share/rpcd/acl.d/luci-app-system-hub.json | jq .

# Vérifier que 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 ACL et redémarrer rpcd.

---

## Validation Checklist

### Pre-Commit Checklist

Avant chaque commit, vérifier:

- [ ] **RPCD Script:**
  - [ ] Nom fichier correspond à objet ubus
  - [ ] Exécutable (chmod +x)
  - [ ] Structure list/call correcte
  - [ ] Retourne JSON valide
  - [ ] Toutes méthodes implémentées

- [ ] **Menu & ACL:**
  - [ ] Path menu correspond au fichier vue
  - [ ] 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 API calls
  - [ ] Event handlers bindés correctement

- [ ] **CSS:**
  - [ ] Variables CSS utilisées (pas de hardcode)
  - [ ] Classes prefixées (sh-, sb-, module-)
  - [ ] Dark mode supporté
  - [ ] Responsive (max-width: 768px)
  - [ ] Transitions cohérentes

- [ ] **Makefile:**
  - [ ] PKG_VERSION incrémenté
  - [ ] LUCI_DEPENDS correct
  - [ ] Include path correct (../../luci.mk)

### Pre-Deploy Checklist

Avant déploiement sur routeur:

- [ ] **Validation scripts:**
  ```bash
  ./secubox-tools/validate-modules.sh
  ```

- [ ] **Test RPCD local:**
  ```bash
  /usr/libexec/rpcd/luci.module-name list
  /usr/libexec/rpcd/luci.module-name call getStatus
  ```

- [ ] **Test JSON:**
  ```bash
  find . -name "*.json" -exec jsonlint {} \;
  ```

- [ ] **Shellcheck:**
  ```bash
  shellcheck root/usr/libexec/rpcd/*
  ```

- [ ] **Permissions:**
  ```bash
  # RPCD scripts
  chmod 755 root/usr/libexec/rpcd/*

  # CSS/JS files
  chmod 644 htdocs/luci-static/resources/**/*
  ```

### Post-Deploy Checklist

Après déploiement:

- [ ] **Services:**
  ```bash
  /etc/init.d/rpcd status
  /etc/init.d/uhttpd status
  ```

- [ ] **ubus objects:**
  ```bash
  ubus list | grep luci.module-name
  ```

- [ ] **Fichiers présents:**
  ```bash
  ls -la /www/luci-static/resources/view/module-name/
  ls -la /www/luci-static/resources/module-name/
  ```

- [ ] **Permissions correctes:**
  ```bash
  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 console (F12) - pas d'erreurs
  - [ ] Vérifier Network tab - tous les fichiers chargent (200)
  - [ ] Tester dark/light mode
  - [ ] Tester responsive (mobile view)

---

## Deployment Procedures

### Deployment Workflow

The following flowchart illustrates the complete deployment process with validation checkpoints:

```mermaid
flowchart TD
    START([Start Deployment]) --> LOCAL_VAL{Local Validation<br/>Passed?}
    LOCAL_VAL -->|No| FIX_LOCAL[Fix Issues Locally]
    FIX_LOCAL --> LOCAL_VAL
    LOCAL_VAL -->|Yes| CHECK_DISK{Disk Space<br/>< 90%?}

    CHECK_DISK -->|No| CLEAN_DISK[Clean Temp Files<br/>& Old Backups]
    CLEAN_DISK --> CHECK_DISK
    CHECK_DISK -->|Yes| FIX_PERM_LOCAL[Fix Permissions<br/>Local Source]

    FIX_PERM_LOCAL --> COPY[Copy Files to Router<br/>scp JS/CSS/RPCD]
    COPY --> FIX_PERM_REMOTE[Fix Permissions<br/>Remote Files<br/>755 RPCD / 644 CSS-JS]
    FIX_PERM_REMOTE --> CLEAR[Clear LuCI Cache<br/>/tmp/luci-*]
    CLEAR --> RESTART[Restart Services<br/>rpcd + uhttpd]

    RESTART --> V1{ubus Object<br/>Available?}
    V1 -->|No| DEBUG1[Debug RPCD Script<br/>Check naming & permissions]
    DEBUG1 --> FIX_PERM_REMOTE

    V1 -->|Yes| V2{Files<br/>Accessible?}
    V2 -->|403 Error| DEBUG2[Fix File Permissions<br/>chmod 644]
    DEBUG2 --> FIX_PERM_REMOTE

    V2 -->|Yes| V3{Menu Path<br/>Matches View?}
    V3 -->|404 Error| DEBUG3[Fix Menu JSON Path]
    DEBUG3 --> COPY

    V3 -->|Yes| V4{UI Loads<br/>Correctly?}
    V4 -->|Errors| DEBUG4[Check Browser Console<br/>Fix JavaScript Errors]
    DEBUG4 --> COPY

    V4 -->|Yes| TEST[Browser Testing<br/>Private Mode<br/>Dark/Light Mode<br/>Responsive]
    TEST --> SUCCESS([✅ Deployment Success])

    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
```

**Deployment Stages:**
1. **Local Validation:** Run `validate-modules.sh` and `fix-permissions.sh --local`
2. **Pre-Flight Checks:** Disk space and permission verification
3. **File Transfer:** Copy JavaScript, CSS, and RPCD scripts
4. **Remote Setup:** Fix permissions and clear caches
5. **Service Restart:** Reload rpcd and uhttpd daemons
6. **Validation:** Multi-stage verification (ubus, files, menu, UI)
7. **Testing:** Browser testing in private mode

**Common Error Recovery Paths:**
- **Object not found (-32000):** Check RPCD script naming and permissions
- **403 Forbidden:** Fix file permissions to 644 for CSS/JS
- **404 Not Found:** Verify menu path matches view file location
- **JavaScript errors:** Check browser console and fix code issues

---

### ⚠️ Pre-Deployment Checks (CRITICAL)

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

#### 1. Vérification de l'Espace Disque

```bash
# 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 (STOP deployment):
# /dev/loop0    98.8M    98.8M       0  100% /overlay  ← PLEIN!
```

**Si l'overlay est plein (≥95%):**
```bash
# Libérer de l'espace avant déploiement
ssh root@192.168.8.191 << 'EOF'
# Supprimer fichiers temporaires
rm -rf /tmp/*.ipk /tmp/luci-* 2>/dev/null

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

# Vérifier 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:**
- Netdata web UI: ~22MB (considérer suppression si non utilisé)
- Modules LuCI: ~1-2MB chacun
- Fichiers CSS/JS: ~10-50KB chacun

#### 2. Vérification des Permissions (Critique pour Éviter Erreurs 403)

**Permissions OBLIGATOIRES:**

| Type | Permission | Octal | Raison |
|------|-----------|-------|--------|
| **RPCD scripts** | `rwxr-xr-x` | `755` | Exécutable par system |
| **CSS files** | `rw-r--r--` | `644` | Lecture web server |
| **JS files** | `rw-r--r--` | `644` | Lecture web server |
| **JSON files** | `rw-r--r--` | `644` | Lecture rpcd |

**Erreur commune:** 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:**
```bash
# Vérifier permissions des fichiers déployés
ssh root@192.168.8.191 "ls -la /www/luci-static/resources/view/MODULE_NAME/"

# Chercher fichiers avec 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 web!

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

**Correction immédiate:**
```bash
# 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:

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

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

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

Le script `fix-permissions.sh` effectue automatiquement:
- ✅ Fixe tous les RPCD scripts à 755
- ✅ Fixe tous les CSS à 644
- ✅ Fixe tous les JS à 644
- ✅ Vérifie qu'aucun fichier 600 ne reste
- ✅ Clear cache et restart services (remote mode)
- ✅ 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:

```bash
./secubox-tools/validate-modules.sh

# Check 7 validera:
# ✓ Tous les RPCD sont 755
# ✓ Tous les CSS sont 644
# ✓ Tous les JS sont 644
# ❌ Affichera erreurs si permissions incorrectes
```

**Workflow recommandé:**
1. Développer/modifier code
2. `./secubox-tools/fix-permissions.sh --local` (avant commit)
3. `./secubox-tools/validate-modules.sh` (vérifier tout)
4. Commit & push
5. Deploy sur routeur
6. `./secubox-tools/fix-permissions.sh --remote` (après deploy)

#### 3. Post-Deployment Verification

**Checklist après déploiement:**

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

echo "🔍 Post-Deployment Verification"
echo ""

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

# 2. Vérifier 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 "❌ FAIL - Permissions incorrectes"; fi

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

# 4. Vérifier ubus object
echo "4. ubus object disponible:"
ssh "$ROUTER" "ubus list | grep -q luci.$MODULE" && echo "✅ OK" || echo "❌ FAIL"

# 5. Vérifier fichiers 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 cache cleared
echo "6. Cache LuCI cleared:"
ssh "$ROUTER" "test ! -f /tmp/luci-indexcache" && echo "✅ OK" || echo "⚠️  Cache encore présent"

echo ""
echo "✅ Vérification terminée"
```

#### 4. Common Deployment Errors

| 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 anciens backups |
| **Object not found -32000** | RPCD pas exécutable ou mal nommé | `chmod 755 rpcd/luci.*` + vérifier nom |
| **Module not appearing** | Cache LuCI pas cleared | `rm /tmp/luci-*` + restart services |
| **Changes not visible** | Cache navigateur | Mode privé + Ctrl+Shift+R |

#### 5. Emergency Disk Space Recovery

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

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

echo "🚨 Emergency Disk Space Recovery"
echo ""

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

# 2. Nettoyer temporaires
echo ""
echo "Cleaning temp files..."
ssh "$ROUTER" "rm -rf /tmp/*.ipk /tmp/luci-* /root/*.ipk 2>/dev/null"

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

# 4. Option: Supprimer Netdata Web UI (libère ~22MB)
echo ""
echo "⚠️  Option: Remove Netdata Web UI (saves ~22MB)?"
read -p "Continue? (y/N) " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]; then
    ssh "$ROUTER" "opkg remove netdata-web 2>/dev/null || rm -rf /usr/share/netdata/web/*"
fi

# 5. Vérifier espace libéré
echo ""
echo "Space after cleanup:"
ssh "$ROUTER" "df -h | grep overlay"
```

### Standard Deployment Script Template

```bash
#!/bin/bash
# Deploy <Module Name>

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. Deploy JS files
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. Deploy CSS files
echo "2. Copie des fichiers CSS..."
scp "$LOCAL_DIR/$MODULE/"*.css "$ROUTER:$REMOTE_DIR/$MODULE/"

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

# 4. Fix 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. Clear cache
echo "5. Nettoyage du cache..."
ssh "$ROUTER" "rm -f /tmp/luci-indexcache /tmp/luci-modulecache/* 2>/dev/null"

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

# 7. Verify
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"
```

### Rollback Procedure

En cas de problème:

```bash
#!/bin/bash
# Rollback to previous version

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

# 1. Créer backup avant deploy
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, restore
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"
```

### Version Control

**Toujours incrémenter les versions:**

```makefile
# Makefile
PKG_VERSION:=0.3.0
PKG_RELEASE:=1
```

```css
/* CSS files */
/**
 * Module - Styles
 * Version: 0.3.0
 */
```

```javascript
// JavaScript
// Version: 0.3.0
```

**Semantic Versioning:**
- MAJOR.MINOR.PATCH (1.2.3)
- MAJOR: Breaking changes
- MINOR: New features (backward compatible)
- PATCH: Bug fixes

---

## Quick Reference

### Essential Commands

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

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

# Deploy files
scp file.js root@router:/www/luci-static/resources/

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

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

# Restart services
ssh root@router "/etc/init.d/rpcd restart && /etc/init.d/uhttpd restart"

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

# Validate JSON
jsonlint file.json
jq . file.json
```

### CSS Classes Quick Reference

```css
/* Layout */
.sh-page-header          /* Page header container */
.sh-page-title           /* Page title (gradient text) */
.sh-page-subtitle        /* Page subtitle */

/* Stats */
.sh-stats-grid           /* Grid for stat badges (130px min) */
.sh-stat-badge           /* Stat badge container */
.sh-stat-value           /* Stat value (monospace) */
.sh-stat-label           /* Stat label (uppercase) */

/* Cards */
.sh-card                 /* Card container (with gradient border on hover) */
.sh-card-success         /* Card with green border */
.sh-card-danger          /* Card with red border */
.sh-card-warning         /* Card with orange border */
.sh-card-header          /* Card header */
.sh-card-title           /* Card title */
.sh-card-body            /* Card content */

/* Buttons */
.sh-btn                  /* Base button */
.sh-btn-primary          /* Primary button (gradient) */
.sh-btn-success          /* Success button (green) */
.sh-btn-danger           /* Danger button (red) */
.sh-btn-secondary        /* Secondary button (outline) */

/* Tabs */
.sh-filter-tabs          /* Filter tabs container */
.sh-filter-tab           /* Filter tab */
.sh-filter-tab.active    /* Active filter tab (gradient) */
.sh-nav-tabs             /* Navigation tabs (sticky) */
.sh-nav-tab              /* Navigation tab */
.sh-nav-tab.active       /* Active nav tab (underline) */

/* Utilities */
.sh-gradient-text        /* Gradient text effect */
.sh-id-display           /* Monospace ID display */
.sh-empty-state          /* Empty state placeholder */
```

### Color Variables Quick Reference

```css
/* Text */
var(--sh-text-primary)      /* Main text */
var(--sh-text-secondary)    /* Secondary text */

/* Backgrounds */
var(--sh-bg-primary)        /* Main background */
var(--sh-bg-secondary)      /* Secondary background */
var(--sh-bg-tertiary)       /* Tertiary background */
var(--sh-bg-card)           /* Card background */

/* Borders */
var(--sh-border)            /* Border color */

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

/* Effects */
var(--sh-shadow)            /* Box shadow */
var(--sh-hover-shadow)      /* Hover shadow */
var(--sh-hover-bg)          /* Hover background */
```

---

## AI Assistant Context Files

SecuBox work is shared between Claude and Codex assistants. Keep the context folders synchronized so any agent can resume work quickly:

| Directory | File | Usage |
|-----------|------|-------|
| `.claude/` | `HISTORY.md` | Chronological log of UI/theme changes and major deployments |
| `.claude/` | `TODO.md` | High-level backlog (UX polish, docs, automation ideas) |
| `.claude/` | `WIP.md` | Active tasks, risks, and immediate next steps |
| `.codex/` | `HISTORY.md` | Mirrors the development timeline for Codex sessions |
| `.codex/` | `TODO.md` | Tooling-focused tasks (linting, scripts, build automation) |
| `.codex/` | `WIP.md` | Status tracker for ongoing Codex efforts |

**Maintenance rules**

1. **Update after each session:** When finishing work, append a short bullet to HISTORY and adjust WIP/TODO so they reflect the new state.
2. **Reference deployment scripts:** Note which `secubox-tools/*.sh` script was used (dashboard vs. full deploy) so the next assistant knows how to reproduce it.
3. **Keep entries concise:** A single paragraph or bullet per update is enough; detailed specs remain in DOCS.
4. **Cross-check before big changes:** Read both folders before starting work to avoid conflicts or duplicate efforts.

Treat these files as living handoff notes—if they drift, onboarding a new AI/teammate becomes significantly slower.

---

## 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ébugger 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 browser (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
