Skip to content

Heriade Contacts — User stories & MVP

Document de référence pour le développement de la v1. Compagnon du README.md (architecture) et de la maquette HTML (UX).

Statut : v1 cadrée, prête à entrer en sprint. Auteur de la v1 : 1 développeur, ~12 jours dev focus. Utilisateur cible v1 : François D., administrateur de l'enterprise Heriade.


1. Personas

🎯 Persona principal — François (v1)

Rôle : commercial / business developer chez Heriade Quotidien : prospecte sur LinkedIn, échange par Gmail, lance des campagnes Lemlist Frustration : le contexte de chaque conversation est éparpillé sur trois plateformes, impossible de répondre à "où en suis-je avec Sophie ?" sans 5 minutes de recherche Niveau technique : utilisateur avancé d'outils SaaS, attend rapidité et fiabilité Comportement clé : copie-colle ses derniers messages dans un outil tiers pour s'en souvenir

🔮 Personas secondaires (v2+, à anticiper mais pas implémenter)

  • Marie — membre de l'équipe Heriade, doit voir ses propres contacts sans déranger ceux de François
  • Admin d'un client Heriade — gère ses propres contacts dans son tenant isolé
  • Super-admin Heriade — supervise tous les tenants depuis la console admin

2. MVP — ce qui doit absolument fonctionner

2.1 Le test du MVP

Si François utilise l'app pendant une semaine comme remplacement de son carnet de prospection éclaté, et qu'il ne revient pas à l'ancien fonctionnement, le MVP est validé.

2.2 Capacités minimales

Un MVP qui passe ce test doit permettre à François de :

  1. Se connecter via son compte Heriade existant — pas d'inscription séparée
  2. Créer un contact avec une entreprise rattachée, en moins de 30 secondes
  3. Coller un message LinkedIn/Gmail/Lemlist dans la fiche en moins de 10 secondes, taggé par canal
  4. Retrouver un contact par recherche texte sur n'importe quel champ
  5. Poser un rappel sur un contact, et le voir apparaître quand il arrive à échéance
  6. Filtrer sa liste pour répondre à "qui dois-je relancer cette semaine ?"
  7. Installer l'app sur son ordi/téléphone pour y accéder sans ouvrir un navigateur

2.3 Ce qui N'EST PAS dans le MVP

  • Connecteurs réels (LinkedIn, Gmail, Lemlist) → tout est manuel
  • Partage avec d'autres utilisateurs
  • Notifications email automatiques
  • Enrichissement via Pappers
  • Intégration avec Bloc Note ou autres apps Heriade
  • Import CSV
  • Vue calendrier
  • Application mobile native

Voir le README.md §9 pour le détail des évolutions prévues.

2.4 Métriques de succès du MVP

MétriqueCible v1Comment la mesurer
AdoptionFrançois utilise l'app au moins 4 jours/semaineLogs de connexion
Volume≥ 30 contacts saisis dans le premier moisCompte BDD
Vélocité de saisie≤ 15 secondes pour ajouter un échangeMesure UX en interview
Bugs bloquants0 bug critique en 30 joursSuivi tickets
PerformanceTime-to-interactive < 2s au loginLighthouse

3. Découpage en Epics

Les user stories sont organisées en 7 épics. Chaque epic correspond à un groupe fonctionnel cohérent et livrable.

EpicNomStoriesPriorité MVP
E1Authentification & accès4🔴 Critique
E2Gestion des contacts6🔴 Critique
E3Gestion des entreprises4🔴 Critique
E4Échanges & historique5🔴 Critique
E5Rappels & tâches4🟠 Important
E6Recherche & filtres5🟠 Important
E7PWA & polish4🟡 Confort

32 user stories au total, dont 22 critiques MVP (E1 à E4 + 3 de E5/E6).


4. User stories

🔐 Epic E1 — Authentification & accès


US-1.1 — Connexion via SSO Heriade

🔴 Critique MVP

En tant que François Je veux me connecter à Heriade Contacts en utilisant mon compte Heriade existant Afin de ne pas gérer un mot de passe supplémentaire

Critères d'acceptation

  • Au premier accès à contacts.heriade.fr, je suis redirigé vers le portail SSO Heriade (/auth-app/portal de la console admin)
  • Après authentification réussie, je suis renvoyé sur l'app avec un token JWT Supabase valide
  • Le token est stocké en cookie httpOnly (pas accessible au JS)
  • Si le token est invalide ou expiré, je suis redirigé automatiquement vers le login
  • Le bouton "Se déconnecter" dans le menu utilisateur révoque ma session et me ramène au login

Notes techniques

  • Bloquant : contrat exact du flow /auth-app/portal à clarifier avec l'équipe console admin
  • Fallback de dev : token mocké via NUXT_DEV_FAKE_TOKEN pour ne pas bloquer le sprint

US-1.2 — Identification de l'enterprise active

🔴 Critique MVP

En tant que François Je veux que l'app sache automatiquement à quelle enterprise j'appartiens Afin de ne voir que les contacts de mon organisation

Critères d'acceptation

  • Au login, le back appelle GET /auth/me sur la console admin et récupère profile.enterprise_id
  • Si je n'ai pas d'enterprise rattachée, j'obtiens un message clair "Aucune organisation rattachée à votre compte. Contactez votre administrateur."
  • Si mon enterprise est de type personal, l'accès est refusé avec message "Heriade Contacts est réservé aux comptes professionnels."
  • Le nom de mon enterprise s'affiche dans la sidebar (sous mon nom)

US-1.3 — Rôle et permissions appliqués

🔴 Critique MVP

En tant que François (administrateur Heriade) Je veux voir mes propres contacts par défaut, et tous ceux de mon enterprise si je suis admin Afin de garder une visibilité utile sans polluer mon espace

Critères d'acceptation

  • Le rôle est récupéré depuis permissions.isAdmin / permissions.isSuperAdmin
  • Un user member voit uniquement les contacts dont il est ownerUserId
  • Un user administrateur voit tous les contacts de son enterpriseId
  • Un user super-admin peut traverser plusieurs enterprises (mais l'UI v1 ne propose pas de switcher — accès via console admin)
  • Aucune fuite de données entre enterprises : test multi-enterprise validé

US-1.4 — Session persistante et sécurisée

🟠 Important

En tant que François Je veux rester connecté entre deux visites sans avoir à me relogger Afin de ne pas perdre de temps quotidiennement

Critères d'acceptation

  • La session dure tant que le token Supabase est valide (durée standard Supabase, ~1h par défaut avec refresh)
  • Le refresh token est utilisé en transparence pour prolonger la session
  • Une révocation côté console admin prend effet en moins de 60 secondes (TTL du cache de permissions)
  • Si la session expire pendant que je travaille, je suis prévenu via toast et redirigé vers le login

👥 Epic E2 — Gestion des contacts


US-2.1 — Créer un contact rapidement

🔴 Critique MVP

En tant que François Je veux créer un nouveau contact en moins de 30 secondes Afin de capturer une rencontre ou une mise en relation sans friction

Critères d'acceptation

  • Un bouton "Nouveau contact" est accessible depuis n'importe quelle page
  • Le formulaire ne requiert que firstName + lastName (le reste est optionnel)
  • Je peux remplir : nom, prénom, email, LinkedIn, téléphone, rôle, entreprise rattachée, tags, notes
  • Si je tape un nom d'entreprise inexistant, je peux la créer à la volée depuis le même formulaire
  • À la validation, je suis redirigé vers la fiche du contact créé
  • Toutes les validations échouées affichent un message clair sous le champ concerné

US-2.2 — Voir une fiche contact complète

🔴 Critique MVP

En tant que François Je veux ouvrir la fiche d'un contact et voir d'un coup d'œil tout son contexte Afin de reprendre la conversation sans chercher

Critères d'acceptation

  • La fiche affiche : en-tête (avatar, nom, fonction, entreprise, statut, tags), métadonnées (email, LinkedIn, téléphone, date de premier contact), timeline d'échanges, rappels liés, mini-fiche entreprise
  • La fiche se charge en moins de 500ms
  • Les liens email/LinkedIn sont cliquables
  • Un lien "Voir l'entreprise" mène à la fiche entreprise miroir

US-2.3 — Modifier un contact

🔴 Critique MVP

En tant que François Je veux corriger ou enrichir les informations d'un contact existant Afin de garder mes données à jour

Critères d'acceptation

  • Un bouton "Modifier" ouvre le formulaire pré-rempli
  • Je peux modifier tous les champs y compris l'entreprise rattachée
  • À la sauvegarde, la fiche se rafraîchit sans recharger la page
  • Un toast confirme "Contact mis à jour"
  • L'historique des échanges et les rappels ne sont pas affectés

US-2.4 — Supprimer un contact

🟠 Important

En tant que François Je veux supprimer un contact qui n'a plus d'intérêt Afin de garder ma base propre

Critères d'acceptation

  • Un bouton "Supprimer" dans le menu kebab de la fiche
  • Une confirmation obligatoire avant suppression ("Supprimer définitivement ?")
  • À la suppression : les échanges liés sont supprimés en cascade, les rappels deviennent autonomes (contactId = null) — à confirmer
  • Je suis redirigé vers la liste des contacts
  • Toast "Contact supprimé"

US-2.5 — Voir la liste de mes contacts

🔴 Critique MVP

En tant que François Je veux voir tous mes contacts dans un tableau scannable Afin de avoir une vue d'ensemble de ma prospection

Critères d'acceptation

  • Tableau avec colonnes : Contact (avatar + nom + fonction), Entreprise, Dernier échange (canal + date), Statut, Tags, Rappels
  • Tri par n'importe quelle colonne en cliquant sur l'en-tête
  • Tri par défaut : dernier échange descendant (les plus récents en premier)
  • Pagination ou virtualisation à partir de 50 contacts
  • Cliquer sur une ligne ouvre la fiche du contact
  • Le compteur "X contacts" s'affiche en haut du tableau

US-2.6 — Gérer les tags d'un contact

🟠 Important

En tant que François Je veux taguer mes contacts (RH, Tech, VIP, Q2 2026…) Afin de les classer selon mes propres critères

Critères d'acceptation

  • Un champ "Tags" dans le formulaire de création/édition, format multi-select avec création à la volée
  • Les tags existants sont suggérés en autocomplete au fur et à mesure de la saisie
  • Les tags s'affichent comme pastilles sur la fiche et dans la liste
  • Pas de limite de nombre de tags par contact
  • Les tags sont scopés à l'enterprise (Marie ne voit pas les tags de François s'ils ne sont pas admin du même tenant)

🏢 Epic E3 — Gestion des entreprises


US-3.1 — Créer une entreprise

🔴 Critique MVP

En tant que François Je veux ajouter une entreprise à laquelle rattacher mes contacts Afin de structurer ma vision par compte

Critères d'acceptation

  • Bouton "Nouvelle entreprise" depuis la page Entreprises ou depuis le formulaire de création de contact
  • Seul name est requis ; domain, industry, size, notes optionnels
  • Pas d'enrichissement Pappers en v1 — saisie 100% manuelle
  • À la création, redirection vers la fiche entreprise

US-3.2 — Voir une fiche entreprise

🔴 Critique MVP

En tant que François Je veux voir une entreprise et tous ses contacts d'un coup Afin de comprendre mon niveau de pénétration d'un compte

Critères d'acceptation

  • En-tête entreprise avec logo (initiale), nom, secteur, taille
  • Liste des contacts rattachés (mini-table)
  • Métadonnées agrégées : nombre total d'échanges, dernière activité, statut global
  • Bouton "Nouveau contact dans cette entreprise" pré-remplit le champ companyId

US-3.3 — Lister les entreprises

🔴 Critique MVP

En tant que François Je veux voir toutes mes entreprises dans un tableau Afin de retrouver une entreprise rapidement

Critères d'acceptation

  • Tableau avec : Entreprise (logo + nom + domaine), Secteur, Taille, Nb contacts, Nb échanges, Dernière activité
  • Recherche texte sur nom et domaine
  • Filtres : secteur, taille
  • Cliquer sur une ligne ouvre la fiche entreprise

US-3.4 — Modifier / supprimer une entreprise

🟠 Important

En tant que François Je veux mettre à jour ou supprimer une entreprise Afin de garder une base cohérente

Critères d'acceptation

  • Modification via formulaire identique à la création
  • Suppression bloquée si l'entreprise a encore des contacts rattachés ("Détachez d'abord les X contacts")
  • Confirmation obligatoire avant suppression

💬 Epic E4 — Échanges & historique


US-4.1 — Coller un message dans la fiche contact

🔴 Critique MVP

En tant que François Je veux coller le dernier message LinkedIn/Gmail/Lemlist reçu ou envoyé dans la fiche d'un contact Afin de garder une trace centralisée du contexte de chaque échange

Critères d'acceptation

  • Une zone "Coller un message" est visible en permanence en haut de la timeline (pas planquée dans une modale)
  • La zone réagit à Cmd+V même si elle n'a pas le focus (focus auto si la fiche est ouverte)
  • Dès que du contenu est collé, des contrôles apparaissent : sélecteur de canal (LinkedIn/Gmail/Lemlist/Autre), direction (sortant/entrant), bouton Enregistrer
  • Le canal LinkedIn est sélectionné par défaut (canal le plus fréquent pour François)
  • La direction "sortant" est sélectionnée par défaut
  • La date de l'échange est automatiquement remplie à now(), modifiable par l'utilisateur
  • Le bouton Enregistrer est désactivé si le contenu est vide

US-4.2 — Voir la timeline d'un contact

🔴 Critique MVP

En tant que François Je veux voir tous les échanges avec un contact dans l'ordre chronologique Afin de comprendre où on en est sans rouvrir LinkedIn / Gmail / Lemlist

Critères d'acceptation

  • Timeline verticale, échanges les plus récents en haut
  • Chaque entrée affiche : direction (qui → qui), canal (pastille colorée), date relative ("il y a 3 jours"), contenu intégral
  • Pastilles de canal avec codes couleur : LinkedIn (bleu), Gmail (magenta), Lemlist (ambre)
  • Possibilité de filtrer la timeline par canal (onglets en haut)
  • Les échanges sortants et entrants ont des marqueurs visuels distincts (point violet vs point vert)

US-4.3 — Modifier un échange

🟡 Confort

En tant que François Je veux corriger une faute de frappe ou changer le canal d'un échange existant Afin de garder un historique propre

Critères d'acceptation

  • Clic sur un échange ouvre une modale d'édition
  • Champs modifiables : contenu, canal, direction, date
  • Pas de soft delete : la modification écrase l'ancienne version (pas d'historique de version en v1)

US-4.4 — Supprimer un échange

🟡 Confort

En tant que François Je veux supprimer un échange ajouté par erreur Afin de ne pas polluer la timeline

Critères d'acceptation

  • Menu kebab sur chaque entrée → "Supprimer"
  • Confirmation obligatoire
  • Suppression définitive (pas de poubelle)

US-4.5 — Vue agrégée des échanges au niveau entreprise

🟠 Important

En tant que François Je veux voir tous les échanges avec une entreprise (tous ses contacts confondus) Afin de mesurer mon niveau d'activité sur un compte

Critères d'acceptation

  • Sur la fiche entreprise, un onglet "Échanges" affiche la timeline consolidée
  • Chaque entrée indique le contact concerné (lien cliquable)
  • Filtrage par canal et par contact
  • Pas de saisie d'échange à ce niveau : on doit passer par la fiche contact

🔔 Epic E5 — Rappels & tâches


US-5.1 — Créer un rappel sur un contact

🔴 Critique MVP

En tant que François Je veux poser un rappel sur un contact ("Relancer Sophie pour démo T3") Afin de ne pas oublier mes prochaines actions

Critères d'acceptation

  • Bouton "Rappel" sur la fiche contact ouvre une modale
  • Champs : titre (requis), date d'échéance (requise), description (optionnelle)
  • À la création, le rappel apparaît dans le bloc Rappels de la fiche et dans la vue Rappels globale
  • Toast "Rappel créé pour le [date]"

US-5.2 — Créer un rappel sur une entreprise ou autonome

🟠 Important

En tant que François Je veux poser un rappel lié à une entreprise sans contact précis, ou un rappel totalement autonome ("Préparer le pitch RH") Afin de gérer toutes mes tâches dans un seul outil

Critères d'acceptation

  • Depuis la fiche entreprise : bouton "Rappel" attache le rappel à companyId
  • Depuis la page Rappels globale : bouton "Nouveau rappel" permet de choisir contact OU entreprise OU rien
  • Un rappel autonome (contactId = null et companyId = null) est valide

US-5.3 — Vue globale des rappels

🔴 Critique MVP

En tant que François Je veux voir tous mes rappels groupés par échéance Afin de prioriser ma journée

Critères d'acceptation

  • Page "Rappels" accessible depuis la sidebar
  • Trois groupes : "En retard" (rouge), "Aujourd'hui" (neutre), "À venir" (neutre)
  • Chaque rappel affiche : titre, date relative, contact ou entreprise liée (lien cliquable)
  • Compteurs par groupe
  • Si je n'ai aucun rappel : état vide avec "Tout est sous contrôle 🎉"

US-5.4 — Marquer un rappel comme fait

🔴 Critique MVP

En tant que François Je veux cocher un rappel comme terminé Afin de le faire disparaître de mes alertes

Critères d'acceptation

  • Une checkbox sur chaque rappel
  • En cochant : le rappel passe en barré, doneAt = now()
  • Les rappels faits ne s'affichent pas par défaut dans la vue globale (toggle "Afficher les rappels terminés")
  • Décocher annule (doneAt = null)

🔍 Epic E6 — Recherche & filtres


US-6.1 — Recherche texte dans la liste contacts

🔴 Critique MVP

En tant que François Je veux taper le nom d'un contact, son email ou son entreprise et voir la liste se filtrer en direct Afin de retrouver quelqu'un en moins de 5 secondes

Critères d'acceptation

  • Champ de recherche en haut de la liste, focus automatique au chargement
  • Recherche fuzzy sur : prénom, nom, email, entreprise, tags
  • Résultats filtrés en temps réel (pas de bouton "Rechercher" à cliquer)
  • Compteur "X contacts trouvés" mis à jour
  • État vide si aucun résultat avec bouton "Effacer la recherche"

US-6.2 — Filtres inline sur la liste contacts

🔴 Critique MVP

En tant que François Je veux filtrer ma liste par statut, tags, canal, entreprise Afin de zoomer sur un sous-ensemble

Critères d'acceptation

  • Filtres en barre horizontale au-dessus du tableau
  • Chaque filtre est un dropdown multi-select
  • Les filtres se cumulent (logique ET entre filtres, OU dans un filtre)
  • Chip actif affiché au-dessus du tableau pour chaque filtre posé, avec croix pour retirer
  • Bouton "Tout effacer" si au moins un filtre est actif

US-6.3 — Panneau "Plus de filtres"

🟠 Important

En tant que François Je veux accéder à des filtres avancés (période, présence de rappel, direction…) sans les avoir tout le temps à l'écran Afin de garder l'interface respirable au quotidien

Critères d'acceptation

  • Bouton "Plus de filtres" (icône réglages) à droite de la barre de filtres
  • Clic ouvre un panneau latéral droit (380px)
  • Filtres disponibles : Période d'activité, Rappels (en retard / à venir / aucun), Propriétaire, Avec/sans email, Direction du dernier échange
  • Boutons "Réinitialiser" et "Appliquer" en bas du panneau
  • Esc ou clic sur le backdrop ferme le panneau sans appliquer

US-6.4 — Vues sauvegardées

🟠 Important

En tant que François Je veux sauvegarder une combinaison de filtres ("Prospects chauds + LinkedIn + en retard") sous un nom Afin de y revenir en un clic

Critères d'acceptation

  • Bouton "Enregistrer cette vue" apparaît dès qu'au moins un filtre est actif
  • Modale demande : nom de la vue, icône (optionnelle)
  • Les vues sauvegardées apparaissent dans la sidebar sous "Vues sauvegardées"
  • Cliquer sur une vue applique tous ses filtres et navigue vers la liste contacts
  • Menu kebab par vue : Renommer, Supprimer
  • 3 vues pré-configurées par défaut : Prospects chauds, En attente de réponse, À relancer cette semaine

US-6.5 — Recherche globale Cmd+K

🟠 Important

En tant que François Je veux une recherche universelle accessible depuis n'importe où Afin de sauter directement à un contact ou une entreprise sans naviguer

Critères d'acceptation

  • Raccourci Cmd+K (Mac) / Ctrl+K (Windows) ouvre une palette de commande au centre de l'écran
  • Champ de recherche avec focus auto
  • Résultats groupés : Contacts, Entreprises, Actions rapides (Nouveau contact, Nouveau rappel…)
  • Navigation au clavier (flèches haut/bas, Entrée pour ouvrir)
  • Esc ferme la palette
  • Bouton d'icône dans la barre de filtres pour utilisateurs sans raccourci clavier

📱 Epic E7 — PWA & polish


US-7.1 — Installer l'app comme PWA

🔴 Critique MVP

En tant que François Je veux installer Heriade Contacts sur mon Mac et mon téléphone Afin de y accéder sans passer par mon navigateur

Critères d'acceptation

  • Manifest PWA valide avec icônes 192, 512, maskable
  • Service worker enregistré, app installable depuis Chrome desktop / Safari iOS / Chrome Android
  • Icône d'install dans la barre d'URL Chrome
  • Au premier lancement après install, prompt "Bienvenue dans Heriade Contacts"
  • Mode standalone (sans barre de navigation du navigateur)

US-7.2 — Lecture offline des fiches visitées

🟡 Confort

En tant que François Je veux consulter une fiche contact que j'ai déjà ouverte même sans internet Afin de ne pas être bloqué dans le train ou en clientèle

Critères d'acceptation

  • Service worker met en cache les fiches contact et entreprise visitées
  • En mode offline : les fiches en cache restent accessibles
  • Un indicateur visuel "Mode hors-ligne — lecture seule" s'affiche dans la barre du haut
  • Les actions de modification sont désactivées en offline (boutons grisés avec tooltip)
  • Au retour online, l'indicateur disparaît automatiquement

US-7.3 — États vides et loading

🟠 Important

En tant que François Je veux comprendre ce qui se passe quand l'app charge ou quand je n'ai rien à voir Afin de ne pas penser que l'app est cassée

Critères d'acceptation

  • Skeleton loaders sur la liste contacts pendant le chargement initial
  • État vide à la première utilisation : "Bienvenue ! Créez votre premier contact" avec CTA
  • État vide sur recherche/filtre sans résultat : "Aucun contact ne correspond" + bouton "Effacer les filtres"
  • État vide sur fiche contact sans échange : "Aucun échange pour l'instant. Collez votre premier message ci-dessus"
  • État vide sur Rappels : "Tout est sous contrôle 🎉"

US-7.4 — Toasts et feedbacks d'action

🟠 Important

En tant que François Je veux un retour visuel quand je crée, modifie ou supprime quelque chose Afin de savoir que mon action a été prise en compte

Critères d'acceptation

  • Toast en bas de l'écran pour : création, modification, suppression, erreur
  • Toast vert pour succès, rouge pour erreur, gris neutre pour info
  • Disparition automatique après 2.5s
  • Possibilité de cliquer sur le toast pour le fermer immédiatement
  • Action "Annuler" sur le toast pour les suppressions (5s pour annuler)

5. Tickets techniques transverses

Ces tickets ne correspondent pas directement à des user stories utilisateur mais sont indispensables au projet. Ils sont à intercaler dans le sprint.

🛠 Setup & fondations

TicketDescriptionEstiméJalon
T-0.1Init monorepo Yarn workspaces (apps/web, apps/api, packages/shared)0.5 jJ1
T-0.2Configuration ESLint, Prettier, EditorConfig0.25 jJ1
T-0.3Setup Docker Compose pour PostgreSQL local0.25 jJ1
T-0.4Configuration .env.example + lecture par Nest et Nuxt0.25 jJ1
T-0.5Pipeline CI minimal (lint + typecheck + tests)0.5 jJ1

🔐 Auth backend

TicketDescriptionEstiméJalon
T-1.1ConsoleAdminClient : wrapper HTTP avec GET /auth/me0.5 jJ1
T-1.2Cache LRU des contextes utilisateur (TTL 60s)0.25 jJ1
T-1.3AuthGuard Nest qui valide le token et peuple req.ctx0.5 jJ1
T-1.4EnterpriseContextMiddleware + PrismaService scopé enterpriseId0.5 jJ1
T-1.5RolesGuard + décorateurs @RequireAdmin / @RequireSuperAdmin0.25 jJ1
T-1.6Décorateur @Ctx() pour injecter le contexte dans les controllers0.25 jJ1

🗄 Modèle de données

TicketDescriptionEstiméJalon
T-2.1Schéma Prisma complet (Company, Contact, Exchange, Reminder)0.5 jJ1
T-2.2Migration initiale + seed minimal (1 contact, 1 entreprise)0.25 jJ1
T-2.3Schémas Zod partagés dans packages/shared0.5 jJ1

🎨 Front fondations

TicketDescriptionEstiméJalon
T-3.1Setup Nuxt 3 SPA + @vite-pwa/nuxt + Tailwind0.5 jJ1
T-3.2Tokens Heriade en variables CSS dans tokens.css0.25 jJ1
T-3.3Composants UI primitifs (Button, Input, Badge, Card, Dropdown)1 jJ1-J2
T-3.4Layout principal (sidebar + main)0.5 jJ1
T-3.5Store auth Pinia + interceptor ofetch injectant le Bearer0.5 jJ1
T-3.6Middleware route auth.global.ts pour redirections SSO0.25 jJ1
T-3.7Setup TanStack Vue Query avec configuration globale0.25 jJ1

🔍 Modules backend

TicketDescriptionEstiméJalon
T-4.1Module Contacts (controller + service + DTOs + tests unitaires)1 jJ2
T-4.2Module Companies (idem)0.75 jJ2
T-4.3Module Exchanges (idem)0.5 jJ3
T-4.4Module Reminders (idem)0.5 jJ3
T-4.5Endpoint Health /health pour monitoring0.1 jJ1

📦 Polish & QA

TicketDescriptionEstiméJalon
T-5.1Génération manifest PWA + icônes (192, 512, maskable)0.5 jJ4
T-5.2Service worker (vite-pwa) avec stratégie cache pour fiches0.5 jJ4
T-5.3Skeleton loaders + états vides + toasts0.5 jJ4
T-5.4Suite de tests E2E (Playwright) couvrant le happy path1 jJ4
T-5.5Documentation utilisateur courte (page "Aide" dans l'app)0.5 jJ4

6. Roadmap synthétique

┌────── J1 (3.5j) ───────┐ ┌──── J2 (4j) ────┐ ┌─── J3 (3j) ────┐ ┌── J4 (2j) ───┐
│ Fondations             │ │ Contacts &      │ │ Échanges &     │ │ Polish PWA   │
│                        │ │ Entreprises     │ │ Rappels        │ │              │
│ • Monorepo + setup     │ │                 │ │                │ │ • Manifest   │
│ • Schéma Prisma        │ │ • US-2.1, 2.2,  │ │ • US-4.1, 4.2  │ │ • SW offline │
│ • AuthGuard + Console  │ │   2.3, 2.5      │ │ • US-5.1, 5.3, │ │ • Skeletons  │
│ • Tenant scoping       │ │ • US-3.1, 3.2,  │ │   5.4          │ │ • US-6.5     │
│ • Nuxt PWA setup       │ │   3.3           │ │ • US-6.1, 6.2  │ │   (Cmd+K)    │
│ • US-1.1, 1.2, 1.3     │ │                 │ │                │ │ • Tests E2E  │
└────────────────────────┘ └─────────────────┘ └────────────────┘ └──────────────┘
        ▲                          ▲                    ▲                ▲
   Auth marche               François saisit       App utilisable    PWA installable
                             ses contacts          au quotidien      v1 livrable

Total estimé : 12.5 jours de dev focus


7. Définition de "Done" v1

Une story est "Done" quand toutes ces conditions sont remplies :

Code

  • [ ] Le code passe lint + typecheck + tests unitaires
  • [ ] Aucune régression sur les tests E2E existants
  • [ ] PR reviewée et mergée
  • [ ] Les variables sensibles sont en .env, jamais commitées

Fonctionnel

  • [ ] Tous les critères d'acceptation de la story sont validés
  • [ ] La story marche en local sur Chrome, Firefox, Safari
  • [ ] Aucune fuite de données cross-tenant (testée avec deux comptes)
  • [ ] Les états d'erreur sont gérés (401, 403, 500, network down)

UX

  • [ ] Conforme au design system Heriade (couleurs, typo, spacing)
  • [ ] Responsive desktop + mobile (≥ 375px)
  • [ ] Skeleton ou loader sur les chargements > 200ms
  • [ ] Toast de feedback sur les actions

Critères techniques globaux v1

  • [ ] PWA installable sur Chrome, Safari iOS, Chrome Android
  • [ ] Time-to-interactive < 2s en login (cold start)
  • [ ] Score Lighthouse ≥ 90 sur Performance et Accessibilité
  • [ ] Aucune erreur console en navigation normale

8. Hors scope explicite v1 — pour mémoire

Ces points reviennent souvent dans les discussions, autant les figer :

  • Pas de chat ou messagerie temps réel — l'app n'envoie pas de messages
  • Pas de notifications push — natives ni email
  • Pas d'export PDF d'une fiche — copy-paste suffit en v1
  • Pas de duplication ou import en masse de contacts — saisie manuelle
  • Pas d'API publique — accès uniquement via le front pour les utilisateurs
  • Pas de mode invité ou de partage public d'une fiche — tout est authentifié
  • Pas d'audit log — qui a modifié quoi quand, pas en v1

Pour le détail des évolutions prévues post-v1, voir README.md §9.


9. Risques et points d'attention

RisqueProbabilitéImpactMitigation
Spec /auth-app/portal floueÉlevéeBloquant J1Stub d'auth en dev, branche réelle quand spec dispo
Surcharge cognitive avec trop de filtresMoyenneAdoptionTest utilisateur avec François à J3
Saisie manuelle des échanges trop lourdeMoyenneAdoptionMesurer le temps de saisie en interview semaine 1
Performance dégradée avec 500+ contactsFaibleScalingVirtualisation de la table + indices BDD
François n'utilise pas l'appMoyenneÉchec MVPImplication tôt en design, démos régulières

Document v1 · mai 2026 · à mettre à jour à chaque sprint review