Architecture Logicielle
Ce document décrit l'architecture technique de Bindr avec les technologies, versions et librairies principales.
Vue d'ensemble
Architecture: Client-serveur avec API REST
- Backend: Java Spring Boot (API REST)
- Frontend: Next.js (React, web uniquement)
- Base de données: SQLite (V1) → PostgreSQL (V2)
- Stockage: Infomaniak Object Storage (S3-compatible) + Cloudflare CDN
- Paiements: Stripe Connect
Compatibilité & points de vigilance
Cette section liste les incompatibilités confirmées et contraintes importantes entre les librairies choisies. À consulter avant tout ajout de dépendance ou montée de version.
Backend (Java / Spring Boot)
| Sévérité | Librairie | Problème | Action |
|---|---|---|---|
| CRITIQUE | iText7 8.0.3 |
Licence AGPLv3 — usage commercial sans licence payante interdit. Chaque PDF généré doit mentionner iText (producer line). | Acheter une licence commerciale avant mise en production, ou remplacer par Apache PDFBox (Apache 2.0). |
| HAUTE | Lombok + MapStruct 1.5.5 |
L'ordre des annotation processors doit être explicite : Lombok → lombok-mapstruct-binding → MapStruct. Sans cela, compilation échoue (Unknown property in result type). |
Configurer <annotationProcessorPaths> dans le plugin Maven compiler (voir snippet ci-dessous). |
| HAUTE | jjwt 0.12.5 |
API cassante vs 0.11.x : parseClaimsJws() → parseSignedClaims(), setSigningKey() → verifyWith(). Les 3 modules sont requis : jjwt-api, jjwt-impl, jjwt-jackson. |
S'assurer que les 3 artifacts sont déclarés avec la même version 0.12.5. |
| MOYENNE | Sentry 7.6.0 |
Utiliser sentry-spring-boot-starter-jakarta (et non la variante javax). La capture automatique des erreurs HTTP peut impacter le quota Sentry. |
Vérifier le nom de l'artifact ; ajuster sentry.traces-sample-rate si nécessaire. |
| BASSE | Flyway 10.x |
Architecture modulaire : les drivers PostgreSQL/MySQL ne sont plus dans flyway-core. SQLite reste dans le core. |
Ajouter flyway-database-postgresql si migration vers PostgreSQL. |
<!-- Configuration Maven requise pour Lombok + MapStruct -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<annotationProcessorPaths>
<path><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></path>
<path><groupId>org.projectlombok</groupId><artifactId>lombok-mapstruct-binding</artifactId><version>0.2.0</version></path>
<path><groupId>org.mapstruct</groupId><artifactId>mapstruct-processor</artifactId></path>
</annotationProcessorPaths>
</configuration>
</plugin>
Frontend (Next.js)
| Sévérité | Librairie | Problème | Action |
|---|---|---|---|
| HAUTE | @stripe/react-stripe-js |
Les éléments Stripe nécessitent un contexte Elements wrappant la page de checkout. Incompatible avec React Server Components. |
Marquer la page checkout avec "use client". |
| MOYENNE | next/image |
En développement local, l'optimisation d'image peut ralentir le chargement. En production sur Infomaniak Jelastic, configurer le domaine S3 dans next.config.js. |
Ajouter le domaine Infomaniak Object Storage dans images.remotePatterns. |
| BASSE | react-dropzone |
Sur iOS Safari, le drag & drop n'est pas supporté. L'input <input type="file"> natif est utilisé en fallback automatique. |
Prévoir un bouton "Choisir des fichiers" visible sur mobile. |
Backend - API REST
Technologies principales
| Technologie | Version | Description |
|---|---|---|
| Java | 21 LTS | Langage principal |
| Spring Boot | 3.3.x | Framework application |
| Spring Data JPA | Inclus | ORM et repositories |
| Spring Security | Inclus | Authentification & autorisation |
| Spring Validation | Inclus | Validation des données |
Base de données
| Technologie | Version | Usage |
|---|---|---|
| SQLite | 3.45+ | V1 (développement, MVP) |
| PostgreSQL | 16.x | V2 (production, scalabilité) |
| Flyway | 10.x | Migrations de schéma |
Librairies essentielles
Authentification & Sécurité
Problématique : Les utilisateurs (organisateurs, photographes) doivent pouvoir s'authentifier de manière sécurisée sans maintenir de session serveur. Les mots de passe stockés en base ne doivent jamais être lisibles en clair, même en cas de fuite.
<!-- JWT : génère et valide des tokens d'authentification stateless.
Chaque requête API porte son propre token, sans état côté serveur. -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt-api</artifactId>
<version>0.12.5</version>
</dependency>
<!-- BCrypt : hache les mots de passe avec un salt aléatoire.
Résistant aux attaques par dictionnaire et rainbow tables. -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
</dependency>
Stockage et traitement d'images
Problématique : Chaque photo uploadée doit être déclinée en plusieurs variantes (thumbnail, medium, watermarked) pour servir le bon format selon le contexte (galerie, lightbox, achat). Les fichiers originaux haute résolution doivent être stockés séparément et accessibles uniquement après achat. Les métadonnées EXIF (date, GPS) sont utiles pour organiser et filtrer les photos.
<!-- AWS S3 SDK : upload, téléchargement et génération de liens signés
temporaires (30 jours) pour les fichiers achetés. -->
<dependency>
<groupId>software.amazon.awssdk</groupId>
<artifactId>s3</artifactId>
<version>2.25.x</version>
</dependency>
<!-- Thumbnailator : resize fluide avec API chaînée, watermark natif.
Génère les variantes thumbnail/medium/watermarked à l'upload. -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.20</version>
</dependency>
<!-- TwelveMonkeys ImageIO : étend le support de formats de Java.
Ajoute la lecture/écriture WebP et AVIF via le mécanisme ImageIO standard,
utilisé de manière transparente par Thumbnailator. -->
<dependency>
<groupId>com.twelvemonkeys.imageio</groupId>
<artifactId>imageio-webp</artifactId>
<version>3.12.0</version>
</dependency>
<!-- metadata-extractor : lit les données EXIF embarquées dans les fichiers
JPEG/HEIC (date, heure, coordonnées GPS, modèle d'appareil). -->
<dependency>
<groupId>com.drewnoakes</groupId>
<artifactId>metadata-extractor</artifactId>
<version>2.19.0</version>
</dependency>
Paiements
Problématique : L'application doit encaisser les paiements clients et redistribuer une partie aux organisateurs, sans gérer directement les coordonnées bancaires. Stripe Connect permet de créer des flux de paiement multi-parties conformes PCI-DSS.
<!-- Stripe SDK : intégration complète PaymentIntent, webhooks,
Stripe Connect pour les paiements vers les organisateurs. -->
<dependency>
<groupId>com.stripe</groupId>
<artifactId>stripe-java</artifactId>
<version>25.x</version>
</dependency>
Processing asynchrone
Problématique : Le traitement des photos (resize, watermark, extraction EXIF) peut prendre plusieurs secondes par image. Bloquer la requête HTTP d'upload le temps du traitement dégraderait fortement l'expérience utilisateur, surtout lors d'uploads en masse.
<!-- Quartz : planificateur de jobs pour le processing asynchrone
des photos et les tâches récurrentes (nettoyage, rapports). -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-quartz</artifactId>
</dependency>
Problématique : Plusieurs événements déclenchent des emails automatiques : confirmation de commande, accès photographe, lien de téléchargement. Ces emails doivent être rendus en HTML avec des données dynamiques (nom, montant, lien signé).
<!-- JavaMail : envoi d'emails SMTP depuis Spring Boot. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- Thymeleaf : moteur de templates HTML pour les emails transactionnels.
Permet d'injecter des variables (nom, commande, lien) dans des templates. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
Génération PDF
Problématique : Chaque commande payée doit générer une facture PDF conforme (numéro, TVA, coordonnées). Les organisateurs ont besoin d'attestations fiscales annuelles téléchargeables.
<!-- iText 7 : génération programmatique de PDFs (factures, attestations).
Supporte la mise en page, les tableaux, les logos et les signatures. -->
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itext7-core</artifactId>
<version>8.0.3</version>
</dependency>
Validation & Utilities
Problématique : Le code Java Spring Boot génère beaucoup de boilerplate (getters, setters, constructeurs, equals/hashCode). Le mapping entre entités JPA et DTOs (objets exposés à l'API) est répétitif et source d'erreurs.
<!-- Lombok : génère automatiquement le boilerplate Java à la compilation
(@Data, @Builder, @RequiredArgsConstructor, etc.). -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<scope>provided</scope>
</dependency>
<!-- MapStruct : génère le code de mapping entité ↔ DTO à la compilation.
Plus performant et sûr que le mapping manuel ou par réflexion. -->
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.5.5.Final</version>
</dependency>
<!-- Apache Commons Lang : utilitaires courants (manipulation de chaînes,
dates, tableaux) qui complètent la bibliothèque standard Java. -->
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
</dependency>
Tests
Problématique : L'API REST doit être testée à tous les niveaux : unitaire (services, logique métier), intégration (comportement des endpoints), et contrats (format des réponses JSON). Les dépendances externes (base de données, S3) doivent être mockées pour isoler les tests.
<!-- Spring Boot Test : contexte de test intégré, assertions, mocks
et support JUnit 5 pour les tests unitaires et d'intégration. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!-- Mockito : crée des doublures (mocks) des dépendances pour tester
une classe en isolation, sans ses collaborateurs réels. -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<!-- REST Assured : DSL fluide pour tester les endpoints HTTP.
Permet de valider le status code, les headers et le corps JSON. -->
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
<version>5.4.0</version>
<scope>test</scope>
</dependency>
Monitoring & Logs
Problématique : En production, il faut pouvoir détecter les anomalies (erreurs, lenteurs) avant que les utilisateurs ne les signalent, et diagnostiquer rapidement les incidents. Les métriques métier (uploads, ventes) doivent aussi être visibles.
<!-- Actuator : expose des endpoints HTTP de santé (/health, /metrics)
pour les checks de l'infrastructure et le monitoring. -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- Sentry : capture et remonte les exceptions en production en temps réel,
avec contexte (stack trace, utilisateur, requête). -->
<dependency>
<groupId>io.sentry</groupId>
<artifactId>sentry-spring-boot-starter</artifactId>
<version>7.6.0</version>
</dependency>
Frontend - Next.js
Technologies principales
| Technologie | Version | Description |
|---|---|---|
| Next.js | 15.x | Framework React (App Router) |
| React | 19.x | Bibliothèque UI |
| TypeScript | 5.x | Typage statique |
| Tailwind CSS | 4.x | Styling utilitaire |
Plateformes cibles
- Web (responsive, mobile-first) : application web accessible depuis tous navigateurs
- Application mobile native : non prévu — la PWA (Progressive Web App) couvre les usages mobiles essentiels (V2 si besoin)
Librairies principales
Routing & State Management
Problématique : Next.js App Router gère le routing. L'état côté client (panier, session) doit être partagé entre composants sans prop drilling.
{
"dependencies": {
"next": "^15.0.0",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"zustand": "^5.0.0"
}
}
Réseau & API
Problématique : Le frontend consomme l'API REST Java via fetch natif (Next.js Server Components) ou axios côté client. Les tokens JWT sont stockés en cookie httpOnly pour la sécurité.
{
"dependencies": {
"axios": "^1.7.0",
"swr": "^2.2.0",
"jose": "^5.0.0"
}
}
UI Components
Problématique : La galerie photo est le cœur de l'UX — lazy loading, lightbox avec zoom/swipe, sélection multiple pour le panier, drag & drop pour l'upload.
{
"dependencies": {
"yet-another-react-lightbox": "^3.0.0",
"react-dropzone": "^14.0.0",
"react-hot-toast": "^2.4.0",
"lucide-react": "^0.400.0",
"clsx": "^2.0.0"
}
}
Formulaires & Validation
{
"dependencies": {
"react-hook-form": "^7.50.0",
"zod": "^3.22.0",
"@hookform/resolvers": "^3.3.0"
}
}
Paiement
{
"dependencies": {
"@stripe/stripe-js": "^4.0.0",
"@stripe/react-stripe-js": "^2.4.0"
}
}
Internationalisation
{
"dependencies": {
"next-intl": "^3.0.0"
}
}
Tests
{
"devDependencies": {
"jest": "^29.0.0",
"@testing-library/react": "^16.0.0",
"@testing-library/jest-dom": "^6.0.0",
"playwright": "^1.45.0"
}
}
Points d'attention architecturaux
Galerie photo — performance & panier
La galerie est un composant central et critique. Elle doit être :
- Responsive : expérience fluide sur desktop et mobile, avec layout adaptatif (grille masonry ou grid selon la taille d'écran)
- Performante : chargement lazy des images, thumbnails servis depuis le CDN, virtualisation de la liste pour les grandes galeries
- Compatible panier : sélection multi-photos directement depuis la galerie (overlay de sélection sur chaque photo), affichage du nombre d'éléments sélectionnés, ajout au panier sans quitter la galerie
- Formats optimisés : WebP/AVIF avec fallback JPEG, srcset adapté à la résolution de l'écran
Solutions techniques retenues (Next.js)
| Besoin | Package | Notes |
|---|---|---|
| Layout masonry/grid responsive | CSS Grid natif + Tailwind | Pas de dépendance externe |
| Lazy loading images | next/image (natif Next.js) |
Optimisation automatique WebP/AVIF |
| Lightbox / zoom / galerie swipeable | yet-another-react-lightbox |
Léger, accessible, swipe mobile |
| Sélection multiple (panier) | Zustand (Set<photoId>) |
State global léger |
{
"dependencies": {
"yet-another-react-lightbox": "^3.0.0",
"zustand": "^5.0.0"
}
}
CDN custom — gestion des assets photos
- Toutes les images doivent transiter par le CDN (aucun accès direct au bucket S3)
- 3 variantes générées à l'upload : thumbnail (300px), medium (1200px), full (original)
- Une variante watermarkée pour la prévisualisation publique (logo Bindr en surimpression)
- Les fichiers originaux (achetés) sont servis via liens signés temporaires (30 jours)
- Invalidation de cache CDN automatique si une photo est supprimée ou masquée
- Headers de cache agressifs sur les variantes statiques (
Cache-Control: max-age=31536000, immutable)
Solutions techniques retenues (Java / Backend)
Resize + watermark
| Librairie | Maven | Liens |
|---|---|---|
Thumbnailator — resize fluide, watermark natif |
net.coobird:thumbnailator:0.4.20 |
GitHub · Doc |
TwelveMonkeys ImageIO — support WebP/AVIF en lecture et écriture |
com.twelvemonkeys.imageio:imageio-webp:3.10.1 |
GitHub |
// Exemple : resize + watermark avec Thumbnailator
Thumbnails.of(inputStream)
.size(1200, 900)
.watermark(Positions.BOTTOM_RIGHT, watermarkImage, 0.5f)
.outputFormat("jpg")
.toOutputStream(out);
Stockage — Infomaniak Object Storage (compatible S3) + Cloudflare CDN
| Librairie | Maven | Liens |
|---|---|---|
AWS SDK v2 for Java |
software.amazon.awssdk:s3:2.25.x |
Doc officielle · GitHub |
L'Object Storage Infomaniak est compatible API S3 — le SDK AWS fonctionne tel quel avec un
endpointOverride. Cloudflare (free tier) est utilisé en frontal CDN pour la distribution mondiale des images.
// Lien signé 30 jours (Infomaniak Object Storage via SDK AWS S3)
S3Presigner presigner = S3Presigner.builder()
.endpointOverride(URI.create("https://s3.pub1.infomaniak.cloud"))
.region(Region.of("dc3-a"))
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(accessKey, secretKey)))
.build();
PresignedGetObjectRequest req = presigner.presignGetObject(r -> r
.signatureDuration(Duration.ofDays(30))
.getObjectRequest(g -> g.bucket("bindr-photos").key(key)));
// Invalidation cache Cloudflare après suppression (via API Cloudflare)
// POST https://api.cloudflare.com/client/v4/zones/{zone_id}/purge_cache
Upload de photos — mobile & desktop
- Multiplateforme : drag & drop sur desktop, sélection native galerie/caméra sur mobile
- Upload multipart : découpage en chunks pour les fichiers volumineux (résistance aux coupures réseau)
- Upload parallèle : plusieurs photos uploadées simultanément (limite configurable, ex: 5 en parallèle)
- Feedback en temps réel : barre de progression par photo + status global
- Validation côté client : type MIME (JPEG, PNG, HEIC), taille max avant envoi
- Retry automatique : en cas d'échec réseau, reprise de l'upload sans recommencer depuis zéro
- Processing asynchrone : l'upload retourne immédiatement, la génération des variantes se fait en arrière-plan (status
pending→processing→completed)
Solutions techniques retenues (Next.js)
| Besoin | Package | Notes |
|---|---|---|
| Drag & drop fichiers | react-dropzone |
Gère la sélection fichiers + drag & drop |
| HTTP client — upload multipart + progression | axios |
onUploadProgress natif |
{
"dependencies": {
"react-dropzone": "^14.0.0",
"axios": "^1.7.0"
}
}
// Upload avec progression par fichier (axios)
await axios.post('/api/upload', formData, {
onUploadProgress: (event) => {
const progress = Math.round((event.loaded * 100) / event.total!);
updateProgress(progress);
},
});
// Upload parallèle (5 max simultanément)
await Promise.all(files.map((f) => uploadFile(f)));
Processing asynchrone côté backend
| Besoin | Solution | Liens |
|---|---|---|
| V0 — processing simple post-upload | Spring @Async + ThreadPoolTaskExecutor |
natif Spring Boot |
| V1+ — jobs robustes avec retry | Spring Batch |
Doc |
Infrastructure & DevOps
Hébergement & Cloud
Fournisseur retenu : Infomaniak — hébergement souverain suisse
Choix motivé par la souveraineté des données : data centers exclusivement en Suisse (Genève + Zurich), droit suisse (nFADP) + RGPD, société 100% employés, aucune exposition au CLOUD Act américain. ISO 27001, 27701.
| Service | Provider | Usage | Prix estimé |
|---|---|---|---|
| App hosting | Infomaniak Jelastic Cloud (PaaS) | Backend Java + Flutter Web (Docker/Node.js, auto-scaling) | ~CHF 15–25/mois |
| Stockage S3 | Infomaniak Object Storage | Photos originales et traitées (API S3-compatible) | ~CHF 0.02/Go/mois (~CHF 10/mois pour 500 Go) |
| Base de données | Infomaniak Public Cloud PostgreSQL | PostgreSQL managé (1 nœud v0, 3 nœuds HA en prod) | ~CHF 22/mois (v0) |
| Egress réseau | Inclus Infomaniak | Sortie réseau gratuite jusqu'à 10 To/mois | CHF 0 |
| CDN | Cloudflare (free tier) | Distribution images mondiale en frontal de l'Object Storage | Gratuit |
Budget total estimé v0 (~500 Go d'images) : ~CHF 47–57/mois
Note SDK S3 : L'Object Storage Infomaniak est compatible API S3. Le SDK AWS (
software.amazon.awssdk:s3) fonctionne sans modification en changeant l'endpoint vershttps://s3.pub1.infomaniak.cloud. Les liens signés (PresignedGetObjectRequest) fonctionnent de la même manière.
// Configuration endpoint Infomaniak Object Storage (compatible S3)
S3Client s3 = S3Client.builder()
.endpointOverride(URI.create("https://s3.pub1.infomaniak.cloud"))
.region(Region.of("dc3-a")) // région Infomaniak
.credentialsProvider(StaticCredentialsProvider.create(
AwsBasicCredentials.create(accessKey, secretKey)))
.build();
CI/CD
# GitHub Actions ou GitLab CI
Backend:
- Build: Maven / Gradle
- Tests: JUnit + REST Assured
- Docker: Image Docker
- Deploy: Infomaniak Jelastic Cloud (Docker container)
Frontend:
- Build: flutter build web
- Tests: flutter test
- Deploy: Infomaniak Jelastic Cloud (Node.js container)
Monitoring & Logs
| Service | Usage |
|---|---|
| Sentry | Erreurs applicatives (backend + frontend) |
| LogRocket | Session replay frontend (optionnel V2) |
| Datadog / New Relic | APM et monitoring infrastructure (V2) |
| CloudWatch | Logs AWS (si AWS) |
Services externes
Requis V1
| Service | Usage | Plan |
|---|---|---|
| Stripe | Paiements + Connect | Standard (commission par transaction) |
| SendGrid / Mailgun | Emails transactionnels | Free tier puis payant |
| Printful / Gelato | Print-on-demand | Commission par produit |
Optionnel V2
| Service | Usage | Plan |
|---|---|---|
| Algolia | Recherche photos avancée | Payant |
| Cloudinary | Traitement images (alternative) | Free tier puis payant |
| Twilio | SMS notifications | Payant |
| Google Vision API | Reconnaissance faciale, OCR dossards | Pay-per-use |
Architecture réseau
┌─────────────┐
│ Clients │ (Browser, iOS, Android)
└──────┬──────┘
│
│ HTTPS
│
┌──────▼──────────┐
│ Cloudflare │ (CDN + WAF + DDoS protection — free tier)
└──────┬──────────┘
│
├──────────────────┬──────────────────────┐
│ │ │
┌──────▼──────┐ ┌───────▼────────┐ ┌──────────▼──────────┐
│ Flutter Web │ │ API REST │ │ Object Storage S3 │
│ (Static) │ │ Spring Boot │ │ Infomaniak (CH) │
│ Jelastic │ │ Jelastic │ │ (images, variantes) │
└─────────────┘ └────────┬───────┘ └──────────────────────┘
Infomaniak │ Infomaniak
Suisse (CH) ┌────────▼────────┐ Suisse (CH)
│ PostgreSQL │
│ Infomaniak │
│ Suisse (CH) │
└─────────────────┘
Toutes les données (app, base, stockage) sont hébergées en Suisse chez Infomaniak. Cloudflare agit uniquement comme proxy/CDN edge sans stocker de données persistantes.
Versions & Compatibilité
Minimum requis - Développement
- Java: JDK 21 (LTS)
- Maven: 3.9+
- Node.js: 20+ (LTS)
- npm: 10+ (ou pnpm 9+)
Minimum requis - Production
- JVM: OpenJDK 21 / Amazon Corretto 21
- PostgreSQL: 16+
Standards de code
Backend Java
- Style: Google Java Style Guide
- Linting: Checkstyle
- Formatting: Spotless
- Coverage: JaCoCo (objectif: >80%)
Frontend Next.js
- Style: Airbnb ESLint config
- Linting: ESLint + TypeScript strict
- Formatting: Prettier
- Coverage: Jest (objectif: >70%)
Sécurité
Backend
- HTTPS obligatoire (TLS 1.3)
- JWT pour authentification (expiration: 24h)
- Refresh tokens (expiration: 30j)
- Rate limiting: 100 req/min par IP
- CORS configuré strictement
- Helmet headers (CSP, HSTS, etc.)
- SQL injection prevention (JPA parameterized queries)
- XSS prevention (output encoding)
Frontend
- Tokens JWT en cookie httpOnly (pas de localStorage)
- Input validation côté client (Zod) + serveur
- Content Security Policy (CSP) via headers Next.js
- Variables d'environnement côté serveur uniquement pour les secrets
Dernière mise à jour: 12 mars 2026