Sécurité
- JWT : un JWT_SECRET d'exemple ou trop court est ignoré au profit d'un
secret aléatoire conservé en base (avant, la valeur publique de
docker-compose.yml permettait de forger un jeton admin).
- Le compte est relu en base à chaque requête : désactivation, changement
de rôle et réinitialisation du mot de passe prennent effet immédiatement.
- Connexion : 10 échecs max par e-mail / 15 min, temps constant que l'e-mail
existe ou non, mot de passe admin retiré des logs.
- Validation des entrées (ids, dates, mois, longueurs, e-mail) : 400 au
lieu de 500. Un admin ne peut plus se désactiver ni se rétrograder.
- Mots de passe : 8 caractères minimum ; changement en libre-service.
- Export : nom de fichier conforme RFC 5987 (un nom de société avec « — »
faisait planter l'export).
- esc() échappe aussi les guillemets (injection d'attributs HTML).
- En-têtes CSP / X-Frame-Options / nosniff (Nginx + API), API et Postgres
publiés sur 127.0.0.1 seulement, image backend non-root via npm ci.
Optimisations
- Export : une requête pour tout le mois au lieu d'une par cadre.
- Saisie groupée : un seul INSERT (unnest), doublons dédupliqués.
- Dates renvoyées en chaînes (plus de décalage d'un jour selon le TZ).
- Planning : chaque clic met à jour l'affichage localement au lieu de
recharger le mois ; les réponses de mois périmées sont ignorées.
- Recherche Utilisateurs / Plannings filtrée localement (plus une requête
par touche) ; statuts des sociétés chargés en parallèle.
UI/UX
- Mobile : toutes les destinations dans la barre basse (Sociétés et Ma
saisie étaient inaccessibles à l'admin) ; tableaux affichés en cartes
(les boutons d'action étaient hors écran).
- Boutons désactivés pendant l'envoi, focus et Échap dans les dialogues,
retour à l'écran de connexion quand la session est révoquée, erreurs
d'export affichées au lieu d'un fichier JSON téléchargé, actions
destructives signalées, confirmation avant désactivation.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01D5Bdayziw6tybgqETZoNSt
- Renomme les services (db/backend/frontend -> presencia-db/
presencia-backend/presencia-frontend) : sur le réseau externe partagé
nginx_default, un nom générique comme "db" peut entrer en collision
avec un service du même nom dans une autre stack, et Docker résout
alors le nom en round-robin vers le mauvais container. Confirmé en
prod : le bootstrap réussissait puis une requête suivante échouait
avec une erreur d'authentification alors que le mot de passe était
correct.
- nginx résout maintenant le backend dynamiquement (resolver + variable)
au lieu de résoudre une seule fois au démarrage, pour survivre à une
recréation du container backend.
- Ajoute express-async-errors : une erreur dans une route async (ex. la
requête pg qui échoue) était une rejection non gérée et faisait
planter tout le process Node au lieu de renvoyer une 500 propre.
Testé en local : avant le fix, une erreur d'auth pg tuait le process ;
après le fix, il répond 500 et reste opérationnel.
Le précédent remplacement du mot de passe Postgres n'avait touché que
la clé POSTGRES_PASSWORD du service db, laissant le backend avec
l'ancien mot de passe sous la clé PGPASSWORD — cause de l'échec
d'authentification systématique malgré la réinitialisation du volume.
Permet à un reverse proxy nginx déjà en place (sur le réseau
nginx_default) d'atteindre les containers de Presencia directement.
Le réseau doit déjà exister sur l'hôte avant docker compose up.
Supprime le fichier .env racine : ports, mot de passe Postgres,
JWT_SECRET et identifiants admin sont désormais définis en dur dans
docker-compose.yml, à éditer avant le premier démarrage.
Application complète : API Node/Express + PostgreSQL, frontend HTML/JS
mono-page, et déploiement Docker sur ports non standards (8781/4790/6543).
- Cadres : calendrier mensuel, saisie de présence par demi-journée
(présent/absent/congé/RTT), validation de fin de mois qui verrouille
leurs propres saisies.
- Admin : gestion des sociétés et utilisateurs (rattachement société <->
cadre), consultation de tous les plannings, validation d'une société
entière une fois tous ses cadres validés, réouverture en cas de
correction, export PDF et Excel par société/mois.