spring-code-review-rubric
Pre-commit code review rubric for Spring Boot 4 changes. Used by `spring-code-reviewer` to produce `08-code-review.md` before any commit. Covers traceability, architecture, Spring idioms, error handli
Files1
View on GitHubSKILL.md.claude/skills/spring-code-review-rubric/SKILL.md
GitHubSpring code review rubric
Severity ladder
- blocker — must fix before commit. (Security hole, broken behavior, gate-bypass.)
- major — must fix before commit OR document as ADR + waiver.
- minor — should fix; leave a note if not.
- nit — taste; mention once, don't insist.
Ten sections
1. Traceability
- Every diff hunk maps to an
AC-NNNand aT-NNN. - Files-in-scope honored (no edits outside the task's declared paths).
- Any new public API has a test referencing the AC.
2. Architecture
- Module boundaries respected (no
internalcross-imports). - ArchUnit rules pass (see
archunit-rules). - Layering correct (no controller→repository skip).
- No new circular dependency.
3. Spring idioms
- Constructor injection only (
spring-boot-4-conventions). - Package layout is by feature/domain, not by layer (no top-level
controller/service/repository/modelpackages). @HttpExchange/RestClient(no newRestTemplate).@MockitoBean, not@MockBean.- No
@Autowiredon fields or constructors. - No
@SpringBootTestwhere a slice would do. - No Lombok anywhere in the diff (any
lombok.*import is a must-fix). - No fully-qualified type names (FQNs) inline in code — method parameters, return types,
throwsclauses, and bodies must use simple names backed by properimportstatements at the top of the file. E.g.jakarta.servlet.http.HttpServletResponse responseas a parameter is a must-fix; it must beHttpServletResponse responsewithimport jakarta.servlet.http.HttpServletResponse;.
4. Error handling
- Exceptions translated at the controller boundary, not in the service.
- Single error envelope shape, documented in OpenAPI.
- No
catch (Exception e) { throw new RuntimeException(e); }. - Domain exceptions are checked or sealed, not raw
RuntimeException.
5. Data access
- No N+1 queries (look for entity navigation in a loop).
- All list endpoints paginated.
- Migration script forward-only OR rollback documented.
- No raw SQL with string concatenation.
- Transactions on services, not controllers.
6. Security
- Apply
spring-security-baselinerubric. - No secrets in source.
- Input validation at boundary AND service.
- Sensitive logs masked.
- No new High/Critical CVE.
7. Test quality
- Tests fail for the right reason (re-read the red excerpt in
05-implementation-log.md). - One AC per test where possible.
- No
@Disabledwithout# DisabledReason. - No removed assertions.
- Coverage holds; new code ≥95%.
- Mutants in changed packages all killed (or ADR-justified).
- Testcontainers used where required by stack detection.
8. Clarity over cleverness
- Apply
clarity-over-clevernessskill. - Names match domain language from
01-spec.mdglossary. - No dead code, no commented-out blocks.
- Public methods have a single responsibility.
- Method length ≤ 30 lines (guideline, not hard rule).
9. Migration / contract
- OpenAPI diff matches actual code (springdoc check).
- Breaking changes have an ADR.
- DB migration follows
flyway-or-liquibase-detection. - No edits to a previously-released migration script.
10. Performance
Apply .claude/skills/performance-optimization/SKILL.md. Block on:
- Any controller method returning
List<T>without pagination (Pageable). - N+1 queries (entity navigation in a loop or stream).
- New external HTTP call without explicit connect/read/write timeouts.
@Cacheableadded without a TTL or a size cap.@Transactionalwrapping an outbound HTTP call.synchronizedblock around an I/O call (pins virtual-thread carriers).- Hikari
maximumPoolSizechange without a measurement artifact. - A
Counterused to record a duration (useTimerwith histogram). - A perf-labeled change without a profile, JMH result, or before/after metric in
05-implementation-log.md.
Findings table format
| ID | Severity | Section | File | Line | Finding | Suggested fix |
|----|---------|---------|------|------|---------|---------------|
| F-001 | blocker | security | CheckoutController.java | 47 | `@CrossOrigin("*")` on a state-changing endpoint | restrict to allowed origins or remove |
| F-002 | minor | clarity | PriceCalculator.java | 23 | nested ternary `a ? b ? c : d : e` | extract two helper methods |
Verdict
End with one of:
- ✅ Approve — no blockers; minors noted; safe to commit.
- ⚠️ Approve with waivers — blockers/majors waived via the listed ADRs; commit OK.
- ❌ Request changes — blockers exist, no waivers; commit blocked.