$ mvn -pl order-fulfillment -am test -Dtest=ModularityTests#verifiesModuleStructure (captured with OrderManagement depending on InventoryManagement -- inventory's actual public API, not an internal type -- expecting this to fix the earlier violation) org.springframework.modulith.core.Violations: - Cycle detected: Slice inventory -> Slice order -> Slice inventory 1. Dependencies of Slice inventory - Method has parameter of type in (InventoryManagement.java:0) - Method calls method in (InventoryManagement.java:44) - Method calls method in (InventoryManagement.java:45) - Method calls method in (InventoryManagement.java:48) - Method calls method in (InventoryManagement.java:48) 2. Dependencies of Slice order - Constructor (com.ankurm.modulithdemo.order.internal.OrderRepository, org.springframework.context.ApplicationEventPublisher, com.ankurm.modulithdemo.inventory.InventoryManagement)> has parameter of type in (OrderManagement.java:0) - Field has type in (OrderManagement.java:0) - Method calls method in (OrderManagement.java:40) Tests run: 1, Failures: 0, Errors: 1, Skipped: 0 -- BUILD FAILURE Notice: no "non-exposed type" complaint this time -- InventoryManagement is inventory's real public API, exactly as advertised. Only "Cycle detected" remains, which proves the point: going through the public API fixes visibility violations, not direction violations. inventory already depends on order (its listener takes OrderPlaced as a parameter), so order depending on inventory in return -- through any type, public or not -- closes a cycle. The fix is to remove the dependency, not to launder it.