Aller au contenu

Vue d'ensemble de l'architecture

ikloze suit une architecture en couches stricte. Chaque couche a une seule responsabilité, et franchir une frontière est un point bloquant en revue.

┌─────────────────────────────────────────────────────────────┐
│  web/<module>/        HTTP uniquement                         │
│  Contrôleurs NestJS, DTO/Swagger, gardes, filtres            │
│  → parse l'entrée → appelle le service → renvoie le résultat  │
└───────────────┬─────────────────────────────────────────────┘
                │ appelle
┌───────────────▼─────────────────────────────────────────────┐
│  app/<module>/        Logique métier (TypeScript sans framework) │
│  Services use-case : autorise → valide → logique → persiste   │
└───────────────┬─────────────────────────────────────────────┘
        ┌───────┴───────────────────┐
        │ utilise                    │ persiste via
┌───────▼──────────┐      ┌──────────▼──────────────────────────┐
│  domain/         │      │  database/sequelize/                │
│  Entités + erreurs│      │  Modèles, migrations, accesseurs    │
│  fromRecord, pur  │      │  typés, associations                │
└──────────────────┘      └─────────────────────────────────────┘
        │ I/O externe via
┌───────▼─────────────────────────────────────────────────────┐
│  adapters/   SMTP, paiement, stockage S3, géocodage, IA…      │
└─────────────────────────────────────────────────────────────┘

Responsabilité de chaque couche

web/ — HTTP uniquement

Contrôleurs, DTO/schémas Swagger, gardes, filtres. Aucune logique métier, aucun appel Sequelize. Le corps d'un contrôleur doit être : parser l'entrée → appeler le service → renvoyer le résultat.

app/<module>/ — Logique métier

Classes TypeScript sans framework. Les services autorisent, valident, mutent, persistent. Aucun type HTTP (Request, Response, codes de statut), aucun décorateur Swagger. Les services accèdent à la base directement via les accesseurs typés de database/sequelize/models.ts.

domain/ — Données pures

Classes d'entités (données + mapper statique fromRecord) et classes d'erreurs de domaine. Aucune I/O, aucun Sequelize, aucun Nest.

database/sequelize/ — Persistance

Modèles, migrations, accesseurs et associations. Voir Accès aux données.

adapters/ — I/O externe

SMTP, géocodage HTTP, passerelles de paiement, stockage S3, IA. Encapsulés pour que les services dépendent d'une interface, pas du SDK du fournisseur.

Signal d'alerte

Si vous importez depuis @nestjs/* dans app/ ou domain/, ou si vous appelez un accesseur Sequelize dans web/ — arrêtez : vous êtes dans la mauvaise couche.

La recette de service en 6 étapes

Tout service use-case dans app/<module>/ suit le même squelette :

  1. Autoriser — vérifier user.hasPerm(...) (voir Permissions).
  2. Valider — parser l'entrée avec un schéma Zod.
  3. Logique — appliquer les règles métier.
  4. Persister — écrire via les accesseurs typés, en transaction si plusieurs écritures.
  5. Journaliser — historique / effets de bord.
  6. Retourner — une entité de domaine, jamais un record Sequelize brut.

Signature des méthodes de service

Les méthodes publiques de service prennent user: User en dernier paramètre positionnel, nommé user (jamais actor/caller).

La compétence ikloze-define-service du dépôt détaille cette recette (schémas Zod, scoping workspace anti-énumération, politique d'erreurs, transactions, effets de bord).

Conventions transverses