Tableau de bord d'audit technique d'ISI-APP, réservé aux super-développeurs ISI. Centralise cinq indicateurs de santé du codebase et des données, accessibles sans impacter les tenants clients.
Le Hub Santé de l'app est une page d'administration (/admin/app-health) qui permet aux super-développeurs ISI d'auditer l'état interne d'ISI-APP : cohérence des données, qualité du code UI, fraîcheur des dépendances. Chaque audit est lancé manuellement, s'exécute en arrière-plan, et le résultat est persisté en base pour une lecture instantanée à tout moment.
/admin/app-healthisSuperDeveloper() — super-développeurs ISI uniquement. Toute tentative d'accès sans ce droit retourne un 403.| Onglet | Rôle |
|---|---|
| Vue d'ensemble | Grille de 5 cartes résumant le statut et la valeur principale de chaque type d'audit. Permet de lancer ou relancer un scan. Cliquer sur une carte (en dehors du bouton d'action) ouvre directement le détail correspondant dans l'onglet Intégrité des données ou Audit Onyx. |
| Intégrité des données | Détail des résultats des 4 indicateurs d'intégrité (carte des relations, orphelins, normalisation, fraîcheur). Navigation par sous-onglet. |
| Audit Onyx | Résultat de l'audit de conformité UI : statistiques d'usage des composants Onyx et liste des anti-patterns Bootstrap/global détectés dans les vues Blade. |
Si un scan du même type est déjà en cours, un second clic est ignoré silencieusement (protection anti-doublon).
Construit une carte de toutes les relations entre tables depuis trois sources complémentaires : les clés étrangères déclarées en base (information_schema), les relations Eloquent parsées dans app/Models/, et les jointures explicites détectées par grep dans app/. La valeur principale affichée est le nombre total de relations dédupliquées.
S'appuie sur la carte des relations (dernière disponible) pour détecter les enregistrements enfants sans parent valide. Un scan « Carte des relations » réussi doit exister au préalable — sans lui, le scan des orphelins échoue explicitement avec un message invitant à lancer d'abord la cartographie, plutôt que de renvoyer un faux résultat « 0 orphelin » qui donnerait une confiance trompeuse.
Quatre niveaux de sévérité sont distingués, chacun détecté par une requête SQL dédiée et mutuellement exclusive (une ligne ne peut matcher qu'une seule des quatre) :
| Sévérité | Signification |
|---|---|
| FK null | La colonne FK elle-même n'est pas renseignée — absence de relation, pas une relation brisée |
| Orphelin vrai | FK renseignée mais parent totalement absent de la table, dans aucun tenant |
| Parent soft-deleted | Parent présent mais archivé (dtdel non nul) |
| Fuite cross-tenant | Parent présent et actif, mais idc différent de l'enfant |
La valeur principale affichée est le nombre total d'orphelins (toutes sévérités confondues), calculé
de façon exacte (aucun plafonnement) via un COUNT SQL par catégorie. Toutes les relations de la
carte sont analysées à chaque scan (aucune limite par défaut).
Une même relation physique détectée par plusieurs sources de la carte des relations (ex. une clé étrangère à la fois déclarée en base et devinée par l'analyse du code Eloquent) est dédupliquée en amont : sans cette déduplication, ses orphelins auraient été comptés plusieurs fois dans le total affiché.
Le détail de tous les enregistrements orphelins (aucun plafond par relation) est affiché dans un tableau filtrable et triable côté serveur — deux filtres sont disponibles :
Seule la dernière génération d'échantillons est conservée (un nouveau scan remplace intégralement la précédente) — l'historique des scans eux-mêmes reste consultable, mais pas le détail ligne par ligne des scans antérieurs.
Vérifie que les données stockées en base respectent les règles de normalisation appliquées par les triggers SQL (migration 2026_06_05). Les règles couvrent : trim, trim_collapse, email, phone, siret, postal. Un échantillon de 500 lignes est analysé par colonne concernée. La valeur principale affichée est le taux de conformité global en pourcentage. Le détail par colonne (« Violations par colonne ») est trié par taux de conformité croissant : les colonnes les plus problématiques (0 % en premier) apparaissent en tête.
Un bouton « Voir » sur chaque colonne comportant des violations ouvre une fenêtre listant jusqu'à 3 exemples concrets — la valeur brute en base et sa version normalisée attendue — pour comprendre en un coup d'œil ce qui ne respecte pas la règle, sans avoir à interroger la base manuellement.
Appelle composer outdated et npm outdated pour comparer les versions installées aux dernières disponibles. Classe chaque package en a_jour, retard_mineur (patch/minor) ou retard_majeur (major). La valeur principale affichée est le nombre de packages obsolètes. La note globale est : rouge (au moins un retard majeur), orange (retard mineur uniquement), vert (tout à jour) — un sous-texte précise systématiquement sa composition (ex. « 2 paquet(s) en retard majeur »).
Scanne toutes les vues Blade de resources/views/ pour détecter :
x-onyx.* utilisés (inventaire de l'adoption Onyx)<input>, <select>, <textarea>), classes Bootstrap (btn btn-*, badge bg-*, alert alert-*, card, etc.), anciens composants x-global.*La valeur principale affichée est le nombre total d'occurrences d'anti-patterns. L'onglet Audit Onyx détaille par règle, fichier et ligne.
Les scans ne s'exécutent jamais de façon synchrone. Le flux est :
AppHealthHub::startScan() crée un enregistrement AppHealthScan en base avec le statut pending, puis dispatche AppHealthScanJob sur la queue default.running, exécute le service correspondant, puis enregistre le résultat JSON dans jsresult et passe le statut à done (ou failed avec message d'erreur).AppHealthHub::render() lit uniquement les derniers scans done depuis la base — il n'exécute aucun calcul. Le polling Livewire (3 s) rafraîchit la vue jusqu'à disparition des scans actifs.Ce design garantit qu'un scan long (plusieurs minutes) n'impacte pas le temps de réponse HTTP et que le résultat reste consultable indéfiniment après la fin du job.
La détection des fuites cross-tenant dans DataIntegrityService nécessite de lire les colonnes idc de tables qui appartiennent à des tenants différents, sans scoper la requête. Ce contournement est intentionnel et documenté dans le code. Il est réservé aux super-développeurs ISI, qui ont précisément besoin d'une vision cross-tenant pour identifier les anomalies. Aucune écriture n'est effectuée.
Le sous-lot suppression d'orphelins (§6.8 de la spec) est volontairement non implémenté. Le hub est en lecture seule : il signale les anomalies mais ne les corrige pas automatiquement. La suppression d'orphelins fera l'objet d'un développement séparé avec des gardes-fous adaptés.