Décisions d'Architecture (ADR)
Ce fichier documente les choix structurants du projet. Chaque décision inclut le contexte, la décision, les raisons, et les alternatives rejetées.
ADR-001 : FastAPI pour le backend
Date : 2026-02-21 Statut : Accepté
Contexte
Nous avions besoin d'un framework Python pour exposer une API REST consommée par 3 frontends Next.js différents (Discover, Career, Admin).
Décision
Nous utilisons FastAPI.
Pourquoi
- Validation automatique des données via Pydantic
- Génération automatique d'OpenAPI/Swagger (documentation API intégré)
- Performances élevées grâce à l'async natif pour les opérations I/O
- Léger et minimal comparé à Django
Alternatives rejetées
- Django REST Framework : Trop de overhead pour un projet API-only. Utile si nous avions besoin du panneau admin Django.
- Flask : Trop minimal, configuration manuelle pour la validation et la documentation.
Conséquences
- Nous gérons nous-mêmes certaines choses que Django fait automatiquement (admin panel).
- La documentation API est générée automatiquement → gain de temps.
ADR-002 : PostgreSQL via Supabase
Date : 2026-02-21 Statut : Accepté
Contexte
Nous avions besoin d'une base de données relationnelle et d'un système d'authentification.
Décision
Nous utilisons PostgreSQL via Supabase, avec une approche hybride.
Pourquoi
- Supabase Auth : Gère directement email/password, reset password, sessions utilisateurs
- PostgreSQL : Base de données relationnelle pour les données métier via SQLAlchemy
- Row Level Security (RLS) : Sécurité des données au niveau base
Alternatives rejetées
- Firebase : Verrouillage fournisseur, moins de contrôle sur les données.
- Auth0 : Coût additionnel, nous préférons garder le contrôle.
Conséquences
- Deux clients Supabase : normal (respecte RLS) et admin (bypass RLS pour opérations système).
ADR-003 : Migrations SQL brutes → Adoption d'Alembic
Date : 2026-02-21 Statut : Mis à jour
Contexte
Nous avons démarré avec des fichiers SQL bruts pour les migrations, ce qui fonctionnait pour un projet de petite taille. Cependant, avec 46+ tables et plusieurs développeurs, la traçabilité entre environnements est devenue un risque réel : désynchronisation entre staging et production, difficulté à reproduire un état exact, et risque d'erreur humaine sur les scripts manuels.
Décision
Nous adoptons Alembic avec une approche par migration initiale vide + stamp head :
- Première migration vide (
61e524cfcce2_initial_state.py) avecupgrade()etdowngrade()vides alembic stamp headmarque cette migration comme appliquée sans exécuter de SQL- Les futures modifications de schéma créent des migrations versionnées
- Les modèles SQLAlchemy sont créés progressivement, uniquement pour les tables nécessitant une migration — le projet utilisant le client Supabase natif directement
Pourquoi
- Traçabilité :
alembic currentmontre l'état exact de chaque environnement - Rollback possible : chaque migration peut être annulée
- Onboarding simplifié :
alembic upgrade headsuffit pour mettre à jour la DB - Cohérence avec les bonnes pratiques : approche standard dans l'écosystème Python/SQLAlchemy
Alternatives rejetées
- Garder les SQL bruts : Risque de désynchronisation entre environnements, pas de rollback facile.
- Créer 46 modèles ORM immédiatement : Over-engineering inutile — nous n'utilisons pas SQLAlchemy ORM pour les opérations de données, seulement pour les migrations.
Conséquences
alembic currentaffiche l'état exact de chaque environnement- Chaque modification de schéma = fichier de migration versionné dans
alembic/versions/ - Limite connue : sans ORM complet,
autogeneratenécessite de créer le modèle SQLAlchemy pour la table concernée avant de générer la migration - Le client Supabase natif reste utilisé pour toutes les opérations de données — Alembic gère uniquement les migrations de schéma
ADR-004 : Redis pour cache uniquement
Date : 2026-02-21 Statut : Accepté
Contexte
Nous avions besoin d'améliorer les performances des requêtes fréquentes.
Décision
Nous utilisons Redis uniquement pour le cache de performance, pas pour la gestion de sessions.
Pourquoi
- Amélioration ~40x sur les endpoints dashboard (15-20s → 20-50ms)
- JWT est stateless, pas besoin de sessions serveur
- TTL configurable (3-10 min selon endpoint)
- Fallback automatique vers Supabase si Redis unavailable
Alternatives rejetées
- Sessions serveur : Incompatible avec notre architecture stateless JWT.
- Memcached : Moins de fonctionnalités que Redis.
Conséquences
- Pas de révocation de tokens possible (voir lacunes dans security-policy.md).
ADR-005 : Multi-repo (5 repos)
Date : 2026-02-21 Statut : Accepté
Contexte
Nous avons 3 applications frontend différentes + 1 backend + 1 doc.
Décision
Nous utilisons 5 repos GitHub séparés.
Pourquoi
- Déploiement indépendant de chaque application
- Équipes peuvent travailler séparément sur chaque frontend
- CI/CD simplifié par projet
Alternatives rejetées
- Monorepo : Plus complexe à configurer, deployments plus longs.
Conséquences
- Nous devons maintenir des versions cohérentes entre les repos.
- Le code partagé est dupliqué ou extrait dans des packages.
ADR-006 : Vercel (frontends) + Dokploy (backend)
Date : 2026-02-21 Statut : Accepté
Contexte
Nous avions besoin d'hébergement pour nos applications. Nous voulions une solution flexible et économique pour le backend.
Décision
- Vercel : Pour les 3 frontends Next.js (Discover, Career, Admin)
- Dokploy : Pour le backend FastAPI (sur notre propre VPS)
- Cloudflare Pages : Pour la documentation Docusaurus
Pourquoi
- Vercel : Optimisé pour Next.js, preview PRs automatiques, CDN global
- Dokploy : Alternative auto-hébergée à Coolify/Railway, déployé sur notre VPS, contrôle total sur l'infrastructure
- Cloudflare Pages : Hébergement gratuit pour sites statiques, protection via Cloudflare Access pour limiter l'accès
Alternatives rejetées
- Railway : Solution cloud pratique mais nous avons privilégié l'auto-hébergement pour réduire les coûts.
- Heroku : Plus cher, moins flexible.
- Coolify : Alternative intéressante, Dokploy choisi pour sa simplicité.
Conséquences
- Trois cibles d'hébergement distinctes : Vercel (frontends), Dokploy (backend), Cloudflare Pages (docs).
- Nous gérons nous-mêmes le maintien à jour du serveur Dokploy (sécurité, mises à jour).
- La documentation est protégée par Cloudflare Access — accès restreint aux utilisateurs autorisés.