AltForge
Générateur d'alt-text par IA pour la conformité WCAG. Single + batch synchrone + batch asynchrone (job polling), audit DB Postgres, rate-limiting par IP, stats agrégées. 4 onglets UI, 27 tests, deploy free-tier Render + Cloudflare Pages.
Pourquoi j'ai construit ça
Depuis juin 2025, l'European Accessibility Act impose aux sites e-commerce, banques et services publics européens des images correctement décrites pour les lecteurs d'écran. La plupart des sites ont des milliers d'images legacy sans alt-text, et la rédaction manuelle ne passe pas à l'échelle. AltForge automatise la première passe en restant aligné avec les bonnes pratiques WCAG (pas de « image de », descriptif, concis), avec une couche d'audit et de rate-limiting prête pour de la production multi-tenant.
Ce qui est intéressant techniquement
Audit DB Postgres avec interceptor chain
Chaque appel à l'API est enregistré dans `request_audits` (Spring Data JPA + Flyway, IP hashée SHA-256, latence, status, langue, modèle). Un HandlerInterceptor mesure le temps de réponse côté serveur, le controller pose les métadonnées métier via request attributes — séparation claire entre cross-cutting et logique métier.
Rate-limiting par IP sans Redis
Un deuxième interceptor compte les appels du même hash IP sur les 60 dernières minutes via la table d'audit, renvoie 429 + `Retry-After` au-dessus du seuil. Ordre des interceptors choisi pour que les 429 soient eux-mêmes audités (`error_code = rate_limited`). Activable par feature flag, fail-open si la DB tombe.
Pipeline async avec @Async + ThreadPoolTaskExecutor
`POST /batch/async` retourne 202 + UUID immédiatement, un worker dédié (1 core / 2 max / queue 10) traite les images séquentiellement, met à jour `processed_images` après chaque appel Gemini. Le front polle `GET /api/jobs/{id}` toutes les 2s et anime une progress bar.
Multi-modal Gemini depuis Spring Boot, sans SDK
RestClient typé Spring 6.1, image encodée en base64 `inline_data`, prompts système soigneusement écrits en FR et EN pour respecter les règles WCAG (interdire « image de / picture of », ~125 chars, décrire avant d'interpréter).
Stats agrégées en JPQL
`GET /api/stats?hours=N` calcule total / success rate / avg latency + breakdowns par langue et endpoint via des derived queries Spring Data + JPQL `GROUP BY`. UI dédiée avec barres horizontales et sélecteur de fenêtre 24h / 7j / 30j.
Pyramide de tests sans Docker en CI
27 tests JUnit 5 : `@DataJpaTest` sur H2 en mode PostgreSQL pour faire tourner les vraies migrations Flyway sur les queries du repository, `@WebMvcTest` + MockMvc avec @MockitoBean pour les controllers, unit tests pour les interceptors. Aucune dépendance Testcontainers.
Sous le capot
Statut actuel
v2.2 livré et live sur altforge.pages.dev — 4 onglets (single / batch / async / stats). Repo public sur GitHub. Reste v3 (auth + billing) si besoin d'en faire un vrai SaaS public.