All notable changes to this project will be documented in this file.
- #27 — Memory leak dans le rate limiting : Remplacement du
ConcurrentHashMapnon borné par un cache Caffeine avec éviction automatique (expireAfterAccess1 heure,maximumSize100 000 entrées) dansRateLimitConfig; mise à jour deAnthropicControllerpour utiliserCache<String, Bucket>etcache.get()à la place decomputeIfAbsent; la Gauge Micrometerratelimit.buckets.sizeutilise désormaisestimatedSize(); taille maximale et durée d'expiration configurables viaapp.ratelimit.cache-max-sizeetapp.ratelimit.cache-expiry-hours(surchargeables par variables d'environnementRATELIMIT_CACHE_MAX_SIZEetRATELIMIT_CACHE_EXPIRY_HOURS) - #25 — Validation manquante sur le body de la requête : Ajout de
spring-boot-starter-validation, annotations@NotBlanket@Size(max = 4000)surChatRequest.message,@Validsur le@RequestBodydu contrôleur, et handlerMethodArgumentNotValidExceptiondansGlobalExceptionHandlerpour retourner HTTP 400 avec le détail de la contrainte violée — élimine le risque de NPE surrequest.message().length()et bloque les abus par message surdimensionné avant d'atteindre le modèle
- #42 — Spring Boot Actuator: Ajout de
spring-boot-starter-actuatoretmicrometer-registry-prometheuspour l'exposition des métriques de performance- Endpoints exposés :
health,info(publics),metrics,prometheus(authentifiés) - Timer
anthropic.chat.durationsur chaque appel au modèle Anthropic - Counter
ratelimit.rejectedincrémenté à chaque dépassement de rate limit - Gauge
ratelimit.buckets.sizesur la taille du cache de buckets IP
- Endpoints exposés :
AnthropicControllerexposingPOST /api/v1/anthropic/chatto call Claude via Spring AIChatRequestrecord as the request body DTOPromptValidatorfor input sanitizationSecurityConfigfor HTTP Basic authenticationRateLimitConfigwith per-IP Bucket4j rate limitingGlobalExceptionHandlerfor safe error responsesCorsConfigfor cross-origin access controlHTTPS.mddocumenting TLS setup for development and production- Spring AI Anthropic starter (
spring-ai-starter-model-anthropic) and BOM (spring-ai-bom 2.0.0-M4) spring-boot-starter-securitybucket4j-core 8.10.1for rate limitingspringboot4-dotenvfor.envfile loadingANTHROPIC_API_KEY,APP_USERNAME,APP_PASSWORD,CORS_ALLOWED_ORIGINS,SSL_*,SERVER_PORTenvironment variable mappings inapplication.properties
- #39 — Brute force protection on HTTP Basic authentication : Ajout de
IpUtils(utilitaire partagé pour l'extraction de l'IP client viaX-Forwarded-For),BruteForceProtectionService(tracks failed attempts per IP with time-based block) andBruteForceAuthenticationEntryPoint(increments counter onBadCredentialsException, returns HTTP 429 after N consecutive failures, 401 otherwise); wired intoSecurityConfigviahttpBasic().authenticationEntryPoint()- Configurable via
app.security.max-auth-attempts(default: 5) andapp.security.block-duration-minutes(default: 15) - Metrics:
security.auth.failurecounter (per IP) andsecurity.bruteforce.blockedcounter (per IP) exposed via Micrometer - Missing credentials (no
Authorizationheader) do not increment the counter
- Configurable via
- #38 — CORS GET method unnecessarily allowed: Removed
GETfromallowedMethodsinCorsConfig; onlyPOSTandOPTIONSare now permitted, matching the actual API surface - #28 — Missing HTTP security headers: Added explicit
X-Frame-Options: DENY,X-Content-Type-Options: nosniff,Content-Security-Policy: default-src 'self'andStrict-Transport-Security(HSTS, 1 year, includeSubDomains) inSecurityConfig - #24 — CORS allowedHeaders overly permissive: Replaced
allowedHeaders("*")with an explicit allowlist (Content-Type,Authorization,X-Requested-With) to prevent unauthorized cross-origin requests with credentials; configurable viaCORS_ALLOWED_HEADERSenvironment variable - #26 — IP Spoofing via X-Forwarded-For: Added
getClientIp()inAnthropicControllerto extract the real client IP from theX-Forwarded-Forheader (first entry) before falling back togetRemoteAddr(), ensuring rate limiting works correctly behind reverse proxies and load balancers - #32 — Stack trace exposure in GlobalExceptionHandler:
handleGenericnow logs only the exception message atERRORlevel; the full stack trace is relegated toDEBUGto prevent internal architecture details from appearing in production logs - #3 — Prompt injection prevention: Added
PromptValidatorto sanitize user input and block common injection patterns before forwarding to Claude - #4 — HTTP Basic authentication: Secured all API endpoints with Spring Security HTTP Basic auth; credentials loaded from environment variables (
APP_USERNAME,APP_PASSWORD); passwords encoded with BCrypt - #5 — Rate limiting (Denial of Wallet protection): Integrated Bucket4j (
bucket4j-core 8.10.1) to cap requests at 10 per minute per IP; returns HTTP 429 when exceeded - #6 — POST endpoint: Replaced
GET /api/anthropic/{message}withPOST /api/v1/anthropic/chataccepting a JSON body{"message": "..."}to avoid exposing user input in URLs and server logs - #7 — Global error handler: Added
GlobalExceptionHandlerto return generic error responses and prevent stack traces or internal details from leaking to clients - #8 — CORS configuration: Added
CorsConfigrestricting cross-origin requests to allowed origins configured viaCORS_ALLOWED_ORIGINSenvironment variable (default:http://localhost:3000) - #9 — HTTPS/TLS support: Added SSL/TLS configuration via
application.properties; HTTPS is opt-in via environment variables (SSL_ENABLED,SSL_KEY_STORE,SSL_KEY_STORE_PASSWORD,SSL_KEY_ALIAS,SERVER_PORT); seeHTTPS.mdfor setup instructions - #11 — Logging and audit trail: Added SLF4J structured logging in
AnthropicControllerrecording client IP and message/response lengths on each request
- #33 — API versioning: Renamed all endpoints from
/api/anthropic/...to/api/v1/anthropic/...to enable future breaking-change versions without disrupting existing clients
- Logging framework: Replaced Logback with Log4j2 (
spring-boot-starter-log4j2);spring-boot-starter-loggingexcluded from all starters - #40 — Log4j2 pattern: Added
log4j2-spring.xmlto replace the Logback-specificlogging.pattern.consoleproperty that was silently ignored - Test logging capture:
GlobalExceptionHandlerTestnow uses a Log4j2AbstractAppender-basedTestListAppenderto assert logging behavior (no throwable atERROR, throwable present atDEBUG) - JaCoCo coverage: Added JaCoCo
0.8.13(required for Java 25) with a minimum 90% line coverage and 80% branch coverage gate enforced at build time - Unit tests: Added test suites for all components —
PromptValidator,SecurityConfig,RateLimitConfig,AnthropicController,GlobalExceptionHandler,CorsConfig— usingMockMvc.standaloneSetup()and@SpringBootTestcompatible with Spring Boot 4.x
- Spring Boot 4.0.5 project setup with Java 25
- Maven wrapper (
mvnw)