diff --git a/95_a_capitaliser.md b/95_a_capitaliser.md index 8c0be0d..0995975 100644 --- a/95_a_capitaliser.md +++ b/95_a_capitaliser.md @@ -29,10 +29,6 @@ Ce fichier ne doit donc **jamais devenir une documentation permanente**. --- -_Aucune entrée pour le moment_ - ---- - # Format attendu Chaque proposition doit suivre ce format : @@ -83,6 +79,10 @@ Description courte, factuelle, orientée réutilisation. --- +_Aucune entrée pour le moment_ + +--- + # Rôle dans l'architecture ``` diff --git a/knowledge/backend/patterns/auth.md b/knowledge/backend/patterns/auth.md index e9b2f69..1c1b767 100644 --- a/knowledge/backend/patterns/auth.md +++ b/knowledge/backend/patterns/auth.md @@ -296,3 +296,49 @@ Le helper `requireRoleAccess` doit retourner : - [ ] 401 pour tout problème de token (absent, expiré, malformé) - [ ] 403 uniquement quand le token est valide mais le rôle insuffisant - [ ] Frontend redirige vers `/login` sur 401, affiche "accès refusé" sur 403 + +--- + + +## Pattern : Dernier admin actif non supprimable + auto-action admin encadrée + +- Objectif : préserver l'accès administratif global et éviter les auto-actions destructrices. +- Contexte : endpoints d'administration utilisateurs/rôles. +- Quand l'utiliser : toute action de suppression, désactivation, rétrogradation d'un compte admin. +- Quand l'éviter : jamais. + +### Règle +- Interdire toute action qui laisserait le système sans admin actif. +- Encadrer les auto-actions admin (self-disable, self-demote, self-delete) avec règles explicites. + +### Checklist +- Vérification atomique "reste au moins un admin actif". +- Codes d'erreur explicites (`LAST_ADMIN_LOCKOUT`, `SELF_ACTION_FORBIDDEN` ou équivalent). +- Test dédié pour chaque cas limite. + +- Validé le : 17-04-2026 +- Contexte technique : auth / RBAC admin — RL799_V2 + +--- + + +## Pattern : Distinguer audit best-effort et audit régalien + +- Objectif : expliciter quelles écritures d'audit sont non-bloquantes vs bloquantes. +- Contexte : endpoints sensibles avec journalisation. +- Quand l'utiliser : toute opération ayant une exigence de traçabilité. +- Quand l'éviter : jamais. + +### Règle +- Audit best-effort : ne bloque pas l'opération métier principale. +- Audit régalien/traçabilité critique : fait partie de la transaction logique et bloque en cas d'échec. + +### Checklist +- Classification explicite de chaque événement d'audit. +- Politique d'échec documentée par endpoint. +- Tests de comportement en cas de panne du canal d'audit. + +- Validé le : 17-04-2026 +- Contexte technique : auth / audit — RL799_V2 + +--- diff --git a/knowledge/backend/risques/auth.md b/knowledge/backend/risques/auth.md index 4c38886..0059991 100644 --- a/knowledge/backend/risques/auth.md +++ b/knowledge/backend/risques/auth.md @@ -330,3 +330,39 @@ it('retourne 403 si subscription inactive', async () => { - **Signal review** : import de `verifyToken` dans un fichier service (hors `authHelpers.ts`) - Contexte technique : auth / architecture — RL799_V2 08-04-2026 + +--- + + +## ACL unique pour ressource globale et sous-champ sensible + +### Risques +- Champs sensibles exposés à des rôles qui ne devraient accéder qu'à la vue agrégée. + +### Symptômes +- Endpoint fonctionnellement "autorisé" mais fuite de notes/valeurs sensibles en clair. + +### Bonnes pratiques / mitigations +- Séparer explicitement les règles d'accès : liste globale vs détails sensibles. +- Appliquer des guards dédiés au niveau du champ ou du sous-endpoint. + +- Contexte technique : auth / ACL granulaire — RL799_V2 13-04-2026 + +--- + + +## JWT valide mais utilisateur introuvable en base + +### Risques +- Retour `403` trompeur (authz) au lieu d'un `401` (auth invalide côté sujet). + +### Symptômes +- Frontend affiche "accès refusé" au lieu de forcer une ré-authentification. + +### Bonnes pratiques / mitigations +- Si le sujet JWT ne résout plus un user actif : répondre `401`. +- Déclencher invalidation de session côté client. + +- Contexte technique : auth / cycle de vie compte — RL799_V2 17-04-2026 + +--- \ No newline at end of file diff --git a/knowledge/backend/risques/general.md b/knowledge/backend/risques/general.md index c90e299..91eb6e2 100644 --- a/knowledge/backend/risques/general.md +++ b/knowledge/backend/risques/general.md @@ -748,3 +748,123 @@ try { - Les checks applicatifs seuls ne suffisent pas sous concurrence - Contexte technique : Prisma / contraintes — RL799_V2 08-04-2026 + +--- + + +## Docker Compose — migrations exécutées après redémarrage applicatif + +### Risques +- Fenêtre de non-compatibilité entre code déployé et schéma DB. +- Crash silencieux sur colonnes/contraintes nouvellement requises. + +### Symptômes +- Redéploiement "vert" puis erreurs runtime immédiates sur accès DB. + +### Bonnes pratiques / mitigations +- Appliquer les migrations avant le redémarrage applicatif. +- Séquence recommandée : `docker compose build` -> `docker compose run --rm api prisma migrate deploy` -> `docker compose up -d`. + +- Contexte technique : Docker Compose / déploiement — RL799_V2 08-04-2026 + +--- + + +## Scripts shell — sourcing global de `.env` + +### Risques +- `set -a; source .env` exporte tous les secrets à tous les sous-processus. + +### Symptômes +- Secrets inutiles visibles dans l'environnement de commandes annexes (docker/curl/webhooks). + +### Bonnes pratiques / mitigations +- Charger uniquement les variables nécessaires (`grep`/`cut` ou équivalent). +- Réserver `source .env` aux scripts qui ont réellement besoin de tout le contexte. + +- Contexte technique : shell / secrets env — RL799_V2 08-04-2026 + +--- + + +## Docker Compose — services auxiliaires sans `healthcheck` + +### Risques +- Faux positifs de disponibilité d'un service qui démarre mais n'est pas prêt. + +### Symptômes +- Service "up" mais non exploitable (port bloqué, DB locale corrompue, etc.). + +### Bonnes pratiques / mitigations +- Ajouter un `healthcheck` homogène sur tous les services critiques et auxiliaires. +- Aligner la politique de readiness/liveness sur l'ensemble du compose. + +- Contexte technique : Docker Compose / observabilité service — RL799_V2 08-04-2026 + +--- + + +## Configuration fail-open d'un bind réseau en production + +### Risques +- Dashboard/service exposé publiquement si variable d'environnement manquante. + +### Symptômes +- Service censé rester localement accessible exposé sur `0.0.0.0`. + +### Bonnes pratiques / mitigations +- Forcer le bind sûr dans l'override de production (`127.0.0.1` ou réseau privé explicite). +- Ne pas dépendre d'un `.env` optionnel pour une contrainte de sécurité. + +- Contexte technique : Docker Compose / sécurité réseau — RL799_V2 08-04-2026 + +--- + + +## Logging de previews payload/HTML contenant des PII + +### Risques +- Fuite de données personnelles via logs applicatifs agrégés. + +### Symptômes +- Logs de debug contenant noms/emails/contenu message en clair. + +### Bonnes pratiques / mitigations +- Ne jamais logger le body complet d'un message métier en prod. +- Journaliser uniquement des métadonnées minimales (id, statut, taille, hash tronqué). + +- Contexte technique : logs / conformité — RL799_V2 15-04-2026 + +--- + + +## Base64 invalide — `Buffer.from(..., 'base64')` ne lève pas d'exception + +### Risques +- Configuration/signature invalide traitée comme erreur avaleuse (401 répétés sans cause claire). + +### Symptômes +- Échec systématique de vérification HMAC sans signal de configuration corrompue. + +### Bonnes pratiques / mitigations +- Valider explicitement le format/base64 attendu avant dérivation HMAC. +- Retourner un signal d'erreur opérationnelle explicite (config invalide) côté logs internes. + +- Contexte technique : crypto / intégration webhook — RL799_V2 15-04-2026 + +--- + + +## Dates localisées sans `timeZone` explicite + +### Risques +- Rendu de date divergent entre dev/CI/prod selon TZ machine. + +### Symptômes +- Même ISO affiché sur des jours différents selon environnement. + +### Bonnes pratiques / mitigations +- Toujours passer `timeZone` dans `toLocaleDateString`/`Intl.DateTimeFormat` pour les sorties métier. +- Définir une timezone métier unique pour les communications utilisateur. + +- Contexte technique : dates / formatage serveur — RL799_V2 15-04-2026 diff --git a/knowledge/backend/risques/prisma.md b/knowledge/backend/risques/prisma.md index e2bbf31..b002284 100644 --- a/knowledge/backend/risques/prisma.md +++ b/knowledge/backend/risques/prisma.md @@ -407,3 +407,37 @@ Checklist minimale après `prisma migrate resolve --applied` : - **Signal review** : `catch {` ou `catch (e) {` sans vérification de `e.code` dans un repository Prisma - Contexte technique : Prisma / error handling — RL799_V2 08-04-2026 + +--- + + +## Filtre de lecture appliqué mais filtre d'écriture oublié + +### Risques +- Mutation (`updateMany`/`deleteMany`) affectant des lignes hors périmètre autorisé. + +### Symptômes +- Le listing semble correct, mais les opérations d'écriture touchent des données invisibles pour l'utilisateur. + +### Bonnes pratiques / mitigations +- Aligner strictement les prédicats lecture/écriture sur les mêmes dimensions métier (ex: grade, tenant, statut). +- Factoriser le filtre dans un helper partagé côté service/repository. + +- Contexte technique : Prisma / filtres métier — RL799_V2 09-04-2026 + +--- + + +## `deleteMany` partiel sans clé de partition métier + +### Risques +- Suppression transversale de données d'autres partitions (ex: grade, segment, scope logique). + +### Symptômes +- Comportement correct tant que le frontend envoie un payload complet, puis corruption lors d'un refactor/concurrence. + +### Bonnes pratiques / mitigations +- Inclure toutes les dimensions de partition dans les clauses `deleteMany`/`updateMany`. +- Ajouter des tests ciblés sur payload partiel et concurrence logique. + +- Contexte technique : Prisma / partition logique — RL799_V2 09-04-2026 diff --git a/knowledge/frontend/patterns/navigation.md b/knowledge/frontend/patterns/navigation.md index 8526cdf..27cad8e 100644 --- a/knowledge/frontend/patterns/navigation.md +++ b/knowledge/frontend/patterns/navigation.md @@ -176,3 +176,25 @@ return ( ); ``` +--- + + +## Pattern : Overlay/drawer accessible avec focus trap + +### Synthèse +Teleport + backdrop + Escape + scroll-lock n'est pas suffisant : le focus trap est obligatoire. + +### Analyse +Sans focus trap, le clavier peut sortir de la sheet/panel et casser l'ordre de navigation. + +### Validation +- Validé le : 09-04-2026 +- Contexte technique : Vue 3 / accessibilité overlays — RL799_V2 +- Applicable à tout drawer/sheet/modal custom en SPA (desktop et mobile clavier). + +### Implémentation +- Capturer le focus à l'ouverture (premier élément interactif). +- Boucler Tab/Shift+Tab dans le conteneur. +- Restaurer le focus au trigger à la fermeture. + +--- diff --git a/knowledge/frontend/patterns/state.md b/knowledge/frontend/patterns/state.md index 962ba73..3636489 100644 --- a/knowledge/frontend/patterns/state.md +++ b/knowledge/frontend/patterns/state.md @@ -187,3 +187,24 @@ Ne jamais : - [ ] Garde-fou explicite contre les doubles actions - [ ] Refresh explicite après mutation réussie - [ ] Tests sur succès, erreur et action concurrente + +--- + + +## Pattern : Hydratation auth asynchrone avec états explicites + +### Synthèse +Lors d'un passage sync -> async au boot, exposer un statut d'hydratation explicite (`idle`/`hydrating`/`ready`). + +### Analyse +Sans état transitoire formel, les guards lisent des valeurs incomplètes et déclenchent des redirections erronées. + +### Validation +- Validé le : 18-04-2026 +- Contexte technique : Vue 3 / Pinia / boot async — RL799_V2 +- Applicable à toute initialisation critique : session, feature flags, restore état persistant. + +### Implémentation (exemple minimal) +- Store : `hydrateStatus` + promesse partagée en cours pour les appels concurrents. +- Guards : `await hydrate()` avant toute décision d'accès. +- UI : fallback de rendu tant que l'hydratation n'est pas `ready`. diff --git a/knowledge/frontend/patterns/tests.md b/knowledge/frontend/patterns/tests.md index 1d359b8..c86f630 100644 --- a/knowledge/frontend/patterns/tests.md +++ b/knowledge/frontend/patterns/tests.md @@ -132,3 +132,24 @@ expect(aBeforeB).toBe(true); ### Risque associé `boundingBox().y` vérifie la position visuelle rendue par CSS, pas l'ordre dans le DOM. De plus `boundingBox()` retourne `null` pour les éléments hors viewport → crash non déterministe. + +--- + + +## Pattern : Sélecteurs E2E stables orientés intention + +### Synthèse +Les tests E2E doivent cibler des sélecteurs stables (`data-testid`, role/name) et non la structure CSS/XPath. + +### Analyse +Les classes et la structure DOM changent fréquemment sans régression fonctionnelle. + +### Validation +- Validé le : 14-04-2026 +- Contexte technique : Playwright / sélecteurs robustes — RL799_V2 +- Ce pattern s'applique à Playwright/Cypress sur toutes les UIs réactives. + +### Implémentation +- Préférer `data-testid` paramétré par identifiant métier stable. +- Éviter `locator.first()` si l'ordre peut muter. +- Isoler les tests mutateurs avec stratégie de remise à l'état (snapshot/restore). diff --git a/knowledge/frontend/risques/auth.md b/knowledge/frontend/risques/auth.md index bea133c..7056558 100644 --- a/knowledge/frontend/risques/auth.md +++ b/knowledge/frontend/risques/auth.md @@ -135,3 +135,39 @@ if (user === null || user.role !== 'ADMIN') return ; - **Signal review** : `Authorization: Bearer` dans les tests alors que le code production utilise `credentials: 'include'` - Contexte technique : Vue 3 / auth migration — RL799_V2 08-04-2026 + +--- + + +## Migration vers `/auth/me` — fallback localStorage réintroduit une confiance client + +### Risques +- Un blocage réseau ciblé peut forcer un fallback sur des données locales falsifiables. + +### Symptômes +- Rôle/grade consommés depuis localStorage en cas d'erreur endpoint d'autorité. + +### Bonnes pratiques / mitigations +- Si l'endpoint d'autorité échoue, conserver un état non authentifié/dégradé, pas un fallback de privilèges. +- Garder localStorage strictement pour métadonnées UX non sensibles. + +- Contexte technique : auth frontend / source d'autorité — RL799_V2 18-04-2026 + +--- + + +## Source de vérité auth déplacée vers store, appels directs service laissés en place + +### Risques +- Guards/router lisent un état store non synchronisé après login/logout. + +### Symptômes +- Login réussi puis redirection immédiate vers `/login`. + +### Bonnes pratiques / mitigations +- Interdire les appels directs au service auth depuis les pages une fois le store source de vérité. +- Centraliser login/logout/change-password via actions store. + +- Contexte technique : auth frontend / Pinia store — RL799_V2 18-04-2026 + +--- diff --git a/knowledge/frontend/risques/design-tokens.md b/knowledge/frontend/risques/design-tokens.md index b4df2e0..618023b 100644 --- a/knowledge/frontend/risques/design-tokens.md +++ b/knowledge/frontend/risques/design-tokens.md @@ -119,3 +119,39 @@ Erreurs courantes : - Activer `@typescript-eslint/no-unused-vars` et `no-unused-imports` dans la config ESLint mobile - Lors de toute migration de tokens, auditer les imports de chaque composant UI concerné - Contexte technique : React Native / ESLint — app-alexandrie, 25-03-2026 + +--- + + +## Fallbacks de tokens incohérents avec le thème actif + +### Risques +- Composants lisibles en dev mais illisibles quand une variable manque en production. + +### Symptômes +- Fallback hardcodé light-theme dans un contexte dark-theme. + +### Bonnes pratiques / mitigations +- Utiliser des fallbacks cohérents avec le thème de référence. +- Préférer un fallback vers alias sémantique existant plutôt qu'une couleur brute. + +- Contexte technique : design tokens / thèmes CSS — RL799_V2 10-04-2026 + +--- + + +## Variables CSS utilisées mais non définies (fallback silencieux) + +### Risques +- Dérive invisible du design system (les fallbacks masquent les oublis de token). + +### Symptômes +- L'UI semble correcte mais contourne les tokens sur une part significative des règles. + +### Bonnes pratiques / mitigations +- Auditer régulièrement : variables utilisées moins variables définies. +- Traiter chaque variable non définie comme dette explicite. + +- Contexte technique : design tokens / audit CSS vars — RL799_V2 17-04-2026 + +--- diff --git a/knowledge/frontend/risques/general.md b/knowledge/frontend/risques/general.md index d7d0fb8..821d667 100644 --- a/knowledge/frontend/risques/general.md +++ b/knowledge/frontend/risques/general.md @@ -248,3 +248,74 @@ Poser `role="menu"` / `role="menuitem"` implique obligatoirement : - **Signal review** : tout `.catch(() => {})` ou `catch { /* ignore */ }` mérite au minimum un log ou un feedback visuel - Contexte technique : frontend / actions async — RL799_V2 07-04-2026 + +--- + + +## Monorepo ESM — shim runtime `.js` désynchronisé de l'index TypeScript + +### Risques +- Le typecheck passe mais le runtime navigateur casse (`named export not found`). + +### Symptômes +- Erreur Vite/browser sur export absent alors que `index.ts` est correct. + +### Bonnes pratiques / mitigations +- Si un shim `.js` est maintenu, imposer une mise à jour miroir à chaque nouvel export. +- Ajouter un test/guard de cohérence exports TS vs JS shim. + +- Contexte technique : monorepo / ESM shim runtime — RL799_V2 15-04-2026 + +--- + + +## ESLint flat config TypeScript sans `tsconfigRootDir` + +### Risques +- Erreurs de parsing massives en IDE/monorepo selon CWD d'exécution. + +### Symptômes +- `No TsConfigRootDir` / `Cannot read tsconfig.json` alors que le build TS passe. + +### Bonnes pratiques / mitigations +- Toujours définir `tsconfigRootDir: import.meta.dirname` quand `parserOptions.project` est utilisé. +- Redémarrer le serveur ESLint après correction. + +- Contexte technique : tooling / ESLint flat config — RL799_V2 17-04-2026 + +--- + + +## PWA + auth cookie httpOnly — stratégie de cache non maîtrisée + +### Risques +- Réponses sensibles servies depuis cache offline. +- Comportement d'auth incohérent entre réseau/cached. + +### Symptômes +- Session/app state divergents après activation SW ou reprise réseau. + +### Bonnes pratiques / mitigations +- Exclure explicitement les routes authentifiées sensibles du cache persistant. +- Définir une stratégie stricte par classe de route (auth, API privée, assets publics). + +- Contexte technique : PWA / service worker / auth cookie — RL799_V2 18-04-2026 + +--- + + +## PWA install prompt — capture tardive de `beforeinstallprompt` + +### Risques +- Événement perdu au cold boot, prompt jamais proposé. + +### Symptômes +- Implémentation correcte en apparence mais aucun déclenchement sur Android. + +### Bonnes pratiques / mitigations +- Installer l'écouteur le plus tôt possible dans le cycle d'initialisation. +- Ne pas baser la détection iOS uniquement sur l'UA (cas iPad en mode desktop). + +- Contexte technique : PWA / install prompt — RL799_V2 18-04-2026 + +--- diff --git a/knowledge/frontend/risques/navigation.md b/knowledge/frontend/risques/navigation.md index ea75bcd..92d3336 100644 --- a/knowledge/frontend/risques/navigation.md +++ b/knowledge/frontend/risques/navigation.md @@ -277,3 +277,22 @@ const routes = [ - **Signal review** : guards de navigation couverts uniquement par des tests `includes()` sans test comportemental - Contexte technique : Vue 3 / Vue Router 4 / node:test — RL799_V2 08-04-2026 + +--- + + +## `router.push` construit avec segment potentiellement `undefined` + +### Risques +- Navigation vers `/.../undefined`, historique pollué et diagnostics trompeurs. + +### Symptômes +- Warnings Vue Router en cascade au boot ou à la reprise d'événements globaux. + +### Bonnes pratiques / mitigations +- Valider les segments dynamiques avant `push/replace`. +- Préférer la navigation nommée avec params validés plutôt que concaténation de string. + +- Contexte technique : Vue Router / navigation dynamique — RL799_V2 15-04-2026 + +--- diff --git a/knowledge/product/patterns/general.md b/knowledge/product/patterns/general.md index 3934992..a7147f7 100644 --- a/knowledge/product/patterns/general.md +++ b/knowledge/product/patterns/general.md @@ -70,3 +70,46 @@ Plutôt que d'ouvrir un domaine `achievements` ou `analytics` dès la V1 : - [ ] Compteurs calculés depuis la source de vérité existante - [ ] Catalogue d'objectifs en code (pas en DB) - [ ] Interface de sortie stable même si les sources de données évoluent + +--- + + +## Pattern : Produit à cercle restreint — canal primaire externe conservé + +- Objectif : calibrer la stratégie produit pour des communautés fermées/invitation-only. +- Contexte : app interne/associative où email/SMS précède l'usage applicatif. +- Quand l'utiliser : produit B2B/intranet/communauté restreinte. +- Quand l'éviter : produits mass-market où l'app doit devenir canal primaire. + +### Description +Pour une app invitation-only (B2B/interne/associatif), email/SMS reste le canal d'information principal et fiable ; l'app le complète sans le remplacer. + +### Checklist +- KPI de succès alignés sur l'usage réel (consultation/confirmation), pas sur le remplacement du canal primaire. +- Roadmap UX alignée avec une adoption progressive et non exclusive. + +- Validé le : 18-04-2026 +- Contexte produit : PWA / adoption progressive — RL799_V2 + +--- + + +## Pattern : Trigger UX basé sur signal métier serveur (`loginCount`) + +- Objectif : déclencher les prompts UX via un signal robuste et auditable. +- Contexte : prompts d'installation PWA, notifications, feedback. +- Quand l'utiliser : tout trigger UX nécessitant un critère de maturité utilisateur. +- Quand l'éviter : prompts one-shot purement contextuels de page. + +### Description +Pour des prompts significatifs (install PWA, notifications, feedback), privilégier un déclencheur serveur métier (ex: `loginCount`) plutôt que des heuristiques client fragiles (timer/scroll/pages vues). + +### Checklist +- Signal incrémenté côté serveur sur événement métier confirmé. +- Règle de déclenchement unique partagée entre plateformes. +- Possibilité de désactiver/ajuster sans dépendre du contexte runtime navigateur. + +- Validé le : 18-04-2026 +- Contexte produit : PWA / triggers engagement — RL799_V2 + +--- diff --git a/knowledge/workflow/risques/story-tracking.md b/knowledge/workflow/risques/story-tracking.md index 42e4dba..c32dd39 100644 --- a/knowledge/workflow/risques/story-tracking.md +++ b/knowledge/workflow/risques/story-tracking.md @@ -251,3 +251,22 @@ source_projects: [app-alexandrie, app-template-resto, RL799_V2] - **Règle** : toute métrique dans les Completion Notes doit être vérifiable par une commande simple - Contexte technique : BMAD / workflow agent — RL799_V2 08-04-2026 + +--- + + +## Story impose une convention absente du code projet + +### Risques +- Divergence silencieuse entre specification story et implémentation réelle. + +### Symptômes +- Le dev adapte une convention introuvable sans la tracer dans la story/notes de review. + +### Bonnes pratiques / mitigations +- Si une convention prescrite n'existe pas dans le repo, documenter explicitement l'adaptation retenue. +- Mettre à jour la story (Change Log / Completion Notes) avec justification et impact. + +- Contexte technique : BMAD / traçabilité adaptation story — RL799_V2 15-04-2026 + +---