You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
🐛 [BUG] - Le backfill des rôles système ignore les projets partiellement peuplés #2819
Toute instance où la migration v9.26+ a déjà été déployée et où des projets ont un jeu de rôles partiel.
La migration resserre l'anti-join au niveau rôle (name + position + oidcGroup + permissions) au lieu du niveau projet
Un projet sans aucun rôle reçoit toujours les rôles système (comportement actuel préservé)
Un projet avec un jeu de rôles partiel reçoit exactement les rôles manquants, les lignes existantes inchangées
La migration est idempotente (ré-exécution = no-op)
La migration a été validée sur une base vierge (prisma migrate deploy sur la chaîne complète)
Comportement observé
La migration 20260907170000_backfill_project_roles (les deux arbres apps/server et apps/server-nestjs) utilise un anti-join par projet : WHERE NOT EXISTS (SELECT 1 FROM "ProjectRole" existing WHERE existing."projectId" = p."id"). Un projet reçoit les 4 rôles uniquement s'il n'a AUCUN rôle.
Un projet ayant au moins un rôle (même un seul rôle personnalisé créé manuellement) ne reçoit jamais les rôles système manquants : la condition existing."projectId" = p."id" est vraie dès la première ligne. Le seeding TS (generateProjectCreateInput) garantit les 5 rôles sur tout nouveau projet, mais les projets legacy partiellement peuplés restent incomplets après le backfill.
Le correctif resserre l'anti-join au niveau rôle (name + position + oidcGroup + permissions) : chaque rôle système manquant est inséré individuellement, les lignes existantes quelles qu'elles soient restent intactes.
Étapes de reproduction
Créer un projet puis supprimer une seule ligne ProjectRole (DELETE FROM "ProjectRole" WHERE id = <un seul rôle système>)
Exécuter prisma migrate deploy sur la chaîne complète
SELECT r.name FROM "ProjectRole" r JOIN "Project" p ON p.id = r."projectId" WHERE p.slug = '<slug>' ORDER BY r.position — le rôle supprimé n'est jamais réinséré
Activity