Application Flask modulaire pour le pilotage de webhooks et l'ingestion d'e-mails via Gmail Push. Ce dépôt a été refactoré pour passer d'un fichier monolithique (app_render.py) à une architecture claire et testable.
- Documentation principale :
docs/README.md - Architecture & services :
docs/architecture/overview.md - API HTTP :
docs/architecture/api.md - Pôles Fonctionnels :
docs/features/(gmail_push_ingress.md,webhooks.md,frontend_dashboard_features.md) - Configuration & Stockage :
docs/configuration/(configuration.md,storage.md,installation.md) - Déploiement & Opérations :
docs/operations/(deploiement.md,operational-guide.md,checklist_production.md,depannage.md) - Tests & qualité :
docs/quality/testing.md - Intégrations :
docs/integrations/(r2_offload.md,r2_dropbox_limitations.md,gmail-oauth-setup.md)
- L’application est construite via le
Dockerfileracine, qui embarque Gunicorn et la configuration des threads/fils de poller (GUNICORN_*). - Le workflow GitHub Actions
.github/workflows/render-image.yml:- Construit l’image depuis la racine du dépôt.
- La pousse sur GitHub Container Registry (
ghcr.io/<owner>/<repo>:latest+:<sha>). - Déclenche Render par ordre de priorité : Deploy Hook (
RENDER_DEPLOY_HOOK_URL) → API Render (RENDER_API_KEY,RENDER_SERVICE_ID,RENDER_DEPLOY_CLEAR_CACHE) → fallback manuel.
- Les secrets GHCR/Render doivent être configurés côté GitHub Actions. Render récupère ensuite l’image et injecte les variables historiques (
ENABLE_BACKGROUND_TASKS,WEBHOOK_URL, etc.). - URL actuelle :
https://render-signal-server-latest.onrender.com(cf.memory-bank/activeContext.mdpour l’instance vivante). - Pour les environnements on-premise, les instructions “Gunicorn + Reverse Proxy” restent valables (cf.
docs/deploiement.md).
- Démarrage : Vérifiez
CFG WEBHOOK: Custom webhook URL configuredpour confirmer la configuration des webhooks. - Ingestion Gmail : Les logs
API INGRESS: Gmail push processed successfullyconfirment la réception des e-mails via Apps Script. - Arrêt :
PROCESS: SIGTERM receivedindique un arrêt propre du service. - Watcher Make :
MAKE_WATCHER: background thread startedconfirme que le watcher est actif (nécessiteMAKECOM_API_KEY).
- Configurez une alerte sur l'absence de logs
API INGRESS: Gmail pushpendant plus de 15 minutes. - Surveillez les échecs d'envoi de webhooks et les erreurs de traitement Gmail Apps Script.
- Consultez les logs pour les entrées
WARNINGetERRORpour détecter les problèmes potentiels.
Consultez la documentation opérationnelle pour plus de détails sur la configuration et le dépannage.
- Fonctionnalité : Blocage complet de l'envoi de webhooks sur des jours spécifiques de la semaine
- Configuration : Via l'interface dashboard ou API (
/api/webhooks/config) - Priorité : Plus haute priorité, ignore les autres règles (fenêtre horaire, bypass DESABO)
- Implémentation : Service
WebhookConfigServiceavec champsabsence_pause_enabled/absence_pause_days
- Service :
MagicLinkService(singleton) pour générer/valider des tokens signés HMAC SHA-256 - Stockage : Tokens dans
MAGIC_LINK_TOKENS_FILE(JSON verrouillé) avec TTL configurable - API : Endpoint
/api/auth/magic-link(session requise) pour générer liens one-shot ou permanents - Interface : Dashboard
dashboard.htmlavec bouton de génération et copie automatique - Sécurité : Logs
MAGIC_LINK:*, nettoyage auto tokens expirés, support stockage partagé via API PHP
- Service :
R2TransferService(singleton) pour économiser la bande passante Render - Architecture : Worker Cloudflare
deployment/cloudflare-worker/worker.jsavec authentificationX-R2-FETCH-TOKEN - Fonctionnalités : Normalisation Dropbox, fetch distant, persistance paires
source_url/r2_urldanswebhook_links.json - Intégration : Orchestrator
email_processing/orchestrator.py#645-711enrichitdelivery_linkssiR2_FETCH_ENABLED=true - Économies : ~$5/mois pour 50 GB transférés, auto-nettoyage 24h via
cleanup.js
- Pipeline : Workflow GitHub Actions
.github/workflows/render-image.yml(build/push GHCR, déclenchement Render) - Image :
Dockerfileracine avec Gunicorn, variablesGUNICORN_*, logs stdout/stderr - Déploiement : URL
https://render-signal-server-latest.onrender.comvia Deploy Hook ou API Render - Avantages : Temps de déploiement réduit, image pré-buildée, logs centralisés
- Architecture modulaire ES6 : Refactorisation complète de
dashboard.js(1488 → ~600 lignes) en 5 modules spécialisés - Services frontend :
ApiService.js(client API),WebhookService.js(config+logs),LogService.js(timer intelligent),TabManager.js(accessibilité),MessageHelper.js(utilitaires) - Sécurité renforcée : Protection XSS (construction DOM sécurisée), conditional logging (localhost only), gestion 401/403 centralisée, validation robuste
- Performance : Lazy loading des onglets, responsive design mobile-first, timer avec visibility API, accessibilité WCAG AA complète
- Audit complet : Audit frontend unifié ✅ toutes phases terminées (sécurité, architecture, UX/accessibilité)
- Verrou distribué Redis : Prévention multi-polling sur Render multi-conteneurs avec clé
render_signal:poller_lock(TTL 5min) + fallback fcntl - Fallback R2 garanti : Conservation URLs sources, try/except large, flux continu même si Worker R2 échoue
- Watchdog IMAP : Timeout 30s anti-zombie sur connexions
imaplib.IMAP4_SSL/IMAP4 - Anti-OOM : Troncature HTML à 1MB avant parsing pour prévenir les OOM kills sur conteneurs 512MB
- Tests résilience :
test_lock_redis.py,test_r2_resilience.pyavec validation complète des scénarios de défaillance
ConfigService– Gestion centralisée de la configurationAuthService– Authentification et autorisationRuntimeFlagsService– Gestion dynamique des fonctionnalités (Singleton)WebhookConfigService– Configuration et validation des webhooks (Singleton)DeduplicationService– Prévention des doublons (Redis + fallback mémoire)PollingConfigService– Configuration du polling IMAPMagicLinkService– Gestion des magic links pour l’authentification sans mot de passe (Singleton)R2TransferService– Offload Cloudflare R2 pour économiser la bande passante (Singleton)
render_signal_server-main/
├── app_logging/
├── auth/
│ ├── user.py # Flask-Login (User, LoginManager)
│ └── helpers.py # API key (X-API-Key), décorateur api_key_required
├── background/
│ └── polling_thread.py # Boucle de polling IMAP (thread) + dépendances injectées
├── config/
│ ├── settings.py # Variables ENV, constantes REF_*, chemins
│ ├── polling_config.py # Timezone, vacation mode, validation polling
│ └── webhook_time_window.py # Fenêtre horaire des webhooks (+ override persistant)
├── deduplication/
│ └── redis_client.py # Dédoublonnage (email ID, groupes de sujet) via Redis (fallback mémoire)
├── email_processing/
│ ├── imap_client.py # Connexion IMAP
│ ├── pattern_matching.py # Patterns (Média Solution, DESABO)
│ ├── webhook_sender.py # Envoi des webhooks externes (timeouts, retries)
│ └── orchestrator.py # Orchestration du traitement des emails
├── preferences/
│ └── processing_prefs.py # Préférences de traitement (validation, persistance, Redis + JSON)
├── routes/
│ ├── __init__.py # Blueprints regroupés
│ ├── api_webhooks.py # Gestion de la configuration des webhooks
│ ├── api_polling.py # Endpoints liés au polling IMAP
│ ├── api_processing.py # Préférences de traitement (GET/POST)
│ ├── api_test.py # /api/test/* (X-API-Key)
│ ├── api_admin.py # Administration (redémarrage, déploiement Render, check emails)
│ ├── api_config.py # Configuration runtime (fenêtres horaires, flags, polling)
│ ├── api_utility.py # Ping, triggers locaux, statut
│ ├── api_make.py # Pilotage manuel des scénarios Make (legacy)
│ ├── api_auth.py # Authentification Magic Link
│ ├── dashboard.py # UI /, /login, /logout
│ └── health.py # GET /health
├── services/ # Services orientés métier/configuration (ConfigService, AuthService, etc.)
│ ├── config_service.py # Gestion centralisée de la configuration
│ ├── auth_service.py # Authentification et autorisation
│ ├── runtime_flags_service.py # Gestion dynamique des fonctionnalités (Singleton)
│ ├── webhook_config_service.py # Configuration et validation des webhooks (Singleton)
│ ├── deduplication_service.py # Prévention des doublons (Redis + fallback mémoire)
│ ├── polling_config_service.py # Configuration du polling IMAP
│ ├── r2_transfer_service.py # Offload Cloudflare R2 (Singleton)
│ └── magic_link_service.py # Gestion des magic links (Singleton)
├── static/ # JS/CSS (dashboard)
├── utils/
│ ├── time_helpers.py # parse_time_hhmm(), is_within_time_window_local()
│ ├── text_helpers.py # normalize_*, strip_leading_reply_prefixes(), detect_provider()
│ └── validators.py # env_bool(), normalize_make_webhook_url()
├── app_render.py # Serveur Flask (point d'entrée), enregistrement des blueprints et services
├── dashboard.html # UI principale (onglets)
├── login.html # Page de login
├── docs/ # Documentation technique (voir docs/README.md)
├── test_app_render.py # Tests historiques sur app_render.py
└── tests/ # Suite de tests principale (pytest)
Références détaillées : docs/README.md, docs/architecture.md, docs/api.md, docs/email_polling.md, docs/testing.md.
Le refactoring complet vers l'architecture orientée services (services dédiés, blueprints, nettoyage d'app_render.py, montée en couverture de tests) est documenté en détail dans :
docs/refactoring-conformity-report.md– rapport de conformité finalACHIEVEMENT_100_PERCENT.md– récapitulatif "100% refactoring" (historique)
Prérequis : Python 3.10+, Redis (optionnel).
Environnement virtuel prioritaire (partagé)
Pour économiser l’espace disque local et mutualiser les dépendances, utilise le virtualenv partagé monté sur /mnt/venv_ext4/venv_render_signal_server :
python3 -m venv /mnt/venv_ext4/venv_render_signal_server
source /mnt/venv_ext4/venv_render_signal_server/bin/activate
python -m pip install -r requirements.txtAssure-toi que which python et python -m pip --version pointent vers /mnt/venv_ext4/venv_render_signal_server/bin avant de lancer la moindre commande Flask/pytest.
Alternative locale
Si tu n’as pas accès au montage /mnt/venv_ext4, tu peux encore créer un virtualenv local à la racine :
python3 -m venv .venv
source .venv/bin/activate
python -m pip install -r requirements.txtCréer un fichier d’environnement pour le dev (voir docs/configuration.md et debug/render_signal_server.env). Principales variables:
FLASK_SECRET_KEYDASHBOARD_USER,DASHBOARD_PASSWORD(anciennementTRIGGER_PAGE_*)EMAIL_ADDRESS,EMAIL_PASSWORD,IMAP_SERVER,IMAP_PORT,IMAP_USE_SSLWEBHOOK_URL,WEBHOOK_SSL_VERIFYPOLLING_*(jours actifs, créneaux, timezone, vacances)ENABLE_BACKGROUND_TASKSREDIS_URL(optionnel)- Variables R2 (
R2_FETCH_*) pour l'offload Cloudflare - Variables Magic Link (
MAGIC_LINK_TTL_SECONDS,MAGIC_LINK_TOKENS_FILE) - Variables Render (
RENDER_*) pour le déploiement via Render
Voir docs/configuration.md pour la liste complète et à jour.
export FLASK_APP=app_render:app
flask run --host=0.0.0.0 --port=5000En production: Gunicorn derrière Nginx (voir docs/deploiement.md). Le poller email doit être activé sur un seul process (lock fichier /tmp/render_signal_server_email_poller.lock).
pytest test_app_render.py -vRésultats actuels : 389 passed, 13 skipped, 0 failed (couverture ~70%)
- Tests unitaires : Services, helpers, validation
- Tests d'intégration : Routes API, services ensemble
- Tests résilience : Redis lock, fallback R2, anti-OOM
- Tests frontend : Architecture modulaire, sécurité, accessibilité
Voir docs/quality/testing.md pour l'état détaillé et docs/quality/performance.md pour les optimisations.
- Authentification par session (Flask-Login) pour l’UI.
- Endpoints
/api/test/*protégés parX-API-Key(voirauth/helpers.py). - Variables d’environnement pour tous les secrets. Aucun secret dans le code.
- Logs applicatifs via
app.logger. - Logs des webhooks centralisés via
app_logging/webhook_logger.py(Redis si dispo, sinon fichier JSON).
- Les décisions sont tracées dans
memory-bank/decisionLog.md. - La progression est suivie dans
memory-bank/progress.md. - La roadmap de refactoring se trouve dans
docs/refactoring-roadmap.md.