mirror of
https://github.com/MaksTinyWorkshop/_Assistant_Lead_Tech
synced 2026-04-06 21:41:42 +02:00
ajout patterns
This commit is contained in:
@@ -8,7 +8,7 @@ Ce fichier contient **uniquement** des patterns back-end :
|
||||
|
||||
Objectif : éviter de réinventer la roue et réduire le temps de debug.
|
||||
|
||||
Dernière mise à jour : 10-03-2026
|
||||
Dernière mise à jour : 12-03-2026
|
||||
|
||||
---
|
||||
|
||||
@@ -31,6 +31,7 @@ Dernière mise à jour : 10-03-2026
|
||||
- [Sémantique explicite `Trial` vs `Paid` dans Subscription](#pattern-subscription-trial-vs-paid)
|
||||
- [Restauration d’achats Stripe en 3 étapes](#pattern-restauration-achats-stripe)
|
||||
- [Mapping explicite de `P2002` Prisma sur update de champ unique](#pattern-prisma-p2002-update-unique)
|
||||
- [Autorisation interne minimale sans RBAC complet](#pattern-autorisation-interne-minimale)
|
||||
|
||||
---
|
||||
|
||||
@@ -88,6 +89,7 @@ Si ce n’est pas confirmé comme fonctionnel et utile, **ça n’a rien à fair
|
||||
---
|
||||
|
||||
<a id="pattern-format-derreur-api-standardise"></a>
|
||||
|
||||
## Pattern : Format d’erreur API standardisé
|
||||
|
||||
- Objectif : fournir des erreurs prévisibles, exploitables et cohérentes pour tous les clients.
|
||||
@@ -125,6 +127,7 @@ Si ce n’est pas confirmé comme fonctionnel et utile, **ça n’a rien à fair
|
||||
---
|
||||
|
||||
<a id="pattern-middleware-correlation-requestid-traceid"></a>
|
||||
|
||||
## Pattern : Middleware de corrélation (requestId / traceId)
|
||||
|
||||
- Objectif : relier chaque requête aux logs et erreurs associées.
|
||||
@@ -156,6 +159,7 @@ Si ce n’est pas confirmé comme fonctionnel et utile, **ça n’a rien à fair
|
||||
---
|
||||
|
||||
<a id="pattern-idempotency-key-operations-sensibles"></a>
|
||||
|
||||
## Pattern : Idempotency key pour opérations sensibles
|
||||
|
||||
- Objectif : empêcher les doublons lors de retries ou timeouts.
|
||||
@@ -187,6 +191,7 @@ Si ce n’est pas confirmé comme fonctionnel et utile, **ça n’a rien à fair
|
||||
---
|
||||
|
||||
<a id="pattern-pagination-robuste-cursor-based"></a>
|
||||
|
||||
## Pattern : Pagination robuste (cursor-based) pour les listings
|
||||
|
||||
- Objectif : fournir des listings stables et performants sans incohérences entre pages.
|
||||
@@ -222,6 +227,7 @@ Si ce n’est pas confirmé comme fonctionnel et utile, **ça n’a rien à fair
|
||||
---
|
||||
|
||||
<a id="pattern-execution-asynchrone-taches-longues"></a>
|
||||
|
||||
## Pattern : Exécution asynchrone des tâches longues (queue + outbox light)
|
||||
|
||||
- Objectif : sortir les opérations longues ou fragiles du chemin request/response.
|
||||
@@ -259,6 +265,7 @@ Si ce n’est pas confirmé comme fonctionnel et utile, **ça n’a rien à fair
|
||||
---
|
||||
|
||||
<a id="pattern-soft-delete-archivage-explicite"></a>
|
||||
|
||||
## Pattern : Soft delete et archivage explicite
|
||||
|
||||
- Objectif : permettre la suppression logique sans perte immédiate de données.
|
||||
@@ -295,6 +302,7 @@ Si ce n’est pas confirmé comme fonctionnel et utile, **ça n’a rien à fair
|
||||
---
|
||||
|
||||
<a id="pattern-webhooks-sortants-robustes-idempotents"></a>
|
||||
|
||||
## Pattern : Webhooks sortants robustes et idempotents
|
||||
|
||||
- Objectif : garantir des intégrations fiables avec des systèmes externes.
|
||||
@@ -332,6 +340,7 @@ Si ce n’est pas confirmé comme fonctionnel et utile, **ça n’a rien à fair
|
||||
---
|
||||
|
||||
<a id="pattern-contracts-first-zod-infer-no-dto"></a>
|
||||
|
||||
## Pattern : Contracts-First / Zod-Infer / No-DTO (monorepo TypeScript fullstack)
|
||||
|
||||
- Objectif : avoir une seule source de vérité pour les contrats d’interface entre API et client, sans redéfinition manuelle de types.
|
||||
@@ -407,6 +416,7 @@ packages/contracts/src/
|
||||
---
|
||||
|
||||
<a id="pattern-guard-global-nestjs"></a>
|
||||
|
||||
## Pattern : Guard global NestJS — ordre d’enregistrement et décorateurs de bypass
|
||||
|
||||
- Objectif : protéger tous les endpoints par défaut, avec un mécanisme explicite pour les exceptions.
|
||||
@@ -455,6 +465,7 @@ if (skip) return true;
|
||||
---
|
||||
|
||||
<a id="pattern-provider-strategy-integrations-tierces"></a>
|
||||
|
||||
## Pattern : Provider-Strategy pour intégrations tierces — périmètre complet
|
||||
|
||||
- Objectif : isoler intégralement la logique propre à un prestataire (Stripe, Brevo, Firebase…) derrière une interface stable, pour éviter la contamination du domaine par le SDK tiers.
|
||||
@@ -502,6 +513,7 @@ async handleWebhook(rawBody: Buffer, signature: string): Promise<void> {
|
||||
---
|
||||
|
||||
<a id=”pattern-stripe-subscription-metadata”></a>
|
||||
|
||||
## Pattern : Stripe — metadata sur `subscription_data`, pas sur la Session
|
||||
|
||||
- Objectif : garantir que `userId` (ou tout identifiant métier) soit accessible dans les events `customer.subscription.*`, pas seulement dans `checkout.session.completed`.
|
||||
@@ -515,14 +527,15 @@ async handleWebhook(rawBody: Buffer, signature: string): Promise<void> {
|
||||
|
||||
```typescript
|
||||
stripe.checkout.sessions.create({
|
||||
metadata: { userId }, // pour checkout.session.completed
|
||||
subscription_data: { metadata: { userId } }, // pour customer.subscription.*
|
||||
metadata: { userId }, // pour checkout.session.completed
|
||||
subscription_data: { metadata: { userId } }, // pour customer.subscription.*
|
||||
});
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
<a id=”pattern-webhook-parsing-unique”></a>
|
||||
|
||||
## Pattern : Webhooks entrants — parsing unique (single `constructWebhookEvent`)
|
||||
|
||||
- Objectif : appeler `constructWebhookEvent` une seule fois par requête, puis router vers des extracteurs purs.
|
||||
@@ -545,6 +558,7 @@ handlePackWebhookEvent(event): PackWebhookResult | null
|
||||
---
|
||||
|
||||
<a id=”pattern-contracts-error-codes”></a>
|
||||
|
||||
## Pattern : Contracts-First — error codes comme contrat obligatoire
|
||||
|
||||
- Objectif : maintenir les codes d’erreur API dans `packages/contracts` pour éviter les clients stringly-typed.
|
||||
@@ -563,6 +577,7 @@ handlePackWebhookEvent(event): PackWebhookResult | null
|
||||
---
|
||||
|
||||
<a id="pattern-redis-health-cache-court"></a>
|
||||
|
||||
## Pattern : RedisHealthService avec cache interne court
|
||||
|
||||
- Objectif : exposer un état Redis exploitable par les guards globaux sans ping Redis à chaque requête.
|
||||
@@ -596,6 +611,7 @@ handlePackWebhookEvent(event): PackWebhookResult | null
|
||||
---
|
||||
|
||||
<a id="pattern-subscription-trial-vs-paid"></a>
|
||||
|
||||
## Pattern : Sémantique explicite `Trial` vs `Paid` dans Subscription
|
||||
|
||||
- Objectif : aligner le modèle métier, les guards et les jeux de tests sur une définition unique de l’abonnement payant actif.
|
||||
@@ -627,6 +643,7 @@ handlePackWebhookEvent(event): PackWebhookResult | null
|
||||
---
|
||||
|
||||
<a id="pattern-restauration-achats-stripe"></a>
|
||||
|
||||
## Pattern : restauration d’achats Stripe en 3 étapes
|
||||
|
||||
- Objectif : reconstruire un état local cohérent à partir de Stripe sans dépendre d’une hypothèse fragile.
|
||||
@@ -658,6 +675,7 @@ handlePackWebhookEvent(event): PackWebhookResult | null
|
||||
---
|
||||
|
||||
<a id="pattern-prisma-p2002-update-unique"></a>
|
||||
|
||||
## Pattern : mapping explicite de `P2002` Prisma sur update de champ unique
|
||||
|
||||
- Objectif : transformer un conflit d’unicité prévisible en erreur métier exploitable plutôt qu’en 500 opaque.
|
||||
@@ -688,6 +706,43 @@ handlePackWebhookEvent(event): PackWebhookResult | null
|
||||
|
||||
---
|
||||
|
||||
<a id="pattern-autorisation-interne-minimale"></a>
|
||||
|
||||
## Pattern : Autorisation interne minimale sans RBAC complet
|
||||
|
||||
- Objectif : sécuriser une capacité interne sensible sans ouvrir trop tôt un chantier RBAC complet.
|
||||
- Contexte : application avec peu de rôles, besoin ponctuel d’une capacité admin ou opérateur clairement identifiée.
|
||||
- Quand l’utiliser : quand une story métier demande un pouvoir interne limité mais réel.
|
||||
- Quand l’éviter : si les permissions deviennent nombreuses, hiérarchiques ou contextuelles.
|
||||
- Avantage :
|
||||
- sécurisation rapide et lisible d’une capacité sensible
|
||||
- source de vérité backend explicite
|
||||
- chemin d’évolution propre vers un RBAC plus complet
|
||||
- Limites / vigilance :
|
||||
- ne pas laisser proliférer des rôles ad hoc non gouvernés
|
||||
- ne remplace pas un vrai modèle de permissions si le domaine grossit
|
||||
- Validé le : 10-03-2026
|
||||
- Contexte technique : NestJS / auth par session ou JWT / API métier interne
|
||||
|
||||
### Implémentation (exemple minimal)
|
||||
|
||||
```txt
|
||||
- introduire un enum de rôle minimal côté backend (ex. USER | ADMIN)
|
||||
- propager ce rôle dans la session ou le token d’auth
|
||||
- créer un décorateur + guard dédiés pour la capacité sensible
|
||||
- interdire les booléens front, emails hardcodés ou `if` dispersés dans les contrôleurs
|
||||
```
|
||||
|
||||
### Checklist
|
||||
|
||||
- Le rôle vit dans la source de vérité backend
|
||||
- Le rôle est propagé dans le mécanisme d’auth existant
|
||||
- Les endpoints sensibles passent par un guard dédié
|
||||
- Aucun contrôle d’accès critique n’est piloté par le front
|
||||
- Le passage à RBAC reste possible sans casser le contrat existant
|
||||
|
||||
---
|
||||
|
||||
### Notes importantes
|
||||
|
||||
- On préfère 5 patterns solides à 50 “bons conseils”.
|
||||
|
||||
Reference in New Issue
Block a user