# Plan d'Implémentation: WebModule

**Objectif**: Ajouter un module hot-reload permettant aux autres modules de faire des requêtes HTTP de manière dynamique via IIO.

**Status**: 📋 Planifié
**Priorité**: Moyenne
**Durée estimée**: 2-3h

---

## 1. Vue d'Ensemble

### Architecture

```
┌─────────────────────────────────────────────────┐
│         Modules Clients                          │
│  (AI, Monitoring, Scheduler, etc.)               │
│                                                  │
│  → Publient: "web:request"                       │
│  ← Reçoivent: "web:response"                     │
└──────────────┬──────────────────────────────────┘
               │ IIO pub/sub
               ▼
┌─────────────────────────────────────────────────┐
│           WebModule (Hot-reload)                 │
│                                                  │
│  • Subscribe: "web:request"                      │
│  • Execute HTTP via HttpClient.hpp               │
│  • Publish: "web:response"                       │
│  • Track stats (total, success, failed)          │
│  • State preservation (hot-reload)               │
└──────────────┬──────────────────────────────────┘
               │ Uses existing HttpClient.hpp
               ▼
           Internet
```

### Avantages

✅ **Hot-reload**: Rechargement sans arrêter le système
✅ **Découplage**: Modules clients ignorent les détails HTTP
✅ **Centralisé**: Un seul point pour toutes les requêtes HTTP
✅ **Statistiques**: Tracking automatique (total, succès, échecs)
✅ **État persistant**: Stats survivent au hot-reload
✅ **Réutilisation**: Utilise HttpClient.hpp existant

---

## 2. Fichiers à Créer

### 2.1 Module Core

#### `src/modules/WebModule.h` (70 lignes)
```cpp
#pragma once
#include <grove/IModule.h>
#include <memory>
#include <spdlog/spdlog.h>

namespace celuna {

class WebModule : public grove::IModule {
public:
    WebModule();
    ~WebModule() override = default;

    // IModule interface
    void setConfiguration(const grove::IDataNode& config,
                         grove::IIO* io,
                         grove::ITaskScheduler* scheduler) override;
    const grove::IDataNode& getConfiguration() override;
    void process(const grove::IDataNode& input) override;
    std::unique_ptr<grove::IDataNode> getHealthStatus() override;
    void shutdown() override;

    // State management (hot-reload)
    std::unique_ptr<grove::IDataNode> getState() override;
    void setState(const grove::IDataNode& state) override;

private:
    void processMessages();
    void handleWebRequest(const grove::IDataNode& request);

    grove::IIO* m_io = nullptr;
    std::shared_ptr<spdlog::logger> m_logger;
    std::unique_ptr<grove::IDataNode> m_config;

    // Configuration
    int m_requestTimeoutMs = 30000;
    int m_maxConcurrentRequests = 10;

    // Statistics
    int m_totalRequests = 0;
    int m_successfulRequests = 0;
    int m_failedRequests = 0;
};

} // namespace celuna
```

#### `src/modules/WebModule.cpp` (180 lignes)
- Implémentation complète
- Gestion GET/POST
- Gestion des erreurs
- Publication des réponses
- État pour hot-reload

### 2.2 Configuration

#### `config/web.json` (nouveau)
```json
{
    "enabled": true,
    "requestTimeoutMs": 30000,
    "maxConcurrentRequests": 10,
    "allowedDomains": [
        "api.example.com",
        "*.openai.com"
    ],
    "blockedDomains": []
}
```

### 2.3 Tests

#### `tests/modules/WebModuleTests.cpp` (10 tests)
```
TI_WEB_001: Simple GET Request
TI_WEB_002: POST Request with Body
TI_WEB_003: Invalid URL Handling
TI_WEB_004: Timeout Handling
TI_WEB_005: Multiple Concurrent Requests
TI_WEB_006: Request ID Tracking
TI_WEB_007: Statistics Tracking
TI_WEB_008: State Serialization
TI_WEB_009: Configuration Loading
TI_WEB_010: Error Response Format
```

---

## 3. Protocole IIO

### 3.1 Requête (`web:request`)

**Topic**: `web:request`

**Payload**:
```json
{
    "requestId": "unique-id-123",
    "url": "https://api.example.com/data",
    "method": "GET",
    "headers": {
        "Authorization": "Bearer xxx",
        "Content-Type": "application/json"
    },
    "body": "{\"key\": \"value\"}",
    "timeoutMs": 5000
}
```

**Champs**:
- `requestId` (string, required): ID unique pour matcher la réponse
- `url` (string, required): URL complète avec schéma
- `method` (string, optional): "GET", "POST", "PUT", "DELETE" (default: "GET")
- `headers` (object, optional): Headers HTTP custom
- `body` (string, optional): Body pour POST/PUT
- `timeoutMs` (int, optional): Timeout custom (default: 30000)

### 3.2 Réponse (`web:response`)

**Topic**: `web:response`

**Payload (Success)**:
```json
{
    "requestId": "unique-id-123",
    "success": true,
    "statusCode": 200,
    "body": "{\"result\": \"data\"}",
    "headers": {
        "Content-Type": "application/json"
    },
    "durationMs": 234
}
```

**Payload (Error)**:
```json
{
    "requestId": "unique-id-123",
    "success": false,
    "error": "Connection timeout",
    "errorCode": "TIMEOUT",
    "durationMs": 30001
}
```

---

## 4. Étapes d'Implémentation

### Phase 1: Core Module (1h)

1. **Créer les fichiers de base**
   - [ ] `src/modules/WebModule.h`
   - [ ] `src/modules/WebModule.cpp`
   - [ ] `config/web.json`

2. **Implémenter les méthodes IModule**
   - [ ] `setConfiguration()` - Subscribe "web:request"
   - [ ] `process()` - Appeler processMessages()
   - [ ] `getHealthStatus()` - Retourner stats
   - [ ] `shutdown()` - Log final
   - [ ] `getState()` / `setState()` - Sérialisation stats

3. **Implémenter handleWebRequest()**
   - [ ] Extraction des paramètres
   - [ ] Validation URL
   - [ ] Appel HttpClient (GET/POST)
   - [ ] Gestion erreurs (try/catch)
   - [ ] Publication "web:response"

4. **Ajouter au CMakeLists.txt**
   ```cmake
   add_library(WebModule SHARED
       src/modules/WebModule.cpp
   )
   target_link_libraries(WebModule PRIVATE grove_impl)
   ```

5. **Ajouter au main.cpp**
   ```cpp
   // Load WebModule
   moduleConfigs.push_back({
       "WebModule",
       "./build/modules/libWebModule.so",
       "./config/web.json"
   });
   ```

### Phase 2: Tests (1h)

6. **Créer les tests**
   - [ ] `tests/modules/WebModuleTests.cpp`
   - [ ] Mock HTTP server (simple echo server)
   - [ ] 10 tests unitaires
   - [ ] Intégration avec MockIO

7. **Exécuter les tests**
   ```bash
   cmake --build build --target celuna_tests
   ./build/tests/celuna_tests "[web]"
   ```

### Phase 3: Documentation & Exemples (30min)

8. **Documenter l'utilisation**
   - [ ] Ajouter exemple dans `docs/modules/WebModule.md`
   - [ ] Mettre à jour `CLAUDE.md`
   - [ ] Mettre à jour `README.md`

9. **Créer un exemple d'utilisation**
   - [ ] Exemple dans AIModule ou nouveau module

---

## 5. Exemple d'Utilisation

### Dans un module client (ex: AIModule)

```cpp
// 1. Dans setConfiguration() - S'abonner aux réponses
if (m_io) {
    grove::SubscriptionConfig subConfig;
    m_io->subscribe("web:response", subConfig);
}

// 2. Faire une requête HTTP
void AIModule::fetchExternalData() {
    auto request = std::make_unique<grove::JsonDataNode>("request");
    request->setString("requestId", "weather-" + std::to_string(m_requestCounter++));
    request->setString("url", "https://api.weather.com/current");
    request->setString("method", "GET");

    // Optional headers
    auto headers = std::make_unique<grove::JsonDataNode>("headers");
    headers->setString("Authorization", "Bearer " + m_apiKey);
    request->setChild("headers", std::move(headers));

    m_io->publish("web:request", std::move(request));
}

// 3. Dans processMessages() - Recevoir la réponse
if (msg.topic == "web:response" && msg.data) {
    std::string requestId = msg.data->getString("requestId", "");

    if (requestId.find("weather-") == 0) {
        bool success = msg.data->getBool("success", false);

        if (success) {
            std::string body = msg.data->getString("body", "");
            int statusCode = msg.data->getInt("statusCode", 0);

            m_logger->info("Weather data received: {} bytes", body.size());
            // Parse JSON and use data
        } else {
            std::string error = msg.data->getString("error", "Unknown");
            m_logger->error("Weather request failed: {}", error);
        }
    }
}
```

---

## 6. Sécurité & Limitations

### Sécurité

1. **Validation URL**
   - Vérifier schéma (https:// recommandé)
   - Whitelist/Blacklist de domaines (config)
   - Pas d'exécution de code arbitraire

2. **Rate Limiting**
   - Max concurrent requests (config)
   - Timeout par défaut (30s)
   - Pas de retry automatique (responsabilité du client)

3. **Sanitization**
   - Headers validés
   - Pas d'injection possible

### Limitations

- **Pas de streaming**: Requêtes one-shot uniquement
- **Pas de websockets**: HTTP classique seulement
- **Pas de retry**: Le client doit gérer
- **Pas de cache**: Chaque requête est exécutée
- **Thread-safe**: Mais pas de parallélisation interne

---

## 7. Extensions Futures (Optionnel)

### Phase 4: Features Avancées

- [ ] **Cache HTTP**: LRU cache pour réponses GET
- [ ] **Retry automatique**: Avec backoff exponentiel
- [ ] **Circuit breaker**: Protection contre services down
- [ ] **Métriques avancées**: Latence P50/P95/P99
- [ ] **Support HTTPS custom**: Certificats custom
- [ ] **Compression**: gzip/deflate support
- [ ] **Streaming**: Support chunked transfer

### Phase 5: Tools pour l'Agent LLM

- [ ] Ajouter `fetch_url` tool dans InternalTools
- [ ] Agent peut faire "Fetch https://example.com"
- [ ] Parsing HTML automatique (option)

---

## 8. Critères de Succès

### Fonctionnel
- [ ] Module compile et charge sans erreur
- [ ] GET requests fonctionnent
- [ ] POST requests fonctionnent
- [ ] Erreurs sont gérées correctement
- [ ] Stats sont trackées
- [ ] Hot-reload préserve l'état

### Tests
- [ ] 10/10 tests passent
- [ ] Coverage > 80%
- [ ] Pas de memory leaks (valgrind)

### Documentation
- [ ] README.md updated
- [ ] Exemples d'utilisation fournis
- [ ] Protocol IIO documenté

### Performance
- [ ] Latency < 100ms overhead (vs direct HTTP)
- [ ] Pas de blocking de la main loop
- [ ] Memory footprint < 1MB

---

## 9. Checklist de Validation

Avant de merger:

- [ ] Code review (self-review)
- [ ] Tests unitaires passent
- [ ] Tests d'intégration passent
- [ ] Documentation à jour
- [ ] Pas de warnings de compilation
- [ ] Module hot-reload testé manuellement
- [ ] Config JSON validé
- [ ] Exemple fonctionnel créé
- [ ] Commit message descriptif
- [ ] Branch mergée vers master

---

## 10. Fichiers Affectés

### Nouveaux fichiers
```
src/modules/WebModule.h
src/modules/WebModule.cpp
config/web.json
tests/modules/WebModuleTests.cpp
plans/webmodule-implementation.md (ce fichier)
```

### Fichiers modifiés
```
CMakeLists.txt                  # Ajouter WebModule target
src/main.cpp                    # Charger WebModule
README.md                       # Documentation
CLAUDE.md                       # Règles de développement
```

### Fichiers utilisés (existants)
```
src/shared/http/HttpClient.hpp  # Réutilisé pour HTTP
external/GroveEngine/           # IModule, IIO, etc.
```

---

## Notes Techniques

### Dépendances
- ✅ HttpClient.hpp (déjà implémenté)
- ✅ GroveEngine (IModule, IIO)
- ✅ nlohmann/json (parsing)
- ✅ spdlog (logging)

### Compatibilité
- ✅ Windows (HTTPS via WinHTTP)
- ✅ Linux/WSL (HTTPS via libcurl si disponible)
- ✅ Hot-reload ready

### Performance
- Requêtes asynchrones dans le sens où elles ne bloquent pas la main loop
- Mais chaque requête est synchrone (HttpClient bloque jusqu'à réponse)
- Pour async vrai, il faudrait un thread pool (Phase 4+)

---

**Auteur**: Claude Code
**Date**: 2025-11-28
**Version**: 1.0
