SB
projets
Live · 2026 Personnel

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.

Le problème

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.

Highlights

Ce qui est intéressant techniquement

01

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.

02

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.

03

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.

04

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).

05

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.

06

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.

Stack

Sous le capot

Backend
Java 17 Spring Boot 3.5 Spring Web Spring @Async HandlerInterceptor Lombok
Persistence
PostgreSQL 17 (Neon) Spring Data JPA Hibernate Flyway HikariCP
Frontend
React 18 TypeScript Vite
AI
Gemini 2.5 Flash Lite Vision multi-modal Prompt FR / EN
Tests
JUnit 5 @DataJpaTest @WebMvcTest MockMvc H2 (PostgreSQL mode)
Ops
Docker multi-stage Render (free tier) Cloudflare Pages

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.