Résout définitivement « Role sbc_app does not exist » : l'initialisation
ne dépend plus de docker-entrypoint-initdb.d ni de bind mounts du dépôt
(fragiles selon le mode de déploiement Portainer).
- Nouveau bootstrap idempotent exécuté par l'app à chaque démarrage avec
le superuser (PG_SUPERUSER_PASSWORD) : création de la base et du rôle
sbc_app si absents, réalignement du mot de passe, schéma en
CREATE ... IF NOT EXISTS, données de démo si la base est vide, grants
- Schéma et seed embarqués dans l'image (server/src/sql), seed par
recherche de noms (indépendant des séquences)
- Compose réduit à deux services (db + app), suppression de db-sync et
du montage ./db/init ; répertoire db/ retiré
Vérifié : volume totalement vierge auto-initialisé, redémarrage sans
re-seed, changement d'APP_DB_PASSWORD auto-réparé, 34 tests e2e verts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
Affiche host/port/db/user à la connexion et un message explicite en cas
d'échec d'authentification persistant, pour identifier immédiatement une
stack déployée avec une ancienne version du compose.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
Sur le réseau partagé nginx_default, le nom « db » peut résoudre vers le
PostgreSQL d'une autre stack : l'application se connectait au mauvais
serveur (password authentication failed pour sbc_app alors que db-sync,
lui, visait le bon). Reproduit et vérifié avec un conteneur leurre.
- La base obtient l'alias réseau unique « sbc-db » ; l'app et db-sync
s'y connectent via ce nom, jamais via « db »
- DATABASE_URL remplacé par PGHOST/PGPORT/PGDATABASE/PGUSER/PGPASSWORD :
insensible aux caractères spéciaux du mot de passe et aux ambiguïtés
de résolution DNS
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
Plus aucune référence au port 3000 : l'application écoute sur 8321 dans
le conteneur (PORT, EXPOSE, healthcheck, mapping 8321:8321, upstream
nginx sbc-app:8321, proxy de dev Vite, README).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
- docker-compose : valeurs par défaut pour POSTGRES_PASSWORD,
APP_DB_PASSWORD et les mots de passe initiaux (admin SlucAdmin2026!,
membres SlucMembre2026!) — surchargeables par variables d'environnement
- JWT_SECRET devient optionnel : l'application génère un secret aléatoire
au démarrage s'il est absent (les sessions expirent alors au redémarrage
du conteneur), aucun secret de signature n'est committé
- .env.example et README mis à jour (démarrage clé en main, consignes de
surcharge pour la production)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o
- Un seul conteneur applicatif : Express sert l'API, le frontend React
compilé (fallback SPA, cache immutable sur /assets) et les images
/uploads (nosniff + CSP default-src 'none')
- En-têtes de sécurité (CSP stricte, X-Frame-Options DENY, etc.) portés
de nginx vers helmet, compression gzip ajoutée
- Application exposée sur le port 8321 (APP_PORT), PostgreSQL sur
127.0.0.1:56432 (DB_PORT, loopback uniquement pour l'admin locale)
- TRUST_PROXY pilote la confiance aux en-têtes X-Forwarded-* (désactivé
par défaut hors reverse-proxy)
- Dockerfile multi-étages unique à la racine (build React → deps → image
finale non-root, fs en lecture seule)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Fkg15RCxNgUys4ru73He2o