activo 0.4.3 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (166) hide show
  1. package/README.md +203 -1
  2. package/data/2026-03-04_20-54.json +181 -0
  3. package/data/2026-03-04_20-56.json +181 -0
  4. package/data/apex-rulesets/egov.yaml +469 -0
  5. package/data/apex-rulesets/modernize.yaml +687 -0
  6. package/data/apex-rulesets/quality.yaml +1677 -0
  7. package/data/apex-rulesets/rule-schema.yaml +587 -0
  8. package/data/apex-rulesets/secure.yaml +1688 -0
  9. package/data/apex-rulesets/spring.yaml +455 -0
  10. package/data/apex-rulesets/sql-format.yaml +99 -0
  11. package/data/apex-rulesets/sql-oracle.yaml +281 -0
  12. package/data/apex-rulesets/sql.yaml +1660 -0
  13. package/dist/cli/headless.d.ts.map +1 -1
  14. package/dist/cli/headless.js +32 -10
  15. package/dist/cli/headless.js.map +1 -1
  16. package/dist/cli/index.js +31 -3
  17. package/dist/cli/index.js.map +1 -1
  18. package/dist/core/agent.d.ts +3 -3
  19. package/dist/core/agent.d.ts.map +1 -1
  20. package/dist/core/agent.js +255 -17
  21. package/dist/core/agent.js.map +1 -1
  22. package/dist/core/commands.d.ts +2 -1
  23. package/dist/core/commands.d.ts.map +1 -1
  24. package/dist/core/commands.js +61 -9
  25. package/dist/core/commands.js.map +1 -1
  26. package/dist/core/config.d.ts +14 -0
  27. package/dist/core/config.d.ts.map +1 -1
  28. package/dist/core/config.js +41 -4
  29. package/dist/core/config.js.map +1 -1
  30. package/dist/core/conversation.d.ts +2 -2
  31. package/dist/core/conversation.d.ts.map +1 -1
  32. package/dist/core/conversation.js.map +1 -1
  33. package/dist/core/intentRouter.d.ts +43 -0
  34. package/dist/core/intentRouter.d.ts.map +1 -0
  35. package/dist/core/intentRouter.js +804 -0
  36. package/dist/core/intentRouter.js.map +1 -0
  37. package/dist/core/llm/anthropic.d.ts +24 -0
  38. package/dist/core/llm/anthropic.d.ts.map +1 -0
  39. package/dist/core/llm/anthropic.js +226 -0
  40. package/dist/core/llm/anthropic.js.map +1 -0
  41. package/dist/core/llm/ollama.d.ts +5 -14
  42. package/dist/core/llm/ollama.d.ts.map +1 -1
  43. package/dist/core/llm/ollama.js +3 -0
  44. package/dist/core/llm/ollama.js.map +1 -1
  45. package/dist/core/llm/types.d.ts +22 -0
  46. package/dist/core/llm/types.d.ts.map +1 -0
  47. package/dist/core/llm/types.js +2 -0
  48. package/dist/core/llm/types.js.map +1 -0
  49. package/dist/core/mcp/client.d.ts +6 -0
  50. package/dist/core/mcp/client.d.ts.map +1 -1
  51. package/dist/core/mcp/client.js +16 -0
  52. package/dist/core/mcp/client.js.map +1 -1
  53. package/dist/core/mcp/init.d.ts +12 -0
  54. package/dist/core/mcp/init.d.ts.map +1 -0
  55. package/dist/core/mcp/init.js +55 -0
  56. package/dist/core/mcp/init.js.map +1 -0
  57. package/dist/core/mcp/logger.d.ts +14 -0
  58. package/dist/core/mcp/logger.d.ts.map +1 -0
  59. package/dist/core/mcp/logger.js +50 -0
  60. package/dist/core/mcp/logger.js.map +1 -0
  61. package/dist/core/tools/analyzeAll.d.ts.map +1 -1
  62. package/dist/core/tools/analyzeAll.js +16 -28
  63. package/dist/core/tools/analyzeAll.js.map +1 -1
  64. package/dist/core/tools/analyzePatterns.d.ts +3 -0
  65. package/dist/core/tools/analyzePatterns.d.ts.map +1 -0
  66. package/dist/core/tools/analyzePatterns.js +293 -0
  67. package/dist/core/tools/analyzePatterns.js.map +1 -0
  68. package/dist/core/tools/apexPaths.d.ts +14 -0
  69. package/dist/core/tools/apexPaths.d.ts.map +1 -0
  70. package/dist/core/tools/apexPaths.js +54 -0
  71. package/dist/core/tools/apexPaths.js.map +1 -0
  72. package/dist/core/tools/apexUtils.d.ts +36 -0
  73. package/dist/core/tools/apexUtils.d.ts.map +1 -0
  74. package/dist/core/tools/apexUtils.js +83 -0
  75. package/dist/core/tools/apexUtils.js.map +1 -0
  76. package/dist/core/tools/explainIssue.d.ts +3 -0
  77. package/dist/core/tools/explainIssue.d.ts.map +1 -0
  78. package/dist/core/tools/explainIssue.js +181 -0
  79. package/dist/core/tools/explainIssue.js.map +1 -0
  80. package/dist/core/tools/fixGen.d.ts +3 -0
  81. package/dist/core/tools/fixGen.d.ts.map +1 -0
  82. package/dist/core/tools/fixGen.js +338 -0
  83. package/dist/core/tools/fixGen.js.map +1 -0
  84. package/dist/core/tools/generateImprovements.d.ts +21 -0
  85. package/dist/core/tools/generateImprovements.d.ts.map +1 -0
  86. package/dist/core/tools/generateImprovements.js +602 -0
  87. package/dist/core/tools/generateImprovements.js.map +1 -0
  88. package/dist/core/tools/generateReport.d.ts +3 -0
  89. package/dist/core/tools/generateReport.d.ts.map +1 -0
  90. package/dist/core/tools/generateReport.js +315 -0
  91. package/dist/core/tools/generateReport.js.map +1 -0
  92. package/dist/core/tools/index.d.ts +7 -0
  93. package/dist/core/tools/index.d.ts.map +1 -1
  94. package/dist/core/tools/index.js +62 -23
  95. package/dist/core/tools/index.js.map +1 -1
  96. package/dist/core/tools/javaAst.d.ts.map +1 -1
  97. package/dist/core/tools/javaAst.js +191 -0
  98. package/dist/core/tools/javaAst.js.map +1 -1
  99. package/dist/core/tools/recommendProfile.d.ts +3 -0
  100. package/dist/core/tools/recommendProfile.d.ts.map +1 -0
  101. package/dist/core/tools/recommendProfile.js +334 -0
  102. package/dist/core/tools/recommendProfile.js.map +1 -0
  103. package/dist/core/tools/ruleGen.d.ts +3 -0
  104. package/dist/core/tools/ruleGen.d.ts.map +1 -0
  105. package/dist/core/tools/ruleGen.js +1103 -0
  106. package/dist/core/tools/ruleGen.js.map +1 -0
  107. package/dist/core/tools/standards.d.ts.map +1 -1
  108. package/dist/core/tools/standards.js +7 -3
  109. package/dist/core/tools/standards.js.map +1 -1
  110. package/dist/ui/App.d.ts.map +1 -1
  111. package/dist/ui/App.js +86 -35
  112. package/dist/ui/App.js.map +1 -1
  113. package/dist/ui/components/InputBox.d.ts +1 -3
  114. package/dist/ui/components/InputBox.d.ts.map +1 -1
  115. package/dist/ui/components/InputBox.js +146 -5
  116. package/dist/ui/components/InputBox.js.map +1 -1
  117. package/dist/ui/components/MessageList.d.ts +3 -1
  118. package/dist/ui/components/MessageList.d.ts.map +1 -1
  119. package/dist/ui/components/MessageList.js +13 -7
  120. package/dist/ui/components/MessageList.js.map +1 -1
  121. package/dist/ui/components/StatusBar.d.ts +1 -1
  122. package/dist/ui/components/StatusBar.d.ts.map +1 -1
  123. package/dist/ui/components/StatusBar.js +3 -2
  124. package/dist/ui/components/StatusBar.js.map +1 -1
  125. package/dist/ui/components/ToolStatus.d.ts +3 -1
  126. package/dist/ui/components/ToolStatus.d.ts.map +1 -1
  127. package/dist/ui/components/ToolStatus.js +19 -4
  128. package/dist/ui/components/ToolStatus.js.map +1 -1
  129. package/package.json +7 -1
  130. package/demo.gif +0 -0
  131. package/demo.tape +0 -53
  132. package/screenshot.png +0 -0
  133. package/src/cli/banner.ts +0 -38
  134. package/src/cli/headless.ts +0 -63
  135. package/src/cli/index.ts +0 -57
  136. package/src/core/agent.ts +0 -237
  137. package/src/core/commands.ts +0 -118
  138. package/src/core/config.ts +0 -98
  139. package/src/core/conversation.ts +0 -235
  140. package/src/core/llm/ollama.ts +0 -351
  141. package/src/core/mcp/client.ts +0 -143
  142. package/src/core/tools/analyzeAll.ts +0 -494
  143. package/src/core/tools/ast.ts +0 -826
  144. package/src/core/tools/builtIn.ts +0 -221
  145. package/src/core/tools/cache.ts +0 -570
  146. package/src/core/tools/cssAnalysis.ts +0 -324
  147. package/src/core/tools/dependencyAnalysis.ts +0 -363
  148. package/src/core/tools/embeddings.ts +0 -746
  149. package/src/core/tools/frontendAst.ts +0 -802
  150. package/src/core/tools/htmlAnalysis.ts +0 -466
  151. package/src/core/tools/index.ts +0 -160
  152. package/src/core/tools/javaAst.ts +0 -812
  153. package/src/core/tools/memory.ts +0 -655
  154. package/src/core/tools/mybatisAnalysis.ts +0 -322
  155. package/src/core/tools/openapiAnalysis.ts +0 -431
  156. package/src/core/tools/pythonAnalysis.ts +0 -477
  157. package/src/core/tools/sqlAnalysis.ts +0 -298
  158. package/src/core/tools/standards.test.ts +0 -186
  159. package/src/core/tools/standards.ts +0 -889
  160. package/src/core/tools/types.ts +0 -38
  161. package/src/ui/App.tsx +0 -334
  162. package/src/ui/components/InputBox.tsx +0 -37
  163. package/src/ui/components/MessageList.tsx +0 -80
  164. package/src/ui/components/StatusBar.tsx +0 -36
  165. package/src/ui/components/ToolStatus.tsx +0 -38
  166. package/tsconfig.json +0 -21
@@ -0,0 +1,469 @@
1
+ # eGovernment Framework Standards Ruleset
2
+ # 전자정부 표준프레임워크 개발 표준 규칙
3
+ # - 계층 구조 및 명명 규칙
4
+ # - Service / Mapper / DAO 표준
5
+ # - 공통 컴포넌트 활용
6
+ # - 메서드 명명 표준 (CRUD 접두사)
7
+ # - 아키텍처 위반 검출
8
+ version: "1.0"
9
+ profile: "egov"
10
+
11
+ languages:
12
+ - language: java
13
+ rules:
14
+ # ==================== 1. 계층 명명규칙 ====================
15
+
16
+ - id: "egov-naming-001"
17
+ name: "Controller 클래스 접미사 누락"
18
+ severity: "high"
19
+ category: "naming"
20
+ description: "Controller 역할 클래스는 *Controller 접미사를 사용해야 합니다."
21
+ enabled: true
22
+ pattern:
23
+ type: "regex-multiline"
24
+ regex: "@Controller[\\s\\S]*?class\\s+(?!\\w*Controller\\b)\\w+"
25
+ custom:
26
+ rule_id: "EGOV-NAME-001"
27
+ fix: "클래스명에 Controller 접미사를 추가하세요 (예: UserMngController)"
28
+
29
+ - id: "egov-naming-002"
30
+ name: "Service 인터페이스 접미사 누락"
31
+ severity: "high"
32
+ category: "naming"
33
+ description: "Service 역할 인터페이스는 *Service 접미사를 사용해야 합니다."
34
+ enabled: true
35
+ pattern:
36
+ type: "regex-multiline"
37
+ regex: "interface\\s+(?![A-Z]\\w*Service\\b)\\w+\\s*\\{[\\s\\S]*?(select|insert|update|delete)\\w+\\s*\\("
38
+ custom:
39
+ rule_id: "EGOV-NAME-002"
40
+ fix: "인터페이스명에 Service 접미사를 추가하세요 (예: UserMngService)"
41
+
42
+ - id: "egov-naming-003"
43
+ name: "ServiceImpl 클래스 접미사 누락"
44
+ severity: "high"
45
+ category: "naming"
46
+ description: "Service 구현 클래스는 *ServiceImpl 접미사를 사용해야 합니다."
47
+ enabled: true
48
+ pattern:
49
+ type: "regex-multiline"
50
+ regex: "class\\s+(?!\\w*ServiceImpl\\b)\\w+[^{]*implements\\s+\\w+Service\\b"
51
+ custom:
52
+ rule_id: "EGOV-NAME-003"
53
+ fix: "클래스명에 ServiceImpl 접미사를 추가하세요 (예: UserMngServiceImpl)"
54
+
55
+ - id: "egov-naming-004"
56
+ name: "Mapper/DAO 인터페이스 접미사 위반"
57
+ severity: "medium"
58
+ category: "naming"
59
+ description: "데이터 접근 인터페이스는 *Mapper 또는 *DAO 접미사를 사용해야 합니다."
60
+ enabled: true
61
+ pattern:
62
+ type: "regex-multiline"
63
+ regex: "@Mapper[\\s\\S]*?interface\\s+(?!\\w*(Mapper|DAO)\\b)\\w+"
64
+ custom:
65
+ rule_id: "EGOV-NAME-004"
66
+ fix: "인터페이스명에 Mapper 접미사를 추가하세요 (예: UserMngMapper)"
67
+
68
+ - id: "egov-naming-005"
69
+ name: "VO/DTO 클래스 접미사 위반"
70
+ severity: "low"
71
+ category: "naming"
72
+ description: "데이터 전달 객체는 *Vo, *VO, *Dto, *DTO 접미사를 사용해야 합니다."
73
+ enabled: true
74
+ pattern:
75
+ type: "regex"
76
+ regex: "class\\s+(?!\\w*(Vo|VO|Dto|DTO|Entity|Model)\\b)\\w+\\s+implements\\s+Serializable"
77
+ custom:
78
+ rule_id: "EGOV-NAME-005"
79
+ fix: "클래스명에 Vo 또는 Dto 접미사를 추가하세요 (예: UserMngVo)"
80
+
81
+ - id: "egov-naming-006"
82
+ name: "패키지 구조 표준 위반"
83
+ severity: "medium"
84
+ category: "naming"
85
+ description: "전자정부프레임워크 표준 패키지 구조(web/service/service.impl/dao)를 따르지 않습니다."
86
+ enabled: true
87
+ pattern:
88
+ type: "regex"
89
+ regex: "^package\\s+(?!.*(web|controller|service|dao|mapper|repository|vo|dto|model|util|common|config))[^;]+;"
90
+ custom:
91
+ rule_id: "EGOV-NAME-006"
92
+ fix: "표준 패키지 구조를 따르세요: web, service, service.impl, dao(mapper), vo(dto)"
93
+ example: "gov.nges.benefit.usm.web / gov.nges.benefit.usm.service.impl"
94
+
95
+ # ==================== 2. Service 표준 ====================
96
+
97
+ - id: "egov-svc-001"
98
+ name: "ServiceImpl이 EgovAbstractServiceImpl 미상속"
99
+ severity: "medium"
100
+ category: "egov-standard"
101
+ description: "ServiceImpl 클래스는 EgovAbstractServiceImpl을 상속하여 프레임워크 표준 기능(로깅, 예외처리)을 활용해야 합니다."
102
+ enabled: true
103
+ pattern:
104
+ type: "regex"
105
+ regex: "class\\s+\\w+ServiceImpl\\s+(?!.*extends.*Egov)(?=.*implements)"
106
+ custom:
107
+ rule_id: "EGOV-SVC-001"
108
+ fix: "EgovAbstractServiceImpl을 상속하세요"
109
+ example: "public class UserMngServiceImpl extends EgovAbstractServiceImpl implements UserMngService"
110
+
111
+ - id: "egov-svc-002"
112
+ name: "Service에서 다른 Service 직접 생성"
113
+ severity: "high"
114
+ category: "egov-standard"
115
+ description: "Service에서 new로 다른 Service 인스턴스를 직접 생성하면 의존성 주입이 작동하지 않습니다."
116
+ enabled: true
117
+ pattern:
118
+ type: "regex"
119
+ regex: "new\\s+\\w+ServiceImpl\\s*\\("
120
+ custom:
121
+ rule_id: "EGOV-SVC-002"
122
+ fix: "Spring DI(@Autowired 또는 생성자 주입)를 사용하세요"
123
+
124
+ - id: "egov-svc-003"
125
+ name: "Service에서 HttpServletRequest/Response 사용"
126
+ severity: "high"
127
+ category: "egov-standard"
128
+ description: "Service 계층에서 Servlet API를 사용하면 웹 계층에 종속됩니다."
129
+ enabled: true
130
+ pattern:
131
+ type: "regex-multiline"
132
+ regex: "@Service[\\s\\S]*?(HttpServletRequest|HttpServletResponse)\\s+\\w+"
133
+ custom:
134
+ rule_id: "EGOV-SVC-003"
135
+ fix: "Servlet 관련 로직은 Controller에서 처리하고 Service에는 비즈니스 데이터만 전달하세요"
136
+
137
+ - id: "egov-svc-004"
138
+ name: "ServiceImpl 과대 클래스"
139
+ severity: "medium"
140
+ category: "egov-standard"
141
+ description: "ServiceImpl 클래스의 메서드가 너무 많습니다. 도메인별로 분리하세요."
142
+ enabled: false # quality-ast-009와 동일 검출 중복
143
+ pattern:
144
+ type: "ast-class"
145
+ name_pattern: ".*ServiceImpl$"
146
+ custom:
147
+ max_methods: 25
148
+ rule_id: "EGOV-SVC-004"
149
+ fix: "도메인별로 Service 클래스를 분리하세요 (단일 책임 원칙)"
150
+
151
+ # ==================== 3. Mapper/DAO 표준 ====================
152
+
153
+ - id: "egov-dao-001"
154
+ name: "DAO에서 EgovAbstractDAO 상속 (iBatis 잔존)"
155
+ severity: "high"
156
+ category: "egov-standard"
157
+ description: "EgovAbstractDAO는 iBatis 기반입니다. MyBatis의 EgovAbstractMapper로 변경하세요."
158
+ enabled: true # mod-egov-003 비활성화 → 이 규칙이 대표
159
+ pattern:
160
+ type: "regex"
161
+ regex: "extends\\s+EgovAbstractDAO\\b"
162
+ custom:
163
+ rule_id: "EGOV-DAO-001"
164
+ fix: "EgovAbstractMapper를 상속하거나 @Mapper 인터페이스로 전환하세요"
165
+
166
+ - id: "egov-dao-002"
167
+ name: "DAO에서 직접 SQL 문자열 사용"
168
+ severity: "high"
169
+ category: "egov-standard"
170
+ description: "DAO에서 SQL을 직접 문자열로 작성하면 SQL Injection 위험이 있고 유지보수가 어렵습니다."
171
+ enabled: true
172
+ pattern:
173
+ type: "regex"
174
+ regex: "\"\\s*(SELECT|INSERT|UPDATE|DELETE)\\s+"
175
+ custom:
176
+ rule_id: "EGOV-DAO-002"
177
+ fix: "MyBatis XML Mapper를 사용하여 SQL을 관리하세요"
178
+
179
+ - id: "egov-dao-003"
180
+ name: "Mapper에서 @Select/@Insert 어노테이션 SQL"
181
+ severity: "medium"
182
+ category: "egov-standard"
183
+ description: "Mapper 인터페이스에 @Select 등으로 SQL을 직접 작성하면 관리가 어렵습니다. XML Mapper를 사용하세요."
184
+ enabled: true
185
+ pattern:
186
+ type: "regex"
187
+ regex: "@(Select|Insert|Update|Delete)\\s*\\("
188
+ custom:
189
+ rule_id: "EGOV-DAO-003"
190
+ fix: "MyBatis XML Mapper 파일에 SQL을 작성하세요 (전자정부프레임워크 표준)"
191
+
192
+ # ==================== 4. 공통 컴포넌트 활용 ====================
193
+
194
+ - id: "egov-common-001"
195
+ name: "직접 파일 업로드 구현"
196
+ severity: "medium"
197
+ category: "egov-common"
198
+ description: "파일 업로드는 전자정부프레임워크 공통 컴포넌트(EgovFileUploadUtil)를 활용하세요."
199
+ enabled: true
200
+ pattern:
201
+ type: "regex-multiline"
202
+ regex: "MultipartFile\\s+\\w+\\s*[,)].*\\n.*transferTo\\s*\\("
203
+ custom:
204
+ rule_id: "EGOV-COMMON-001"
205
+ fix: "전자정부프레임워크 파일 업로드 공통 컴포넌트를 활용하세요"
206
+
207
+ - id: "egov-common-002"
208
+ name: "직접 페이징 쿼리 구현"
209
+ severity: "low"
210
+ category: "egov-common"
211
+ description: "페이징은 전자정부프레임워크 페이징 공통 컴포넌트(EgovPaginationSQLiteDAO)를 활용하세요."
212
+ enabled: true
213
+ pattern:
214
+ type: "regex"
215
+ regex: "\\bROWNUM\\b.*<|\\bLIMIT\\s+\\d+"
216
+ custom:
217
+ rule_id: "EGOV-COMMON-002"
218
+ fix: "전자정부프레임워크 페이징 공통 컴포넌트를 활용하세요"
219
+
220
+ - id: "egov-common-003"
221
+ name: "직접 ID 생성 로직"
222
+ severity: "medium"
223
+ category: "egov-common"
224
+ description: "ID 생성은 전자정부프레임워크 ID Generation 서비스(EgovIdGnService)를 활용하세요."
225
+ enabled: true
226
+ pattern:
227
+ type: "regex"
228
+ regex: "UUID\\.randomUUID\\s*\\(\\s*\\)"
229
+ custom:
230
+ rule_id: "EGOV-COMMON-003"
231
+ fix: "EgovIdGnService를 사용하여 표준화된 ID를 생성하세요"
232
+
233
+ - id: "egov-common-004"
234
+ name: "직접 프로퍼티 파일 로딩"
235
+ severity: "low"
236
+ category: "egov-common"
237
+ description: "프로퍼티 파일은 전자정부프레임워크 Properties 서비스 또는 Spring @Value를 활용하세요."
238
+ enabled: true
239
+ pattern:
240
+ type: "regex"
241
+ regex: "new\\s+Properties\\s*\\(\\s*\\)"
242
+ custom:
243
+ rule_id: "EGOV-COMMON-004"
244
+ fix: "EgovProperties 또는 Spring @Value/@ConfigurationProperties를 사용하세요"
245
+
246
+ - id: "egov-common-005"
247
+ name: "직접 메일 발송 구현"
248
+ severity: "low"
249
+ category: "egov-common"
250
+ description: "메일 발송은 전자정부프레임워크 Mail 공통 컴포넌트를 활용하세요."
251
+ enabled: true
252
+ pattern:
253
+ type: "regex"
254
+ regex: "new\\s+MimeMessage\\s*\\(|Transport\\.send\\s*\\("
255
+ custom:
256
+ rule_id: "EGOV-COMMON-005"
257
+ fix: "전자정부프레임워크 Mail 공통 컴포넌트 또는 Spring JavaMailSender를 사용하세요"
258
+
259
+ # ==================== 5. 메서드 명명 표준 ====================
260
+
261
+ - id: "egov-method-001"
262
+ name: "조회 메서드 접두사 위반"
263
+ severity: "medium"
264
+ category: "method-naming"
265
+ description: "조회 메서드는 select*, get*, find* 접두사를 사용해야 합니다."
266
+ enabled: true
267
+ pattern:
268
+ type: "regex-multiline"
269
+ regex: "@(GetMapping|RequestMapping).*\\n\\s*public\\s+\\w+\\s+(?!(select|get|find|search|retrieve|view|download|check|is)\\w+)([a-z]\\w+)\\s*\\("
270
+ custom:
271
+ rule_id: "EGOV-METHOD-001"
272
+ fix: "조회 메서드: select*, get*, find* 접두사 사용"
273
+ example: "selectUserList(), getUserDetail(), findActiveUsers()"
274
+
275
+ - id: "egov-method-002"
276
+ name: "등록 메서드 접두사 위반"
277
+ severity: "medium"
278
+ category: "method-naming"
279
+ description: "등록 메서드는 insert*, add*, create*, register* 접두사를 사용해야 합니다."
280
+ enabled: true
281
+ pattern:
282
+ type: "regex-multiline"
283
+ regex: "@PostMapping.*\\n\\s*public\\s+\\w+\\s+(?!(insert|add|create|register|save|upload|send|process|exec)\\w+)([a-z]\\w+)\\s*\\("
284
+ custom:
285
+ rule_id: "EGOV-METHOD-002"
286
+ fix: "등록 메서드: insert*, add*, create* 접두사 사용"
287
+ example: "insertUser(), addBoardArticle(), createOrder()"
288
+
289
+ - id: "egov-method-003"
290
+ name: "수정 메서드 접두사 위반"
291
+ severity: "medium"
292
+ category: "method-naming"
293
+ description: "수정 메서드는 update*, modify*, change* 접두사를 사용해야 합니다."
294
+ enabled: true
295
+ pattern:
296
+ type: "regex-multiline"
297
+ regex: "@PutMapping.*\\n\\s*public\\s+\\w+\\s+(?!(update|modify|change|edit|set|reset)\\w+)([a-z]\\w+)\\s*\\("
298
+ custom:
299
+ rule_id: "EGOV-METHOD-003"
300
+ fix: "수정 메서드: update*, modify*, change* 접두사 사용"
301
+ example: "updateUser(), modifyBoard(), changePassword()"
302
+
303
+ - id: "egov-method-004"
304
+ name: "삭제 메서드 접두사 위반"
305
+ severity: "medium"
306
+ category: "method-naming"
307
+ description: "삭제 메서드는 delete*, remove*, cancel* 접두사를 사용해야 합니다."
308
+ enabled: true
309
+ pattern:
310
+ type: "regex-multiline"
311
+ regex: "@DeleteMapping.*\\n\\s*public\\s+\\w+\\s+(?!(delete|remove|cancel|withdraw|drop)\\w+)([a-z]\\w+)\\s*\\("
312
+ custom:
313
+ rule_id: "EGOV-METHOD-004"
314
+ fix: "삭제 메서드: delete*, remove* 접두사 사용"
315
+ example: "deleteUser(), removeBoard(), cancelOrder()"
316
+
317
+ # ==================== 6. 예외 처리 표준 ====================
318
+
319
+ - id: "egov-ex-001"
320
+ name: "EgovBizException 미사용"
321
+ severity: "medium"
322
+ category: "exception"
323
+ description: "비즈니스 예외는 EgovBizException을 사용하여 프레임워크 표준 예외 처리를 활용하세요."
324
+ enabled: true
325
+ pattern:
326
+ type: "regex"
327
+ regex: "throw\\s+new\\s+(Runtime|IllegalArgument|IllegalState)Exception\\s*\\("
328
+ custom:
329
+ rule_id: "EGOV-EX-001"
330
+ fix: "EgovBizException 또는 프로젝트 표준 BusinessException을 throw하세요"
331
+ example: "throw new EgovBizException(messageSource, \"fail.common.update\")"
332
+
333
+ - id: "egov-ex-002"
334
+ name: "Service에서 Exception 직접 throw"
335
+ severity: "medium"
336
+ category: "exception"
337
+ description: "Service 계층에서 checked Exception을 직접 throw하면 상위 계층에 불필요한 의존성이 전파됩니다."
338
+ enabled: true
339
+ pattern:
340
+ type: "regex"
341
+ regex: "throws\\s+(SQLException|IOException|ClassNotFoundException)"
342
+ custom:
343
+ rule_id: "EGOV-EX-002"
344
+ fix: "checked Exception은 Service에서 catch하여 EgovBizException으로 변환하세요"
345
+
346
+ - id: "egov-ex-003"
347
+ name: "Controller에서 throws Exception 선언"
348
+ severity: "medium"
349
+ category: "exception"
350
+ description: "Controller 메서드에 throws Exception을 선언하면 예외가 클라이언트에 그대로 노출될 수 있습니다."
351
+ enabled: true
352
+ pattern:
353
+ type: "regex-multiline"
354
+ regex: "@(GetMapping|PostMapping|PutMapping|DeleteMapping|RequestMapping).*\\n[^{]*throws\\s+Exception\\s*\\{"
355
+ custom:
356
+ rule_id: "EGOV-EX-003"
357
+ fix: "try-catch로 예외를 처리하거나 @ExceptionHandler를 사용하세요"
358
+
359
+ # ==================== 7. 로깅 표준 ====================
360
+
361
+ - id: "egov-log-001"
362
+ name: "System.out/err 사용"
363
+ severity: "high"
364
+ category: "logging"
365
+ description: "System.out/err 대신 SLF4J Logger를 사용하세요. 전자정부프레임워크는 egovLogger를 제공합니다."
366
+ enabled: false # quality-lg-001, secure-debug-001과 동일 검출 중복
367
+ pattern:
368
+ type: "regex"
369
+ regex: "System\\.(out|err)\\.(print|println|printf)"
370
+ custom:
371
+ rule_id: "EGOV-LOG-001"
372
+ fix: "egovLogger 또는 LoggerFactory.getLogger()를 사용하세요"
373
+
374
+ - id: "egov-log-002"
375
+ name: "Logger 문자열 연결 사용"
376
+ severity: "medium"
377
+ category: "logging"
378
+ description: "Logger 호출 시 문자열 연결(+)은 성능에 불리합니다. {} 플레이스홀더를 사용하세요."
379
+ enabled: false # quality-lg-005와 동일 검출 중복
380
+ pattern:
381
+ type: "regex"
382
+ regex: "\\b(log|logger|egovLogger|LOGGER)\\.(debug|info|warn|error)\\s*\\([^)]*\\+"
383
+ custom:
384
+ rule_id: "EGOV-LOG-002"
385
+ fix: "log.info(\"사용자: {}\", userId)와 같이 {} 플레이스홀더를 사용하세요"
386
+
387
+ - id: "egov-log-003"
388
+ name: "e.printStackTrace() 사용"
389
+ severity: "high"
390
+ category: "logging"
391
+ description: "printStackTrace()는 로그 파일이 아닌 System.err로 출력됩니다. Logger를 사용하세요."
392
+ enabled: false # secure-err-001과 동일 검출 중복
393
+ pattern:
394
+ type: "regex"
395
+ regex: "\\.printStackTrace\\s*\\(\\s*\\)"
396
+ custom:
397
+ rule_id: "EGOV-LOG-003"
398
+ fix: "logger.error(\"message\", e)를 사용하세요"
399
+
400
+ # ==================== 8. 보안 표준 ====================
401
+
402
+ - id: "egov-sec-001"
403
+ name: "XSS 필터 미적용"
404
+ severity: "high"
405
+ category: "security"
406
+ description: "외부 입력값을 HTML에 출력할 때 XSS 필터링이 필요합니다."
407
+ enabled: true
408
+ pattern:
409
+ type: "regex"
410
+ regex: "request\\.getParameter\\s*\\([^)]*\\)"
411
+ custom:
412
+ rule_id: "EGOV-SEC-001"
413
+ fix: "EgovWebUtil.clearXSSMinimum() 또는 HTML 인코딩을 적용하세요"
414
+
415
+ - id: "egov-sec-002"
416
+ name: "SQL Injection 취약 패턴"
417
+ severity: "critical"
418
+ category: "security"
419
+ description: "SQL 문자열에 외부 입력값을 직접 연결하면 SQL Injection에 취약합니다."
420
+ enabled: true
421
+ pattern:
422
+ type: "regex"
423
+ regex: "\"(SELECT|INSERT|UPDATE|DELETE)\\s[^\"]*\"\\s*\\+\\s*\\w+"
424
+ custom:
425
+ rule_id: "EGOV-SEC-002"
426
+ fix: "PreparedStatement의 바인드 변수(?) 또는 MyBatis #{} 를 사용하세요"
427
+
428
+ - language: xml
429
+ rules:
430
+ # ==================== 9. MyBatis XML 표준 ====================
431
+
432
+ - id: "egov-mybatis-001"
433
+ name: "Mapper XML namespace 누락"
434
+ severity: "high"
435
+ category: "mybatis"
436
+ description: "MyBatis Mapper XML에는 namespace가 반드시 지정되어야 합니다."
437
+ enabled: false # quality-mb-201과 동일 검출 중복
438
+ pattern:
439
+ type: "regex"
440
+ regex: "<mapper\\s+(?!.*namespace)"
441
+ custom:
442
+ rule_id: "EGOV-MYBATIS-001"
443
+ fix: "<mapper namespace=\"패키지.인터페이스명\">을 지정하세요"
444
+
445
+ - id: "egov-mybatis-002"
446
+ name: "MyBatis에서 ${} 사용"
447
+ severity: "critical"
448
+ category: "mybatis"
449
+ description: "${} 구문은 SQL Injection에 취약합니다. #{} 바인드 변수를 사용하세요."
450
+ enabled: false # secure-sql-003, sql-mybatis-001과 동일 regex 중복
451
+ pattern:
452
+ type: "regex"
453
+ regex: "\\$\\{[^}]+\\}"
454
+ custom:
455
+ rule_id: "EGOV-MYBATIS-002"
456
+ fix: "#{variable} 형식으로 변경하세요. 테이블명/컬럼명이 동적인 경우만 ${}를 사용하고, 화이트리스트 검증을 추가하세요."
457
+
458
+ - id: "egov-mybatis-003"
459
+ name: "MyBatis SELECT * 사용"
460
+ severity: "medium"
461
+ category: "mybatis"
462
+ description: "SELECT *는 불필요한 컬럼까지 조회하여 성능에 불리합니다."
463
+ enabled: false # sql-mybatis-002, sql-sel-001과 동일 검출 중복
464
+ pattern:
465
+ type: "regex"
466
+ regex: "SELECT\\s+\\*\\s+FROM"
467
+ custom:
468
+ rule_id: "EGOV-MYBATIS-003"
469
+ fix: "필요한 컬럼만 명시적으로 나열하세요"