layered-architecture — independently scanned and version-tracked by SaferSkills.
SaferSkills independently audited layered-architecture (Agent Skill) and scored it 100/100 (green). The audit ran 55 deterministic rules across Security, Supply Chain, Maintenance, Transparency, and Community; it found 0 high-severity and 0 lower-severity findings. The full rule-by-rule trace and per-finding evidence are below. Free, methodology-open.
Findings & checks · 0 flagged
Every scanned point with the score it earned and what moved between them.
First recorded scan — no prior version to compare against.
The primary manifest — the file an agent reads to learn what this artifact does.
@RestController ← HTTP only. No business logic. No JPA entities in responses.
↓ DTOs
@Service ← All business logic lives here. Orchestrates repositories.
↓ Domain objects / Entities
@Repository ← Data access only. No business logic. Returns entities or projections.
↓ JPA / JDBC
Database@Valid), returning responses@Entity classes directly — always map to response DTOs@Repository — always goes through a @Service@ControllerAdvice, never try/catch in controllers// ✅ GOOD
@PostMapping("/orders")
public ResponseEntity<OrderResponse> createOrder(@Valid @RequestBody CreateOrderRequest request) {
Order order = orderService.createOrder(request);
return ResponseEntity.status(HttpStatus.CREATED).body(OrderResponse.from(order));
}
// ❌ BAD — business logic in controller
@PostMapping("/orders")
public ResponseEntity<Order> createOrder(@RequestBody CreateOrderRequest request) {
if (request.getItems().isEmpty()) throw new RuntimeException("No items");
Order order = orderRepository.save(new Order(request)); // direct repo access
return ResponseEntity.ok(order); // returning entity
}@Transactional lives here, not in controllers or repositories@Autowired field injectionHttpServletRequest / HttpServletResponse// ✅ GOOD
@Service
@RequiredArgsConstructor
public class OrderService {
private final OrderRepository orderRepository;
private final InventoryService inventoryService;
@Transactional
public Order createOrder(CreateOrderRequest request) {
inventoryService.reserve(request.getItems());
Order order = Order.from(request);
return orderRepository.save(order);
}
}
// ❌ BAD — field injection, HTTP concern in service
@Service
public class OrderService {
@Autowired private OrderRepository orderRepository;
public ResponseEntity<Order> createOrder(...) { ... } // HTTP type in service
}JpaRepository<Entity, ID> or CrudRepository@Query or query derivation — no raw SQL unless unavoidableObject[]@NotNull, @Size, etc.) on Request DTOs onlyResponseDto.from(Entity entity) for mapping// ✅ GOOD
public record OrderResponse(UUID id, String status, List<LineItemResponse> items) {
public static OrderResponse from(Order order) {
return new OrderResponse(order.getId(), order.getStatus().name(),
order.getItems().stream().map(LineItemResponse::from).toList());
}
}OrderResponse.from(order))Order.from(request)) or a mapper class.stream().map(OrderResponse::from).toList() — never manual loops// ✅ GOOD — dedicated mapper for complex mappings
public class OrderMapper {
public static OrderResponse toResponse(Order order) {
return new OrderResponse(
order.getId(),
order.getStatus().name(),
order.getItems().stream().map(OrderMapper::toLineItem).toList(),
order.getCreatedAt()
);
}
public static Order toEntity(CreateOrderRequest request, User user) {
Order order = Order.create(request.customerEmail(), user);
request.items().forEach(item ->
order.addItem(item.productId(), item.quantity()));
return order;
}
private static LineItemResponse toLineItem(OrderItem item) {
return new LineItemResponse(item.getProductId(), item.getQuantity(), item.getPrice());
}
}@Configuration classes live in a config/ package — never in service/ or controller/@ConfigurationProperties for type-safe config — never raw @Value for groups of related settings@Slf4j — never System.out.println@Valid on controller parameters, custom validators as @Component@RestControllerAdvice class, never try/catch in controllers@CreatedDate / @LastModifiedDate with @EnableJpaAuditing@Transactional on controllers — move it to services@Autowired field injection — always use constructor injection (@RequiredArgsConstructor)List<Entity> from controllers — always map to List<ResponseDto>OrderAndInventoryService god classes — split by aggregate@Configuration classes that depend on @Service beans — configuration should only wire infrastructure~30 seconds. Free. No account. Every finding cites a rule and a line of evidence.