Apparence
14. Exigences non-fonctionnelles observées
La colonne de gauche liste l'exigence ; les observations distinguent l'existant v1 de la cible v2 quand la stack change la donne.
| Catégorie | v1 (existant) → v2 (cible) |
|---|---|
| Rendu | v1 : Server Components + dynamic = 'force-dynamic'. v2 : Next.js 16 (App Router) pour le shell + queries Convex réactives → données en temps réel, sans re-fetch manuel. |
| Performance | v1 : mises à jour optimistes manuelles + revalidatePath. v2 : réactivité Convex native (plus d'optimistic à écrire), pagination (convex-helpers), index Convex sur les colonnes de filtre. |
| Résilience | v1 : repli sur données mock (TRIMET) + rollback Storage manuel. v2 : backend managé Convex ; uploads fiabilisés par action-retrier. |
| Accessibilité | v1 : ❓ non traitée (styles inline, dépendance à la couleur). v2 : primitives @recette/ui (base a11y de type Radix/shadcn) — meilleure assise, mais conformité RGAA/WCAG formelle toujours ❓ à valider. |
| Responsive | v1 : ❓ styles inline à largeurs fixes. v2 : Tailwind 4 (utilitaires responsive) → design adaptable par défaut. |
| Thème | v1 : pas de mode sombre. v2 : clair/sombre (packages/ui theme.tsx). |
| Navigateurs | ❓ Non spécifié (cible desktop probable). |
| SEO | Non applicable (application privée derrière authentification). |
| i18n | Français uniquement (inchangé). |
| Observabilité | v1 : console.log/console.error laissés en place. v2 : logs & insights du dashboard Convex (exécutions de fonctions, erreurs) — observabilité structurée. |
| Typage | v1 : JavaScript. v2 : TypeScript strict de bout en bout (schéma → fonctions → UI), Zod partagé. |
| Analytique | v1 : SQL disponible (PostgreSQL) mais non exploité. v2 : ⚠️ Convex est transactionnel, pas analytique — voir §14.1. Toute lecture agrégée doit être pré-agrégée ou paginée. |
| Portabilité | ❓ à trancher (Q32) — Convex est open source et auto-hébergeable (Docker, backend PostgreSQL/MySQL), avec convex export/import pour les données. La logique métier reste du TypeScript. |
| Volumétrie | ❓ à chiffrer (Q33) — conditionne le plan d'hébergement (egress, stockage des preuves) et les seuils de pagination. |
14.1 Limites de plateforme — connues et assumées
👔 En clair
La technologie retenue (Convex) est conçue pour des applications interactives temps réel. Elle est excellente pour ça, et volontairement limitée sur un autre terrain : les grandes requêtes d'analyse. Ce n'est pas un défaut à corriger, c'est une limite à connaître avant de promettre.
Ce que ça veut dire concrètement, sans entrer dans les chiffres :
| Ce qui marche très bien | Ce qui demande une conception adaptée |
|---|---|
| Les écrans se mettent à jour tout seuls pendant que plusieurs testeurs travaillent | Les grands totaux (avancement global, matrice de traçabilité) doivent être calculés à l'avance, pas à chaque affichage |
| Les listes se chargent vite, quel que soit le volume, grâce au chargement progressif | Les listes très longues se lisent page par page — pas de « tout afficher » sur 30 000 lignes |
| Les traitements longs (import Excel, génération IA) tournent côté serveur, sans bloquer l'écran | Un import ou un export volumineux n'est pas instantané : l'écran affiche une progression |
Et une limite à connaître avant de s'engager auprès du client : l'outil n'est pas un outil d'analyse de données. Il répond parfaitement aux questions prévues par ses écrans ; une demande d'extraction libre (« je veux croiser X et Y comme dans un tableur ») se traite par une extraction périodique vers un outil dédié, pas par une nouvelle requête dans l'application.
Limites chiffrées
| Limite | Valeur | Où elle nous concerne |
|---|---|---|
| Documents lus par transaction | 32 000 | Écran Synthèse sur une grosse campagne · matrice de traçabilité · export Excel |
| Documents écrits par transaction | 16 000 | Import Excel · ajout au périmètre d'une campagne · édition en masse |
| Temps de code utilisateur (query / mutation) | 1 s | Interdit tout traitement lourd en lecture ou écriture → passer par une action |
| Durée d'une action | 30 min (runtime Convex) / 10 min (Node) | Confortable pour un parsing Excel ou un appel IA |
| Argument d'une action Node | 5 Mio | ⚠️ Un fichier volumineux ne se passe pas en argument → File Storage d'abord |
| Taille d'un document | 1 Mio | Non contraignant (nos documents sont des lignes métier) |
| Index par table | 32 | Non contraignant |
| Egress de données | 1 à 50 Go/mois selon le plan | ⚠️ Les preuves (captures d'écran) consomment de l'egress à chaque affichage — à dimensionner (Q33) |
Trois règles de conception qui en découlent
- Pré-agréger plutôt que recalculer. Convex n'a ni
count()ni projection de champ : on lit des documents entiers et on agrège dans le code. C'est pourquoi le tableau de bord (A1) persiste des instantanés hebdomadaires au lieu de recalculer à l'affichage. Le composant@convex-dev/aggregate(agrégats maintenus transactionnellement) est le renfort si des compteurs temps réel deviennent nécessaires. - Paginer toute lecture de liste, avec index sur les colonnes de filtre.
.paginate()et les bornesmaximumRowsRead/maximumBytesReadsont les garde-fous. - Sortir les traitements lourds des queries : parsing de fichier, génération de classeur, appel à un modèle → action, jamais query ni mutation.
💡 Le modèle A3bis n'est pas seulement un choix fonctionnel : en supprimant la duplication du référentiel par campagne, il fait passer le volume
etapesde ~32 000 lignes (10 campagnes) à ~3 200 — c'est-à-dire de la limite de la plateforme à un dixième de celle-ci.
Ce que la plateforme ne fera pas
Pas de SQL ad hoc, pas de jointure multi-tables complexe en une requête, pas d'agrégation libre sur des millions de lignes. Un besoin de BI (tableaux croisés libres, corrélations inter-projets, entrepôt) passe par un export périodique (convex export) ou une réplication vers un entrepôt externe — jamais par une requête directe.
➡️ Q31 : si le client attend ce type d'extraction, il faut le poser maintenant, pas le découvrir en production.