Yayaw
Documentation

Tableau de bord

Architecture d'information du tableau de bord, navigation, accueils selon les rôles et comportement du shell partagé.

Vue d'ensemble

Le tableau de bord est le shell produit authentifié. Ce n'est pas une page d'accueil générique unique; c'est un ensemble de surfaces opérationnelles adaptées aux rôles et enracinées sous:

  • /dashboard

  • /dashboard/admin

  • /dashboard/content

  • /dashboard/organization

  • /dashboard/settings

  • /dashboard/test

Toutes les routes du tableau de bord sont préfixées par la locale au runtime, par exemple /en/dashboard/content/pages.

Groupes de routes

Les routes du tableau de bord sont organisées par intention utilisateur:

SectionRacine de routeObjectif
Accueil/dashboardRépertoire conscient des permissions de toutes les destinations dashboard autorisées.
Admin/dashboard/adminSanté plateforme et contrôles superadmin.
Contenu/dashboard/contentCMS, médias, pages, sections, composants, données, design tokens et e-mails transactionnels.
Organisation/dashboard/organizationFacturation d'organisation, plans, accès au code, membres et réglages d'organisation.
Réglages/dashboard/settingsCompte personnel, sécurité, préférences, organisations et clés API développeur.
Test/dashboard/testDiagnostics internes d'autorisation et de routes.

Les éléments parents de la barre latérale sont des tableaux de bord de section navigables. Une route parente ne doit jamais pointer vers une page masquée ou manquante. Cela garde la navigation au clavier via le menu de commande, les fils d'Ariane et les liens directs prévisibles.

Shell partagé

Le shell du tableau de bord fournit:

  • le layout authentifié et les vérifications d'organisation active

  • la navigation de barre latérale

  • les actions de barre applicative

  • les fils d'Ariane

  • le menu de commande

  • le sélecteur d'organisation active

  • le menu utilisateur

  • l'overlay de focus pour le contenu de tableau de bord gardé

Les lectures serveur du tableau de bord utilisent une organisation active effective, résolue depuis la session Better Auth et les appartenances d'organisation de l'utilisateur. Lorsque l'organisation active stockée par Better Auth est absente ou n'appartient plus à l'utilisateur, le serveur se rabat sur l'organisation par défaut de l'utilisateur, puis sur la première appartenance. Les view-models du tableau de bord, le filtrage de navigation et les actions serveur doivent s'appuyer sur ce contexte de session serveur plutôt que d'attendre l'hydratation client de l'organisation.

Fichiers clés:

  • src/app/[locale]/dashboard/layout.tsx

  • src/blocks/dashboard/navigation/*

  • src/blocks/dashboard/auth-checker.server.tsx

  • src/blocks/dashboard/auth-checker.client.tsx

  • src/blocks/dashboard/section-navigation.tsx

Les routes du tableau de bord devraient utiliser PageDashboard ou les modèles locaux de blocs de tableau de bord plutôt que de créer un chrome de page sans rapport.

Tableaux de bord de section

Les tableaux de bord de section sont des pages compactes de racine de route qui résument les signaux de santé utiles pour la section courante. Ils évitent que les parents de barre latérale se comportent comme des libellés non cliquables, sans répéter le titre de page déjà possédé par la barre applicative du tableau de bord.

Le shell du tableau de bord rend sur desktop une barre de navigation de section partagée dans un sous-en-tête sticky directement sous la barre applicative, avec les fils d'Ariane au-dessus lorsque le flag breadcrumb est actif. Elle est dérivée de l'arbre de barre latérale filtré et ne liste que les routes enfants de la section active; elle reste donc compacte, consciente des permissions et centrée sur la navigation locale de sous-section au lieu de dupliquer les sections de tableau de bord de premier niveau. Le fil d'Ariane et la barre de navigation de section sont contrôlés indépendamment par les indicateurs de fonctionnalité gérés dashboard-breadcrumbs-enabled et dashboard-section-navigation-enabled.

Tableaux de bord de section actuels:

  • /dashboard/admin

  • /dashboard/content

  • /dashboard/organization

  • /dashboard/settings

  • /dashboard/test

/dashboard/admin, /dashboard/content, /dashboard/organization et /dashboard/settings sont des écrans (voir Écrans) ; /dashboard/test est une page écrite dans le code (voir Tableau de bord test).

Chaque tableau de bord de section devrait:

  • s'appuyer sur la navigation de section du shell pour les liens enfants visibles

  • respecter la visibilité authz

  • afficher des cartes, graphiques et appels à l'action opérationnels propres à cette section

  • éviter de dupliquer les actions cachées d'admin, de facturation ou de navigation de premier niveau via des cartes de raccourcis autonomes

Écrans

L'accueil (/dashboard), le tableau de bord du contenu (/dashboard/content), la médiathèque (/dashboard/content/media) et sa corbeille, la liste des pages (/dashboard/content/pages), celle des modèles d'e-mails (/dashboard/content/email-templates), celles des données et des modèles de données CMS (/dashboard/content/data, /dashboard/content/data-models), la vue d'ensemble de l'organisation (/dashboard/organization), la page des devis et signatures (/dashboard/organization/signatures), la vue d'ensemble d'administration (/dashboard/admin), la page des autorisations (/dashboard/admin/authorization), celle des registres approuvés (/dashboard/admin/registry-templates), le catalogue de facturation (/dashboard/admin/billing-products), le catalogue des modèles de données dynamiques (/dashboard/admin/dynamic-data), la vue d'ensemble des réglages (/dashboard/settings), les pages de gestion des écrans (/dashboard/organization/screens, /dashboard/admin/screens) et la page des enregistrements de chaque modèle de données dynamiques (/dashboard/<section>/dynamic-data/<scope>/<model>, voir Écrans des modèles) sont des écrans : des documents de tableau de bord YaYaw Table faits de sections, de widgets et de filtres. L'écran par défaut est défini dans le code et versionné. La copie propre à une organisation n'est enregistrée en base qu'à sa première personnalisation, et l'écran par défaut peut toujours être rétabli. Le tableau de bord test reste une page écrite dans le code (voir Tableau de bord test), comme le catalogue de la documentation, les catalogues des sections et des composants, et les pages des utilisateurs, des membres et des clés API. Une organisation peut aussi créer ses propres écrans (voir Écrans créés par l'organisation).

Les widgets lisent leurs lignes et leurs chiffres dans des sources que le document désigne par leur identifiant, comme system:pages ou un modèle de données dynamiques déployé. Une source vérifie can() à chaque lecture. Les personnes qui ne modifient ni ne publient un écran le reçoivent sans les widgets dont elles ne peuvent pas lister la source.

La personnalisation est désactivée tant que l'indicateur de fonctionnalité screen-customization n'est pas actif ; d'ici là, chaque écran affiche son défaut. Une fois l'indicateur actif, les admins d'organisation (les rôles Organization Admin et Super Admin, par la permission screen:manage) gèrent les écrans de leur organisation ; les autres voient l'écran publié. Les admins d'organisation peuvent aussi donner à d'autres personnes Voir, Modifier ou Publier sur un écran, ou sur tous les écrans d'une section du menu (voir Accès à un écran).

Un écran global n'appartient à aucune organisation : il a une seule copie pour toute la plateforme (c'est le cas de la vue d'ensemble d'administration, de la liste des modèles d'e-mails, de la page des autorisations, de celle des registres approuvés et du catalogue de facturation). Seuls les Super Admins le gèrent, par la permission screen:manage détenue globalement : celle d'un admin d'organisation ne vaut que dans son organisation. Sa barre d'état parle de la copie de la plateforme. L'assistant d'un Super Admin y accède avec scope: "global" : il liste les écrans globaux, les lit et enregistre leurs brouillons, et un Super Admin les publie.

Les personnes qui modifient ou publient un écran voient une barre d'état au-dessus de l'écran. Celles qui le modifient consultent ce qui est préparé ; celles qui le publient (et les admins d'organisation) peuvent aussi publier, abandonner, revenir au défaut et garder la copie :

  • Personnalisé, avec Revenir au défaut, quand l'organisation a publié sa propre copie ;

  • Historique, quand l'écran garde des versions publiées, même revenu à son défaut (voir Historique) ;

  • Un brouillon de cet écran est en attente : préparé dans le tableau de bord ou par un assistant, par qui, quand et pourquoi (et la version qu'il restaure), avec Consulter (le brouillon s'affiche à la place de l'écran, sans rien enregistrer), Publier et Abandonner. Un brouillon qui a des problèmes les liste et ne peut pas être publié ;

  • un avertissement quand le brouillon part d'un ancien défaut ;

  • L'écran par défaut a été mis à jour, quand le défaut du code a changé depuis la copie de l'organisation, avec Voir le défaut, Revenir au défaut et Garder le mien.

Publier, abandonner et revenir au défaut demandent d'abord une confirmation.

Les personnes qui modifient un écran le modifient aussi sur place : Modifier ouvre l'éditeur d'écran de YaYaw Table sur l'écran tel que tout le monde le voit, ou sur le brouillon qu'elles consultent (un brouillon en attente se modifie pendant qu'on le consulte, pour ne jamais être remplacé sans avoir été vu). Elles ajoutent et déplacent des sections, ajoutent des widgets à partir des sources qu'elles peuvent lire et des blocs que l'écran peut placer, modifient la vue d'un widget dans la table réelle et changent les filtres. Enregistrer le brouillon enregistre un brouillon venu du tableau de bord, vérifié comme les autres : les problèmes que l'éditeur voit lui-même l'arrêtent aussitôt, et ceux que seul le serveur connaît (un bloc que l'écran garde, sa table pleine page, une source que le membre ne peut pas lire, le nombre de widgets) sont listés au-dessus de l'écran, widget par widget. Le brouillon s'affiche ensuite pour être consulté, et Publier dans la barre d'état le publie.

Le MCP prépare, un humain publie : un assistant liste les écrans, les lit et enregistre des brouillons (yayaw_screens_list, yayaw_screen_get et yayaw_screen_save_draft), lit leurs versions publiées et en restaure une comme brouillon (yayaw_screen_revisions et yayaw_screen_revision_restore), tous décrits dans la page Plan de contrôle. Publier, abandonner, revenir au défaut et garder une copie se font uniquement dans la barre d'état ou sur les pages de gestion des écrans, et le brouillon est vérifié de nouveau pour le membre qui le publie.

Les écrans se trouvent dans src/lib/server/services/screens/ et src/blocks/dashboard/screens/ ; docs/dashboard/screens.md est le guide développeur.

Gestion des écrans

Écrans liste chaque écran avec son état, pour qu'aucun brouillon n'attende sans être vu :

  • /dashboard/organization/screens, dans la section Organisation, liste les écrans de l'organisation aux membres qui y détiennent screen:read (les admins d'organisation et les Super Admins, que leur screen:manage autorise) ;

  • /dashboard/admin/screens, dans la section Admin, liste les écrans globaux de la plateforme. Sa route est protégée comme la vue d'ensemble d'administration (feature-flag:manage), et ses lignes demandent screen:read détenu globalement : la permission d'un admin d'organisation ne vaut que dans son organisation, il ne l'ouvre donc jamais.

Chaque page indique combien d'écrans sont personnalisés, combien de brouillons attendent et combien viennent d'assistants, combien de copies dérivent d'un ancien défaut, les écrans par statut, puis la table des écrans. La page garde sa table : une personnalisation peut la déplacer, jamais la retirer. Chaque ligne donne l'écran, sa section et son statut (Par défaut, Personnalisé ou Défaut mis à jour), son brouillon en attente (venu du tableau de bord ou d'un assistant par le MCP, avec sa raison, son auteur et sa date, et s'il part d'un ancien défaut), quand et par qui sa copie a été publiée, et les versions du défaut. Un auteur apparaît tant qu'il est membre de l'organisation (pour un écran global, tant que son compte existe). La page ne lit jamais les documents des écrans.

Le menu d'une ligne propose Ouvrir, puis Consulter le brouillon et Voir le défaut, qui ouvrent l'écran sur son brouillon en attente ou sur son nouveau défaut, où sa barre d'état propose la suite, puis Historique quand l'écran garde des versions publiées (voir Historique). Les membres qui gèrent les écrans ont aussi Publier le brouillon, Abandonner le brouillon, Revenir au défaut (pour une copie) et Garder le mien (quand le défaut a changé). Chaque changement demande une confirmation, puis passe par les mêmes vérifications que la barre d'état, à la révision que la ligne affichait : quand l'écran a changé depuis, la page le dit et recharge les lignes. Rien ne change pendant qu'un administrateur incarne le membre, et quand screen-customization est désactivé, la page indique que la personnalisation est désactivée au lieu de lister les écrans.

Historique

Chaque publication d'un écran est conservée comme une version numérotée (1, 2, …) : les 25 dernières de chaque écran, supprimées avec l'écran. Chaque copie publiée avant l'historique est devenue la version 1. Une version garde l'écran publié, quand et par qui il a été publié, le brouillon qu'elle a publié (préparé dans le tableau de bord ou par un assistant, par qui et pourquoi) et la version que ce brouillon restaurait. Les versions sont une provenance : elles n'accordent rien.

Historique s'ouvre depuis la barre d'état et depuis une ligne des pages de gestion des écrans. Il liste les versions, de la plus récente à la plus ancienne, et signale celle que l'écran affiche. Pour chaque version :

  • Prévisualiser l'affiche à la place de l'écran (l'adresse de la page reçoit ?screen-preview=version:<n>, qu'un lien conserve), avec Revenir à l'écran, Comparer et Restaurer comme brouillon dans la barre d'état. Ses blocs affichent les données que la page a chargées pour l'écran ;

  • Comparer liste ce que la version change par rapport à ce que l'écran affiche (sa copie publiée, sinon son défaut) ou à une autre version : widgets, sections et filtres ajoutés, supprimés ou modifiés, chacun avec son chemin JSON et les chemins des valeurs qui diffèrent ;

  • Restaurer comme brouillon, une fois confirmé, fait de la version le brouillon en attente, à la place de celui qui y attend s'il y en a un. Elle est vérifiée pour le membre comme tout brouillon (une version qui nomme une source qu'il ne peut pas lire est refusée) et jamais publiée : le brouillon s'affiche pour être consulté, indique la version qu'il restaure, et Publier le publie. La version que l'écran affiche n'a rien à restaurer.

Toute personne qui peut lire l'écran (screen:read sur celui-ci : les lecteurs des pages de gestion des écrans, et quiconque a reçu un accès à l'écran) liste et compare ses versions, entières pour les personnes qui le modifient ou le publient, sans les widgets des sources qu'elles ne peuvent pas lire pour les autres. Prévisualiser une version est réservé à celles qui le modifient ou le publient ; restaurer une version enregistre un brouillon, ce qui est réservé à celles qui le modifient : cela redemande screen:update, et n'a jamais lieu pendant qu'un administrateur incarne le membre. Un assistant lit les versions et en restaure une comme brouillon avec yayaw_screen_revisions et yayaw_screen_revision_restore ; une personne qui peut publier l'écran le publie toujours.

Accès à un écran

Sur la page de l'organisation, le menu d'une ligne propose aussi Gérer l'accès, aux membres qui gèrent les écrans. Il ouvre le panneau d'accès de l'écran, qui liste qui a accès et à quel niveau, sur cet écran ou sur tous les écrans de sa section, retire un accès, et donne accès à :

  • un membre de l'organisation, sur cet écran ;

  • une équipe de l'organisation, sur cet écran ou sur tous les écrans de sa section ;

  • tous les membres de l'organisation, sur cet écran ou sur tous les écrans de sa section.

NiveauCe qu'il permet
VoirVoir l'écran.
ModifierAussi consulter son brouillon en attente, enregistrer des brouillons dans l'éditeur et restaurer une version comme brouillon.
PublierAussi publier ou abandonner le brouillon, et remettre l'écran à son défaut.

Chaque niveau comprend le précédent, et donner un autre niveau le remplace. Sur un écran système, l'accès dit ce qu'une personne peut faire de l'écran, jamais si elle ouvre sa page : sa route en décide toujours. Seuls les admins d'organisation gèrent l'accès. L'accès est une appartenance à un groupe, jamais un réglage posé sur une personne : un membre rejoint le groupe propre de l'écran, une équipe ou le groupe des membres de l'organisation est lié à l'écran ou à sa section (voir Autorisation). Une personne qui quitte l'organisation perd ces accès. Rien ne change pendant qu'un administrateur incarne le membre, et un assistant ne change jamais qui a accès. Un écran ne donne aucune donnée : chaque widget ne lit sa source que si cette source le permet.

Écrans créés par l'organisation

Une fois screen-customization actif, les admins d'organisation créent leurs propres écrans (la permission screen:create, que leur screen:manage comprend). Un écran créé par l'organisation est un tableau de bord comme les autres, fait de sections, de widgets et de filtres, avec :

  • sa propre adresse, /dashboard/screens/<slug> : le slug peut changer (les anciens liens ne fonctionnent alors plus), l'écran lui-même jamais ;

  • un titre en anglais et en français ;

  • une entrée de menu : dans la section Contenu ou Organisation après leurs propres pages, ou dans un groupe Écrans, avec une icône et un ordre.

Un nouvel écran commence par un brouillon que seules les personnes qui le modifient voient, et le publier le montre aux personnes qui peuvent le voir. Sauf si la personne qui le crée ne choisit personne, tous les membres de l'organisation reçoivent Voir sur l'écran ; les autres accès se donnent comme sur tout écran, sa section étant son emplacement dans le menu (voir Accès à un écran). Un écran qu'un assistant prépare par MCP n'a personne tant qu'une personne ne l'a pas publié et n'a pas donné d'accès.

Un écran créé par l'organisation n'a pas de défaut : il n'est jamais remis à son défaut, ni marqué personnalisé. Les personnes qui le modifient y placent des widgets sur les sources qu'elles peuvent lire, les blocs prévus pour ces écrans (À traiter, le stockage des médias et la facturation de l'organisation) et au plus un tableau pleine page, sur une source qu'elles peuvent lire. Son historique fonctionne comme celui de tout écran (voir Historique).

Archiver un écran le cache à tous sauf aux admins d'organisation et le fige jusqu'à sa restauration, tel qu'il était. Seul un écran archivé peut être supprimé, avec son historique et tous les accès donnés sur lui. Une personne qui ne peut pas voir un écran obtient la même réponse « introuvable » que pour un écran qui n'existe pas. Une organisation garde au plus 50 écrans créés par elle, archivés compris, et au plus 10 créés par des assistants que personne n'a encore publiés. La page de gestion des écrans liste ces écrans après les autres, avec leur état : Non publié, Publié ou Archivé.

Dans le menu, un écran publié apparaît aux personnes qui peuvent le voir : après les pages de sa section (Contenu ou Organisation), ou dans le groupe Écrans, juste après la section Organisation, dont le lien ouvre son premier écran. Les entrées suivent leur ordre, puis leur titre dans la langue de la personne. Un brouillon, un écran archivé et les écrans d'une autre organisation n'y apparaissent jamais. L'annuaire de l'accueil et la vue d'ensemble de la section les listent aussi, et le fil d'Ariane et le titre de la page nomment l'écran comme son entrée.

Sur la page de gestion des écrans de l'organisation, Nouvel écran (pour les admins d'organisation) demande les titres de l'écran en anglais et en français, son adresse (prise du titre anglais tant que vous ne la changez pas), sa place dans le menu, son icône, son ordre, et si toute l'organisation peut le voir une fois publié (coché par défaut). L'écran est créé en brouillon, qui s'ouvre pour que vous le construisiez avec Modifier, puis le publiiez. La ligne d'un écran créé par l'organisation propose aussi :

  • Entrée de menu : son adresse, ses titres, sa place, son icône et son ordre. Une nouvelle adresse casse les liens vers l'ancienne, et une autre place dans le menu change qui y a accès par cette section ;

  • Archiver et Restaurer, chacun confirmé ;

  • Supprimer, pour un écran archivé seulement, une fois son adresse saisie : l'écran, ses versions et tous les accès donnés sur lui sont supprimés définitivement.

Publier pour la première fois un écran qu'un assistant a préparé propose Voir à toute l'organisation, coché par défaut, sur sa ligne comme dans sa barre d'état.

Écrans des modèles

La page des enregistrements de chaque modèle de données dynamiques est un écran de l'organisation, modèles globaux compris : chaque organisation en garde sa propre copie. Par défaut, c'est une seule table pleine largeur des enregistrements du modèle, qui garde les réglages de table du modèle, ses vues enregistrées et ses favoris. Autour de la table, la page montre toujours ce qu'elle montrait : l'enregistrement ouvert depuis une ligne (son résumé, ses enregistrements liés et ses chronologies d'événements) et, pour qui peut gérer le modèle, la création, la modification, la suppression, la modification groupée et l'import d'enregistrements, le formulaire d'enregistrement, les déplacements de l'arborescence, les plans du Gantt, les destinations de connexion, les liens de formulaire et la recherche d'adresse. Chaque écriture est vérifiée à nouveau sur le serveur.

  • Qui le voit. Qui peut lister le modèle (dynamic-data:list sur le modèle, sur son organisation, ou globalement pour un modèle global) ; pour les autres, la page n'existe pas. La page d'une section (/dashboard/content/dynamic-data, /dashboard/organization/dynamic-data, /dashboard/<section>/dynamic-data) montre l'écran de son premier modèle. La page d'administration d'un modèle (/dashboard/admin/dynamic-data/<scope>/<model>) montre la définition du modèle (contrat, révisions, plan de déploiement) au-dessus de son écran, à qui gère le modèle.

  • Le personnaliser. Avec screen-customization activé, ses éditeurs le modifient comme tout écran : ajouter des chiffres, des graphiques ou d'autres tables, donner à la table une vue propre, puis publier. La section de l'écran, pour l'accès, est la section de menu du modèle (Admin par défaut, Contenu, Organisation ou la sienne) : un accès donné sur cette section, ou sur l'écran lui-même, le couvre (voir Accès à un écran). La page de gestion des écrans liste l'écran d'un modèle dès qu'il a eu un brouillon ou une publication, à qui liste son modèle sur sa portée.

  • Liens. Un lien qui filtre les enregistrements d'un modèle nomme désormais la table de l'écran (dynamic-data:<scope>:<slug>-filters) ; un lien enregistré avec les anciennes clés de la table des enregistrements (dynamic-data-records-table:<id du modèle>-…) est traduit une fois à son ouverture.

  • Les assistants préparent des brouillons de ces écrans par MCP ; une personne les publie.

Accueil adapté aux rôles

La route principale /dashboard est l'accueil de navigation conscient des permissions, rendu à partir de l'écran d'accueil (dashboard.root). Son défaut est fait de blocs de l'hôte : le résumé de l'espace, la connexion d'un assistant, À traiter, les favoris et destinations récentes côte à côte, le répertoire de toutes les destinations (un accueil personnalisé doit le garder) et les applications. Les blocs de navigation sont pilotés par un view-model serveur qui lit l'arbre de barre latérale filtré et construit un répertoire exhaustif des destinations statiques accessibles par l'acteur courant. Une section peut rester dans le répertoire parce qu'elle contient une route enfant autorisée, mais son lien d'aperçu/racine n'est rendu que si cette racine a été autorisée indépendamment.

Comme la page d'accueil dérive de navigationConfig.nav.sidebar.groups après filterNavigationByPermissions(...), les futures pages dashboard peuvent y apparaître en étant ajoutées au modèle normal de sidebar et en passant les mêmes filtres authz. Ne maintenez pas un second registre de raccourcis pour l'accueil et ne tronquez pas le répertoire statique autorisé.

Le répertoire propose une recherche locale insensible aux accents. Les favoris et destinations récentes sont des accélérateurs côté client stockés dans un payload localStorage versionné et scopé sur l'utilisateur et l'organisation active. Les hrefs stockés sont toujours intersectés avec le dernier ensemble de destinations filtré par le serveur avant affichage ou réécriture, afin qu'une préférence obsolète ne puisse pas réexposer une route après un changement d'autorisation. Ces préférences de navigation ne remplacent jamais les gardes serveur des routes.

Le nombre de modèles de données dynamiques déployés peut évoluer indépendamment de la navigation statique. Ils sont donc regroupés dans un navigateur applications/données séparé et recherchable au lieu de développer chaque section en ligne. Ses entrées proviennent toujours du même modèle de navigation filtré par permissions et restent soumises à l'autorisation serveur dynamic-data.

Tous les utilisateurs authentifiés:

  • reçoivent toutes les destinations statiques autorisées, groupées par section

  • reçoivent un lien d'aperçu de section uniquement lorsque sa racine est autorisée indépendamment

  • peuvent rechercher le répertoire et gérer des favoris et destinations récentes re-filtrés par permissions dans leur navigateur courant

  • parcourent les applications et données dynamiques autorisées dans une surface recherchable séparée

  • voient le contexte d'organisation active lorsqu'il existe

  • ne reçoivent pas de doublons de santé organisationnelle, facturation, contenu, revenus ou analytics fournisseur sur la page d'accueil

Services clés:

  • src/lib/server/services/dashboard/dashboard-home.ts (la navigation de l'accueil)

  • src/lib/server/services/screens/ (les écrans, leurs sources et leurs blocs)

Les écrans lisent leurs sources par lots via des actions serveur, et les agrégats des sources système sont mis en cache 5 minutes par source, organisation, accès et requête. Les sources qui lisent un fournisseur (PostHog, Umami, Stripe) ne cassent jamais un écran : quand le fournisseur n'est pas configuré, échoue ou met trop de temps à répondre, leurs widgets le disent au lieu d'afficher des zéros, et l'erreur reste dans les logs du serveur.

Tableau de bord admin

/dashboard/admin est la surface de santé plateforme superadmin. Sa vue d'ensemble est l'écran d'administration (dashboard.admin.root, voir Écrans), un écran global : le même pour toute la plateforme, quelle que soit l'organisation active. Son défaut affiche :

  • un filtre Période, les 30 derniers jours par défaut, sur ce qui évolue dans le temps : les revenus, l'audience, les nouveaux utilisateurs et les nouvelles organisations ; les totaux restent entiers ;

  • neuf chiffres : le revenu net sur la période, comparé à la période précédente, avec une tendance hebdomadaire ; le revenu brut et les frais Stripe ; les abonnements actifs ou récupérables, les abonnements en retard de paiement et les organisations ; les utilisateurs, les nouveaux utilisateurs et les événements ;

  • À traiter à côté des chiffres ;

  • le revenu par jour (revenu net et frais) et l'audience par jour (événements et utilisateurs quotidiens) ;

  • les nouveaux utilisateurs et les nouvelles organisations par jour ;

  • les abonnements par statut et le déploiement (hébergement, environnement, version et URL de la release en cours) ;

  • les pages d'administration que la personne peut ouvrir.

À traiter liste les webhooks de facturation ponctuelle en échec, les produits de facturation non synchronisés avec Stripe, Stripe sans sa clé secrète et un fournisseur d'analyse choisi sans la configuration de son API. Chaque élément est compté derrière sa propre vérification can(), et ceux qui n'ont rien à signaler sont omis.

Chaque chiffre vient d'une source globale qui vérifie can() sans aucune organisation : les utilisateurs et l'audience demandent user:manage, les organisations organization:manage, les abonnements et les revenus billing:manage, et le déploiement system-settings:manage. Les permissions d'un admin d'organisation ne valent que dans son organisation : elles n'ouvrent jamais ces chiffres ; celles d'un Super Admin sont globales. La page garde sa propre garde (feature-flag:manage), et chacun ne voit que les widgets dont il peut lister la source.

Les revenus sont lus dans le solde Stripe de la plateforme : les paiements et les remboursements par jour du fuseau de la personne, sur 90 jours au plus (les widgets de revenus refusent une période plus longue), et 500 transactions Stripe au plus par lecture (au-delà, les chiffres ne couvrent qu'une partie de la période). L'audience est lue dans PostHog ou Umami. Les utilisateurs sont comptés jour par jour : une personne active plusieurs jours compte chaque jour, si bien que le graphique d'audience montre les utilisateurs quotidiens, puisqu'on ne peut pas additionner les utilisateurs d'une période à partir des jours. Tout actualiser recharge l'écran, et un fournisseur non configuré ou en échec le signale dans ses propres widgets.

/dashboard/admin/users est la surface superadmin de gestion des utilisateurs. Elle est gardée par Yayaw user:manage, pas par Better Auth user.role. Elle liste les utilisateurs Better Auth, l'état de bannissement et 2FA, les organisations par défaut, les sessions actives et les compteurs d'appartenance aux organisations. Le tiroir de détail permet aux superadmins d'ajouter un utilisateur à une autre organisation, de modifier le rôle d'appartenance Better Auth à une organisation, de retirer une appartenance, de définir l'organisation par défaut, d'inspecter les groupes Yayaw correspondants et de démarrer ou d'arrêter une impersonation contrôlée par RBAC.

Traitez /dashboard/admin comme l'URL canonique du statut plateforme dans les docs et la navigation.

Tableau de bord contenu

/dashboard/content est l'écran du contenu (dashboard.content.root, voir Écrans). Son défaut affiche :

  • un filtre Période sur les pages vues et les pages les plus vues, les 30 derniers jours par défaut ;

  • quatre chiffres : les pages publiées ; les pages en attente de publication (jamais publiées, ou publiées avec des modifications non publiées ; pages archivées exclues) ; les pages vues sur la période, comparées à la période précédente, avec une tendance par semaine ; le stockage des médias, hors corbeille ;

  • les pages vues par jour et les pages les plus vues ;

  • les pages modifiées récemment et À traiter ;

  • les médias par type et les pages créées par mois.

À traiter liste les pages jamais publiées, les pages publiées avec des modifications non publiées, les sections non publiées, les exécutions IA en échec depuis 7 jours, les médias sans miniature, le stockage des médias utilisé à 80 % du forfait ou plus, et un fournisseur d'analyse d'audience choisi sans sa configuration. Chaque élément est compté derrière son propre contrôle can(), et les éléments sans rien à signaler n'apparaissent pas.

Chaque chiffre vient d'une source d'écran (system:pages, system:page-views, system:top-pages, system:media et system:attention) qui vérifie can() à chaque lecture. Les chiffres et les éléments à traiter des pages comptent les pages que la liste des pages montre à la personne : les pages globales avec une politique globale page read, list ou manage, celles de l'organisation avec un accès page dans celle-ci. Les pages vues de l'organisation demandent l'accès aux pages dans l'organisation active ; les pages vues globales demandent page:manage global, parce que page:read global peut représenter l'accès public du runtime. Les pages vues sont les événements cms_page_viewed du runtime des pages CMS, lus dans PostHog ou Umami. Quand l'analyse d'audience est désactivée ou non configurée, ou que son fournisseur échoue, les widgets de pages vues l'indiquent au lieu d'afficher des zéros.

Docs propres au contenu:

Tableau de bord organisation

/dashboard/organization est la racine de section pour les opérations de l'organisation active : résumé de facturation, choix de l'offre, accès au code acheté, membres et réglages d'organisation. Sa vue d'ensemble est l'écran de l'organisation (dashboard.organization.root, voir Écrans). Son défaut affiche :

  • un filtre Période, les 30 derniers jours par défaut, sur les nouveaux membres et l'activité par jour seulement : le total des membres et les listes restent complets ;

  • trois chiffres : les membres ; les nouveaux membres sur la période, comparés à la période précédente, avec une tendance par semaine ; les invitations en attente (une invitation expirée n'est plus en attente) ;

  • l'activité par jour (pages, sections, médias et membres ajoutés), le résumé de facturation (offre, statut, places et fin d'une période de grâce) et À traiter ;

  • l'activité récente et les membres par mois ;

  • les pages de l'organisation que la personne peut ouvrir.

À traiter liste la facturation restreinte ou annulée, la période de grâce d'un paiement échoué avec les jours restants et les places de l'offre toutes prises, pour les membres qui peuvent lire la facturation de l'organisation, et les invitations en attente qui expirent d'ici un jour, pour les membres qui gèrent les invitations.

Chaque chiffre vient d'une source d'écran ou d'un bloc qui vérifie can() : les membres demandent member:list, les invitations invitation:manage, et chaque type d'activité sa propre permission de pages, sections, médias ou membres (pages et sections hors archives, médias hors corbeille). Le résumé de facturation et ses éléments À traiter demandent billing:read : le rôle d'un membre dans l'organisation (propriétaire, admin, manager) n'affiche jamais la facturation à lui seul, et le résumé indique aux autres qu'elle ne leur est pas accessible. Les comptes de contenu sont sur le tableau de bord contenu.

Les surfaces de facturation restent volontairement séparées:

  • /dashboard/organization/billing pour l'état et l'activité courants

  • /dashboard/organization/plans pour les actions de checkout

  • /dashboard/organization/code-access pour les livrables de code source achetés

Cette séparation évite de tasser la comparaison des plans, l'historique de facturation et les flux d'accès post-achat dans une seule page.

Devis et signatures

/dashboard/organization/signatures est l'écran des devis et signatures (dashboard.organization.signatures, voir Écrans). Il s'ouvre aux membres de l'organisation qui peuvent lire ses devis (signature:read, vérifiée à nouveau à chaque lecture, et l'appartenance à l'organisation), jamais pendant qu'un administrateur usurpe l'identité de quelqu'un. Son défaut affiche :

  • quatre chiffres : les devis à envoyer, à signer, signés, et ceux à traiter (encore en préparation, une invitation non remise, ou expirés), comptés sur tous les devis ;

  • la connexion Stripe : si le compte Stripe de l'organisation est connecté et si l'envoi pour signature est configuré sur cette instance, avec Connecter Stripe pour les membres qui gèrent les devis. L'écran la garde : c'est là que le compte se connecte ;

  • les devis, les plus récents d'abord, 20 par page, avec les files de travail de la liste, un kanban par statut et un calendrier par date d'expiration. Nouveau devis prépare un devis ; une ligne ouvre son PDF, ses téléchargements et son dossier de preuve, et les actions pour l'envoyer, l'annuler, reprendre sa préparation ou réessayer sa facture.

Les montants restent dans la devise de chaque devis et ne sont jamais additionnés. Préparer, envoyer, annuler et réconcilier passent par les actions serveur des signatures, qui vérifient de nouveau l'organisation, l'appartenance et signature:manage. L'écran liste tous les devis de l'organisation.

Tableau de bord réglages

/dashboard/settings regroupe les réglages personnels et développeur:

  • profil du compte

  • sécurité et MFA

  • préférences

  • organisations rejointes

  • clés API développeur

Sa vue d'ensemble est l'écran des réglages (dashboard.settings.root, voir Écrans). Toute personne connectée l'ouvre, avec ou sans organisation, et ses blocs montrent toujours son propre compte. Son défaut affiche :

  • Sécurité du compte, que l'écran garde toujours : l'authentification à deux facteurs et la vérification de l'e-mail, puis le nombre de passkeys, de sessions actives et de clés API personnelles du compte, chaque ligne menant à la page qui la modifie. Une session reste active jusqu'à son expiration ; l'impersonation d'un administrateur n'est pas comptée, la page Sécurité ne la listant pas. Une clé API compte tant qu'elle est activée et non expirée.

  • Votre compte : le nom, l'e-mail, la date de création du compte, le thème et la langue, avec des liens vers les pages du compte et des préférences.

  • Les pages des réglages.

Ces chiffres sont calculés côté serveur pour la seule personne connectée, et la page ne reçoit que des booléens et des nombres : jamais un jeton, une clé, un identifiant ou le détail d'une session. Les sources des écrans ne lisent jamais les sessions, les clés API, les passkeys, les comptes liés ni les secrets à deux facteurs : aucun widget, brouillon d'assistant ou lecture d'écran ne peut les atteindre.

La page Réglages développeur utilise le bloc de clé API personnalisé de Yayaw, pas l'UI générique de clés API Better Auth, car les permissions de plan de contrôle (control plane) sont gérées côté serveur et doivent être écrites par le flux d'émission/réparation de permissions de Yayaw.

Tableau de bord test

/dashboard/test est une vue d'ensemble de diagnostics internes, protégée comme ses pages par feature-flag:manage. Elle liste, une ligne chacun :

  • les routes du tableau de bord, et les routes publiques, protégées et avec permission de la configuration de navigation ;

  • les indicateurs de fonctionnalité gérés présents en base parmi ceux déclarés dans le code, les indicateurs stockés activés et les indicateurs gérés exposés au navigateur ;

  • les ressources et actions d'autorisation et leurs paires ressource/action.

Elle donne ensuite les liens vers les pages de test que la personne peut ouvrir (Routes et Autorisations), tirées de la même navigation filtrée par les permissions que les pages de section des écrans.

Ce n'est pas un écran : elle compte ce que le build déclare, et les indicateurs stockés, pour quelques détenteurs de feature-flag:manage, et personne ne la personnaliserait. C'est un petit composant serveur (src/blocks/dashboard/test/overview/).

Règles de navigation

La navigation devrait utiliser la configuration partagée route/navigation et les helpers @/i18n/navigation. Évitez next/link brut et la concaténation de chemins brute dans les composants de navigation du tableau de bord, sauf raison spécifique au niveau route.

Règles:

  • les libellés de barre latérale et les entrées du menu de commande doivent se résoudre depuis le même modèle de routes

  • les fils d'Ariane devraient refléter de vrais parents navigables

  • les routes masquées ne devraient pas apparaître dans la barre latérale ou le menu de commande

  • les éléments parents devraient avoir une vraie page, pas seulement des enfants expansibles

  • la visibilité des routes devrait correspondre aux gates authz/ressource

Autorisation

L'accès aux routes du tableau de bord utilise le service d'autorisation Yayaw au-dessus de la session Better Auth et de l'appartenance d'organisation.

Contrats importants:

  • les vérifications de routes sont côté serveur

  • les actions DB générées exécutent toujours can(...)

  • la visibilité de navigation ne remplace pas l'autorisation serveur

  • la gestion des utilisateurs plateforme et l'impersonation utilisent user:manage

  • Yayaw ne traite jamais Better Auth user.role comme autorisation applicative

  • les routes de test sous /dashboard/test sont uniquement des diagnostics

La page d'administration de l'autorisation vit à:

  • /dashboard/admin/authorization

Elle prend en charge l'inspection des groupes/rôles/policies, l'évaluation rapide, les vues de détail et les diagnostics orientés audit pour le modèle RBAC. C'est un écran global (voir Autorisation) : les chiffres des groupes, l'annuaire des groupes et l'évaluateur rapide, pour les détenteurs d'un group:list global ; la page de chaque groupe (groups/[groupId]) reste écrite dans le code.

Checklist de développement

Lors de l'ajout d'une page au tableau de bord:

  1. Ajoutez la route sous la bonne racine de section.

  2. Ajoutez ou mettez à jour les métadonnées/configuration de navigation de route.

  3. Assurez-vous que le tableau de bord de section parent y renvoie lorsqu'elle est visible.

  4. Ajoutez les vérifications d'accès côté serveur.

  5. Gardez la navigation visible à l'utilisateur avec la même intention authz/ressource.

  6. Ajoutez les traductions sous src/messages/default/dashboard.json et src/messages/fr/dashboard.json.

  7. Mettez à jour les docs anglaises pertinentes.

  8. Ajoutez des tests ciblés lorsque la route modifie la navigation, l'authz ou le comportement de view-model partagé du tableau de bord.

Validation

Vérifications utiles après des changements de navigation du tableau de bord:

bun run check
bunx tsc --noEmit
bun test src/lib/server/authz/contracts.test.ts
bun run build

Comportement des espaces de travail Table

Les tables du dashboard gardent leurs vues enregistrées, leurs favoris et leurs réglages pour l’utilisateur et l’organisation actifs. Les listes et les enregistrements de chaque modèle sont des écrans (ci-dessous) ; le catalogue de la documentation et le catalogue des modèles de données dynamiques partagent le même composant d’espace de travail. Les pages et la documentation conservent leurs éditeurs dédiés et proposent des formulaires groupés pour le référencement des pages ou la navigation documentaire. Les groupes d’autorisation permettent la sélection pour l’export, sans modification groupée. Les données dynamiques respectent les permissions du modèle et ses éditeurs inline explicitement activés.

La liste des pages est aussi un écran (voir Catalogue des pages) : sa table garde les colonnes, les files de travail, les vues enregistrées et les favoris de la liste, ouvre chaque page dans son éditeur, et propose la fenêtre de création, la publication après relecture, l'archivage, la suppression et le référencement d'une sélection à qui peut gérer les pages.

La liste des modèles d'e-mails est un écran global (voir Modèles d'e-mails transactionnels) : sa table garde les colonnes, les files de travail, les vues enregistrées et les favoris de la liste, ouvre chaque modèle dans son éditeur, et propose le formulaire de création ainsi que l'activation, la désactivation et la suppression d'une sélection à qui peut gérer les modèles, sans éditeur groupé Table.

Les listes des données et des modèles de données CMS sont des écrans de l'organisation (voir Modèles de données CMS) : leurs tables gardent les colonnes, les files de travail, les vues enregistrées et les favoris des listes, listent les modèles globaux et ceux de l'organisation active comme les listes, et proposent à qui peut modifier un modèle son formulaire (d'un clic, qui charge d'abord le dernier document du modèle ou de l'entrée), les formulaires de création, ainsi que la publication et l'archivage d'une sélection, sans modification inline ni groupée.

L'annuaire des groupes d'autorisation est aussi un écran global (voir Autorisation) : sa table garde les colonnes, les files, les vues enregistrées et les favoris de l'annuaire, ouvre la page de chaque groupe, et propose le formulaire de création et l'export d'une sélection, sans modification groupée.

Le catalogue des modèles de données dynamiques est un écran de l'organisation (voir Control Plane) : un panneau de préparation opérationnelle (ce qu'il faut corriger en premier parmi les modèles de la section d'administration, leurs comptes, leurs routes et surfaces runtime, et la préparation de la base cible) au-dessus de la table du catalogue, qui garde les colonnes, les vues enregistrées et les favoris que le catalogue gardait et liste les modèles globaux et ceux de l'organisation active, triés, cherchés et paginés en SQL plutôt que chargés entièrement. Qui peut créer des modèles reçoit le constructeur de modèle (un nouveau modèle, ou un nouveau brouillon d'un existant, dans un large formulaire), et chaque modèle que la personne peut gérer reçoit les actions de sa ligne : publier un brouillon prêt, consulter et ouvrir un déploiement, et archiver le modèle une fois confirmé. Un clic sur la ligne, Ouvrir et Consulter le déploiement ouvrent tous la page du modèle (/dashboard/admin/dynamic-data/<portée>/<modèle>) : sa définition (contrat, plan de déploiement, historique de révisions) au-dessus de son propre écran de modèle (voir Écrans des modèles).

Les registres approuvés forment aussi un écran global (voir Architecture) : leur table garde les colonnes, les files de travail, les vues enregistrées et les favoris de la liste, et propose à qui approuve les registres (registry-template:manage détenu globalement) le formulaire de création, le formulaire de modification d'un registre d'un clic sur sa ligne, et sa suppression, sans sélection ni modification groupée. La page synchronise les registres connus à chaque chargement.

Le catalogue de facturation est aussi un écran global (voir Produits de facturation) : ses chiffres ne comptent que des produits, jamais une somme de prix ; les limites de ses plans et sa table gardent les colonnes, les files de travail, les vues enregistrées et les favoris de la liste, et proposent le formulaire de modification d'un produit (prix, devise, en vente, ordre d'affichage), sans modification inline ou groupée.

La page des devis et signatures est un écran de l'organisation (voir Tableau de bord organisation) : sa table garde les colonnes, les files de travail, les vues enregistrées et les favoris de la liste des devis, liste tous les devis de l'organisation, et ouvre le panneau d'un devis d'un clic, sans sélection, modification ni action groupée.

La médiathèque est un écran (voir la page Médiathèque). Elle s’ouvre en Galerie et peut passer en Tableau ou en Arborescence. Un clic sur le visuel ouvre l’aperçu du média ; un clic sur la description ouvre sa fiche en lecture seule dans un panneau latéral. Les images et vidéos respectent le réglage Remplir ou Ajuster. Les tags natifs discrets se répartissent sur l’espace disponible, et la hauteur d’aperçu S/M/L est indépendante de la largeur des cartes. Les vues enregistrées conservent cette hauteur. La galerie conserve les aperçus spécialisés de l’application pour les polices, PDF et vidéos.

Les gestionnaires peuvent déplacer une sélection vers un dossier, dupliquer des fichiers ou les mettre à la corbeille pendant 30 jours. Les utilisateurs en lecture seule conservent l’aperçu, les informations et la sélection sans action de modification. La corbeille, une page à part (/dashboard/content/media/trash), permet la restauration, sans modification, duplication ni suppression répétée. Ctrl/Cmd+A sélectionne les résultats sur toutes les pages ; Ctrl/Cmd+D duplique les fichiers autorisés ; Ctrl/Cmd+Z restaure une suppression réversible. Les raccourcis ne remplacent pas la saisie dans les champs ni les commandes d’une fenêtre modale.

Tous les catalogues fixes activent explicitement les vues privées et partagées avec l’organisation. Le composant respecte une désactivation explicite de la sauvegarde ou du partage et désactive le partage dans un espace personnel. La langue active de l’application s’applique aussi aux dates, aux notifications des raccourcis et aux réglages des vues.

La vue favorite de chaque personne et son ordre des vues enregistrées (Déplacer à gauche et Déplacer à droite dans le menu de la vue, … pour les vues qui ne tiennent pas) sont conservés sur le serveur, par organisation et par table, et ne modifient jamais une vue partagée. La vue propre d’un écran, comme celle de la médiathèque, peut être une favorite.