# 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.
