gigafibre-fsm/docs/architecture/VISION.md
louispaulb f33f7a6309 Optimisation (consolidation helpers address) + doc Vision/modularisation
Optimisation sûre (vérifiée, 0 régression) :
- helpers.js : `cors()` partagé (en-têtes CORS génériques) au lieu de 2 copies locales.
- address-conformity.js : réutilise `pool` (address-db) + `cors` (helpers) au lieu de redéfinir un Pool +
  cors → 1 seul client pg local partagé pour rqa_addresses/fiber.
- address-validate.js : utilise helpers.cors.

docs/architecture/VISION.md (NOUVEAU) — vision + plan de modularisation + roadmap d'optimisation, fondé sur
un audit chiffré (hub 58 modules/23k lignes, Ops 45k lignes, god-files identifiés). Découpe en 9 domaines
(bounded contexts), principe « source de vérité + validation à la saisie + lien stable » (modèle Adresses
généralisé à Client/Device/Service), optimisations P0/P1/P2, métriques de succès. Complète les docs
architecture existants + ENGINEERING_PRACTICES.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-07 01:28:54 -04:00

130 lines
8.4 KiB
Markdown

# Vision, modularisation & optimisation — Plateforme TARGO / Gigafibre
> Document stratégique. Complète `overview.md`, `app-design.md`, `data-model.md`, `module-interactions.md`
> et `../ENGINEERING_PRACTICES.md`. Objectif : passer d'une croissance organique (god-files, modules plats)
> à une architecture **modulaire par domaine** avec des **sources de vérité** fiables — pour livrer vite ET sûr.
## 0. Vision en une phrase
Un **hub d'orchestration léger** (Node) au-dessus d'**ERPNext** (ERP/source de données), organisé en
**domaines métier autonomes** (bounded contexts), chacun avec sa **source de vérité canonique**, sa
**validation à la saisie** et ses **liens stables** — pendant qu'on **éteint progressivement le legacy**.
---
## 1. État actuel (audit chiffré, 2026-06-07)
| Composant | Volume | Plus gros fichiers (god-files) |
|---|---|---|
| **targo-hub** (Node) | 58 modules, ~23 000 lignes, 52 routes (lazy-require) | campaigns 2366 · payments 1376 · network-intel 1221 · contracts 1091 · roster 1040 · tech-mobile 961 · dispatch 852 |
| **Ops SPA** (Vue3/Quasar) | ~45 000 lignes | ProjectWizard 2891 · DispatchPage 2162 · PlanificationPage 1863 · NetworkPage 1829 · ClientDetailPage 1715 |
**Forces** : hub mono-process simple (routage `path.startsWith` + `require` paresseux), ERPNext comme socle
données, frappe_pg (PostgreSQL), intégrations riches (legacy MariaDB, Ministra, GenieACS, OLT SNMP, Stripe,
Mailjet, Authentik, Karrio), base d'adresses RQA **locale** (5,24 M) déjà branchée.
**Dettes techniques** (priorisées plus bas) :
1. **God-files** : 5 fichiers front >1700 lignes, 2 back >1300 — mélangent UI/état/règles métier/I/O.
2. **Modules plats sans frontière de domaine** : 58 fichiers `lib/*.js` au même niveau ; couplage implicite.
3. **Helpers réimplémentés** : `norm()` (accents), `cors()`, `haversine()`, `stripHtml()` dupliqués dans
~6 modules (address-*, legacy-dispatch-sync, roster, serviceability, tech-absence-sms). *(cors/pool : consolidés ✅)*
4. **Pas de tests** ni de **CI/CD** (déploiement = `scp` manuel + `docker restart`).
5. **Observabilité inégale** : `catch {}` muets par endroits ; heartbeat/réconciliation présents seulement
sur le pont legacy. `erp.create/update` ne *throw* pas → des erreurs ont déjà été comptées comme succès.
---
## 2. Principe directeur : Domaines + Source de vérité
Deux règles structurent toute la suite :
**(A) Découper par DOMAINE (bounded context), pas par fichier.** Chaque domaine expose une interface
publique étroite (un `index` + des services) ; le reste est interne. Le routage du hub délègue au domaine.
**(B) Chaque entité a UNE source de vérité + validation à la saisie + lien stable.** On ne re-cherche pas
avec un processus complexe à chaque fois : on **résout une fois**, on **persiste le lien canonique**, le
downstream **lit le lien**. Modèle de référence : les **adresses** (cf. `reference/` + page Conformité) —
`rqa_addresses` (RQA local) ← `aq_address_id`/`linked_address`/`address_validation_status` sur Service Location.
---
## 3. Carte des domaines cible
Regroupement des 58 modules hub + pages Ops en **9 domaines**. (Refactor par déplacement progressif, pas big-bang.)
| Domaine | Hub (lib/…) | Ops (pages/modules) | Source de vérité |
|---|---|---|---|
| **Identité & Accès** | auth, (Authentik) | usePermissions, MainLayout | Authentik + Capabilities |
| **CRM / Clients** | store, **address-db/validate/conformity**, address-search | Clients, ClientDetail | Customer (ERPNext) · **Adresse = RQA** |
| **Dispatch & Terrain** | dispatch, roster, tech-mobile, legacy-dispatch-sync, (geo/routing Mapbox) | Dispatch, Planification, RendezVous, module tech | Dispatch Job · Shift/Roster |
| **Réseau & Infra** | network-intel, olt-snmp, devices, outage-monitor, oktopus, (genieacs) | Network | GenieACS (CPE) · OLT · device |
| **Facturation & Paiements** | payments, contracts, acceptance, store/checkout | Rapports, ContratBLB | **Legacy billing (autoritaire jusqu'au cutover)** → ERPNext |
| **Marketing & Campagnes** | campaigns, offers, ai (traduction) | module campaigns | Campaign · Gift (Giftbit) |
| **IA & Agent** | ai, agent, voice-agent, flow-runtime, conversation | Copilote, AgentFlows | Agent flows |
| **Intégrations & Legacy** | erp, legacy DB, Ministra, Karrio, Giftbit | — | Adaptateurs (anti-corruption layer) |
| **Plateforme** | helpers, config, observabilité | composables partagés, components/shared | — |
**Cible d'arborescence hub** (itératif) : `lib/<domaine>/<module>.js` + `lib/<domaine>/index.js` (interface
publique) ; `lib/util/` (norm, cors, geo, html) ; `server.js` route vers `require('./lib/<domaine>')`.
**Cible Ops** : `src/modules/<domaine>/` (pages + composants + composables + api du domaine), comme
`modules/campaigns` et `modules/tech` le font déjà — étendre ce pattern à dispatch, roster, clients, network.
---
## 4. Optimisations priorisées
### P0 — Hygiène (sûr, rapide, vérifiable au build)
- **Extraire les helpers partagés** dans `lib/util/` : `norm` (accents), `cors` ✅, `haversineKm`, `stripHtml`,
`tzDate`. Remplacer les ~6 réimplémentations. *(cors + pool address déjà consolidés.)*
- **Uniformiser le contrat handler** : `erp.create/update` renvoient `{ok}` → tout appelant DOIT vérifier
`r.ok` (déjà corrigé dans le pont ; auditer payments/contracts/store).
- **Supprimer le code mort** + `catch {}` muets → `log()`.
- **Boundary I/O** : un seul client `pg` partagé pour les lectures locales (address-db.pool, réutilisé ✅).
### P1 — Décomposition des god-files (par domaine, sans changer le comportement)
- Front : `ProjectWizard` (2891), `DispatchPage` (2162), `PlanificationPage` (1863), `ClientDetailPage` (1715)
→ extraire des **composables** (`use*`) + **sous-composants** (détail/sections). PlanificationPage : sortir
packedDay/route-planner, le panneau d'assignation, l'éditeur de journée en composables dédiés.
- Back : `campaigns` (2366) et `payments` (1376) → sous-modules de domaine (envoi, matching, suivi / facturation, rapprochement).
### P2 — Fiabilité & vélocité
- **Tests** (vitest) sur les modules à risque : paiements, pont legacy, conformité adresses, roster solver.
- **CI/CD** : remplacer `scp + docker restart` manuel par un pipeline (Gitea Actions) build+déploiement+santé.
- **Observabilité closed-loop** : généraliser le pattern `_lastRun`/`/status` + réconciliation (déjà sur le
pont) aux jobs critiques ; clés Uptime-Kuma.
---
## 5. Source de vérité — généralisation du pattern « Adresses »
| Entité | Source de vérité | Lien stable | État |
|---|---|---|---|
| **Adresse** | `rqa_addresses` (RQA local) + `fiber_availability` | `aq_address_id` + `linked_address` | ✅ FAIT (16 561 liées ; page Conformité) |
| **Client** | ERPNext Customer | `legacy_account_id` | partiel (matching legacy) |
| **Appareil/CPE** | GenieACS (serial/MAC réels) | MAC ↔ Service Equipment | piège connu (TPLG vs serial réel) |
| **Service TV** | Ministra (SID = id ligne `service` legacy) | `legacy_activation_url` | read-only (pas de 2e chemin d'écriture) |
| **Facturation** | **Legacy (autoritaire)** jusqu'au cutover | — | scheduler ERPNext en pause |
Prochaine application directe : finir le matching **Client** (legacy_account_id) et **Device** (MAC↔GenieACS)
sur le même modèle (résoudre une fois → persister → lire le lien).
---
## 6. Roadmap par phases
- **Phase 1 — Hygiène & fondations** : helpers partagés, code mort, `r.ok` partout, CI/CD minimal, tests des
modules critiques. *(Risque faible, gros gain de fiabilité.)*
- **Phase 2 — Modularisation** : déplacer hub `lib/*``lib/<domaine>/` ; décomposer les god-files front/back.
- **Phase 3 — Sources de vérité** : généraliser (Client, Device, Service) + observabilité closed-loop partout.
- **Phase 4 — Vision produit** : cutover facturation legacy→ERPNext ; app terrain Capacitor (GPS live des
unités, remplace le relevé manuel sur la carte) ; portail client self-service (abonnement + RDV + paiement).
---
## 7. Métriques de succès
- 0 fichier > 800 lignes (front et back).
- 0 helper dupliqué (`norm`/`cors`/`geo`/`html` centralisés).
- 100 % des entités clés avec source de vérité + validation à la saisie + lien persisté.
- Déploiement par pipeline (0 `scp` manuel) ; tests verts sur les modules critiques.
- Tout job inter-systèmes : idempotent + observable + réconcilié (cf. ENGINEERING_PRACTICES).