# AGENTS.md Spring Boot **4.1.0** / Java 17 REST backend for an LMS (PostgreSQL). Root package `aplp.backend.lms`. ## Commands - Build: `./mvnw -DskipTests package` - Run: `./mvnw spring-boot:run` - All tests: `./mvnw test` - Single test: `./mvnw test -Dtest=LmsApplicationTests` - Requires JDK 17. No linter, formatter, or checkstyle is configured — don't invent one. ## Build gotcha: GitLab Maven registry `aplp.backend:core:1.0-SNAPSHOT` is not built here; it resolves from the GitLab package registry (repository id `gitlab-maven` in `pom.xml`). A fresh checkout needs a token for server id `gitlab-maven` in `~/.m2/settings.xml` (or the artifact cached in `~/.m2/repository`). Credentials are not in the repo. ## `aplp.backend.core` shared types Not defined in this repo; import them instead of recreating: - `BaseEntity` — `@MappedSuperclass` for every entity: `id`, `createdAt/By`, `updatedAt/By`, `deletedAt/By`; timestamps set via `@PrePersist`/`@PreUpdate`. - `ApiResponse` — `ok(data)`, `ok(message, data)`, `error(code, message)`. - `PagedResponse` — `of(content, page, size, totalElements)`. - `ErrorCode`, `DomainException`, `ResourceNotFoundException`, `TokenHasher.sha256Hex`. ## Architecture Vertical slices per feature under `aplp.backend.lms.` (currently `course`, `lesson`, `section`); `common/` holds cross-cutting `api`, `config`, `security`. Layers per feature: - `api/controller` — `@RestController`, returns `ResponseEntity>` - `application/services`, `application/dtos` (Java records), `application/mappers` (MapStruct) - `domain/entities`, `domain/enums`, `domain/repositories` (plain interfaces) - `infrastructure/persistence` — `*RepositoryImpl` implements the domain repo and delegates to a Spring Data `*JpaRepository` Conventions: - Entities extend `BaseEntity`, use Lombok `@Getter/@Setter/@NoArgsConstructor`, `@Table` snake_case. - Controllers stay thin; services throw `ResourceNotFoundException`; `GlobalExceptionHandler` maps exceptions to `ApiResponse`. - Mappers are interfaces annotated `@Mapper(componentModel = "spring")`; Lombok/MapStruct annotation processing is already wired in `pom.xml`. - Add derived queries to `*JpaRepository` and expose them through the domain repo interface. ## Database - PostgreSQL, Hibernate default schema `lms`; datasource hardcoded in `src/main/resources/application.yaml`. - **`spring.flyway.enabled: false` + `spring.jpa.hibernate.ddl-auto: update`**: Hibernate maintains the schema at runtime. Scripts in `db/migration` (`V{n}__desc.sql`) are history only and are NOT applied on startup. A schema change needs both the entity field and a migration; don't assume Flyway runs. - jsonb columns use `@JdbcTypeCode(SqlTypes.JSON)` on a `String` field. ## Security - `SecurityConfig` disables CSRF and `permitAll`s every request — endpoints are currently unauthenticated despite OpenAPI declaring a `bearerAuth` JWT scheme (Swagger UI at `/swagger-ui`). - `JpaAuditingConfig` reads the current user from `SecurityContextHolder` and expects `Authentication.getPrincipal()` to be a `Long` userId. ## Testing Only `LmsApplicationTests` (`@SpringBootTest contextLoads`) exists. There is no `src/test/resources` or test profile, so tests use the real `application.yaml` datasource and require access to the remote DB — `./mvnw test` fails without it.