carnum-backend/
├── build.gradle.kts
├── settings.gradle.kts
├── gradle/
│ └── wrapper/
├── docker/
│ ├── Dockerfile
│ └── docker-compose.yml
├── src/
│ ├── main/
│ │ ├── java/az/carnum/
│ │ │ ├── CarnumApplication.java
│ │ │ ├── shared/ # Shared Kernel
│ │ │ ├── auth/ # Auth Module
│ │ │ ├── user/ # User Module
│ │ │ ├── car/ # Car Module
│ │ │ ├── document/ # Document Module
│ │ │ ├── search/ # Search Module
│ │ │ ├── messaging/ # Messaging Module
│ │ │ ├── feed/ # Feed Module
│ │ │ ├── notification/ # Notification Module
│ │ │ ├── admin/ # Admin Module
│ │ │ ├── carcoin/ # CarCoin Module
│ │ │ ├── tracking/ # Tracking Module
│ │ │ └── bff/ # BFF Layer
│ │ └── resources/
│ │ ├── application.yml
│ │ ├── application-dev.yml
│ │ ├── application-test.yml
│ │ ├── application-prod.yml
│ │ └── db/migration/ # Flyway migrations
│ │ ├── V001__create_users.sql
│ │ ├── V002__create_auth.sql
│ │ └── ...
│ └── test/
│ └── java/az/carnum/
│ ├── shared/
│ ├── auth/
│ ├── user/
│ ├── bff/
│ └── ...
└── docs/ # Layihə sənədləri
shared/
├── domain/
│ ├── BaseEntity.java # id, createdAt, updatedAt
│ ├── AuditableEntity.java # + createdBy, updatedBy
│ └── ValueObject.java # Marker interface
├── exception/
│ ├── BusinessException.java
│ ├── NotFoundException.java
│ ├── ForbiddenException.java
│ ├── RateLimitException.java
│ └── ValidationException.java
├── dto/
│ ├── PageRequest.java
│ ├── PageResponse.java
│ └── ErrorResponse.java
├── util/
│ ├── PhoneNumberUtil.java
│ ├── PlateNumberUtil.java
│ └── SlugUtil.java
├── config/
│ ├── JacksonConfig.java
│ ├── SecurityConfig.java
│ ├── RedisConfig.java
│ ├── AsyncConfig.java
│ └── OpenApiConfig.java
├── security/
│ ├── JwtTokenProvider.java
│ ├── JwtAuthenticationFilter.java
│ ├── CurrentUser.java # @CurrentUser annotation
│ └── UserPrincipal.java
└── event/
├── DomainEvent.java # Base event class
├── UserRegisteredEvent.java
├── CarAddedEvent.java
├── SearchPerformedEvent.java
└── DocumentVerifiedEvent.java
auth/
├── domain/
│ ├── model/
│ │ ├── UserCredential.java # Entity
│ │ ├── OtpToken.java # Value Object
│ │ ├── RefreshToken.java # Entity
│ │ ├── UserSession.java # Entity
│ │ └── LoginAttempt.java # Entity
│ ├── port/
│ │ ├── in/
│ │ │ ├── RegisterUseCase.java
│ │ │ ├── LoginUseCase.java
│ │ │ ├── RefreshTokenUseCase.java
│ │ │ ├── ResetPasswordUseCase.java
│ │ │ └── SessionManagementUseCase.java
│ │ └── out/
│ │ ├── UserCredentialRepository.java
│ │ ├── RefreshTokenRepository.java
│ │ ├── SessionRepository.java
│ │ ├── OtpStore.java # Port (Redis impl)
│ │ └── PasswordEncoder.java # Port
│ └── service/
│ └── AuthDomainService.java # Pure domain logic
├── application/
│ ├── usecase/
│ │ ├── RegisterUseCaseImpl.java
│ │ ├── LoginUseCaseImpl.java
│ │ ├── RefreshTokenUseCaseImpl.java
│ │ ├── ResetPasswordUseCaseImpl.java
│ │ └── SessionManagementUseCaseImpl.java
│ ├── dto/
│ │ ├── RegisterCommand.java
│ │ ├── LoginCommand.java
│ │ ├── TokenPair.java
│ │ └── SessionInfo.java
│ └── mapper/
│ └── AuthMapper.java # MapStruct
└── infrastructure/
├── persistence/
│ ├── JpaUserCredentialRepository.java
│ ├── JpaRefreshTokenRepository.java
│ ├── JpaSessionRepository.java
│ └── entity/ # JPA-specific entities (əgər lazımsa)
├── adapter/
│ ├── RedisOtpStore.java
│ ├── BCryptPasswordEncoderAdapter.java
│ └── SmsServiceAdapter.java
└── config/
└── AuthConfig.java
bff/
├── auth/
│ ├── AuthBffController.java
│ ├── dto/
│ │ ├── RegisterRequest.java
│ │ ├── RegisterResponse.java
│ │ ├── LoginRequest.java
│ │ ├── LoginResponse.java
│ │ ├── RefreshTokenRequest.java
│ │ ├── TokenResponse.java
│ │ ├── SendOtpRequest.java
│ │ ├── VerifyOtpRequest.java
│ │ ├── ResetPasswordRequest.java
│ │ └── SessionListResponse.java
│ └── mapper/
│ └── AuthBffMapper.java
├── user/
│ ├── UserBffController.java
│ ├── dto/
│ │ ├── UserProfileResponse.java
│ │ ├── UpdateProfileRequest.java
│ │ ├── PrivacySettingsResponse.java
│ │ └── UpdatePrivacyRequest.java
│ └── mapper/
│ └── UserBffMapper.java
├── car/
│ ├── CarBffController.java
│ ├── dto/
│ └── mapper/
├── search/
│ ├── SearchBffController.java
│ ├── dto/
│ └── mapper/
├── messaging/
│ ├── MessageBffController.java
│ ├── dto/
│ └── mapper/
├── feed/
│ ├── FeedBffController.java
│ ├── dto/
│ └── mapper/
├── notification/
│ ├── NotificationBffController.java
│ ├── dto/
│ └── mapper/
└── admin/
├── AdminBffController.java
├── dto/
└── mapper/
test/java/az/carnum/
├── shared/
│ └── TestFixtures.java # Shared test data builders
├── auth/
│ ├── domain/
│ │ └── service/
│ │ └── AuthDomainServiceTest.java # Unit
│ ├── application/
│ │ └── usecase/
│ │ ├── RegisterUseCaseImplTest.java # Unit
│ │ └── LoginUseCaseImplTest.java # Unit
│ └── infrastructure/
│ └── persistence/
│ └── JpaUserCredentialRepositoryTest.java # Integration
├── bff/
│ ├── auth/
│ │ ├── AuthBffControllerTest.java # MockMvc
│ │ └── AuthBffContractTest.java # No extra fields check
│ └── user/
│ ├── UserBffControllerTest.java
│ └── UserBffContractTest.java
└── architecture/
└── ArchitectureTest.java # ArchUnit rules
V001__create_shared_tables.sql
V002__create_user_credentials.sql
V003__create_refresh_tokens.sql
V004__create_user_sessions.sql
V005__create_login_attempts.sql
V006__create_users.sql
V007__create_cars.sql
V008__create_documents.sql
V009__create_carcoin.sql
...
services:
postgres:
image: timescale/timescaledb:latest-pg16
ports: ["5432:5432"]
environment:
POSTGRES_DB: carnum
POSTGRES_USER: carnum
POSTGRES_PASSWORD: carnum_dev
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
ports: ["6379:6379"]
volumes:
pgdata: