# CLAUDE.md — working context for this repository

Production-grade Spring Boot API server: Item CRUD + full authentication
(registration, activation, JWT login with lockout, refresh-token rotation with
reuse detection, password reset), served over TLS on **port 4455**. The
authoritative specification is `docs/PROMT.md`; this file is the fast-reference
for future sessions.

## Stack

- Java **21**, Spring Boot **3.5.16**, Maven (Spring Boot parent BOM).
- Spring Web MVC, Spring Data JPA, Spring Validation, Spring Security 6.
- PostgreSQL 16, **Flyway** for schema (never Hibernate DDL — `ddl-auto` stays
  `validate`).
- MapStruct (DTO ↔ entity), Lombok limited to
  `@Getter/@Setter/@Builder/@RequiredArgsConstructor` (no `@Data` on entities).
- springdoc-openapi, Actuator + Micrometer.
- Tests: JUnit 5, Mockito, AssertJ, **Testcontainers** (Postgres + GreenMail),
  MockMvc, **ArchUnit**, JaCoCo, PIT.
- Static analysis: Spotless (google-java-format **AOSP**), Checkstyle, SpotBugs.

## Base package & layout

Base package `com.codebyte.api`. Feature-first packages: `config/`, `common/`
(`error`, `audit`, `util`), `item/` (`api`, `domain`, `repository`, `service`,
`mapper`), `auth/` (`api`, `domain`, `repository`, `service`, `security`).

## Layer rules (enforced by ArchUnit from Phase 2)

- Controllers never touch repositories. Services never return entities to the API
  layer — DTOs only.
- `@Transactional` on **service** methods (`readOnly = true` where applicable),
  never on controllers.
- Constructor injection only; no field `@Autowired`.
- All API DTOs are Java `record`s with Bean Validation annotations.
- No `java.util.Date`, no `System.out`/`System.err`, no package cycles, no entity
  in an `api` package.

## Test conventions

- Naming: `should_<expected>_when_<condition>`.
- Unit tests: `*Test` / `*Tests`, no Spring context, run by **Surefire**.
- Integration tests: `*IT`, `@SpringBootTest` + real Postgres via Testcontainers
  `@ServiceConnection`, run by **Failsafe**.
- Never use H2 to stand in for Postgres behaviour. Tests must assert more than
  HTTP 200 — status, body shape, `ProblemDetail` `code`, and headers.

## Commands

Run the build with the pinned JDK 21 (`JAVA_HOME=~/.sdkman/candidates/java/21-tem`):

| Task | Command |
|---|---|
| build (compile + package) | `./mvnw -q clean package` |
| unit tests only | `./mvnw -q test` |
| integration tests + full gate | `./mvnw -q verify` |
| format code | `./mvnw spotless:apply` |
| mutation testing | `./mvnw -Dpitest.skip=false org.pitest:pitest-maven:mutationCoverage` |
| run locally (compose) | `docker compose up --build` (Phase 1+) |
| full local pre-push check | `./scripts/verify.sh` / `make verify` (Phase 9+) |

**Local Docker is Colima.** Integration tests (`*IT`) need these env vars so the
JVM reaches containers over IPv4 and skips the unreachable Ryuk reaper — not
needed on Docker Desktop or in CI:

```bash
export TESTCONTAINERS_HOST_OVERRIDE=127.0.0.1
export TESTCONTAINERS_RYUK_DISABLED=true
```

Compose plugin (`docker compose`) is not installed here; use the standalone
`docker-compose` binary.

Coverage and mutation gates are wired but held off by `-Dcoverage.gate.skip`
and `-Dpitest.skip` (default `true`) until service code exists; CI runs with
them set to `false`. See `docs/adr/0001-stack.md`.

## Delivery rule — STOP AT EVERY PHASE GATE

Work **one phase at a time** (`PLAN.md`). At each gate: run build + tests, report
a short summary and any ADR, then **stop and wait for an explicit "continue"**.
Do not start the next phase unprompted.
