# AUDIT FONCTIONNEL — PROTOTYPE « PAVResearch » (IRAD / MINRESI, programme PAVSGS-2C)

- Date de l'audit : 2026-08-23
- Périmètre : code source complet du prototype web (branche de travail Lovable), exécution locale sur `http://localhost:8080`
- Méthode : lecture du code (routes, composants, librairies de données, configuration), comptage programmatique des jeux de données, test HTTP de toutes les routes, lecture du journal de build
- **Avertissement central** : ce projet est un **prototype de validation métier**. Il n'a **aucun backend, aucune base de données, aucune authentification réelle**. Toutes les données sont fictives et codées en dur dans le dépôt. Aucun résultat affiché n'est scientifiquement validé.

Ce document est destiné à être transmis à un assistant d'analyse (ChatGPT) pour établir un plan de correction vers des fonctionnalités réelles.

---

## 1. Résumé exécutif

| Question | Réponse factuelle |
|---|---|
| Le prototype est-il navigable de bout en bout ? | Oui. 36 routes testées répondent HTTP 200, une URL inconnue renvoie 404 avec écran dédié. |
| Le build passe-t-il ? | Oui — dernier build « build OK » (journal `/tmp/observability/build-errors.log`, 2026-08-23T09:39:36Z). Typecheck sans erreur. |
| Y a-t-il un backend ? | **Non.** Aucun `createServerFn`, aucune route `src/routes/api/*`, aucun appel `fetch()` applicatif, aucune intégration Supabase/Lovable Cloud. |
| Y a-t-il une base de données ? | **Non.** 100 % des données sont des tableaux TypeScript littéraux (`src/lib/pav-data.ts`, `src/lib/recherche-data.ts`). |
| Y a-t-il une authentification ? | **Non.** Sélection de profil en un clic, persistée dans `localStorage` (`pav.profil`). Aucun mot de passe, aucun jeton, aucun contrôle d'accès. |
| Les diagnostics / prédictions sont-ils calculés ? | **Non.** Scores, pondérations et conclusions sont des chaînes de caractères écrites en dur. Aucun modèle, aucune statistique, aucune IA n'est exécutée. |
| Que se passe-t-il au rechargement de la page ? | Seuls le profil et les brouillons de collecte survivent. Journal, retours/objections, exécutions, tâches et filtres de recherche reviennent à leur état initial (sauf filtres, persistés en `localStorage`). |
| Quel est le niveau réel de maturité ? | Maquette interactive haute-fidélité (« clickable prototype ») avec un référentiel de démonstration cohérent — utile pour la validation métier, **inutilisable en production**. |

---

## 2. Pile technique et configuration

| Élément | Valeur constatée | Fichier |
|---|---|---|
| Framework | TanStack Start 1.168.32 + TanStack Router 1.170.18 (routage par fichiers) | `package.json`, `src/routeTree.gen.ts` |
| Build | Vite 8.1.5, Tailwind CSS v4 (`@tailwindcss/vite`) | `package.json`, `src/styles.css` |
| UI | shadcn/ui sur Radix UI, `lucide-react`, `sonner` (toasts), `recharts` (graphiques) | `src/components/ui/*` |
| État applicatif | React Context maison (`PavProvider`) — pas de Redux/Zustand | `src/lib/pav-store.tsx` (578 l.) |
| Données serveur | `@tanstack/react-query` installé et monté (`QueryClientProvider`) mais **jamais utilisé** pour charger des données | `src/routes/__root.tsx` |
| Validation | `zod` installé, **non utilisé** dans le code applicatif | `package.json` |
| Runtime cible | Edge/Cloudflare Worker (`src/server.ts`) | `src/server.ts` |
| Backend / DB / Auth | **absents** | — |
| Volume de code applicatif | ~7 900 lignes (`src/routes`, `src/lib`, `src/components` hors `ui/`) | — |

Aucune dépendance externe réseau n'est appelée à l'exécution : ni tuiles cartographiques, ni API météo, ni service d'IA, ni stockage d'objets, ni service d'export PDF.

---

## 3. Référentiel de données de démonstration (volumes exacts, mesurés)

Source unique : fichiers TypeScript littéraux, chargés en mémoire au démarrage du bundle.

### 3.1 `src/lib/pav-data.ts` (906 lignes)

| Entité | Volume | Remarques |
|---|---|---|
| `sites` | 4 | Nkolbisson, Barombi-Kang, Bafoussam, Ebolowa ; coordonnées `x/y` en unités SVG, **pas des latitudes/longitudes projetées** |
| `parcelles` | 12 | polygones SVG, culture, rendement (certains `null` volontairement) |
| `arbres` | 79 | générés par une fonction `construireArbres()` déterministe |
| `varietes` | 8 | 3 espèces, statuts de caractérisation |
| `analysesSol` | 15 | tableau de tuples compactes converties en objets |
| `experimentations` | 6 | dispositifs, parcelles rattachées |
| `climatAnnuel` | 12 | une valeur mensuelle agrégée (pluie, tmoy, humidité, ETo) |
| `observations` | 10 | observations terrain fictives |
| `maladies` | 4 | pressions sanitaires |
| `alertes` | 4 | alertes générées à la main, pas par une règle |
| `utilisateurs` | 5 | fiches d'administration fictives |
| `jeuxDonnees` | 6 | métadonnées de gouvernance |

### 3.2 `src/lib/recherche-data.ts` (606 lignes) — index scientifique unifié

| Entité | Volume |
|---|---|
| `indexScientifique` (`ObjetSci`) | 79 objets construits par agrégation des entités ci-dessus |
| `CATEGORIES` | 11 |
| `genotypes` | 8 |
| `champsSemenciers` | 3 |
| `parcsABois` | 2 |
| `medias` | 6 (métadonnées uniquement, **aucun fichier image réel**) |
| `documents` | 5 (métadonnées, **aucun PDF réel**) |
| `stationsClimat` | 4 (dérivées des sites) |

### 3.3 États initiaux codés en dur dans le store

`src/lib/pav-store.tsx` : `JOURNAL_INITIAL`, `RETOURS_INITIAUX`, `TACHES_INITIALES`, `EXECUTIONS_INITIALES`, `VERSION_COURANTE` (`DEMO-DATA v2026.06`, `PARAM-DEMO v1.3`, `PAV-DEMO-APT-01 v1.3`).

**Aucune donnée n'est issue d'une saisie réelle de l'IRAD.** Tous les écrans affichent la mention « Données de démonstration · validation scientifique IRAD requise » (`MENTION_DEMO`, composant `AvertissementDemo`).

---

## 4. Persistance — ce qui survit réellement

| Donnée | Mécanisme | Portée | Fichier |
|---|---|---|---|
| Profil sélectionné | `localStorage["pav.profil"]` | Navigateur, permanent | `src/lib/pav-store.tsx:455-472` |
| Brouillons de collecte | `localStorage["pav.brouillons"]` | Navigateur, permanent | `src/lib/pav-store.tsx:474-480` |
| Filtres de recherche | `localStorage` via `useFiltres` | Navigateur, permanent | `src/lib/use-filtres.ts:12-34` |
| Journal de traçabilité | `useState` en mémoire | **Perdu au rechargement** | `src/lib/pav-store.tsx:446` |
| Retours / objections | `useState` en mémoire | **Perdu au rechargement** | `src/lib/pav-store.tsx:447` |
| Tâches « données manquantes » | `useState` en mémoire | **Perdu au rechargement** | `src/lib/pav-store.tsx:448` |
| Exécutions / versions | `useState` en mémoire | **Perdu au rechargement** | `src/lib/pav-store.tsx:449` |

Conséquence directe : **rien n'est partagé entre deux utilisateurs ou deux appareils**. Deux navigateurs ouverts sur la même démo voient deux états divergents.

---

## 5. Audit route par route (36 routes, toutes testées HTTP 200)

Légende État : **R** = réel (fonctionne effectivement dans le navigateur), **S** = simulé (affichage crédible sans logique métier), **P** = partiel.

### 5.1 Entrée et transverses

| Route | Fichier | Objectif | UI | Ce qui marche réellement | Ce qui est simulé |
|---|---|---|---|---|---|
| `/` | `src/routes/index.tsx` (94 l.) | Écran de connexion / choix de profil | 4 cartes profils, bouton « Démo vendredi » | Sélection de profil → `setProfil` + redirection vers l'accueil du profil (R) ; persistance `localStorage` (R) | **Aucune authentification** : pas d'identifiant, pas de mot de passe, pas de session serveur (S) |
| `__root` | `src/routes/__root.tsx` (145 l.) | Layout, providers, 404, erreurs | `QueryClientProvider`, `PavProvider`, `Toaster`, `notFoundComponent`, `errorComponent` | Boundary 404 et erreur opérationnelles (R) | — |
| `/rapport` | `src/routes/rapport.tsx` | Rapport de démonstration | Synthèse + bouton Imprimer | `window.print()` — **génération PDF via la boîte d'impression du navigateur uniquement** (P) | Aucune génération PDF serveur, aucune mise en page paginée, aucun archivage |

### 5.2 Profil Chercheur / Expert

| Route | Fichier | Objectif | Réel | Simulé |
|---|---|---|---|---|
| `/tableau-de-bord` | `tableau-de-bord.tsx` (181 l.) | KPI + qualité des données | Agrégats calculés à la volée sur les tableaux en mémoire (R) ; graphiques Recharts (R) | Indicateurs sans source vérifiable, pas de rafraîchissement, pas d'historique |
| `/carte` | `carte.tsx` (113 l.) + `components/carte.tsx` (245 l.) | Carte Cameroun, drill-down site → parcelle → arbre | Navigation hiérarchique et sélection (R) | **SVG dessiné à la main** : pas de fond cartographique, pas de projection géographique, pas de tuiles, coordonnées non géoréférencées (S) |
| `/sites`, `/sites/$siteId` | `sites.index.tsx`, `sites.$siteId.tsx` | Liste et fiche site | Navigation, filtrage local (R) | Données fictives |
| `/parcelles/$parcelleId` | `parcelles.$parcelleId.tsx` | Fiche parcelle multi-onglets | Onglets, graphiques, timeline (R) | Sol/climat/rendement/photos fictifs, photos = cadres vides |
| `/arbres/$arbreId` | `arbres.$arbreId.tsx` | Fiche arbre | Navigation (R) | Données générées |
| `/genetique`, `/climat`, `/maladies`, `/rendement`, `/alertes`, `/administration` | routes `ModulePage` | Modules listes | Rendu + compteurs (R) | Écrans **génériques** partageant un seul composant (`components/module-page.tsx`) : pas de filtre, pas de tri, pas de détail, pas de CRUD |
| `/vegetal` | `vegetal.tsx` | Suivi végétal | Liens vers parcelles (R) | Contenu figé |
| `/sols`, `/sols/$analyseId` | `sols.index.tsx`, `sols.$analyseId.tsx` | Campagnes et fiches de prélèvement | Navigation, graphiques (R) | Carte thématique de sol simulée, aucun interpolateur spatial |
| `/experimentations`, `/experimentations/$expId` | idem | Dispositifs expérimentaux | Navigation (R) | Pas de plan d'expérience réel, pas d'analyse statistique |
| `/analyses` | `analyses.tsx` | Schéma Données → Moteur → Résultats | Rendu statique (R) | **Purement illustratif** : aucun moteur derrière le schéma |
| `/collecte` | `collecte.tsx` | Collecte terrain mobile | Voir §7 | Voir §7 |
| `/donnees`, `/donnees/journal` | `donnees.index.tsx`, `donnees.journal.tsx` (143 l.) | Traçabilité et export | **Export CSV réel** côté client via `Blob` + `URL.createObjectURL` (R, `pav-store.tsx:558-577`) | Journal en mémoire, non signé, non horodaté par un serveur, effaçable par simple rechargement |
| `/retours`, `/retours/$retourId` | `retours.index.tsx` (205 l.), `retours.$retourId.tsx` (232 l.) | Objections chercheurs + workflow | Création, changement de statut, fil de discussion, historique (R, en mémoire) | Aucun destinataire réel, aucune notification, aucune assignation effective, aucun droit d'accès |
| `/versions`, `/versions/comparer` | `versions.index.tsx` (179 l.), `versions.comparer.tsx` (140 l.) | Registre d'exécutions, diff de versions | Comparaison ligne à ligne avec mise en évidence des différences (R) | Les « exécutions » ne rejouent aucun calcul : elles comparent des chaînes de version figées |

### 5.3 Section Recherche scientifique (inspiration Genotypure)

| Route | Fichier | Objectif | Réel | Simulé |
|---|---|---|---|---|
| `/recherche` | `recherche.index.tsx` (99 l.) | Hub, 11 catégories, graphe de données | Recherche globale sur l'index en mémoire (R) ; graphe SVG (`recherche-graphe.tsx`) (R, décoratif) | Graphe non interactif avec les données réelles |
| `/recherche/categorie/$catId` | `recherche.categorie.$catId.tsx` | Explorateur Liste / Tableau / Carte | Filtres multicritères persistants (R), tri (R), pagination (R), **export CSV du tableau** (R), carte à couches activables avec drill-down zone → site → parcelle → plant (R) | Fond de carte SVG, pas de SIG |
| `/recherche/objet/$objetId` | `recherche.objet.$objetId.tsx` (304 l.) | Fiche scientifique universelle 8 onglets | Onglets, objets liés, timeline de relations (R) | Contenus scientifiques fictifs, médias absents |
| `/recherche/simulation/$objetId` | `recherche.simulation.$objetId.tsx` (132 l.) | Parcours Diagnostic → Prédiction → Recommandation | Navigation par étapes, journalisation, panneau « Pourquoi ? » (R) | **Aucun calcul** : textes construits par `src/lib/simulation.ts` à partir de la disponibilité des données, pondérations libellées « Pondération à définir » (S) |
| `/recherche/speculation/$culture` | `recherche.speculation.$culture.tsx` (151 l.) | Entrée par spéculation | Navigation par zone/site (R) | — |

### 5.4 Profil Producteur / Décideur

| Route | Fichier | Objectif | Réel | Simulé |
|---|---|---|---|---|
| `/producteur`, `/producteur/index` | `producteur.tsx`, `producteur.index.tsx` | Accueil producteur | Navigation (R) | Contenu figé |
| `/producteur/aptitude` | `producteur.aptitude.tsx` | « Mon terrain est-il adapté au cacao ? » 5 étapes | Parcours par étapes, panneau « Pourquoi ce résultat ? » (R) | **Score 78 % écrit en dur**, facteurs `32/40`, `26/30`, `12/20`, `8/10` littéraux ; aucune donnée du terrain de l'utilisateur n'est saisie ni utilisée (S) |
| `/comparateur` | `comparateur.tsx` | Comparateur de variétés | Sélection 2–3 variétés, tableau comparatif (R) | Notes de compatibilité issues des fiches fictives |
| `/decideur` | `decideur.tsx` | Dashboard territorial | Agrégats par zone agroécologique (R) | Aucune source statistique officielle |

---

## 6. Matrice de maturité fonctionnelle

| Fonctionnalité | État | Preuves techniques | Limites | Priorité MEP |
|---|---|---|---|---|
| Navigation multi-profils | **Partiel** | `app-shell.tsx:38-66` (menus filtrés par profil), `pav-store.tsx:PROFILS` | Filtrage purement cosmétique : toute route reste accessible par URL directe | P0 |
| Authentification | **Non fonctionnel** | `index.tsx:29-34` — `setProfil` sans vérification | Aucun compte, aucun mot de passe, aucune session, aucun rôle serveur | P0 |
| Autorisation / RLS | **Absent** | aucune occurrence de politique ou de garde de route | Toutes les données sont publiques dans le bundle client | P0 |
| Persistance des données métier | **Non fonctionnel** | `pav-store.tsx:446-449` (`useState`) | Journal, retours, versions, tâches perdus au rechargement | P0 |
| Référentiel sites/parcelles/arbres | **Simulé** | `pav-data.ts` (4/12/79 enregistrements) | Codé en dur, non modifiable par l'utilisateur, pas de CRUD | P0 |
| Carte interactive | **Simulé** | `components/carte.tsx`, `recherche-vues.tsx:VueCarte` | SVG manuel, coordonnées non géographiques, pas de tuiles, pas de projection, pas de calcul de surface | P1 |
| Géolocalisation GPS | **Simulé** | `collecte.tsx` — valeur `"2.90211, 11.15108 · ±5 m"` en dur | L'API `navigator.geolocation` n'est jamais appelée | P1 |
| Prise de photo | **Simulé** | `collecte.tsx` — `setPhoto("photo-terrain-demo.jpg")` | Aucun `<input type="file">`, aucune capture, aucun stockage | P1 |
| Collecte terrain hors connexion | **Partiel** | `pav-store.tsx:474-480` (`localStorage`) | Brouillons réellement persistés, mais le mode « hors connexion » est un simple interrupteur d'UI (`setEnLigne`) ; pas de Service Worker, pas de PWA, pas de détection réseau | P1 |
| Synchronisation | **Simulé** | `pav-store.tsx` — `synchroniser()` remplace le statut par `"synchronise"` | Aucun envoi réseau, aucune résolution de conflit, aucun accusé serveur | P0 |
| Diagnostic / aptitude | **Simulé** | `producteur.aptitude.tsx` — score et pondérations littéraux | Aucun modèle agronomique, aucun seuil validé | P1 |
| Prédiction | **Simulé** | `src/lib/simulation.ts:20-70` | Textes générés selon la seule disponibilité des données ; « Pondération à définir » | P2 |
| Recommandation | **Simulé** | `src/lib/simulation.ts` | Aucune règle IRAD implémentée | P2 |
| Explicabilité (« Pourquoi ce résultat ? ») | **Réel (UI) / Simulé (contenu)** | `components/pourquoi.tsx` (213 l.), type `Explication` | Le composant est un cadre d'explicabilité réel et systématique ; les contenus expliqués sont fictifs | P1 (à conserver) |
| Actions scientifiques IA (Analyser, Comparer, Adaptabilité) | **Simulé** | `components/actions-scientifiques.tsx` (139 l.) | Aucun appel de modèle ; seule la journalisation est effective | P2 |
| Objets liés / graphe de relations | **Réel (dérivé)** | `src/lib/relations.ts` (269 l.), `components/objets-lies.tsx` | Relations calculées depuis les données fictives : la logique est réelle, les données non | P2 |
| Recherche globale + filtres | **Réel** | `recherche-data.ts:rechercheGlobale/appliquerFiltres`, `use-filtres.ts` | Recherche en mémoire sur 79 objets ; ne passera pas à l'échelle sans index serveur | P1 |
| Vue tableau (tri, pagination, export CSV) | **Réel** | `recherche-vues.tsx` (816 l.), `exporterCsv` | Export limité aux données de démonstration | P2 |
| Export CSV journal | **Réel** | `pav-store.tsx:558-577` | Fichier généré côté client, non signé | P2 |
| Rapport PDF | **Partiel** | `rapport.tsx` — `window.print()` | Dépend du navigateur ; pas de PDF serveur, pas de pagination maîtrisée, pas d'archivage | P2 |
| Objections / commentaires + workflow | **Simulé (persistance)** | `retours.index.tsx`, `retours.$retourId.tsx`, `retour-form.tsx` | Workflow complet en UI (statuts, fil, historique) mais volatil et mono-utilisateur | P0 |
| Versionnage / reproductibilité | **Simulé** | `versions.index.tsx`, `versions.comparer.tsx`, `VERSION_COURANTE` | Compare des étiquettes de version, ne rejoue aucun calcul, ne fige aucun instantané de données | P1 |
| Traçabilité / journal | **Partiel** | `donnees.journal.tsx`, `ajouterJournal` | Écritures réelles pendant la session, aucune inviolabilité, aucun horodatage serveur | P0 |
| Mode « Démo vendredi » | **Réel** | `src/lib/demo-scenario.ts` (142 l.), `components/demo-guide.tsx` | Guide de 16 étapes fonctionnel ; à retirer ou isoler en production | P3 |
| Alertes | **Simulé** | `pav-data.ts:alertes` (4 entrées) | Aucune règle de déclenchement, aucune notification, aucun canal (mail/SMS) | P2 |
| Tableaux de bord | **Partiel** | `tableau-de-bord.tsx`, `decideur.tsx` | Calculs réels sur données fictives ; pas de période, pas de comparaison, pas d'export | P2 |
| Médias / documents | **Non fonctionnel** | `recherche-data.ts:medias/documents` (métadonnées seules) | Aucun fichier, aucun stockage objet, cadres « Photo non disponible » | P2 |
| Internationalisation | **Absent** | — | Français uniquement (conforme au besoin actuel) | P3 |
| Accessibilité | **Partiel** | `role="img"`, `aria-label` sur la carte ; libellés de formulaires présents | Non audité RGAA ; carte SVG peu exploitable au clavier/lecteur d'écran | P2 |
| SEO / métadonnées | **Réel** | `src/lib/head.ts`, `head()` par route | Correct pour un prototype ; à revoir si l'app devient privée | P3 |
| Tests automatisés | **Absent** | aucun fichier de test dans le dépôt | Aucune non-régression garantie | P1 |
| Observabilité / monitoring | **Partiel** | `src/lib/error-capture.ts`, `lovable-error-reporting.ts` | Capture d'erreurs de la plateforme uniquement ; pas de métriques applicatives | P2 |

---

## 7. Analyse détaillée : Collecte terrain (module le plus proche du réel)

Fichier : `src/routes/collecte.tsx` (27 lignes très denses) + `src/lib/pav-store.tsx`.

Réellement fonctionnel :
- parcours en 5 étapes (Contexte, Observation, Mesures, Preuves, Validation) avec navigation avant/arrière ;
- listes déroulantes site → parcelle → arbre **réellement chaînées** (`parcellesDuSite`, `arbresDeParcelle`) ;
- saisie des mesures (hauteur, diamètre, fruits, état sanitaire) et note libre ;
- enregistrement d'un brouillon **réellement persisté** en `localStorage` avec identifiant `BR-<timestamp>` ;
- mise à jour du statut d'une tâche « donnée manquante » associée à la parcelle ;
- retours utilisateur via toasts.

Simulé ou absent :
- **GPS** : chaîne littérale `"2.90211, 11.15108 · ±5 m"`, `navigator.geolocation` jamais appelé ;
- **Photo** : chaîne `"photo-terrain-demo.jpg"`, aucun fichier n'est lu ni stocké ;
- **Hors connexion** : interrupteur d'UI (`enLigne`) sans lien avec `navigator.onLine`, sans Service Worker, sans manifeste PWA — l'application **ne fonctionne pas réellement sans réseau** (le bundle ne serait pas servi) ;
- **Synchronisation** : `synchroniser()` réécrit simplement le statut local, sans requête réseau ni file d'attente durable ;
- aucune validation de saisie (types, bornes, champs obligatoires), aucun schéma Zod appliqué.

---

## 8. Erreurs potentielles, risques et dettes identifiés

### 8.1 Risques bloquants pour un usage réel
1. **Aucune sécurité** : l'ensemble des données et des écrans « Administration » / « Expert » est accessible par simple saisie d'URL. Le filtrage par profil est cosmétique (`app-shell.tsx`).
2. **Perte de données garantie** : objections, journal, tâches et versions disparaissent au rechargement. Un atelier de validation qui rassemble des remarques les perd à la fin de la session.
3. **Risque de méprise scientifique** : bien que tous les écrans portent la mention de démonstration, les scores affichés (78 % d'aptitude, pondérations, alertes) sont plausibles et peuvent être pris pour des résultats. Toute diffusion externe doit être encadrée.
4. **Absence totale de tests** : aucune non-régression n'est détectable autrement que manuellement.

### 8.2 Dettes techniques
- **Fichiers minifiés à la main** : plusieurs routes (`collecte.tsx`, `producteur.aptitude.tsx`, `comparateur.tsx`, `climat.tsx`, `maladies.tsx`, `rendement.tsx`, `alertes.tsx`, `genetique.tsx`, `administration.tsx`) tiennent en 1 à 27 lignes extrêmement denses — illisibles, non maintenables, non testables. **À reformater avant toute reprise.**
- **`recherche-vues.tsx` : 816 lignes** dans un seul fichier — à découper (recherche, filtres, liste, tableau, carte, panneaux).
- **Duplication d'export CSV** : logique présente deux fois (`pav-store.tsx:telechargerCsv` et `recherche-vues.tsx:exporterCsv`).
- **Dépendances installées non utilisées** : `zod`, `react-hook-form`, `@hookform/resolvers`, `date-fns`, `embla-carousel-react`, `input-otp`, `vaul`, `react-day-picker`, `cmdk` (partiellement) — à conserver seulement si le MVP les mobilise.
- **React Query monté mais inutilisé** : le socle est prêt pour des chargements serveur, aucune `queryOptions` n'existe.
- **Coordonnées non géographiques** : `x`/`y` en unités SVG. Aucun champ `lat`/`lon` exploitable n'existe pour les sites (les objets `ObjetSci` exposent `lat`/`lon` souvent `null`).
- **Aucun `loader` de route** : tout est rendu depuis des constantes du bundle, ce qui gonflera le bundle dès que le volume de données augmentera.

### 8.3 Routes et liens
- Aucun lien mort détecté : les 36 routes testées répondent 200 ; `/route-inexistante` renvoie bien le 404 applicatif.
- Points d'attention : les routes « module générique » (`/climat`, `/maladies`, `/rendement`, `/genetique`, `/alertes`, `/administration`) partagent un même composant sans profondeur — elles répondent 200 mais n'offrent ni détail, ni action.

### 8.4 Dépendances externes réellement branchées
| Service | État |
|---|---|
| Base de données (PostgreSQL / Lovable Cloud / Supabase) | **Absent** |
| Authentification | **Absent** |
| Stockage de fichiers (photos, PDF) | **Absent** |
| Fournisseur de tuiles cartographiques / SIG | **Absent** |
| API climat / météo | **Absent** |
| Service d'IA ou de calcul scientifique | **Absent** |
| Envoi d'e-mails / notifications | **Absent** |
| Télémétrie plateforme Lovable | Présente (`src/lib/error-capture.ts`) |

---

## 9. Plan priorisé de migration vers un MVP fonctionnel

### Phase 0 — Assainissement préalable (1 semaine)
1. Reformater les fichiers minifiés à la main (routes denses) et découper `recherche-vues.tsx`.
2. Mettre en place Vitest + tests de rendu sur 10 routes critiques et sur `relations.ts`, `simulation.ts`, `recherche-data.ts`.
3. Factoriser l'export CSV en un utilitaire unique.
4. Geler le référentiel fictif comme jeu de données de test (`fixtures`) séparé du code de production.

### Phase 1 — Socle backend et sécurité (P0, 2–3 semaines)
5. Activer un backend managé (Lovable Cloud) : base PostgreSQL, authentification, stockage de fichiers.
6. Modéliser le schéma : `sites`, `parcelles`, `arbres`, `varietes`, `genotypes`, `analyses_sol`, `experimentations`, `observations`, `climat`, `medias`, `documents`, `journal`, `retours`, `taches`, `executions`.
7. **Rôles dans une table dédiée** (`user_roles` + fonction `has_role` en `security definer`), jamais sur le profil. Politiques RLS par rôle : producteur (lecture de ses propres objets), chercheur (lecture/écriture sur son site), expert (validation), décideur (agrégats en lecture seule).
8. Remplacer la sélection de profil par une authentification réelle (e-mail + mot de passe, puis SSO institutionnel si besoin) ; conserver un mode « démo » explicitement étiqueté et isolé.
9. Garder les routes protégées derrière un layout `_authenticated` et déplacer les lectures dans des `loader` + `queryOptions`.

### Phase 2 — Données réelles et CRUD (P0/P1, 3–4 semaines)
10. Import du référentiel réel IRAD (sites, parcelles, arbres, variétés) via import CSV/Excel administrable.
11. CRUD complet sur parcelles, arbres, analyses de sol, expérimentations, observations, avec validation Zod côté serveur et client.
12. Journal de traçabilité **inviolable** : écriture serveur, horodatage serveur, insertion seule (pas de mise à jour ni de suppression), export signé.
13. Objections/retours persistés, assignables, notifiés par e-mail, avec workflow d'états contrôlé côté serveur.

### Phase 3 — Terrain et cartographie (P1, 3–4 semaines)
14. Transformer la collecte en **PWA installable** : manifeste, Service Worker, cache applicatif, file d'attente durable (IndexedDB) et synchronisation avec résolution de conflits (horodatage + arbitrage utilisateur).
15. GPS réel via `navigator.geolocation` (précision, altitude, horodatage) ; photo réelle via `<input type="file" capture>` + téléversement au stockage objet, avec compression.
16. Cartographie SIG réelle : latitude/longitude, fond de carte (MapLibre + tuiles), polygones de parcelles en GeoJSON, calcul de surface, import/export Shapefile/GeoJSON, couches thématiques serveur.

### Phase 4 — Moteur scientifique (P1/P2, 4–6 semaines)
17. Formaliser avec les agronomes IRAD les **règles d'aptitude** (variables, seuils, pondérations, sources bibliographiques) et les publier comme paramétrage versionné en base.
18. Implémenter le calcul côté serveur (fonction serveur), avec entrées, paramètres, version de modèle et sortie enregistrées dans une table `executions` — c'est ce qui rend le versionnage réellement reproductible (rejeu d'une exécution passée).
19. Brancher le panneau « Pourquoi ce résultat ? » sur les entrées **réellement utilisées** par le calcul (le composant existe déjà et peut être conservé tel quel).
20. Statistiques et prédiction : commencer par des modèles simples et documentés (régressions, ANOVA sur essais) avant toute IA ; toute sortie reste étiquetée tant que la validation scientifique n'est pas prononcée.

### Phase 5 — Restitution et industrialisation (P2/P3, 2–3 semaines)
21. Génération PDF serveur (rapport de parcelle, rapport d'exécution) avec en-tête institutionnel et pagination maîtrisée.
22. Tableaux de bord avec périodes, comparaisons et exports ; alertes déclenchées par règles serveur + notifications.
23. Recherche indexée côté serveur (recherche plein texte PostgreSQL) pour supporter des dizaines de milliers d'objets.
24. Observabilité, sauvegardes, plan de restauration, procédure de publication, documentation utilisateur et administrateur.

### Estimation indicative
Phases 0 à 5 : **15 à 21 semaines** de développement, hors collecte du référentiel réel, hors validation scientifique des modèles (qui est le chemin critique côté IRAD).

---

## 10. Ce qu'il faut conserver du prototype

Ces éléments sont de bonne qualité et devraient être repris tels quels ou avec adaptation :
- **L'architecture de l'information** : hiérarchie Culture → Zone → Site → Parcelle → Plant → Données, 11 catégories, distinction des 3 types métier (parcelle expérimentale, champ semencier, parc à bois).
- **Le cadre d'explicabilité** `PourquoiCeResultat` (`components/pourquoi.tsx`) et son type `Explication` : données utilisées, données manquantes, facteurs, modèle, version, validation.
- **Le moteur de relations qualifiées** `src/lib/relations.ts` : la logique est réelle et transposable à des données réelles.
- **La discipline d'étiquetage** (`AvertissementDemo`, `MENTION_DEMO`, statuts de qualité `complete / partielle / a-verifier`) — à conserver en production sous forme de statuts de validation scientifique.
- **Le modèle de traçabilité** (`EntreeJournal`) et de versionnage (`Execution`) : les structures sont pertinentes, seule l'exécution manque.
- **L'identité visuelle** (palette Encre & cuivre, typographies Urbanist/Epilogue, monogramme) et la charte sobre institutionnelle.

---

## 11. Vérifications effectuées pour cet audit

| Vérification | Résultat |
|---|---|
| Build de production | `build OK` (journal plateforme, 2026-08-23T09:39:36Z) |
| Typecheck TypeScript | 0 erreur |
| Test HTTP des 36 routes | 36 × HTTP 200 |
| Test d'une URL inconnue | HTTP 404 avec écran applicatif |
| Comptage des jeux de données | exécuté programmatiquement sur `pav-data.ts` et `recherche-data.ts` (§3) |
| Recherche d'appels backend | `createServerFn` : 0 · `src/routes/api/*` : 0 · `fetch(` applicatif : 0 · `supabase` : 0 |
| Recherche d'API navigateur | `localStorage` : 3 usages · `navigator.geolocation` : 0 · `window.print` : 1 · `Blob`/`createObjectURL` : 2 |

---

*Document généré à partir d'une inspection directe du code source. Aucune fonctionnalité simulée n'y est présentée comme fonctionnelle.*
