# Best practices — « ne rien échapper » + automatiser au maximum Cadre d'ingénierie pour la plateforme TARGO (ERPNext/PG · targo-hub Node · Ops Quasar · PWA tech · portail Lovable · ponts legacy MariaDB/osTicket/Ministra · intégrations Stripe/Twilio/GenieACS/Forti). Objectif double : **fiabilité (rien ne tombe entre les craques)** + **automatisation closed-loop**. > Principe directeur : **toute action inter-systèmes doit être (1) idempotente, (2) observable, (3) réconciliée.** > Toute automatisation doit être **closed-loop** : agir → vérifier le résultat → réessayer/alerter si échec. --- ## A. Intégrité des données — « rien ne tombe » 1. **Une seule source de vérité par domaine.** Facturation = legacy jusqu'au cutover ; dispatch = ERPNext ; provisioning TV = Ministra. Jamais deux plumes sur la même donnée (cf. analyse Ministra : un 2ᵉ chemin = double facturation). 2. **Idempotence partout** : clé naturelle externe sur chaque objet importé/synchronisé (déjà fait : `legacy_ticket_id`). Étendre aux webhooks Stripe (event.id), SMS, provisioning. 3. **Pattern Outbox** pour les écritures « locale + appel externe » : écrire l'intention en base d'abord, un worker la pousse et marque `done`/`failed`. Évite « écrit en local mais l'API a échoué » (le risque exact du wizard Ministra). 4. **Réconciliation périodique** : un job qui compare source ↔ ERPNext et signale la dérive (ex. tickets `assign_to=3301` côté legacy vs Dispatch Jobs créés ; abonnements Ministra vs `service`). Le pont crée — la réconciliation prouve qu'**aucun n'a été échappé**. 5. **Soft-delete + audit trail** : ne jamais perdre une donnée ; tracer qui/quand/quoi (ERPNext le fait nativement ; l'exposer côté hub pour les actions du hub). ## B. Observabilité — « on SAIT quand ça casse » 1. **Logs structurés** (JSON, pino) avec `correlation_id` par requête/job — finis les `console.log`. Un job legacy-sync = une ligne `{job, created, errors, ms}` traçable. 2. **`/healthz` + `/readyz`** sur le hub (DB ok ? ERPNext ok ? legacy ok ?) → branchés sur **Uptime-Kuma** (déjà en place pour le réseau). 3. **Heartbeat sur CHAQUE tâche planifiée** : le legacy-sync, le PPA cron, les pollers doivent « pinger » à chaque tick ; si un tick manque → alerte. (Un cron muet qui meurt = des tickets non importés sans que personne le sache.) 4. **Alerting** : erreurs (Sentry/GlitchTip self-host) + métriques (Prometheus + Grafana, ou au minimum un endpoint `/metrics`). Alertes vers le canal ops existant (Twilio/email). 5. **Bannir le `catch {}` muet** : tout catch logge + incrémente un compteur d'erreurs. (Plusieurs `catch (e) {}` actuels avalent des échecs silencieusement.) ## C. Fiabilité des intégrations 1. **Retry + backoff exponentiel** (généraliser `retryWrite` à tous les appels externes Ministra/Twilio/Stripe/GenieACS), avec **plafond** et **dead-letter** (file des échecs définitifs à rejouer). 2. **Webhooks idempotents + signés + rejouables** (Stripe a déjà event.id ; vérifier la signature, stocker l'event, rejeu manuel possible). 3. **Circuit breaker** sur un service externe en panne (ne pas marteler Ministra/legacy en boucle → respecte aussi fail2ban legacy). 4. **Timeouts explicites** sur tous les appels réseau (déjà fait sur la DB legacy). 5. **Dégradation gracieuse** : si Ministra est down, le job reste « à activer » et alerte — jamais d'échec silencieux. ## D. Tests + CI/CD — « le scp manuel doit disparaître » 1. **Pipeline Gitea Actions** par push : `lint` → `test` → `build` → deploy auto (staging puis prod sur tag). Remplace les `scp` à la main (source d'erreurs + pas de gate). 2. **Tests** par couche : unitaires sur la logique pure (mapping pont, `jobColor`, `firstFitStart`, calculs facturation) ; intégration sur les endpoints hub (avec ERPNext/MariaDB de test) ; quelques E2E (Playwright) sur les parcours critiques (dispatch, booking, checkout). 3. **Environnement de staging** iso-prod (« on est en lab » → formaliser un vrai staging séparé de la prod). 4. **Migrations versionnées** (les Custom Fields via script idempotent → bon ; versionner toutes les migrations ERPNext + schéma). 5. **Rollback en 1 commande** (garder les N derniers bundles ; le déploiement actuel écrase — conserver l'ancien pour rollback instantané). ## E. Sécurité & secrets 1. **Gestion centralisée des secrets** (Vault/Infisical/ou au moins des `.env` chiffrés + rotation) — aujourd'hui dispersés (creds Ministra **en dur dans le PHP legacy**, tokens en `.env`). 2. **Moindre privilège** : la DB legacy en SELECT-only (bien) ; appliquer partout. Les liens tech non authentifiés (`reply_ticket.php`, `connect_ministra.php`) → tokens à expiration à terme. 3. **Audit d'accès** + 2FA sur les surfaces admin (Authentik déjà là — généraliser). 4. **Sauvegardes testées + DR** : backup auto ERPNext PG + MariaDB legacy + restauration testée (un backup jamais restauré n'existe pas). ## F. Automatisation closed-loop — « le plus possible » 1. **Événementiel > polling** quand possible : le pont legacy poll 15 min → ajouter un trigger côté legacy (webhook/INSERT trigger → ping hub) pour le quasi-temps-réel. Garder le poll comme filet de sécurité. 2. **Auto-dispatch** : le solveur roster (déjà là) propose ; viser l'assignation auto des jobs simples + suggestion classée pour le reste (proximité quand la géo arrivera). 3. **Réconciliation auto-corrective** (self-healing) : un job qui re-crée/re-aligne ce qui a dérivé, plutôt qu'un simple rapport. 4. **Moteur de flux** : `agent-flows` existe déjà → en faire le squelette des automatisations métier (relance, escalade SLA, activation, avis client) plutôt que du code ad hoc dispersé. 5. **SLA monitors** : alerte si un job reste non-assigné > X h, un ticket TV non-activé > X j, un paiement non réconcilié, un client hors quart (déjà le badge ⏰). 6. **AI ciblée** (déjà : OCR, copilote, outage) → étendre : matching compétence↔type de cas (historique), triage/priorisation des tickets, détection d'anomalies de facturation. --- ## Roadmap priorisée (incrémental, sans tout casser) **Quick wins (jours) — fiabilité immédiate** - [ ] `/healthz` + heartbeat du legacy-sync → Uptime-Kuma + alerte si tick manqué. - [ ] Logs structurés + suppression des `catch {}` muets (au moins compter + logguer). - [ ] Endpoint `/dispatch/legacy-sync/reconcile` : compte legacy(3301,open) vs Dispatch Jobs → signale les manquants. - [ ] Conserver le bundle N-1 au déploiement (rollback instantané). **Court terme (semaines) — arrêter l'érosion** - [ ] Pipeline Gitea Actions (lint+build+deploy) → fin du scp manuel + staging réel. - [ ] Premiers tests unitaires sur la logique pure (pont, jobColor, firstFitStart, facturation). - [ ] Retry+backoff+dead-letter généralisés (Ministra/Twilio/Stripe). - [ ] Sentry/GlitchTip self-host + alerting. **Stratégique (mois) — automatiser & sécuriser** - [ ] Outbox + réconciliation auto-corrective sur les ponts. - [ ] Événementiel (triggers legacy → hub) + SLA monitors via agent-flows. - [ ] Gestion centralisée des secrets + rotation + DR testé. - [ ] Cutover progressif des sources de vérité (legacy → ERPNext), domaine par domaine. > Règle d'or pour « ne rien échapper » : **si une action peut échouer silencieusement, elle DOIT être (a) réessayée, (b) mise en dead-letter, et (c) visible sur un tableau de bord.** Aucune exception.