Aller au contenu

Procédure de câblage — @kanmaber/auth-backend et auth-frontend dans jobPipeline

Contexte

jobPipeline installe les packages partagés @kanmaber/auth-backend et @kanmaber/auth-frontend (via tarball local, versions figées) et le schéma Prisma fusionné existe déjà en base. Mais AuthModule n'était appelé nulle part dans le code applicatif — seul un script de smoke test l'instanciait isolément. Cette note documente la procédure de câblage réel (routes HTTP fonctionnelles, pas juste un assemblage DI) suivie et validée le 2026-07-03.

Contenu

Incompatibilité architecturale de départ

jobPipeline a sa propre architecture DI/HTTP, incompatible telle quelle avec ce qu'attend le package :

  1. Deux DIContainer différents du même nom — celui de jobPipeline (container.set/get, registerModule(name, module)) n'est pas celui attendu par AuthModule (DIContainer.getInstance(config), registre de modules à priorités, obtenirPrismaClient()).
  2. GestionnaireModulaire de jobPipeline construit son IHttpContext en castant directement req/res Express, sans les méthodes de confort de l'interface — la quasi-totalité des handlers du package n'en ont pas besoin, sauf RevoquerTousTokensHandler (context.request.getHeader('Authorization'), absente sur un Request Express brut).
  3. Format de JWT différentauthMiddleware.ts de jobPipeline lit payload.sub/payload.id et traite role comme une chaîne ; le package émet payload.idUtilisateur et role comme un objet { idRole, nom, permissions[] }. Un token du package n'est pas interprété correctement par le middleware existant tel quel.

Décision (Option A retenue) : plutôt que corriger le bridge IHttpContext et le format de token du système existant, utiliser le propre bridge du package (AuthModuleController, déjà complet) avec un routeur Express dédié et un container DI dédié, en parallèle du système de jobPipeline, sans le modifier. Suit le pattern documenté dans shared/architecture/guide-architecture-ddd.

Étapes de câblage

  1. Variables d'environnement dans BackEnd/.env : JWT_ACCESS_SECRET, JWT_REFRESH_SECRET, JWT_ACCESS_EXPIRES, JWT_REFRESH_EXPIRES, TOTP_ENCRYPTION_KEY (32 bytes hex), BCRYPT_ROUNDS, SMTP_*, EMAIL_FROM(_NAME), APP_NAME, APP_URL. JWT_SECRET (utilisé par l'authMiddleware existant) reste séparé — deux systèmes de tokens coexistent. Redis optionnel (fallback mémoire automatique).

  2. Container DI dédié + montage des routes — nouveau fichier BackEnd/src/shared/infrastructure/config/AuthPackageConfiguration.ts : instancie AuthDIContainer.getInstance({ enableLogging: true }), crée AuthModule, l'initialise, puis construit AuthModuleController avec le mapping complet des ~36 controllers (auth, twoFactor, password, sessions, tokens, profile, security). Dans app.ts, un Router Express dédié itère sur authModuleRoutes.routes et monte chaque route sur authModuleRoutes.prefix (/api/auth) — en parallèle du GestionnaireModulaire existant, sans le modifier.

Point d'attention : authModuleRoutes marque certaines routes isPublic, mais AuthModuleController ne vérifie pas ce flag lui-même (chaque handler vérifie l'auth via context.getUserId(), qui lève une erreur si non authentifié) — fonctionnellement correct mais moins strict qu'un vrai middleware amont ; à durcir plus tard si besoin.

  1. Middleware d'authentification — décision encore ouverte : dupliquer authMiddleware.ts en authPackageMiddleware.ts (lisant payload.idUtilisateur et role comme objet) seulement si les routes métier de jobPipeline (candidatures, CV...) doivent un jour vérifier un utilisateur connecté via les tokens de ce package. Ne pas l'appliquer sur /api/auth/* (le package gère sa propre validation).

  2. Seed d'un ProfilUtilisateurUtilisateur.profilId est obligatoire. Un script prisma/seeds/seed.ts (référencé par db:seed mais absent) upserte un profil par défaut. Version finale simplifiée : upsert simple par code: 'UTILISATEUR' (id auto-généré) — voir jobPipeline/debug/lecons-cablage-auth-package pour l'historique complet du bug de résolution du profil par défaut (idRole hardcodé côté package, corrigé depuis par un lookup dynamique par code).

  3. Test end-to-end réel — seule preuve valable que le câblage fonctionne : curl sur /api/auth/register puis /api/auth/connexion, pas seulement le typecheck ou le smoke test d'assemblage DI. Réalisé avec succès le 2026-07-03 : inscription, connexion, JWT émis avec le format attendu (idUtilisateur + role: {idRole, nom, permissions[]}). Écarts non documentés à l'origine découverts à cette occasion : Zod exige aussi confirmationMotDePasse et accepteCGU: true ; mot de passe min. 12 caractères avec maj/min/chiffre/spécial ; connexion bloquée tant que emailVerifie n'est pas true en base.

  4. Frontend (non fait) — FrontEnd/src/main.tsx n'existe pas encore (point d'entrée React <BrowserRouter> à créer). Écarts de peer dependencies à résoudre avant install propre : @hookform/resolvers (jobPipeline ^5.0.1 vs package ^3.3.0) et lucide-react (jobPipeline 0.488.0 vs package ^1.7.0, API différente). Ensuite configureAuthModule({ apiBaseUrl, security: { loginUrl, defaultRedirectAfterLogin } }) et montage des pages exportées (LoginPage, RegisterPage...).

Décision / Conclusion

  • Option A confirmée et implémentée : DI + routeur Express dédiés, système existant de jobPipeline non modifié.
  • Câblage backend fonctionnel de bout en bout (inscription + connexion réelles testées), après correction du bug de profil par défaut côté package (voir jobPipeline/debug/lecons-cablage-auth-package).
  • Restent ouverts : décision middleware dupliqué, alignement peer deps frontend, scaffolding main.tsx, test navigateur réel, résolution SMTP (rejet 550 SPAM constaté lors du test — cf. veille-financement/configuration-email-deliverabilite pour un cas similaire déjà traité).

À faire

  • Trancher le middleware d'auth dupliqué (étape 3) selon les besoins des futures routes métier.
  • Aligner @hookform/resolvers/lucide-react, créer main.tsx, appeler configureAuthModule(), tester la connexion réelle dans le navigateur.
  • Résoudre le problème de délivrabilité SMTP (rejet 550).

Liens connexes