|
| 1 | +# Spring Boot Code Guard |
| 2 | + |
| 3 | +Konsist-based static analysis library for Spring Boot. Rules run as JUnit 5 tests. Kotlin + Gradle (Kotlin DSL), JVM 17. Published to Maven Central as `dev.protsenko:spring-boot-code-guard`. |
| 4 | + |
| 5 | +## Tools (mandatory) |
| 6 | + |
| 7 | +- **File & coding tasks**: use the **mcpc idea** tools (skill: /skill:mcpc-idea-strict-workflow) for every read, edit, create, rename, reformat, inspection, build, and run operation — do not use generic shell fallbacks when an mcpc @idea equivalent exists. |
| 8 | +- **Project lookup (when mcpc failed)**: use the **GrepAI** skills (`grepai search`, `grepai trace callers|callees|graph`, `grepai status`) for all code search, symbol discovery, and call-graph questions. |
| 9 | + |
| 10 | +## Layout |
| 11 | + |
| 12 | +``` |
| 13 | +src/main/kotlin/dev/protsenko/codeguard/ |
| 14 | + core/ # SpringBootRule, DSL entry, suppression, RuleBuilder |
| 15 | + rules/{general,jpa,naming,packages,web}/ # rule objects + DSL contexts |
| 16 | +src/test/kotlin/ |
| 17 | + dev/protsenko/codeguard/coverage/ # violation tests per rule group |
| 18 | + fixtures/violations/ # fixture classes triggered by tests |
| 19 | +``` |
| 20 | + |
| 21 | +Entry point: `springBootRules { }.verify()` (`core/SpringBootRulesConfiguration.kt`). |
| 22 | + |
| 23 | +## Rule anatomy |
| 24 | + |
| 25 | +Each rule is an `object : SpringBootRule` with `description`, `suppressKey`, `verify(scope)`. Per-class silence: `@Suppress("CodeGuard:<key>")`. DSL-wide opt-out: `exclude("CodeGuard:<key>")`. |
| 26 | + |
| 27 | +## Adding a new rule — mandatory checklist |
| 28 | + |
| 29 | +Follow every step in order. Do not skip. |
| 30 | + |
| 31 | +### 1. TDD — fixtures and tests first (use `/simplify` skill after) |
| 32 | + |
| 33 | +Use `/skill:mcpc-idea-strict-workflow` to create fixture classes under `src/test/kotlin/fixtures/violations/<category>/<rule>/`: |
| 34 | +- `*Negative.kt` — class that triggers the violation (one per interesting failure case) |
| 35 | +- `*Positive.kt` — class that must pass (one per interesting pass case) |
| 36 | + |
| 37 | +Then add test methods to the matching `*ViolationTest.kt` in `src/test/kotlin/dev/protsenko/codeguard/coverage/`. Each negative test must assert the exact error message. Each positive test just calls `rule.verify(scope)` without `assertFailsWith`. |
| 38 | + |
| 39 | +Typical cases to cover per rule: |
| 40 | +- Wrong stereotype alone in the constrained location → fail |
| 41 | +- Correct stereotype alone → pass |
| 42 | +- Correct stereotype with file-level helpers in same file → pass |
| 43 | +- Unannotated class alone in constrained location → fail |
| 44 | + |
| 45 | +### 2. Implement the rule |
| 46 | + |
| 47 | +Add the rule `object` to the relevant `*Rules.kt` in `src/main/kotlin/.../rules/<category>/`. Use `hasAnnotationWithName(SpringAnnotations.*)` (not `hasAnnotationOf`). Group by `containingFile` when file-level helper exemptions are needed. |
| 48 | + |
| 49 | +### 3. Register in `all*Rules` list |
| 50 | + |
| 51 | +Every `*Rules.kt` file exposes a `val all*Rules: List<SpringBootRule>` at the bottom. Add the new rule there. `AllRulesTest` asserts exact counts — update `allPackageRules contains N rules` (or equivalent) to match. |
| 52 | + |
| 53 | +### 4. Expose in DSL context and `AllRulesTest` individual block |
| 54 | + |
| 55 | +Add a DSL function to the matching `*RuleContext.kt`. Then add the call to the `withIndividual` block in `AllRulesTest.kt` alongside existing peers (e.g. `entitiesInEntityPackage()`). |
| 56 | + |
| 57 | +### 5. Register in `UsageExampleTest` |
| 58 | + |
| 59 | +Add the new DSL call next to its category peers in `src/test/kotlin/dev/protsenko/codeguard/usage/UsageExampleTest.kt`. |
| 60 | + |
| 61 | +### 6. Update README.md |
| 62 | + |
| 63 | +Add one bullet to the matching section in `README.md` under `## Rule Set`. Format: `` - `CodeGuard:<key>`: <what it enforces and why>. Exception: <if any>. `` |
| 64 | + |
| 65 | +### 7. Run `./gradlew codeBaseline` |
| 66 | + |
| 67 | +Must pass clean: tests + detekt + 90% coverage floor. |
0 commit comments