Documentation Index
Fetch the complete documentation index at: https://docs.snakysec.com/llms.txt
Use this file to discover all available pages before exploring further.
UX Audit — Problèmes détectés
Phase 2 — Inventaire des doublons, orphelins, incohérences et pertes de contexte Méthodologie : analyse statique du code (platform/src/app/** et platform/src/components/**).
Chaque problème est sourcé par un chemin de fichier ; les cas marqués (à confirmer) méritent vérification produit.
Tri : par impact décroissant dans chaque catégorie (fort > moyen > faible).
DOUBLONS
PROB-DUP-01 — Lancement d’un audit accessible via 2 surfaces différentes (impact moyen)
- Pages :
/dashboard/clients/[id](header bouton<TriggerAuditButton>) et/dashboard/clients/[id]/documents(lien texte “Lancer un audit” dans empty state) - Description : Le bouton primaire
<TriggerAuditButton>ouvre une modal complète (framework + product areas), tandis que le lien dans le hub documents redirige simplement vers la page client (pas vers une modal). 2 chemins, expérience non équivalente. - Code :
platform/src/app/dashboard/clients/[id]/trigger-audit-button.tsxvsplatform/src/app/dashboard/clients/[id]/documents/page.tsx:357-360
PROB-DUP-02 — <GuideFilterDialog> exposé en parallèle dashboard et portal avec 2 variants (impact moyen)
- Pages :
/dashboard/clients/[id](header) et/portal/remediation(header) - Description : Même composant avec prop
variant: "dashboard" | "portal"qui change uniquement le label du bouton et le styling. Côté MSSP, c’est mêlé à 7 autres boutons dans le header client (cf. PROB-CTX-01) ; côté portal il est aux côtés de 2 autres boutons download. - Code :
platform/src/components/remediation/guide-filter-dialog.tsx(Props.variant)
PROB-DUP-03 — 3 endpoints de téléchargement de plan de remédiation (impact moyen)
- Pages :
/dashboard/clients/[id]/remediation-plan(1 bouton “Download PDF”) +/portal/remediation(2 boutons “Download milestones PDF” + “Download PDF”) +<GrcDocumentCards>(carte “Plan Remédiation”) - Description : 3 surfaces qui téléchargent plus ou moins le même artefact PDF (
/api/v1/clients/[id]/documents/remediation-planet/api/v1/clients/[id]/documents/milestones-plan). L’utilisateur a du mal à comprendre la différence. - Code :
platform/src/app/dashboard/clients/[id]/remediation-plan/page.tsx:73-77platform/src/app/portal/remediation/page.tsx:54-65platform/src/components/grc-document-cards.tsx(typeremediation-plan)
PROB-DUP-04 — Téléchargement audit report dupliqué entre <AuditActions> et <DownloadReportButton> (impact faible)
- Pages :
/dashboard/audits/[id](utilise<AuditActions variant="buttons">avec PDF/Excel/HTML) et/portal/audits/[id](utilise<DownloadReportButton>) - Description : 2 implémentations distinctes pour télécharger des rapports d’audit. Toujours possible que les comportements divergent (formats supportés, gestion erreurs, naming).
- Code :
platform/src/components/audit-actions.tsx:53-75vsplatform/src/components/download-report-button.tsx
PROB-DUP-05 — Logique de calcul documentContexts dupliquée entre dashboard et portal (impact faible — dette technique)
- Pages :
/dashboard/clients/[id]/documents/page.tsx:135-280et/portal/documents/page.tsx:135-216 - Description : Les deux pages reconstruisent indépendamment les classifications domain (isMfa, isCA, isPriv, etc.) et la map
documentContexts. Risque de divergence si les regex évoluent d’un côté. - Code : 2 copies presque identiques, ~80 lignes chacune.
PROB-DUP-06 — signOut() callé depuis 3 endroits (impact faible)
- Pages : Sidebar dashboard footer, PortalSidebar footer, Header dropdown user
- Description : 3 surfaces “Sign Out / Logout” dans le même flow utilisateur (sidebar bottom + header dropdown). Acceptable UX mais incohérent en labels (cf. PROB-INC-04).
- Code :
sidebar.tsx:229,portal-sidebar.tsx:87,header.tsx:98
PROB-DUP-07 — <ImpersonateClientButton> et <PortalClientPicker> font la même chose (impact faible)
- Pages :
/dashboard/clients(button par client card) et/portalmodeadmin_no_selection(cards picker) - Description : Les deux postent à
POST /api/portal/impersonateavec unclientId. La carte sur/dashboard/clientsimpose à l’admin d’aller chercher le bouton ; le picker sur/portalest plus visible. Comportement et endpoint identiques. - Code :
platform/src/components/impersonate-client-button.tsxvsplatform/src/components/portal-client-picker.tsx
ORPHELINS
PROB-ORPH-01 — /dashboard/clients/[id]/documents n’a aucun lien direct dans la nav (impact fort)
- Page concernée :
/dashboard/clients/[id]/documents - Description : Cette page (hub conformité client GRC, 4 documents PDF générables) n’est référencée par AUCUN lien depuis le client overview header (qui pourtant expose 8 boutons : Edit, Credentials, Findings, Remediation, Guide PDF, Trajectory, CISO, Trigger Audit). Pour y accéder il faut connaître l’URL ou passer via un breadcrumb manuel, ou via des entrées comme “Couverture 220 contrôles” dans
/dashboard/documents/technical(qui pointent vers/dashboard/clients/[id], pas/documents). - Impact : Une fonctionnalité majeure (génération de 4 documents GRC clients) est cachée.
- Code :
platform/src/app/dashboard/clients/[id]/documents/page.tsx
PROB-ORPH-02 — /dashboard/clients/[id]/remediation-plan accessible uniquement depuis le hub orphelin documents (impact fort)
- Page concernée :
/dashboard/clients/[id]/remediation-plan - Description : La page du plan exécutif read-only n’a pas de bouton dans le header client. Le bouton header s’appelle “Remediation” et pointe vers
/remediation(le workspace DnD), pas vers/remediation-plan(la vue exécutive). Le seul lien est “Voir tout (X findings)” sur/dashboard/clients/[id]/documentslui-même orphelin (cf. PROB-ORPH-01). - Impact : Vue exécutive du plan inaccessible aux MSSP_ADMIN sauf URL directe.
- Code :
platform/src/app/dashboard/clients/[id]/remediation-plan/page.tsx; lien depuis docs hub :documents/page.tsx:461-465
PROB-ORPH-03 — /dashboard/clients/[id]/controls/[controlId] accessible uniquement par cellule de table (impact moyen)
- Page concernée :
/dashboard/clients/[id]/controls/[controlId] - Description : La page détail d’un contrôle est une page riche (description, mappings réglementaires CIS/ISO/NIS2/DORA/eIDAS/RGPD, DICT, history). Elle est uniquement atteignable en cliquant sur la cellule controlId d’une
<ControlResultsTable>(audit detail dashboard ou portal). Pas dans la sidebar, pas dans une liste de contrôles globale. - Impact : Difficile à découvrir, et impossible de naviguer entre 2 contrôles consécutifs sans repasser par l’audit.
- Code :
platform/src/app/dashboard/clients/[id]/controls/[controlId]/page.tsx, lien implicite via<ControlResultsTable>
PROB-ORPH-04 — /dashboard/audits/[id]/diff exclusivement déclenchée par le <CompareSelector> (impact moyen)
- Page concernée :
/dashboard/audits/[id]/diff?vs=<id> - Description : Aucun lien direct dans
/dashboard/audits(table) ou/dashboard/clients/[id](history tab). Le<CompareSelector>est imbriqué dans le header de la page detail audit. Le diff N vs N-1 est inaccessible directement, ce qui contre-intuitif puisque cette feature est explicitement indexée dans les libellés “Diff Audit N vs N-1”. - Code :
platform/src/app/dashboard/audits/[id]/diff/page.tsx; trigger :audit-diffvia<CompareSelector>dans/audits/[id]/page.tsx:279
PROB-ORPH-05 — /dashboard/clients/[id]/onboarding (sans step) est une route serveur invisible (impact faible — comportement attendu)
- Page concernée :
/dashboard/clients/[id]/onboarding - Description : Pas d’UI ; redirige côté serveur vers
/onboarding/[step]. Comportement intentionnel (resume) mais le bouton “Resume” du banner client overview pointe vers cette URL même. - Code :
platform/src/app/dashboard/clients/[id]/onboarding/page.tsx
PROB-ORPH-06 — /dashboard/settings/notifications n’apparait pas dans la liste i18n des liens settings (impact faible)
- Page concernée :
/dashboard/settings/notifications - Description : Le hub settings (
/dashboard/settings/page.tsx) construit ses cards depuissettingsLinks(5 entries i18n) puis ajoute manuellement la card Notifications hors loop avec un titre français hardcoded “Notifications email”. Si les autres pages settings sont traduites EN/FR, celle-là est figée FR. Idem pour DR Runbook. - Code :
platform/src/app/dashboard/settings/page.tsx:45-57(hardcoded),:8-14(i18n loop)
PROB-ORPH-07 — Sous-pages settings sans entrée sidebar (impact faible)
- Pages concernées :
/dashboard/settings/users,/audit-log,/api-keys,/access-review,/roles,/notifications - Description : Aucune ne figure dans la sidebar — elles sont accessibles uniquement par le hub
/dashboard/settings. La sidebar n’a pas non plus de mode “collapsible” pour Settings comme elle l’a pour Documents. L’utilisateur sait qu’il est dans Settings (item actif sidebar) mais doit revenir au hub à chaque fois. - Code :
sidebar.tsx:198-218(entrée Settings unique, non collapsible)
PROB-ORPH-08 — Page d’erreur “Forbidden” inexistante en UI (impact faible — à confirmer)
- Page concernée : redirect
/dashboard?error=forbidden(cf.controls/[controlId]/page.tsx:101,help/dr/layout.tsx:21) - Description : Plusieurs gardes redirigent vers
/dashboard?error=forbiddenmais la page/dashboardne traite pas le query paramerror. L’utilisateur arrive silencieusement sur le dashboard sans toast ni indication. - Code :
platform/src/app/dashboard/page.tsx(pas de read sursearchParams.error)
INCOHÉRENCES
PROB-INC-01 — Mix EN/FR généralisé dans les labels UI (impact fort)
- Pages concernées : multiples
- Description :
<PortalSidebar>: labels EN hardcoded (“Overview”, “Audits”, “Findings”, “Remediation”, “Documents”, “Logout”) alors que toute la plateforme côté MSSP est traduite via next-intl<DashboardFilters>: “All clients”, “7 days”, “30 days”, “90 days” hardcoded EN<AuditFilters>: “All statuses”, “Pending”, “Running”, “Completed”, “Partial”, “Failed”, “Cancelled” hardcoded EN/dashboard/settings/users/page.tsx: labels FR hardcoded (“Utilisateurs”, “Rôle”, “Accès clients”, “Dernière connexion”) sans i18n/dashboard/settings/audit-log/audit-log-content.tsx: ~30 strings FR hardcoded (“Audit log”, “Traçabilité plateforme”, “Filtres”, “Acteur”, “Ressource”, “Toutes”, “Réinitialiser”, “Charger plus”, etc.)/portal/audits/[id]/page.tsx: “Passed”, “Failed”, “Manual Review”, “Compliance” en EN/portal/documents/page.tsx: titre + description FR hardcoded<EditClientPage>: labels formulaire EN (“Organization Name”, “Slug (identifier)”, “M365 Tenant ID”) + descriptions FR (“Active la planification…”, “Les audits plus anciens…”). Bouton “Save Changes” / “Cancel” EN.
- Impact : Casse le
<LanguageSwitcher>— toggle FR ne traduit qu’une partie de la plateforme. - Code :
portal-sidebar.tsx:24-30,dashboard-filters.tsx:20-24,audits/audit-filters.tsx:19-27,settings/users/page.tsx:78-99,settings/audit-log/audit-log-content.tsx,portal/audits/[id]/page.tsx:51-61,portal/documents/page.tsx:67,clients/[id]/edit/page.tsx:225-457
PROB-INC-02 — Labels “Lancer un audit” vs “Trigger” / “Launch” (impact moyen)
- Pages concernées :
<TriggerAuditButton>,/dashboard/clients/[id]/documents - Description :
<TriggerAuditButton>utiliset("launch")→ “Lancer un audit” en FR/dashboard/clients/[id]/documents:357lien hardcoded “Lancer un audit”- L’API et les commits parlent de “trigger audit”
/portalparle de “Recent audits” mais pas de relancer<AuditActions>parle de “retry” et “sync”
- Code :
trigger-audit-button.tsx,clients/[id]/documents/page.tsx:357-360
PROB-INC-03 — Boutons “Voir” avec comportements différents (impact moyen)
- Pages concernées :
/portal/auditstable cell “Voir” →/portal/audits/[id](link)<ImpersonateClientButton>“Voir comme ce client” → POST + redirect/portal<PortalClientPicker>“Voir comme ce client” → POST + redirect/portal/dashboard/clients/[id]/documents:464“Voir tout (X findings)” →/dashboard/clients/[id]/remediation-plan
- Description : 4 actions différentes labellisées “Voir…”. L’utilisateur ne peut pas anticiper si c’est une nav simple ou une action serveur (impersonate write-side-effect).
- Code :
portal/audits/page.tsx:94,impersonate-client-button.tsx:60-62,portal-client-picker.tsx:99-103,clients/[id]/documents/page.tsx:464
PROB-INC-04 — “Sign Out” vs “Logout” vs “Quitter” (impact moyen)
- Pages concernées : sidebar dashboard, portal-sidebar, header dropdown, portal-impersonation-banner
- Description :
- Sidebar dashboard :
tCommon("signOut")→ “Se déconnecter” (FR) - PortalSidebar : “Logout” hardcoded EN
- Header dropdown :
tCommon("signOut")→ “Se déconnecter” (FR) - PortalImpersonationBanner : “Quitter” hardcoded FR (action différente :
DELETE /api/portal/impersonate)
- Sidebar dashboard :
- Code :
sidebar.tsx:232,portal-sidebar.tsx:90,header.tsx:100,portal-impersonation-banner.tsx:45
PROB-INC-05 — Hiérarchie de breadcrumb incohérente entre routes client (impact moyen)
- Pages concernées : sous-routes
/dashboard/clients/[id]/* - Description :
- Pages avec
<Breadcrumb>shadcn complet (4 niveaux Tableau de bord > Clients > nom > sous-page) :/edit,/secrets,/findings,/remediation,/remediation-plan,/trajectory,/documents,/controls/[controlId] - Pages SANS breadcrumb mais avec back arrow seul :
/dashboard/clients/new,/dashboard/settings/users,/dashboard/settings/api-keys,/dashboard/settings/audit-log,/dashboard/settings/notifications - Pages SANS aucun retour visible :
/dashboard/clients/[id]/onboarding/[step](utilise stepper sidebar à la place) /portal/audits/[id],/portal/findings,/portal/remediation,/portal/documents: aucun breadcrumb ni back arrow (cf. PROB-CTX-02)
- Pages avec
- Code : pattern
<Breadcrumb>cohérent côtéclients/[id]/*mais cassé côtésettings/*etportal/*
PROB-INC-06 — Header client : 8 boutons inline + 1 dropdown vs <AuditActions variant="buttons"> 7 boutons inline (impact moyen)
- Pages concernées :
/dashboard/clients/[id]header et/dashboard/audits/[id]header - Description : Convention de header “stack horizontal de boutons” surchargée. Sur mobile et petits écrans, ça wrap mal. Aucun primary/secondary visuel — tous variant
outlinesauf le primary (TriggerAuditButton). Pas de groupement (Identity vs Operations vs Reports). - Code :
clients/[id]/page.tsx:146-188,audits/[id]/page.tsx:264-281,audit-actions.tsx:131-245
PROB-INC-07 — Filtres dashboard vs filtres audits : design pattern divergent (impact moyen)
- Pages concernées :
/dashboard(DashboardFilters) et/dashboard/audits(AuditFilters) - Description :
- DashboardFilters : Select client + groupe de 3 boutons toggle pour periode (7d/30d/90d) avec UI custom
- AuditFilters : 2 Select (status + client)
- Pourtant les 2 sont des filtres URL-synced à la même fonction
updateParam. Convention divergente.
- Code :
dashboard-filters.tsx:46-82,audits/audit-filters.tsx:51-86
PROB-INC-08 — Sidebar 2 styles différents pour entrées actives (impact faible)
- Pages concernées : sidebar.tsx (top items, documents sub-items, settings)
- Description : 3 patterns de styling actif :
- Top nav :
bg-primary/10 text-primary font-semibold+ variantsecondary - Documents header (button) :
bg-primary/10 text-primary font-semiboldmais c’est un<button>plain (pas un<Button>shadcn) - Documents sub-items :
bg-primary/10 text-primary font-semiboldsur un<Button size="sm" variant="ghost"> - Settings : recopie le pattern top mais sans ChevronDown
- Top nav :
- Code :
sidebar.tsx:101-128, 132-150, 156-167, 199-218
PROB-INC-09 — <CardHeader> parfois cliquable (entire card link), parfois non (impact faible)
- Pages concernées :
/dashboard/clients,/dashboard/settings,/dashboard/documents,/dashboard/help/dr - Description : Sur
/dashboard/clients, la Card est wrapped dans un<Link>mais le footer<ImpersonateClientButton>ne l’est pas. Sur/dashboard/settings, la Card entière est dans un<Link>. Sur/dashboard/documents, idem. Sur/dashboard/help/dr, idem. Convention “card-as-link” inconsistante. - Code :
clients/page.tsx:96-160,settings/page.tsx:30-43,documents/page.tsx:239-292,help/dr/page.tsx:90-103
PROB-INC-10 — Boutons CSV / “CSV + before/after” sans label différencié visuellement (impact faible)
- Pages concernées :
/dashboard/settings/audit-log - Description : 2 boutons côte à côte (“CSV” et “CSV + before/after”). Le 2e a
variant="ghost"au lieu devariant="outline"; à part ça, même icône, même tooltip-only différenciation. Risque de download accidentel d’un CSV très lourd. - Code :
audit-log-content.tsx:300-317
PROB-INC-11 — Termes mixés “Findings” vs “Écarts” vs “Open gaps” (impact faible)
- Pages concernées : multiples
- Description :
- DB schema :
GapFinding - Code utilise
gapFindings,openGaps - UI : “Findings” côté audit detail summary (i18n EN), “écart” dans
<ControlExpandedRow>(FR), “non-conformes” sur/portal/documents /dashboard/clients/[id]/documentsparle de “Findings ouverts” et “Findings critiques”<TopCriticalFindings>parle de “Top Critical Findings”
- DB schema :
- Code : référence taxonomique non figée. Cf.
clients/[id]/documents/page.tsx:399, 415,portal/documents/page.tsx,audit/control-expanded-row.tsx:39-48
PERTE DE CONTEXTE
PROB-CTX-01 — Pas d’indication d’onglet/de tabs actif sur /dashboard/clients/[id] après reload (impact moyen)
- Page concernée :
/dashboard/clients/[id] - Description :
<Tabs defaultValue="overview">n’est pas synchronisé avec un query param. Au reload, on retombe toujours sur “Overview” même si l’utilisateur était sur “History” ou “Findings”. Pas de breadcrumb 4e niveau pour indiquer l’onglet actif. - Code :
clients/[id]/page.tsx:246
PROB-CTX-02 — Pages portal sans breadcrumb ni back arrow (impact moyen)
- Pages concernées :
/portal/audits/[id],/portal/findings,/portal/remediation,/portal/documents - Description : Côté portal client, aucune des sous-pages n’a de breadcrumb ni de bouton de retour. L’utilisateur ne peut revenir qu’en cliquant sur la sidebar. Pour
/portal/audits/[id](qui peut avoir été ouverte depuis/portal/auditsou depuis un email), pas de retour vers la liste. Idem pour le mode impersonate où le banner offre uniquement “Quitter” (qui retourne au dashboard MSSP, pas au portal/audits). - Code :
portal/audits/[id]/page.tsx:64,portal/findings/page.tsx:46,portal/remediation/page.tsx:43,portal/documents/page.tsx:218
PROB-CTX-03 — Le wizard onboarding ne montre pas la position dans le flow global (impact moyen)
- Page concernée :
/dashboard/clients/[id]/onboarding/[step] - Description :
<OnboardingShell>affiche un stepper sidebar 1-7 (mais la step 8 = Done est définie dansSTEP_LABELSet accessible). Pas de breadcrumb (Tableau de bord > Clients > nom > Onboarding step X). Si l’utilisateur arrive sur cette URL via lien externe, il ne sait pas dans quel client il est ni comment sortir (le banner banner client overview n’existe pas ici). - Code :
onboarding/wizard-stepper.tsx:36-93, pas d’utilisation de<Breadcrumb>
PROB-CTX-04 — Active audit banner sur /dashboard/clients/[id] n’utilise pas le live monitor (impact moyen)
- Page concernée :
/dashboard/clients/[id] - Description : Quand un audit est en cours, un banner “Audit en cours” cliquable apparait. Mais c’est juste un lien — pas de progress bar, pas de stage indicator. Le
<AuditLiveMonitor>(SSE complet avec stages) n’est rendu que dans/dashboard/audits/[id]. - Code :
clients/[id]/page.tsx:191-208,audits/[id]/page.tsx:284-294
PROB-CTX-05 — Modales/Dialogs sans titre clair ou contexte (impact moyen)
- Pages concernées : multiples
- Description :
<AuditActions>confirmt("confirmDelete")(toString JS confirm natif) — pas de modale shadcn, pas de doc sur ce qui sera suppriméclients/[id]/secrets:confirm(t("confirmDelete", {key}))natif aussi<TriggerAuditButton>Dialog : titret("dialogTitle", { slug })mais le slug est techy et l’utilisateur perd le contexte du nom client<GuideFilterDialog>: titre opaque, pas d’aperçu de ce que le PDF contient
- Code :
audit-actions.tsx:78,secrets/page.tsx:97,trigger-audit-button.tsx:151
PROB-CTX-06 — Empty states dans /dashboard/clients/[id]/findings peu informatifs (impact moyen)
- Page concernée :
/dashboard/clients/[id]/findings - Description : Si filter ne matche rien :
<p>{t("emptyFilter")}</p>— pas d’icône, pas de bouton “reset filter”. Pas de breadcrumb 4e niveau ni d’indicateur visuel du filtre actif. - Code :
clients/[id]/findings/page.tsx:170-172
PROB-CTX-07 — /dashboard/help/dr/[...slug] enfoui sans hiérarchie de section (impact moyen)
- Page concernée :
/dashboard/help/dr/[...slug] - Description : Le viewer markdown affiche le slug brut “docs/dr/runbooks/01-restore-postgres-pitr.md” en footer mais pas de breadcrumb (DR > Runbooks > Restore Postgres). Le sidebar DR (
<DrDocsSidebar>) montre la structure, mais quand on partage l’URL ou retourne dessus on ne sait pas quelle “section” on consulte sans inspecter le slug. - Code :
help/dr/[...slug]/page.tsx:71-80(pas de breadcrumb)
PROB-CTX-08 — Header DR + sidebar DR + sidebar dashboard = 3 niveaux empilés (impact moyen)
- Pages concernées :
/dashboard/help/dret sub-routes - Description : Le layout DR ajoute un sub-sidebar
<DrDocsSidebar>à l’intérieur de<main>. Donc l’écran montre :- Sidebar gauche dashboard (64 col)
- Header dashboard top (16 row)
- Banner Tampering (conditional)
- Sidebar gauche
<DrDocsSidebar>interne - Contenu doc
- Impact : sur écrans <1280px, il reste très peu de place pour le contenu doc. La hiérarchie de nav crée beaucoup de chrome.
- Code :
dashboard/layout.tsx+help/dr/layout.tsx:37-43
PROB-CTX-09 — Page /dashboard/clients/[id]/edit utilise router.back() pour Cancel (impact faible)
- Page concernée :
/dashboard/clients/[id]/edit - Description :
<Button onClick={() => router.back()}>Cancel</Button>— comportement imprévisible si l’utilisateur arrive depuis un lien externe (pas d’historique). Le breadcrumb pointe vers/clients/[id]mais le bouton Cancel ne le fait pas. - Code :
clients/[id]/edit/page.tsx:457-459
PROB-CTX-10 — Mode prévisualisation (impersonate) sort vers /dashboard au lieu de /dashboard/clients (impact faible)
- Page concernée :
<PortalImpersonationBanner>“Quitter” - Description : Action
DELETE /api/portal/impersonatepuisrouter.push("/dashboard"). Pourtant l’admin venait de/dashboard/clientsvia<ImpersonateClientButton>. Casse le flow naturel “je teste un client puis je reviens à la liste”. - Code :
portal-impersonation-banner.tsx:17
PROB-CTX-11 — EditClientPage n’a pas d’erreur form globale visible (impact faible)
- Page concernée :
/dashboard/clients/[id]/edit - Description : En cas d’erreur PUT, c’est uniquement un toast destructif. Si le form a 30 champs et que la validation serveur échoue sur l’un d’eux, le toast donne un message court et l’utilisateur doit chercher le champ. Pas de scroll-to-error.
- Code :
clients/[id]/edit/page.tsx:160-167
PROB-CTX-12 — Multi-sélection product areas dans <TriggerAuditButton> peu lisible (à confirmer)
- Page concernée :
<TriggerAuditButton>modal - Description : Popover combobox avec checkboxes ; le label affiché (“3 sélectionnés”, “tout sélectionné”, “Entra, Exchange, Teams”) change selon le nombre. Le bouton Launch n’aperçoit pas la sélection à côté. L’utilisateur peut s’embrouiller entre “tous” et “0 sélectionnés”.
- Code :
trigger-audit-button.tsx:81-87, 175-227
Bugs techniques détectés (hors scope UX strict)
BUG-01 — STEP_ORDER dans <OnboardingShell> exclut step 8 mais le wizard a bien 8 étapes
- Fichier :
platform/src/components/onboarding/wizard-stepper.tsx:15 - Description :
const STEP_ORDER: StepIndex[] = [1, 2, 3, 4, 5, 6, 7];maisVALID_STEPScôté[step]/page.tsxinclut[1,2,3,4,5,6,7,8]. Step 8 (Done) est rendu mais ne sera jamais affiché dans la stepper sidebar.
BUG-02 — Document categories: lien “Couverture 220 contrôles” pointe vers /dashboard/clients/[id] (page client) au lieu de la page de couverture
- Fichier :
platform/src/app/dashboard/documents/technical/page.tsx:28 - Description :
viewPath: "/dashboard/clients/{clientId}"pour l’itemcontrol-coverage. Ne mène pas vers une page dédiée de couverture des 220 contrôles, mais redirige sur l’overview client. Entrée non-fonctionnelle pour son but déclaré.
BUG-03 — <DashboardFilters> redirige toujours vers /dashboard même si on est ailleurs
- Fichier :
platform/src/components/dashboard-filters.tsx:42 - Description :
router.push(\/dashboard?$`)` hardcodé. Si jamais ce composant est réutilisé sur une autre page, casse la nav.
BUG-04 — Settings hub link “Notifications email” hardcoded FR sans i18n
- Fichier :
platform/src/app/dashboard/settings/page.tsx:50-51 - Description :
<CardTitle>Notifications email</CardTitle>+<p>Préférences de réception...</p>directement en FR alors que le reste utiliset(\links.$.title`)`.
BUG-05 — <DownloadReportButton> portal vs <AuditActions> MSSP : 2 implémentations divergentes
- Fichiers :
platform/src/components/download-report-button.tsx,platform/src/components/audit-actions.tsx - Description :
<DownloadReportButton>côté portal n’expose probablement que PDF (à vérifier sur le code) tandis que<AuditActions>expose PDF/Excel/HTML. Si le client portal veut un Excel, il ne peut pas l’avoir.
BUG-06 — /dashboard?error=forbidden non géré
- Fichier :
platform/src/app/dashboard/page.tsx - Description : Plusieurs gardes redirigent vers cette URL avec
?error=forbiddenmais la page ne lit pas ce param et ne montre aucun toast (cf. PROB-ORPH-08).
Synthèse priorités
| Catégorie | Total | Impact fort | Impact moyen | Impact faible |
|---|---|---|---|---|
| DOUBLONS | 7 | 0 | 3 | 4 |
| ORPHELINS | 8 | 2 | 2 | 4 |
| INCOHÉRENCES | 11 | 1 | 6 | 4 |
| PERTE DE CONTEXTE | 12 | 0 | 8 | 4 |
| TOTAL UX | 38 | 3 | 19 | 16 |
| Bugs techniques | 6 | — | — | — |
PROB-ORPH-01— Hub documents client orphelin (fonctionnalité majeure invisible)PROB-ORPH-02— Plan exécutif remediation orphelin (vue exec inaccessible)PROB-INC-01— Mix EN/FR généralisé casse le LanguageSwitcherPROB-CTX-02— Portal client sans aucun retour ni breadcrumbPROB-INC-06— Surcharge des headers (8 boutons inline) crée du chaos visuel sur petits écrans