Changelog¶
All notable changes to the Payflow API project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]¶
Added - Documentation Modernization & D2 Engine Migration¶
- Replaced legacy Docsify single-page app with Material for MkDocs static site generator (
mkdocs-material9.5+) featuring instantaneous client search, dark/light theme switching, and responsive design. - Redrew and modernized all 12 architectural topology, sequence, and data flow diagrams across
docs/ARCHITECTURE.md,README.md, anddocs/index.mdusing the declarative D2 diagramming engine (docs/diagrams/*.d2) with offline vector icons and Eclipse Layout Kernel (ELK) collision-free routing. - Implemented Option 1 Hybrid Pre-rendered SVG + Collapsible D2 Source pattern: pre-rendered self-contained SVGs (
docs/assets/diagrams/*.svg) with embedded<details><summary>📐 View Declarative D2 Diagram Source</summary>...blocks, guaranteeing crisp, zero-flicker rendering across GitHub web, IDE previewers, and the documentation portal. - Authored automated compilation script
scripts/generate-diagrams.shwith dual light/dark theme compilation (--theme=0 --dark-theme=200) and--checkdrift detection. - Configured enterprise CI/CD quality gates in
.github/workflows/ci.yml: - Enforced zero diagram drift on PR and push via
./scripts/generate-diagrams.sh --check. - Enforced strict documentation compilation on PR and push via
mkdocs build --strict. - Automated deployment of the documentation portal alongside JaCoCo test coverage reports to GitHub Pages on
mainmerge. - Created
.github/workflows/generate-diagrams.ymlenabling 1-click manual workflow dispatch to recompile D2 diagrams and automatically commit changes without requiring local D2 installation. - Created
requirements.txtspecifying deterministic Python dependencies (mkdocs>=1.6.1,mkdocs-material>=9.5.0,mkdocs-d2-plugin>=1.6.0). - Created offline SVG icon library under
docs/assets/icons/(16 scalable vector icons) for zero-dependency compilation. - Eliminated redundant documentation files and deduplicated governance markdowns (
CHANGELOG.md,CONTRIBUTING.md,SECURITY.md,LICENSE) via single-source relative symlinks indocs/. - Hardened
.gitignoreto prevent committing build artifacts (site/,.cache/,.venv/, Python bytecode). - Corrected API endpoint routes and verified complete parity with Java 25 & Spring Boot 4.1.0 codebase (191 tests, 90% line / 73% branch coverage).
Added - Phase 11A (Multi-Stage Containerization & Full-Stack Docker Compose)¶
- Created hardened multi-stage
Dockerfile: - Stage 1: Build stage utilizing OpenJDK 25 (
eclipse-temurin:25-jdk) and Maven layer caching. - Stage 2: Minimal runtime utilizing
eclipse-temurin:25-jreexecuting under unprivileged non-root userpayflow:10001. - Configured native container
HEALTHCHECKtargeting Spring Boot Actuator readiness probe (/actuator/health/readiness). - Tuned production container JVM flags:
-XX:+UseZGC -XX:+ZGenerational -XX:MaxRAMPercentage=75.0 -Djava.security.egd=file:/dev/./urandom. - Created
.dockerignorestrictly filteringtarget/, git metadata, local scripts, and markdown documentation. - Created production-ready
docker-compose.ymlorchestrating PostgreSQL 17, Redis 7, Apache Kafka (KRaft), Ollama Gen-AI, Prometheus, and Grafana with volume persistence and healthcheck dependency ordering (condition: service_healthy). - Created telemetry infrastructure:
monitoring/prometheus/prometheus.ymlscrapingapp:8080/actuator/prometheus.monitoring/grafana/provisioning/datasources/prometheus.ymlauto-provisioning Prometheus datasource.monitoring/grafana/provisioning/dashboards/dashboard-provider.ymlregistering dashboard providers.monitoring/grafana/provisioning/dashboards/payflow.jsontelemetry dashboard covering JVM memory, HTTP throughput/latency (p95/p99), HikariCP pool metrics, and virtual thread metrics.- Authored ADR-028 (Multi-Stage Containerization and Full-Stack Docker Compose Orchestration).
Added - Phase 11B (Cloud-Native Kubernetes Deployment Topology & Graceful Shutdown)¶
- Created declarative Kubernetes manifest suite in
k8s/: k8s/configmap.yamlandk8s/secret.yamlseparating non-sensitive environment configuration from cryptographic credentials.k8s/deployment.yamldefining 2 replicas, zero-downtimeRollingUpdate(maxSurge: 1,maxUnavailable: 0), non-root security context (runAsUser: 10001), CPU/memory requests and limits, Actuator liveness/readiness probes, and coordinated graceful shutdown pre-stop hook (sleep 10).k8s/service.yamlexposing internalClusterIPon port 8080.k8s/hpa.yamlHorizontalPodAutoscaler scaling between 2 and 10 replicas based on 75% CPU and 80% memory utilization.k8s/pdb.yamlPodDisruptionBudget enforcingminAvailable: 1during node maintenance.- Configured coordinated graceful shutdown by adding
spring.lifecycle.timeout-per-shutdown-phase: 30salongsideserver.shutdown: gracefulinapplication-prod.ymlandapplication-prod-light.yml. - Authored ADR-029 (Cloud-Native Kubernetes Deployment Topology and Horizontal Pod Autoscaling).
Added - Phase 11C (CI/CD Pipeline Hardening & Automated Quality Gates)¶
- Integrated
spotbugs-maven-plugin:4.10.4.1withspotbugs-exclude.xmlfor Java 25 static bytecode auditing; achieved 0 bugs and 0 errors. - Refactored
JwtTokenProvider,Transaction,SecurityUtils, andRequestIdFilterto resolve constructor leaks, serialization warnings, and HTTP header sanitization. - Integrated
jacoco-maven-plugin:0.8.15enforcing minimum 80% line coverage and 70% branch coverage across core business and security packages; achieved 90% line coverage and 73% branch coverage across 191 unit tests with 0 missed classes. - Created comprehensive unit test suites:
JwtAccessDeniedHandlerTest,JwtAuthenticationEntryPointTest,JwtAuthenticationFilterTest,SecurityUtilsTest, andIdempotencyCleanupServiceTest. - Hardened
.github/workflows/ci.ymlexecutingmvn clean verify -Bwith automated artifact upload for JaCoCo coverage reports and SpotBugs analysis (14-day retention). - Added automated GitHub Pages deployment for the Material for MkDocs public documentation portal (
https://shashankch.github.io/payflow-api/), Code Coverage Quality Gate summary (https://shashankch.github.io/payflow-api/coverage/), and live interactive JaCoCo coverage reports (https://shashankch.github.io/payflow-api/coverage-report/). - Authored ADR-030 (Automated CI/CD Quality Gates, JaCoCo Coverage Enforcement, and SpotBugs Static Analysis).
- Added
spring-modulith-events-kafka,spring-kafka,spring-kafka-test, and Testcontainerskafkadependencies topom.xml. - Marked domain event
TransferCompletedEventwith@Externalizedand configured programmatic dynamic routing viaEventExternalizationConfigurationinKafkaConfig.java, routing to${payflow.kafka.transfers-topic}partitioned bysenderUpifor strict chronological delivery per account. - Created
KafkaConfig.java(@Profile({"prod", "kafka"})) registeringNewTopicbean with configurable partitions and replication factor (PAYFLOW_KAFKA_REPLICAS:3in production for high availability, 1 in dev/test). - Created dedicated
application-kafka.ymlenabling Spring Modulith externalization (enabled: true) and configuring Kafka endpoints for thekafkaprofile. - Configured resilient Kafka producer properties in
application-prod.ymlandapplication-kafka.ymlwithacks: all,enable.idempotence: true(producer retry deduplication), and at-least-once end-to-end delivery via the transactional outbox. - Configured default profile isolation (
spring.modulith.events.externalization.enabled: falseinapplication.yml), enabling zero-broker in-process execution inlocal,test, andprod-lightprofiles. - Created unit tests
KafkaConfigTest.java(verifying conditional bean wiring, custom topic resolution, and replication factors) andTransferCompletedEventTest.java(verifying annotation and accessors). - Created full-stack integration test
KafkaOutboxIT.javaagainst Testcontainers Kafka (KRaft mode) verifying transfer execution, outbox persistence, and externalized record consumption. - Added ADR-024 (Kafka Event Streaming via Spring Modulith Event Externalization) to
docs/adr/.
Added / Hardened - Phase 9B (Production Hardening & Architecture Audit Remediation)¶
- Security Hardening (SEC-01, SEC-02, SEC-03, SEC-04):
- Added startup validation in
JwtTokenProvider.javarequiring externalPAYFLOW_SECURITY_JWT_SECRETof >= 256 bits (32 chars) when running inprodprofile, failing fast on default or weak keys. - Enforced
ROLE_ADMINcheck inUserController.javaforGET /api/v1/usersandGET /api/v1/users/balance/{amount}, preventing unauthorized balance enumeration and BOLA vulnerabilities. - Hardened CORS configuration in
SecurityConfig.javato disallow credentials when wildcard origin (*) is present. - Configured clickjacking defense via
frameOptions().sameOrigin()inSecurityConfig.java. - Architecture & Resilience (ARCH-02, ARCH-03, ARCH-04):
- Handled Spring 6.1+ / Spring 7
HandlerMethodValidationException,ConstraintViolationException, andMethodArgumentTypeMismatchExceptioninGlobalExceptionHandler.javareturning RFC 9457ProblemDetailresponses. - Enforced boundary validation for
Idempotency-Keyheader inIdempotencyFilter.java(max 255 chars, pattern^[A-Za-z0-9_.:-]+$). - Implemented scheduled
OutboxCleanupService.javaleveraging Spring Modulith 2.0CompletedEventPublications.deletePublicationsOlderThan(Duration)to purge completed outbox events older than 7 days. - Enhanced Flyway migration
V6__create_event_publication_registry.sqlwithevent_publication_archivetable and indexes, and alignedUser.phoneNumberlength (10 chars) andTransactionjoin column nullability (nullable = false) to satisfy Hibernate schema validation on PostgreSQL. - Performance & Scalability (PERF-01):
- Replaced global cache invalidation (
allEntries = true) inTransactionService.javawith targeted cache eviction, invalidating only affected sender and receiver keys (upi,refId,id, and user ledgers). - Quality, Verification & Build Lifecycle (TEST-01, TEST-02, TEST-03):
- Added
maven-failsafe-plugin3.5.6 bound tointegration-testandverifygoals inpom.xml, separating unit tests (*Test.java) from integration tests (*IT.java). - Added DataJpaTest repository slice tests
TransactionRepositoryTest.javaandIdempotencyRepositoryTest.java. - Added unit test coverage for
OutboxCleanupServiceTest,IdempotencyFilterTest,UserControllerTest, andJwtTokenProviderTest. - Documentation & Configuration Consistency (DOC-01, DOC-02):
- Synchronized
docs/ARCHITECTURE.md(Resilience4j vs Bucket4j, Virtual Threads scheduling for Phase 10B, Redisson lock topology). - Aligned
docker-compose.ymlto useSPRING_PROFILES_ACTIVE: local. - Updated
docs/CONVENTIONS.mdtesting standards for Surefire and Failsafe phases. - Added ADR-025 (Production Hardening and Architecture Audit Remediation) to
docs/adr/. - Integration Testing & Container Pipeline Stabilization:
- Implemented Testcontainers Singleton Container pattern in
AbstractIntegrationTest, eliminating premature container stops across test classes. - Added
spring-boot-restclientand@AutoConfigureTestRestTemplatefor Spring Boot 4.1 test client autowiring. - Resolved Kafka event externalization routing, static singleton container startup, and consumer assignment warmup in
KafkaOutboxIT.javaandKafkaConfig.java. - Configured
ByteArraySerializerinapplication-kafka.ymlensuring raw serialized event bytes on Kafka topics for Spring Modulith externalization. - Bound
TaggedRateLimiterMetricsandTaggedCircuitBreakerMetricsasMeterBinderbeans inResilience4jConfig.javato export resilience metrics to Micrometer and Prometheus. - Configured Resilience4j
configstemplates inapplication.yml/application-test.ymland dynamic instance config fallback inUserRateLimiterService.java. - Normalized phone number generation in
ConcurrentTransferITand aligned BOLA authorization headers inTransferLifecycleIT. - Aligned
ResilienceITtransaction status assertion withTransactionStatusenum and corrected SpEL key expression in@Externalized("payflow.transfers::#{senderUpi()}").
Added - Phase 10A (Gen-AI Spend Categorization & Financial Insights)¶
- Integrated Spring AI 2.0.1 GA (
spring-ai-starter-model-openai) via BOM dependency management inpom.xml. - Created immutable Java 25 record
SpendInsightResponsewith OpenAPI schemas and Jackson serialization for category, amount, summary, budgetingTip, confidenceScore, and source. - Implemented
AiConfig.javaproviding a@ConditionalOnBean(ChatClient.Builder.class)ChatClientbean. - Implemented
LlmInsightClient.javautilizing Spring AI fluentChatCliententity extraction, guarded by Resilience4j@CircuitBreaker(name = "aiCircuitBreaker", fallbackMethod = "ruleBasedFallback")and 8-category deterministic keyword heuristic fallback. - Implemented
SpendInsightsServiceandSpendInsightsServiceImplwith principal transaction verification andpayflow.ai.enabledfeature flag enforcement. - Created
FeatureDisabledExceptionwith centralized RFC 9457 HTTP 503ProblemDetailhandler inGlobalExceptionHandler. - Added endpoint
POST /api/v1/transactions/{id}/insightstoTransactionControllerwith multi-party principal authorization. - Added comprehensive unit tests in
SpendInsightsServiceTest.javaandTransactionControllerTest.java. - Documented ADR-026 (Gen-AI Spend Categorization with Spring AI and Circuit Breaker Fallback).
Added - Phase 10B (Virtual Threads & Resource Optimization)¶
- Enabled Java 25 Project Loom Virtual Threads globally (
spring.threads.virtual.enabled: trueinapplication.yml). - Tuned HikariCP connection pool parameters (
idle-timeout: 300000ms,max-lifetime: 1800000ms,connection-timeout: 30000ms) inapplication-prod.ymlto prevent database connection saturation. - Introduced lightweight single-node production profile
application-prod-light.ymldesigned for <= 1 GiB RAM deployments with local Caffeine caching, bounded HikariCP pool (max 5), and in-process Modulith event publication. - Extended strict production JWT secret entropy verification in
JwtTokenProviderto cover theprod-lightprofile. - Restricted
TransferEventListenerexecution to@Profile({"local", "test", "prod-light"})ensuring zero duplicate processing when Kafka externalization is active. - Documented ADR-027 (Java 25 Virtual Threads and Bounded HikariCP Connection Pool Optimization).
[0.8.0] - 2026-09-09¶
Added - Phase 8D (Redis Distributed Locking with Redisson & Fail-Safe Fallback)¶
- Added
org.redisson:redisson(version 4.7.0) dependency topom.xml, aligning with Netty4.2.15.Finalin Spring Boot 4.1.0. - Created
DistributedLockService.javainterface definingtryLock(key, waitTime, leaseTime), fail-fasttryLock(key, leaseTime),unlock(key), andisLocked(key). - Created
RedissonDistributedLockService.java(@Profile("prod")) implementing distributed locking with RedissonRLock: - Safely verifies
lock.isHeldByCurrentThread()before callingunlock()to eliminateIllegalMonitorStateException. - Restores thread interrupt status on
InterruptedException. - Created
NoOpDistributedLockService.java(@Profile("!prod")) providing an in-memory pass-through forlocal,test, andprod-lightprofiles. - Created
DistributedLockConfig.java(@Profile("prod")) configuringRedissonClientbean with connection pool (20), idle connections (5), and timeout (3000ms). - Configured externalized lock properties under
payflow.lock(wait-time: 2s,lease-time: 10s) inapplication.yml. - Enhanced
IdempotencyFilter.javawith distributed locking: - Acquires distributed lock on
payflow:lock:idemp:<key>before inspecting database records. - Automatically releases lock in
finallyblock across all execution paths (success, conflict, error, and exception). - Returns HTTP
409 ConflictwithLock ContentionProblemDetail when lock acquisition fails within the 2-second wait window. - Defensively defaults to
NoOpDistributedLockServicewhenDistributedLockServicebean is omitted in slice tests (@WebMvcTest). - Created comprehensive unit tests:
NoOpDistributedLockServiceTest.javaverifying pass-through behavior.RedissonDistributedLockServiceTest.javaverifying lock acquisition, contention timeout, interrupt handling, thread-bound unlocking, and exception safety.DistributedLockConfigTest.javaverifying profile-conditional bean wiring.- Updated
IdempotencyFilterTest.javaverifying lock acquisition, contention rejection, and guaranteed unlock infinally. - Added ADR-023 (Redis Distributed Locking with Redisson and Fail-Safe Local Fallback) to
docs/adr/.
Added - Phase 8C (Redis Distributed Caching & Caffeine Local Fallback)¶
- Added
spring-boot-starter-cache,spring-boot-starter-data-redis, andcaffeine(version 3.2.0) dependencies topom.xml. - Created
CacheConfig.javaenabling@EnableCachingwith profile-conditional CacheManager resolution: - Redis CacheManager in
prodprofile withRedisSerializer.string()keys, modern non-deprecatedRedisSerializer.json()values, and granular TTL configurations (10 minutes default andusers, 1 minute foruser_ledgers). - Caffeine CacheManager in
!prod(local,test,prod-light) using specmaximumSize=1000,expireAfterWrite=600s. - Created
RedisConfig.java(@Profile("prod")) configuringLettuceConnectionFactorywith standalone configuration and genericRedisTemplate<String, Object>. - Annotated
UserService.javaquery operations with@Cacheable: getUserById(Long id)->@Cacheable(value = "users", key = "#id", unless = "#result == null").getUserByReferenceId(UUID referenceId)->@Cacheable(value = "users", key = "#referenceId", unless = "#result == null").findByUpiId(String upiId)->@Cacheable(value = "users", key = "#upiId", unless = "#result == null").getUserByUpiId(String upiId)->@Cacheable(value = "users", key = "#upiId", unless = "#result == null").getUserLedger(UUID userReferenceId, Pageable pageable)->@Cacheable(value = "user_ledgers", key = "#userReferenceId + '_' + #pageable.pageNumber", unless = "#result == null").- Annotated mutation operations with
@CacheEvict: UserService.registerUser()->@CacheEvict(value = "users", allEntries = true).TransactionService.sendMoney()->@CacheEvict(value = {"users", "user_ledgers"}, allEntries = true)upon successful transfer execution.- Hardened domain entities for distributed JSON caching:
User.java: Addedimplements SerializableandserialVersionUID = 1L.BalanceLedgerEntry.java: Addedimplements Serializable,serialVersionUID = 1L,@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})to ignore Hibernate proxy fields, and@JsonIgnoreon lazy associations (user,transaction) to prevent circular serialization graphs.- Externalized cache TTL configurations in
application.yml(payflow.cache.*) and Redis connection parameters inapplication-prod.yml. - Created unit and slice tests:
CacheConfigTest.javaverifying Caffeine CacheManager bean creation, cache operations, and profile-conditional activation.UserServiceCacheTest.javaverifying cache hits on reference ID, UPI, and ledger queries, and@CacheEvictonregisterUser().TransactionServiceCacheTest.javaverifying multi-cache eviction onsendMoney().- Created full-stack integration test
CacheIT.javaagainst Testcontainers PostgreSQL verifying caching and eviction mechanics. - Added ADR-022 (Redis Distributed Caching and Caffeine Local Fallback Strategy) to
docs/adr/.
Added - Phase 8B (Resilience4j Fault Tolerance, Dynamic Rate Limiting & Circuit Breakers)¶
- Added
resilience4j-spring-boot3andresilience4j-micrometer(version 2.4.0) dependencies topom.xml. - Created
@PerUserRateLimitercustom annotation andPerUserRateLimiterAspectfor declarative, principal-partitioned rate limiting with optional fallback handling. - Created
RateLimiterKeyResolverinterface andSecurityContextRateLimiterKeyResolverresolving partition keys by authenticated principal (UPI handle) or remote client IP as fallback. - Created
UserRateLimiterServicemanaging dynamic per-user Resilience4jRateLimiterinstances with automated memory leak eviction (evictInactiveLimiters()) every 15 minutes. - Enforced per-user rate limiting (10 req/s) on
TransactionService.sendMoney()via@PerUserRateLimiter(name = "transferLimiter"). - Protected downstream UPI validation in
UpiValidationService.executeValidationWithRetry()using Resilience4j@CircuitBreaker(name = "upiValidation", fallbackMethod = "recoverFromValidationFailure"). - Enhanced
GlobalExceptionHandler.javawith centralized RFC 7807 / RFC 6585 error handling: RequestNotPermitted-> HTTP429 Too Many Requests(https://api.payflow.com/errors/rate-limit-exceeded) withRetry-After: 1header.CallNotPermittedException-> HTTP503 Service Unavailable(https://api.payflow.com/errors/service-unavailable).- Configured externalized Resilience4j settings in
application.ymlfor circuit breaker (COUNT_BASED sliding window 10, min calls 5, 50% threshold, wait duration 5s, ignoresInvalidUpiException), rate limiter (10 req/s, 0 timeout), and time limiter (5s timeout). - Enabled Actuator health contributors (
management.health.circuitbreakers.enabled,management.health.ratelimiters.enabled) and Micrometer/Prometheus metric exports (resilience4j_circuitbreaker_*,resilience4j_ratelimiter_*). - Created unit tests
RateLimiterTest.java,CircuitBreakerTest.java,PerUserRateLimiterAspectTest.java, and enhancedGlobalExceptionHandlerTest.javaandUpiValidationServiceTest.java. - Created full-stack integration test
ResilienceIT.javaon Testcontainers PostgreSQL verifying 10-call rate limit rejection with HTTP 429 andRetry-After: 1, and circuit breaker transitions. - Added ADR-021 (Resilience4j Circuit Breaker, Dynamic Per-User Rate Limiting & Timeout Policies) to
docs/adr/.
Added - Phase 8A (Structured Logging, Prometheus Metrics & OpenTelemetry Tracing)¶
- Added
spring-boot-starter-actuator,micrometer-registry-prometheus,micrometer-tracing-bridge-otel, andopentelemetry-exporter-otlpdependencies topom.xml. - Created
MetricsConfig.javaconfiguringObservedAspectfor@Observedannotation support and registering custom business meters: payflow.transfers.total(Counter tagged by status:COMPLETED,FAILED,INSUFFICIENT_BALANCE,FORBIDDEN).payflow.transfers.amount(DistributionSummary with p50/p95/p99 SLA percentiles).payflow.transfers.duration(Timer with p50/p95/p99 SLA percentiles).- Created
RequestLoggingFilter.javalogging incoming HTTP requests, status codes, execution duration (ms), and MDC tags (http.status,http.method,http.uri,http.latency_ms). - Enhanced
RequestIdFilter.javawith@Order(Ordered.HIGHEST_PRECEDENCE + 1). - Enhanced
TransactionService.javawith@Observedand recording business metrics on transfer completion and failure. - Configured native ECS structured logging (
logging.structured.format.console: ecs) inapplication-prod.ymland console trace pattern withtraceId/spanIdinapplication.yml. - Configured HikariCP connection pool monitoring (
PayflowHikariPool) inapplication.ymlandapplication-prod.yml. - Updated
SecurityConfig.javato permit/actuator/prometheusand/actuator/metrics/**endpoints. - Created unit tests
MetricsConfigTest.javaandRequestLoggingFilterTest.java. - Created full-stack integration test
ObservabilityIT.javaagainst Testcontainers PostgreSQL verifying/actuator/health,/actuator/prometheus, custom metrics, and HikariCP connection metrics. - Added ADR-020 (Structured Logging, Prometheus Metrics & OpenTelemetry Observability Architecture) to
docs/adr/.
[0.7.0] - 2026-08-28¶
Added - Phase 7C (RestClient, Declarative HTTP Interface Client & External UPI Validation)¶
- Added
spring-retrydependency topom.xmlfor declarative retry management. - Created
UpiVerificationResponse.javarecord representing third-party UPI verification response payloads. - Created
UpiValidationClient.javadeclarative HTTP Interface Client interface with@HttpExchangeand@GetExchangeannotations. - Created
RestClientConfig.javaconfiguringRestClient, connection/read timeouts,@EnableRetry, andHttpServiceProxyFactoryproxy generation. - Created
InvalidUpiException.javadomain exception and mapped to RFC 7807422 Unprocessable EntityinGlobalExceptionHandler.java. - Created
UpiValidationService.javaimplementing@Retryableoutbound calls with exponential backoff and randomized jitter (delay = 500ms,multiplier = 2.0,random = true) and@Recovergraceful degradation fallback on downstream service outages. - Integrated UPI validation into
UserService.registerUser()during client onboarding. - Created
UpiValidationClientTest.javaverifying HTTP Interface Client serialization and deserialization viaMockRestServiceServer. - Created
UpiValidationServiceTest.javaunit tests verifying validation pass, invalid UPI rejection, retry, and recover fallback. - Created
UpiValidationIT.javaTestcontainers PostgreSQL integration test verifying end-to-end user onboarding with upstream validation and failure handling. - Added ADR-019 (Declarative HTTP Interface Client (RestClient) & Resilient External Service Integration) to
docs/adr/.
Added - Phase 7B (Authorization & Sender Verification)¶
- Created
ForbiddenOperationException.javadomain exception extendingPayflowException. - Created
SecurityUtils.javastatic helper to retrieve the authenticated principal's UPI handle fromSecurityContextHolder. - Created
JwtAccessDeniedHandler.javaimplementing Spring Security'sAccessDeniedHandler, emitting standardized RFC 7807403 Forbidden(application/problem+json) problem details on access denial. - Enhanced
SecurityConfig.javato registerJwtAccessDeniedHandlerin the security filter chain. - Enhanced
GlobalExceptionHandler.javawith@ExceptionHandlerforForbiddenOperationExceptionandAccessDeniedExceptionmapping to403 Forbidden. - Enforced strict sender authorization in
TransactionService.sendMoney(): rejecting transfer requests when the authenticated subject does not matchsenderUpiIdwith403 Forbiddenbefore acquiring database locks or mutating balances. - Enforced multi-party transaction visibility in
TransactionService.getTransactionByReferenceId()andgetUserTransactions(): ensuring only transaction participants (sender/receiver) or the account owner can view records. - Enforced balance ledger privacy in
UserService.getUserLedger(): preventing users from inspecting other users' double-entry balance ledger audit entries. - Enforced profile ownership in
UserController.getUserById()andgetUserByUpiId(). - Created full-stack integration test
AuthorizationIT.javaagainst Testcontainers PostgreSQL verifying all 403 Forbidden boundaries and authorized user flows. - Added ADR-018 (Principal-Bound Resource Access Control & Sender Verification) to
docs/adr/.
Added - Phase 7A (Spring Security & Stateless JWT Authentication)¶
- Added
spring-boot-starter-security,spring-security-test, and JJWT 0.13.0 (jjwt-api,jjwt-impl,jjwt-jackson) dependencies topom.xml. - Created
JwtTokenProvider.javafor HMAC-SHA256 (HS256) token generation, signature validation, expiration checking, and user claims extraction (upiId,referenceId,roles). - Created
JwtAuthenticationFilter.java(OncePerRequestFilter) to parse Bearer tokens fromAuthorizationheader and populateSecurityContextHolder. - Created
JwtAuthenticationEntryPoint.javarendering standardized RFC 7807401 Unauthorizedproblem details (application/problem+json) on unauthenticated requests to protected endpoints. - Created
SecurityConfig.javaconfiguring statelessSecurityFilterChain, CORS policy with configurable origins/methods/headers, CSRF disabled, public route permit rules (POST /api/v1/auth/login,POST /api/v1/users,/swagger-ui/**,/v3/api-docs/**,/actuator/health/**), and protected route authentication requirements (anyRequest().authenticated()). - Created
AuthController.javawithPOST /api/v1/auth/loginendpoint issuing JWT tokens with 1-hour expiration and user reference metadata. - Created DTOs
LoginRequest.javaandAuthResponse.java. - Created unit tests
JwtTokenProviderTest.javaandAuthControllerTest.java. - Created full-stack integration test
AuthenticationIT.javaagainst Testcontainers PostgreSQL verifying 401 unauthorized rejection, login token acquisition, and authenticated transaction execution. - Added ADR-017 (Stateless JWT Authentication & Spring Security Architecture) to
docs/adr/.
[0.6.0] - 2026-08-16¶
Added - Phase 6B (Spring Modulith Events & Transactional Outbox)¶
- Integrated Spring Modulith 2.0 (
spring-modulith-starter-jpa,spring-modulith-starter-test, andspring-modulith-bom). - Created Flyway migration
V6__create_event_publication_registry.sqlcreatingevent_publicationtable with completion and publication date indexes. - Created
TransferCompletedEventdomain event record containing transaction reference UUID, sender/receiver UPI IDs, amount, status, and post-transfer balances. - Updated
TransactionService.javato publishTransferCompletedEventviaApplicationEventPublisherwithin the@Transactionalboundary, achieving transactional outbox persistence to PostgreSQL with zero dual-write vulnerability. - Created
TransferEventListener.javaannotated with@ApplicationModuleListenerfor asynchronous post-commit event consumption. - Created
ModulithStructureTest.javaverifying architectural boundaries and package encapsulation withApplicationModules.of(PayflowApiApplication.class).verify(). - Created
OutboxIT.javafull-stack integration test verifying atomic event publication toevent_publicationtable against Testcontainers PostgreSQL. - Hardened
IdempotencyFilter.javawith in-flight lease timeout (2 min) for automatic recovery from crashed worker nodes, and catch forDataIntegrityViolationExceptionto gracefully handle concurrent insert collisions as409 Conflict. - Enhanced
GlobalExceptionHandler.javawith structured error logging (LOG.error) for unhandled server exceptions and data integrity violations. - Standardized deterministic alphabetical lock acquisition in
TransactionService.javawithString.CASE_INSENSITIVE_ORDER. - Added ADR-016 (Spring Modulith Event Publication Registry & Transactional Outbox Pattern) to
docs/adr/.
Added - Phase 6A (Durable Idempotency Engine)¶
- Created
IdempotencyFilter.java(OncePerRequestFilter) withCachedBodyHttpServletRequestwrapper to interceptPOST /api/v1/transactions, enforcing mandatoryIdempotency-Keyheader with SHA-256 request payload hashing. - Added database persistence via
idempotency_registrytable andIdempotencyRecordentity with lifecycle states (PROCESSING,SUCCESS,FAILED). - Created Flyway migration
V5__create_idempotency_registry.sqlwith performance indexidx_idemp_created. - Implemented cached HTTP response replay: repeated identical requests immediately return cached 201 Created response without triggering backend transfer logic or double-debiting user balances.
- Implemented validation and conflict handling: rejecting missing
Idempotency-Keyheaders or key reuse with mismatched payloads with400 Bad Request, and concurrent in-flight requests with409 Conflict(RFC 7807 problem details). - Created
IdempotencyCleanupService.javawith@Scheduledpurge job for removing expired idempotency records past configured TTL (payflow.idempotency.ttl-hours, default 24h). - Added unit test suite
IdempotencyFilterTest.javaand integration test suiteIdempotencyIT.javaagainst Testcontainers PostgreSQL. - Added ADR-015 (SHA-256 Request Payload Hashing & Durable Database-Backed Idempotency Engine) to
docs/adr/.
[0.5.0] - 2026-08-15¶
Added - Phase 5B (Integration & Concurrency Test Suites)¶
- Created
TransferLifecycleIT.javafull-stack integration test verifying end-to-end user registration, money transfers, updated balances, and double-entry ledger audit verification against Testcontainers PostgreSQL. - Created
ConcurrentTransferIT.javahigh-concurrency race condition test with 10 synchronized threads (CountDownLatch), asserting that simultaneous withdrawals from an account with insufficient balance for all result in exactly 1 success, 9 failures, zero double-spending, and balance invariance (balance never goes negative). - Created
MutualTransferDeadlockIT.javaverifying deadlock avoidance under concurrent mutual cross-transfers ($A \rightarrow B$ and $B \rightarrow A$) via deterministic alphabetical lock ordering. - Added
spring-boot-resttestclientdependency topom.xmlfor Spring Boot 4.xTestRestTemplateautoconfiguration. - Added structured SLF4J logging across
TransactionServiceandUserServicefor enhanced transaction lifecycle observability.
Added - Phase 5A (Comprehensive Unit & Slice Test Suite)¶
- Created
UserServiceTest.javaverifying user registration, duplicate UPI prevention, UUID reference lookups, and pagination. - Created
UserRepositoryTest.javadata JPA slice test verifying custom query compilation, UUID lookups, and pessimistic locking (SELECT FOR UPDATE). - Created
BalanceLedgerRepositoryTest.javadata JPA slice test verifying aggregate balance reconciliation JPQL queries (SUM(CREDIT) - SUM(DEBIT)) and paginated audit retrieval. - Enhanced
UserControllerTest.javaandTransactionControllerTest.javaWebMvc slice tests verifying HTTP contracts, input validation (422 Unprocessable Entity), RFC 7807 problem details, and paginated ledger endpoints (GET /api/v1/users/{id}/ledger). - Added modular test starters
spring-boot-starter-data-jpa-testandspring-boot-starter-flywaytopom.xml.
[0.4.0] - 2026-08-11¶
Added - Phase 4B (Spring Profiles & Testcontainers Integration)¶
- Profile-specific YAML configuration structure (
application.yml,application-local.yml,application-test.yml,application-prod.yml). - Integrated Testcontainers PostgreSQL (
org.testcontainers:postgresql) andspring-boot-testcontainersBOM. - Abstract base class
AbstractIntegrationTest.javawith@Testcontainers(disabledWithoutDocker = true)and@DynamicPropertySourcefor 100% production-parity integration testing. - Created
PostgreSQLIntegrationTest.javaverifying real PostgreSQL container startup, Flyway schema migration execution, and Hibernateddl-auto=validateverification. - Added
ADR-014(Spring Environment Profiles and Testcontainers Integration Testing Strategy) todocs/adr/.
Added - Phase 4A (Flyway Migrations & PostgreSQL Integration)¶
- Version-controlled Flyway DDL migration scripts (
V1__create_users_table.sql,V2__create_transactions_table.sql,V3__create_balance_ledger_table.sql,V4__add_performance_indexes.sql). - Performance indexes added to database schema for UPI lookups (
idx_users_upi_id), UUID reference lookups (idx_users_reference_id,idx_tx_reference_id), transaction history statements (idx_tx_sender_created,idx_tx_receiver_created), and balance ledger audits (idx_ledger_user_created). - Added PostgreSQL driver (
postgresql),flyway-core, andflyway-database-postgresqldependencies. - Converted monolithic
application.propertiesconfiguration to structuredapplication.ymlsettingspring.jpa.hibernate.ddl-auto=validate. - Added
ADR-013(Flyway Database Migrations over DDL Auto-Generation) todocs/adr/.
[0.3.0] - 2026-08-09¶
Added - Phase 3C (Balance Ledger & Reconciliation)¶
- Double-entry balance ledger (
balance_ledgertable &BalanceLedgerEntryentity) writing atomicDEBIT(sender) andCREDIT(receiver) records on money transfers. - Balance audit tracking capturing
amount,balanceBefore, andbalanceAfterstate transitions for complete financial auditability. - Balance reconciliation aggregate SQL query
calculateReconciledBalanceByUserId()inBalanceLedgerRepositoryallowing reconstruction of authoritative balance state from ledger rows. GET /api/v1/users/{id}/ledgerendpoint returning paginated balance ledger history for a user by UUID reference ID.- Added
ADR-012(Double-Entry Balance Ledger as Immutable Audit Trail) todocs/adr/.
Added - Phase 3B (Pessimistic Locking & Deadlock Avoidance)¶
- Pessimistic write locking (
@Lock(LockModeType.PESSIMISTIC_WRITE)) onUserRepository.findByUpiIdWithLock()generatingSELECT ... FOR UPDATESQL statements to prevent race conditions during high-concurrency balance mutations. - Deterministic alphabetical lock acquisition ordering by UPI ID in
TransactionService.sendMoney()to prevent database deadlock cycles during concurrent reciprocal transfers. - JPA N+1 query optimization via
@EntityGraph(attributePaths = {"sender", "receiver"})onTransactionRepositoryquery methods. - Added
ADR-010(Pessimistic Locking for High-Concurrency Balance Operations) andADR-011(Deterministic Lock Ordering for Deadlock Prevention) todocs/adr/.
Added - Phase 3A (Money Transfer Implementation)¶
- Money transfer orchestration service (
TransactionService.sendMoney()) executed under@Transactional(isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class, timeout = 5). - Domain level validation for self-transfer rejection (
SelfTransferException), user verification (UserNotFoundException), and balance adequacy (InsufficientBalanceException). GET /api/v1/transactions/{id}endpoint to fetch transaction details by UUID reference ID.GET /api/v1/transactions/user/{upiId}endpoint to retrieve paginated transfer history for a given UPI ID.- Comprehensive unit tests (
TransactionServiceTest) and mock controller tests (TransactionControllerTest) covering transfer orchestration and transaction queries.
[0.2.0] - 2026-08-06¶
Added - Phase 2E (Model Refinements & Service Hardening)¶
- Added non-enumerable
UUID referenceIdtoUserentity to insulate REST APIs from auto-increment primary keys (userId). - Added
@Transactional(readOnly = true)annotations across allUserServiceread methods for Hibernate dirty-checking optimization. - Consolidated balance check validation directly inside
User.debit()throwingInsufficientBalanceException. - Enforced transfer upper bound cap (
@DecimalMax("1000000.00")) onTransferMoneyRequest. - Added MDC
%X{requestId}tracking pattern to application console logger. - Removed obsolete static
fromEntity()factories from response DTO records. - Added
ADR-007(UUID Reference IDs over Auto-Increment Primary Keys in APIs) todocs/adr/.
Added - Phase 2D (Error Handling & RFC 7807 Exception Framework)¶
- Implemented custom domain exception hierarchy (
PayflowException,UserNotFoundException,TransactionNotFoundException,InsufficientBalanceException,DuplicateUpiIdException,SelfTransferException). - Implemented global exception handling via
@RestControllerAdvice(GlobalExceptionHandler) producing standardized RFC 7807ProblemDetailresponses. - Implemented
RequestIdFilter(OncePerRequestFilter) forX-Request-IdMDC logging and response header correlation tracking. - Updated domain services (
UserService,TransactionService) and controllers to throw domain exceptions for clean, centralized handling. - Added unit test suites for
GlobalExceptionHandlerTestandRequestIdFilterTest. - Added
ADR-006(RFC 7807 ProblemDetail & Centralized Exception Handling) todocs/adr/.
Added - Phase 2C (Mapper Layer & API Documentation)¶
- Integrated MapStruct
1.6.3compile-time mappers (UserMapper,TransactionMapper) for type-safe DTO <-> Entity conversions. - Integrated Springdoc OpenAPI
3.0.3(springdoc-openapi-starter-webmvc-ui) for live interactive Swagger UI (/swagger-ui.html) and OpenAPI JSON specs (/v3/api-docs). - Added OpenAPI configuration bean (
OpenApiConfig) and controller OpenAPI annotations (@Tag,@Operation,@ApiResponse). - Added MapStruct mapper unit test suite (
UserMapperTest,TransactionMapperTest). - Added
ADR-005(MapStruct for compile-time type-safe DTO mapping) todocs/adr/.
Added - Phase 2B (DTO Layer, Input Validation & API Versioning)¶
- Versioned REST controllers under
/api/v1/usersand/api/v1/transactions. - Added
spring-boot-starter-validationdependency for Jakarta Validation (@Valid,@NotBlank,@Pattern,@DecimalMin,@Size,@Min,@Max). - Implemented request DTOs:
CreateUserRequestandTransferMoneyRequestwith strict validation rules. - Implemented response DTO records:
UserResponse,TransactionResponse, and genericPagedResponse<T>pagination wrapper. - Added controller web slice tests (
UserControllerTest,TransactionControllerTest) verifying HTTP status codes and input validation enforcement. - Added
ADR-004(URI-based API Versioning and DTO Isolation Layer) todocs/adr/.
Added - Phase 2A (Entity Model Hardening & Rich Domain)¶
- Replaced
Doubleprimitives withBigDecimal(precision = 19, scale = 4) acrossUserandTransactionentities. - Implemented Rich Domain methods (
User.debit(),User.credit()) encapsulating balance invariants and state validation. - Added audit timestamps (
createdAt,updatedAt) and optimistic locking (@Version version) support toUser. - Added
TransactionStatus(INITIATED,COMPLETED,FAILED,REFUNDED) andTransactionType(TRANSFER,REFUND) enums. - Added JPA
@ManyToOneforeign key relationships betweenTransactionandUserentities with denormalized UPI strings. - Added UUID
referenceIdauto-generation (@PrePersist) onTransaction. - Refactored all services (
UserService,TransactionService) and controllers (UserController,TransactionController) to use constructor injection. - Unit test suite for
Userdomain logic andTransactionreference ID auto-generation (UserTest,TransactionTest). - Architectural Decision Records:
ADR-001(BigDecimal),ADR-002(Constructor injection),ADR-003(Rich Domain Model).
[0.1.0] - 2026-07-27¶
Added¶
- Baseline Phase 0/1 implementation.
- Basic User (
/users) and Transaction (/transactions) REST endpoints. - Spring Data JPA entities (
User,Transaction) and repositories. - In-memory H2 database persistence for local development builds.
- Initial Spring Boot 4.1.0 project configuration with Java 25.
- System Architecture documentation (
docs/ARCHITECTURE.md), API Specification (docs/API_SPECIFICATION.md), and Phased Roadmap (docs/ROADMAP.md). - Project scaffolding: MIT
LICENSE,CHANGELOG.md,.editorconfig. - Architectural Decision Records log (
docs/adr/) and engineering standards guide (docs/CONVENTIONS.md). - Spotless code formatting plugin (
com.diffplug.spotless:spotless-maven-plugin) integrated into Maven build. - Checkstyle static analysis (
checkstyle.xml) plugin (maven-checkstyle-plugin) enforcing coding rules onvalidatephase. - GitHub Actions CI pipeline (
.github/workflows/ci.yml) for automated build, linting, formatting, and test execution on Java 25. - Repository contribution guidelines and branch protection rules (
CONTRIBUTING.md). - GitHub status badges in
README.md.
Fixed¶
- Dockerfile JDK version mismatch:
eclipse-temurin:21-jre→eclipse-temurin:25-jreto align with project'sjava.version. - Broken GraalVM native profile in
pom.xml: removed invalid dependency declaration with undefined property reference. - Removed
System.out.printlndebug statement fromUserController. - README updated to accurately reflect current project status.