@sfdxy/mule-lint 1.7.1 → 1.8.2

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 (159) hide show
  1. package/README.md +43 -7
  2. package/dist/bin/mule-lint-mcp.d.ts +3 -0
  3. package/dist/bin/mule-lint-mcp.d.ts.map +1 -0
  4. package/dist/bin/mule-lint-mcp.js +13 -0
  5. package/dist/bin/mule-lint-mcp.js.map +1 -0
  6. package/dist/package.json +6 -3
  7. package/dist/src/core/ComplexityCalculator.d.ts.map +1 -1
  8. package/dist/src/core/ComplexityCalculator.js +8 -8
  9. package/dist/src/core/ComplexityCalculator.js.map +1 -1
  10. package/dist/src/core/FileScanner.d.ts.map +1 -1
  11. package/dist/src/core/FileScanner.js +11 -12
  12. package/dist/src/core/FileScanner.js.map +1 -1
  13. package/dist/src/core/XPathHelper.d.ts.map +1 -1
  14. package/dist/src/core/XPathHelper.js +23 -23
  15. package/dist/src/core/XPathHelper.js.map +1 -1
  16. package/dist/src/core/XmlParser.js +1 -1
  17. package/dist/src/core/XmlParser.js.map +1 -1
  18. package/dist/src/core/YamlParser.d.ts.map +1 -1
  19. package/dist/src/core/YamlParser.js +1 -1
  20. package/dist/src/core/YamlParser.js.map +1 -1
  21. package/dist/src/engine/LintEngine.d.ts.map +1 -1
  22. package/dist/src/engine/LintEngine.js +6 -4
  23. package/dist/src/engine/LintEngine.js.map +1 -1
  24. package/dist/src/formatters/CsvFormatter.d.ts.map +1 -1
  25. package/dist/src/formatters/CsvFormatter.js +6 -4
  26. package/dist/src/formatters/CsvFormatter.js.map +1 -1
  27. package/dist/src/formatters/HtmlFormatter.d.ts.map +1 -1
  28. package/dist/src/formatters/HtmlFormatter.js +12 -7
  29. package/dist/src/formatters/HtmlFormatter.js.map +1 -1
  30. package/dist/src/formatters/SarifFormatter.d.ts.map +1 -1
  31. package/dist/src/formatters/SarifFormatter.js +20 -10
  32. package/dist/src/formatters/SarifFormatter.js.map +1 -1
  33. package/dist/src/formatters/TableFormatter.d.ts.map +1 -1
  34. package/dist/src/formatters/TableFormatter.js +1 -1
  35. package/dist/src/formatters/TableFormatter.js.map +1 -1
  36. package/dist/src/mcp/index.d.ts +13 -0
  37. package/dist/src/mcp/index.d.ts.map +1 -0
  38. package/dist/src/mcp/index.js +375 -0
  39. package/dist/src/mcp/index.js.map +1 -0
  40. package/dist/src/rules/api-led/ApiLedRules.d.ts.map +1 -1
  41. package/dist/src/rules/api-led/ApiLedRules.js +3 -1
  42. package/dist/src/rules/api-led/ApiLedRules.js.map +1 -1
  43. package/dist/src/rules/base/BaseRule.d.ts.map +1 -1
  44. package/dist/src/rules/base/BaseRule.js +1 -1
  45. package/dist/src/rules/base/BaseRule.js.map +1 -1
  46. package/dist/src/rules/complexity/FlowComplexityRule.d.ts.map +1 -1
  47. package/dist/src/rules/complexity/FlowComplexityRule.js +3 -5
  48. package/dist/src/rules/complexity/FlowComplexityRule.js.map +1 -1
  49. package/dist/src/rules/dataweave/DataWeaveRules.d.ts.map +1 -1
  50. package/dist/src/rules/dataweave/DataWeaveRules.js +5 -5
  51. package/dist/src/rules/dataweave/DataWeaveRules.js.map +1 -1
  52. package/dist/src/rules/dataweave/Java17DWErrorHandlingRule.d.ts +21 -0
  53. package/dist/src/rules/dataweave/Java17DWErrorHandlingRule.d.ts.map +1 -0
  54. package/dist/src/rules/dataweave/Java17DWErrorHandlingRule.js +162 -0
  55. package/dist/src/rules/dataweave/Java17DWErrorHandlingRule.js.map +1 -0
  56. package/dist/src/rules/documentation/FlowDescriptionRule.d.ts.map +1 -1
  57. package/dist/src/rules/documentation/FlowDescriptionRule.js +1 -1
  58. package/dist/src/rules/documentation/FlowDescriptionRule.js.map +1 -1
  59. package/dist/src/rules/documentation/MissingDocNameRule.d.ts.map +1 -1
  60. package/dist/src/rules/documentation/MissingDocNameRule.js +1 -1
  61. package/dist/src/rules/documentation/MissingDocNameRule.js.map +1 -1
  62. package/dist/src/rules/error-handling/CorrelationIdRule.d.ts.map +1 -1
  63. package/dist/src/rules/error-handling/CorrelationIdRule.js +1 -1
  64. package/dist/src/rules/error-handling/CorrelationIdRule.js.map +1 -1
  65. package/dist/src/rules/error-handling/GenericErrorRule.d.ts.map +1 -1
  66. package/dist/src/rules/error-handling/GenericErrorRule.js +2 -5
  67. package/dist/src/rules/error-handling/GenericErrorRule.js.map +1 -1
  68. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts +1 -1
  69. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts.map +1 -1
  70. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js +2 -2
  71. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js.map +1 -1
  72. package/dist/src/rules/error-handling/HttpStatusRule.d.ts.map +1 -1
  73. package/dist/src/rules/error-handling/HttpStatusRule.js +1 -1
  74. package/dist/src/rules/error-handling/HttpStatusRule.js.map +1 -1
  75. package/dist/src/rules/error-handling/MissingErrorHandlerRule.d.ts.map +1 -1
  76. package/dist/src/rules/error-handling/MissingErrorHandlerRule.js +9 -1
  77. package/dist/src/rules/error-handling/MissingErrorHandlerRule.js.map +1 -1
  78. package/dist/src/rules/experimental/ExperimentalRules.d.ts.map +1 -1
  79. package/dist/src/rules/experimental/ExperimentalRules.js +1 -1
  80. package/dist/src/rules/experimental/ExperimentalRules.js.map +1 -1
  81. package/dist/src/rules/http/HttpContentTypeRule.d.ts.map +1 -1
  82. package/dist/src/rules/http/HttpContentTypeRule.js +1 -1
  83. package/dist/src/rules/http/HttpContentTypeRule.js.map +1 -1
  84. package/dist/src/rules/http/HttpTimeoutRule.d.ts.map +1 -1
  85. package/dist/src/rules/http/HttpTimeoutRule.js +1 -1
  86. package/dist/src/rules/http/HttpTimeoutRule.js.map +1 -1
  87. package/dist/src/rules/http/HttpUserAgentRule.d.ts.map +1 -1
  88. package/dist/src/rules/http/HttpUserAgentRule.js +1 -1
  89. package/dist/src/rules/http/HttpUserAgentRule.js.map +1 -1
  90. package/dist/src/rules/index.d.ts +1 -1
  91. package/dist/src/rules/index.d.ts.map +1 -1
  92. package/dist/src/rules/index.js +7 -5
  93. package/dist/src/rules/index.js.map +1 -1
  94. package/dist/src/rules/logging/LoggerCategoryRule.js +2 -2
  95. package/dist/src/rules/logging/LoggerCategoryRule.js.map +1 -1
  96. package/dist/src/rules/logging/LoggerInUntilSuccessfulRule.js +1 -1
  97. package/dist/src/rules/logging/LoggerInUntilSuccessfulRule.js.map +1 -1
  98. package/dist/src/rules/logging/LoggerPayloadRule.d.ts.map +1 -1
  99. package/dist/src/rules/logging/LoggerPayloadRule.js +3 -3
  100. package/dist/src/rules/logging/LoggerPayloadRule.js.map +1 -1
  101. package/dist/src/rules/naming/FlowCasingRule.d.ts +1 -0
  102. package/dist/src/rules/naming/FlowCasingRule.d.ts.map +1 -1
  103. package/dist/src/rules/naming/FlowCasingRule.js +7 -1
  104. package/dist/src/rules/naming/FlowCasingRule.js.map +1 -1
  105. package/dist/src/rules/naming/FlowNamingRule.d.ts.map +1 -1
  106. package/dist/src/rules/naming/FlowNamingRule.js +12 -1
  107. package/dist/src/rules/naming/FlowNamingRule.js.map +1 -1
  108. package/dist/src/rules/naming/VariableNamingRule.d.ts.map +1 -1
  109. package/dist/src/rules/naming/VariableNamingRule.js +3 -3
  110. package/dist/src/rules/naming/VariableNamingRule.js.map +1 -1
  111. package/dist/src/rules/performance/AsyncErrorHandlerRule.d.ts.map +1 -1
  112. package/dist/src/rules/performance/AsyncErrorHandlerRule.js +1 -1
  113. package/dist/src/rules/performance/AsyncErrorHandlerRule.js.map +1 -1
  114. package/dist/src/rules/performance/LargeChoiceBlockRule.d.ts.map +1 -1
  115. package/dist/src/rules/performance/LargeChoiceBlockRule.js +1 -1
  116. package/dist/src/rules/performance/LargeChoiceBlockRule.js.map +1 -1
  117. package/dist/src/rules/performance/ScatterGatherRoutesRule.d.ts.map +1 -1
  118. package/dist/src/rules/performance/ScatterGatherRoutesRule.js +1 -1
  119. package/dist/src/rules/performance/ScatterGatherRoutesRule.js.map +1 -1
  120. package/dist/src/rules/security/HardcodedCredentialsRule.d.ts.map +1 -1
  121. package/dist/src/rules/security/HardcodedCredentialsRule.js +6 -6
  122. package/dist/src/rules/security/HardcodedCredentialsRule.js.map +1 -1
  123. package/dist/src/rules/security/HardcodedHttpRule.d.ts.map +1 -1
  124. package/dist/src/rules/security/HardcodedHttpRule.js +2 -6
  125. package/dist/src/rules/security/HardcodedHttpRule.js.map +1 -1
  126. package/dist/src/rules/security/InsecureTlsRule.d.ts.map +1 -1
  127. package/dist/src/rules/security/InsecureTlsRule.js +2 -2
  128. package/dist/src/rules/security/InsecureTlsRule.js.map +1 -1
  129. package/dist/src/rules/standards/ChoiceAntiPatternRule.d.ts.map +1 -1
  130. package/dist/src/rules/standards/ChoiceAntiPatternRule.js +8 -2
  131. package/dist/src/rules/standards/ChoiceAntiPatternRule.js.map +1 -1
  132. package/dist/src/rules/standards/DeprecatedComponentRule.d.ts.map +1 -1
  133. package/dist/src/rules/standards/DeprecatedComponentRule.js +1 -1
  134. package/dist/src/rules/standards/DeprecatedComponentRule.js.map +1 -1
  135. package/dist/src/rules/standards/DwlStandardsRule.d.ts.map +1 -1
  136. package/dist/src/rules/standards/DwlStandardsRule.js +1 -1
  137. package/dist/src/rules/standards/DwlStandardsRule.js.map +1 -1
  138. package/dist/src/rules/structure/StructureRules.d.ts.map +1 -1
  139. package/dist/src/rules/structure/StructureRules.js +6 -9
  140. package/dist/src/rules/structure/StructureRules.js.map +1 -1
  141. package/dist/src/rules/yaml/YamlRules.d.ts.map +1 -1
  142. package/dist/src/rules/yaml/YamlRules.js +19 -12
  143. package/dist/src/rules/yaml/YamlRules.js.map +1 -1
  144. package/dist/src/types/Config.d.ts.map +1 -1
  145. package/dist/src/types/Config.js +1 -5
  146. package/dist/src/types/Config.js.map +1 -1
  147. package/docs/README.md +95 -0
  148. package/docs/best-practices/documentation-standards.md +82 -0
  149. package/docs/best-practices/folder-structure.md +61 -0
  150. package/docs/best-practices/mulesoft-best-practices.md +902 -0
  151. package/docs/best-practices/rules-catalog.md +736 -0
  152. package/docs/linter/architecture.md +294 -0
  153. package/docs/linter/extending.md +426 -0
  154. package/docs/linter/folder-structure.md +251 -0
  155. package/docs/linter/images/html-report-dashboard.png +0 -0
  156. package/docs/linter/naming-conventions.md +300 -0
  157. package/docs/linter/rule-engine.md +532 -0
  158. package/docs/mcp-design.md +80 -0
  159. package/package.json +6 -3
@@ -0,0 +1,902 @@
1
+ # MuleSoft Development Best Practices
2
+
3
+ > **Purpose:** Comprehensive guide for building maintainable, secure, and performant Mule applications. This guide covers both practices enforced by mule-lint and general development guidelines for MuleSoft developers.
4
+
5
+ ---
6
+
7
+ ## Table of Contents
8
+
9
+ ### Linter-Enforced Practices
10
+ - [API-Led Connectivity](#api-led-connectivity)
11
+ - [Error Handling](#error-handling)
12
+ - [Logging Standards](#logging-standards)
13
+ - [Security Guidelines](#security-guidelines)
14
+ - [Performance Patterns](#performance-patterns)
15
+ - [Project Structure](#project-structure)
16
+ - [Naming Conventions](#naming-conventions)
17
+ - [Configuration Management](#configuration-management)
18
+ - [DataWeave Best Practices](#dataweave-best-practices)
19
+ - [Documentation Standards](#documentation-standards)
20
+
21
+ ### General Developer Guidelines
22
+ - [Testing with MUnit](#testing-with-munit)
23
+ - [CI/CD Integration](#cicd-integration)
24
+ - [API Versioning](#api-versioning)
25
+ - [Deployment Practices](#deployment-practices)
26
+ - [Monitoring and Observability](#monitoring-and-observability)
27
+
28
+ ---
29
+
30
+ ## API-Led Connectivity
31
+
32
+ MuleSoft's API-Led Connectivity approach organizes APIs into three layers, each with distinct responsibilities.
33
+
34
+ ### The Three Layers
35
+
36
+ ```
37
+ ┌─────────────────────────────────────────────────────────┐
38
+ │ Experience Layer │
39
+ │ (Channel-specific: Web, Mobile, Partner APIs) │
40
+ │ Naming: *-exp-*, *-experience-* │
41
+ └─────────────────────┬───────────────────────────────────┘
42
+
43
+ ┌─────────────────────▼───────────────────────────────────┐
44
+ │ Process Layer │
45
+ │ (Orchestration, Business Logic, Aggregation) │
46
+ │ Naming: *-proc-*, *-process-* │
47
+ └─────────────────────┬───────────────────────────────────┘
48
+
49
+ ┌─────────────────────▼───────────────────────────────────┐
50
+ │ System Layer │
51
+ │ (Backend Connectivity: SAP, Salesforce, Databases) │
52
+ │ Naming: *-sys-*, *-system-* │
53
+ └─────────────────────────────────────────────────────────┘
54
+ ```
55
+
56
+ ### Layer Guidelines
57
+
58
+ | Layer | Should Have | Should NOT Have |
59
+ |-------|-------------|-----------------|
60
+ | **Experience** | HTTP listeners, channel-specific transformations | Direct database access, complex business logic |
61
+ | **Process** | Flow-refs to other APIs, orchestration logic | Direct system connections, database queries |
62
+ | **System** | Database operations, HTTP requests to backends | Business logic, data aggregation |
63
+
64
+ ### Example Flow Structure
65
+
66
+ ```xml
67
+ <!-- Experience Layer: User-facing API -->
68
+ <flow name="orders-exp-get-order-flow">
69
+ <http:listener config-ref="HTTPS_Listener" path="/orders/{orderId}"/>
70
+ <flow-ref name="orders-proc-get-order-subflow"/>
71
+ <ee:transform><!-- Channel-specific response format --></ee:transform>
72
+ </flow>
73
+
74
+ <!-- Process Layer: Orchestration -->
75
+ <sub-flow name="orders-proc-get-order-subflow">
76
+ <flow-ref name="orders-sys-get-order-subflow"/>
77
+ <flow-ref name="customers-sys-get-customer-subflow"/>
78
+ <!-- Aggregate data from multiple sources -->
79
+ </sub-flow>
80
+
81
+ <!-- System Layer: Database access -->
82
+ <sub-flow name="orders-sys-get-order-subflow">
83
+ <db:select config-ref="Database_Config">
84
+ <db:sql>SELECT * FROM orders WHERE id = :orderId</db:sql>
85
+ </db:select>
86
+ </sub-flow>
87
+ ```
88
+
89
+ **Related Rules:** `API-001`, `API-002`, `API-003`
90
+
91
+ ---
92
+
93
+ ## Error Handling
94
+
95
+ Proper error handling ensures consistent API responses and easier debugging.
96
+
97
+ ### Key Principles
98
+
99
+ 1. **Every flow needs error handling** - Either explicit or via global handler
100
+ 2. **Set HTTP status codes** - Always set `httpStatus` variable for API responses
101
+ 3. **Include correlation ID** - Enable distributed tracing
102
+ 4. **Be specific about error types** - Avoid catching `type="ANY"`
103
+
104
+ ### Global Error Handler Pattern
105
+
106
+ Create a reusable global error handler:
107
+
108
+ ```xml
109
+ <!-- src/main/mule/global-error-handler.xml -->
110
+ <error-handler name="global-error-handler">
111
+ <on-error-propagate type="APIKIT:BAD_REQUEST">
112
+ <set-variable variableName="httpStatus" value="400"/>
113
+ <ee:transform>
114
+ <ee:set-payload><![CDATA[%dw 2.0
115
+ output application/json
116
+ ---
117
+ {
118
+ correlationId: correlationId,
119
+ error: "Bad Request",
120
+ message: error.description
121
+ }]]></ee:set-payload>
122
+ </ee:transform>
123
+ </on-error-propagate>
124
+
125
+ <on-error-propagate type="APIKIT:NOT_FOUND">
126
+ <set-variable variableName="httpStatus" value="404"/>
127
+ <!-- ... -->
128
+ </on-error-propagate>
129
+
130
+ <!-- Catch-all for unexpected errors -->
131
+ <on-error-propagate>
132
+ <set-variable variableName="httpStatus" value="500"/>
133
+ <logger category="com.myorg.errors" level="ERROR"
134
+ message="#['Error: ' ++ error.description ++ ' | CorrelationId: ' ++ correlationId]"/>
135
+ <!-- ... -->
136
+ </on-error-propagate>
137
+ </error-handler>
138
+ ```
139
+
140
+ ### Flow Error Handler Reference
141
+
142
+ ```xml
143
+ <flow name="my-api-flow">
144
+ <http:listener config-ref="HTTPS_Listener" path="/resource"/>
145
+ <!-- Flow logic -->
146
+ <error-handler ref="global-error-handler"/>
147
+ </flow>
148
+ ```
149
+
150
+ **Related Rules:** `MULE-001`, `MULE-003`, `MULE-005`, `MULE-007`, `MULE-009`
151
+
152
+ ---
153
+
154
+ ## Logging Standards
155
+
156
+ Effective logging enables debugging and monitoring without compromising security or performance.
157
+
158
+ ### Key Principles
159
+
160
+ 1. **Always use categories** - Enable log filtering in production
161
+ 2. **Never log full payloads** - May contain PII and cause performance issues
162
+ 3. **Include correlation IDs** - Enable request tracing
163
+ 4. **Use structured logging** - JSON format for log aggregation tools
164
+
165
+ ### Logger Category Convention
166
+
167
+ Use hierarchical category names:
168
+
169
+ ```xml
170
+ <!-- ✅ Good - Hierarchical categories -->
171
+ <logger category="com.myorg.orders.api" level="INFO"
172
+ message="#['Processing order: ' ++ vars.orderId]"/>
173
+
174
+ <logger category="com.myorg.orders.db" level="DEBUG"
175
+ message="#['Query executed in ' ++ vars.queryTime ++ 'ms']"/>
176
+ ```
177
+
178
+ ### Avoid Payload Logging
179
+
180
+ ```xml
181
+ <!-- ❌ Bad - Logs entire payload -->
182
+ <logger message="#[payload]"/>
183
+
184
+ <!-- ✅ Good - Logs specific fields -->
185
+ <logger category="com.myorg.orders" level="INFO"
186
+ message="#['Order ' ++ payload.orderId ++ ' received for customer ' ++ payload.customerId]"/>
187
+ ```
188
+
189
+ ### Structured Logging Format
190
+
191
+ ```xml
192
+ <logger category="com.myorg.audit" level="INFO">
193
+ <message><![CDATA[#[%dw 2.0
194
+ output application/json
195
+ ---
196
+ {
197
+ correlationId: correlationId,
198
+ event: "ORDER_CREATED",
199
+ orderId: payload.orderId,
200
+ timestamp: now()
201
+ }]]]></message>
202
+ </logger>
203
+ ```
204
+
205
+ ### Avoid Logging in Retry Loops
206
+
207
+ ```xml
208
+ <!-- ❌ Bad - Logger inside until-successful floods logs -->
209
+ <until-successful maxRetries="5">
210
+ <logger message="Attempting..."/> <!-- Will log 5 times on failure -->
211
+ <http:request config-ref="HTTP_Config" path="/api"/>
212
+ </until-successful>
213
+
214
+ <!-- ✅ Good - Log before and after -->
215
+ <logger category="com.myorg" message="Starting retry operation"/>
216
+ <until-successful maxRetries="5">
217
+ <http:request config-ref="HTTP_Config" path="/api"/>
218
+ </until-successful>
219
+ <logger category="com.myorg" message="Operation completed"/>
220
+ ```
221
+
222
+ **Related Rules:** `MULE-006`, `MULE-301`, `MULE-303`
223
+
224
+ ---
225
+
226
+ ## Security Guidelines
227
+
228
+ Protect sensitive data and follow secure development practices.
229
+
230
+ ### Never Hardcode Secrets
231
+
232
+ ```xml
233
+ <!-- ❌ Bad - Hardcoded credentials -->
234
+ <http:request-config host="api.example.com"
235
+ username="admin"
236
+ password="secret123"/>
237
+
238
+ <!-- ✅ Good - Property placeholders -->
239
+ <http:request-config host="${api.host}"
240
+ username="${api.username}"
241
+ password="${secure::api.password}"/>
242
+ ```
243
+
244
+ ### Never Hardcode URLs
245
+
246
+ ```xml
247
+ <!-- ❌ Bad -->
248
+ <http:request url="https://api.production.example.com/orders"/>
249
+
250
+ <!-- ✅ Good -->
251
+ <http:request url="${api.orders.baseUrl}/orders"/>
252
+ ```
253
+
254
+ ### Encrypt Sensitive Properties
255
+
256
+ Use MuleSoft Secure Properties:
257
+
258
+ ```yaml
259
+ # secure.yaml (encrypted)
260
+ api:
261
+ password: "![encryptedValue]"
262
+ clientSecret: "![encryptedValue]"
263
+ ```
264
+
265
+ ### TLS Configuration
266
+
267
+ ```xml
268
+ <!-- ❌ Bad - Insecure TLS -->
269
+ <tls:context name="Insecure_TLS">
270
+ <tls:trust-store insecure="true"/>
271
+ </tls:context>
272
+
273
+ <!-- ✅ Good - Proper certificate validation -->
274
+ <tls:context name="Secure_TLS">
275
+ <tls:trust-store path="${tls.truststore.path}"
276
+ password="${secure::tls.truststore.password}"/>
277
+ </tls:context>
278
+ ```
279
+
280
+ **Related Rules:** `MULE-004`, `MULE-201`, `MULE-202`, `YAML-004`
281
+
282
+ ---
283
+
284
+ ## Performance Patterns
285
+
286
+ Avoid common performance anti-patterns.
287
+
288
+ ### Async Scope Error Handling
289
+
290
+ Async scopes don't propagate errors to parent flows:
291
+
292
+ ```xml
293
+ <!-- ❌ Bad - Errors silently swallowed -->
294
+ <async>
295
+ <http:request config-ref="HTTP_Config" path="/webhook"/>
296
+ </async>
297
+
298
+ <!-- ✅ Good - Explicit error handling -->
299
+ <async>
300
+ <try>
301
+ <http:request config-ref="HTTP_Config" path="/webhook"/>
302
+ <error-handler>
303
+ <on-error-continue>
304
+ <logger category="com.myorg.async" level="ERROR"
305
+ message="#['Async failed: ' ++ error.description]"/>
306
+ </on-error-continue>
307
+ </error-handler>
308
+ </try>
309
+ </async>
310
+ ```
311
+
312
+ ### Limit Choice Complexity
313
+
314
+ ```xml
315
+ <!-- ❌ Bad - Too many when clauses -->
316
+ <choice>
317
+ <when expression="#[vars.status == 'NEW']">...</when>
318
+ <when expression="#[vars.status == 'PENDING']">...</when>
319
+ <when expression="#[vars.status == 'APPROVED']">...</when>
320
+ <!-- 10+ more conditions -->
321
+ <otherwise>...</otherwise>
322
+ </choice>
323
+
324
+ <!-- ✅ Good - Use DataWeave lookup -->
325
+ <ee:transform>
326
+ <ee:set-variable variableName="handler"><![CDATA[%dw 2.0
327
+ var handlers = {
328
+ "NEW": "new-handler-subflow",
329
+ "PENDING": "pending-handler-subflow",
330
+ "APPROVED": "approved-handler-subflow"
331
+ }
332
+ ---
333
+ handlers[vars.status] default "default-handler-subflow"
334
+ ]]></ee:set-variable>
335
+ </ee:transform>
336
+ <flow-ref name="#[vars.handler]"/>
337
+ ```
338
+
339
+ ### HTTP Timeout Configuration
340
+
341
+ ```xml
342
+ <!-- ✅ Always set explicit timeouts -->
343
+ <http:request-config name="HTTP_Request_Config"
344
+ responseTimeout="30000">
345
+ <http:request-connection host="${api.host}"
346
+ port="${api.port}"/>
347
+ </http:request-config>
348
+ ```
349
+
350
+ ### Scatter-Gather Limits
351
+
352
+ Limit parallel routes to avoid memory pressure:
353
+
354
+ ```xml
355
+ <!-- Keep scatter-gather routes manageable (< 5-7) -->
356
+ <scatter-gather>
357
+ <route><flow-ref name="service1-subflow"/></route>
358
+ <route><flow-ref name="service2-subflow"/></route>
359
+ <route><flow-ref name="service3-subflow"/></route>
360
+ </scatter-gather>
361
+ ```
362
+
363
+ **Related Rules:** `MULE-403`, `MULE-501`, `MULE-502`, `MULE-503`, `MULE-801`
364
+
365
+ ---
366
+
367
+ ## Project Structure
368
+
369
+ Follow standard MuleSoft project organization.
370
+
371
+ ### Required Structure
372
+
373
+ ```
374
+ my-mule-project/
375
+ ├── src/
376
+ │ ├── main/
377
+ │ │ ├── mule/ # Mule configuration files
378
+ │ │ │ ├── global.xml # Shared configs (listeners, error handlers)
379
+ │ │ │ ├── global-error-handler.xml
380
+ │ │ │ ├── orders-api.xml # API implementation
381
+ │ │ │ └── orders-flows.xml # Business flows
382
+ │ │ └── resources/
383
+ │ │ ├── api/ # RAML/OAS specifications
384
+ │ │ ├── dwl/ # External DataWeave files
385
+ │ │ │ ├── common.dwl # Reusable functions
386
+ │ │ │ └── transform-order.dwl
387
+ │ │ ├── dev.yaml # Environment configs
388
+ │ │ ├── qa.yaml
389
+ │ │ └── prod.yaml
390
+ │ └── test/
391
+ │ └── munit/ # MUnit test files
392
+ ├── pom.xml
393
+ └── mule-artifact.json
394
+ ```
395
+
396
+ ### File Organization Guidelines
397
+
398
+ | Guideline | Recommendation |
399
+ |-----------|----------------|
400
+ | Flows per file | Max 10 flows/sub-flows per XML file |
401
+ | File responsibility | One domain/feature per file |
402
+ | Global configs | Centralize in `global.xml` |
403
+ | Error handling | Separate `global-error-handler.xml` |
404
+
405
+ **Related Rules:** `MULE-802`, `MULE-803`, `MULE-804`
406
+
407
+ ---
408
+
409
+ ## Naming Conventions
410
+
411
+ Consistent naming improves readability and maintainability.
412
+
413
+ ### Flows and Sub-flows
414
+
415
+ ```xml
416
+ <!-- Use kebab-case with suffixes -->
417
+ <flow name="orders-api-get-order-flow">
418
+ <sub-flow name="validate-order-input-subflow">
419
+ ```
420
+
421
+ ### Variables
422
+
423
+ ```xml
424
+ <!-- Use camelCase -->
425
+ <set-variable variableName="orderId"/>
426
+ <set-variable variableName="customerData"/>
427
+ ```
428
+
429
+ ### Connector Configurations
430
+
431
+ ```xml
432
+ <!-- Use descriptive names -->
433
+ <http:request-config name="Orders_API_Config"/>
434
+ <db:config name="Orders_Database_Config"/>
435
+ ```
436
+
437
+ **Related Rules:** `MULE-002`, `MULE-101`, `MULE-102`, `EXP-002`
438
+
439
+ ---
440
+
441
+ ## Configuration Management
442
+
443
+ Externalize environment-specific values.
444
+
445
+ ### Environment Files
446
+
447
+ Create separate files for each environment:
448
+
449
+ ```yaml
450
+ # dev.yaml
451
+ http:
452
+ host: "0.0.0.0"
453
+ port: "8081"
454
+
455
+ api:
456
+ orders:
457
+ baseUrl: "http://localhost:8082/api"
458
+ timeout: "30000"
459
+
460
+ db:
461
+ host: "localhost"
462
+ port: "5432"
463
+ ```
464
+
465
+ ### Property Naming
466
+
467
+ Use hierarchical, lowercase naming:
468
+
469
+ ```yaml
470
+ # ✅ Good
471
+ db.host: localhost
472
+ api.orders.baseUrl: http://example.com
473
+ http.request.timeout: 30000
474
+
475
+ # ❌ Bad
476
+ DBHOST: localhost
477
+ ApiOrdersUrl: http://example.com
478
+ HTTP_TIMEOUT: 30000
479
+ ```
480
+
481
+ **Related Rules:** `YAML-001`, `YAML-003`
482
+
483
+ ---
484
+
485
+ ## DataWeave Best Practices
486
+
487
+ Write maintainable and reusable DataWeave code.
488
+
489
+ ### Externalize Complex Transforms
490
+
491
+ ```xml
492
+ <!-- ❌ Bad - Large inline transform -->
493
+ <ee:transform>
494
+ <ee:set-payload><![CDATA[%dw 2.0
495
+ <!-- 50+ lines of DataWeave -->
496
+ ]]></ee:set-payload>
497
+ </ee:transform>
498
+
499
+ <!-- ✅ Good - External file -->
500
+ <ee:transform>
501
+ <ee:set-payload resource="dwl/transform-order-response.dwl"/>
502
+ </ee:transform>
503
+ ```
504
+
505
+ ### Create Reusable Modules
506
+
507
+ ```dataweave
508
+ // src/main/resources/dwl/common.dwl
509
+ %dw 2.0
510
+
511
+ fun formatDate(date: DateTime) =
512
+ date as String {format: "yyyy-MM-dd"}
513
+
514
+ fun maskPII(value: String) =
515
+ value[0 to 2] ++ "****" ++ value[-2 to -1]
516
+
517
+ fun toErrorResponse(error, correlationId: String) = {
518
+ correlationId: correlationId,
519
+ timestamp: now(),
520
+ error: error.errorType.identifier,
521
+ message: error.description
522
+ }
523
+ ```
524
+
525
+ ### File Naming
526
+
527
+ Use kebab-case for DWL files:
528
+ - `transform-order.dwl`
529
+ - `validate-input.dwl`
530
+ - `common-utils.dwl`
531
+
532
+ **Related Rules:** `DW-001`, `DW-002`, `DW-003`
533
+
534
+ ---
535
+
536
+ ## Documentation Standards
537
+
538
+ Document for maintainability.
539
+
540
+ ### Flow Documentation
541
+
542
+ ```xml
543
+ <flow name="orders-api-create-order-flow"
544
+ doc:name="Create Order"
545
+ doc:description="Creates a new order in the system. Validates input, checks inventory, and persists to database.">
546
+ ```
547
+
548
+ ### Component Documentation
549
+
550
+ ```xml
551
+ <logger doc:name="Log Order Received"
552
+ category="com.myorg.orders"
553
+ message="#['Order received: ' ++ payload.orderId]"/>
554
+
555
+ <ee:transform doc:name="Transform to Database Format">
556
+ <!-- ... -->
557
+ </ee:transform>
558
+ ```
559
+
560
+ **Related Rules:** `MULE-601`, `MULE-604`
561
+
562
+ ---
563
+
564
+ ## Quick Reference Card
565
+
566
+ | Practice | Do | Don't |
567
+ |----------|-----|-------|
568
+ | **Error Handling** | Use global handler, set httpStatus | Catch `type="ANY"`, ignore errors |
569
+ | **Logging** | Use categories, log specific fields | Log `#[payload]`, log in retry loops |
570
+ | **Security** | Use `${property}`, encrypt secrets | Hardcode URLs, passwords, keys |
571
+ | **Performance** | Set timeouts, handle async errors | Unlimited retries, huge choice blocks |
572
+ | **Naming** | kebab-case flows, camelCase vars | Inconsistent casing, no suffixes |
573
+ | **Structure** | Separate files by domain | Monolithic XML files |
574
+ | **Config** | Environment-specific YAML files | Hardcoded values |
575
+ | **DataWeave** | External .dwl files, reusable modules | Large inline transforms |
576
+
577
+ ---
578
+
579
+ # General Developer Guidelines
580
+
581
+ > The following sections cover general MuleSoft development best practices that are not enforced by the linter but are important for building production-ready applications.
582
+
583
+ ---
584
+
585
+ ## Testing with MUnit
586
+
587
+ MUnit is MuleSoft's native testing framework. Comprehensive testing is essential for reliable integrations.
588
+
589
+ ### Test Coverage Goals
590
+
591
+ | Test Type | Coverage Target | Purpose |
592
+ |-----------|-----------------|---------|
593
+ | Unit Tests | 80%+ flow coverage | Validate individual flow logic |
594
+ | Integration Tests | All critical paths | Validate end-to-end scenarios |
595
+ | Error Scenario Tests | All error handlers | Validate error responses |
596
+
597
+ ### MUnit Best Practices
598
+
599
+ ```xml
600
+ <!-- test/munit/orders-api-test-suite.xml -->
601
+ <munit:test name="create-order-success-test"
602
+ description="Validates successful order creation">
603
+
604
+ <!-- Mock external dependencies -->
605
+ <munit:behavior>
606
+ <munit-tools:mock-when processor="http:request">
607
+ <munit-tools:with-attributes>
608
+ <munit-tools:with-attribute attributeName="config-ref"
609
+ whereValue="Orders_HTTP_Config"/>
610
+ </munit-tools:with-attributes>
611
+ <munit-tools:then-return>
612
+ <munit-tools:payload value='{"orderId": "12345"}'/>
613
+ </munit-tools:then-return>
614
+ </munit-tools:mock-when>
615
+ </munit:behavior>
616
+
617
+ <!-- Execute -->
618
+ <munit:execution>
619
+ <flow-ref name="create-order-flow"/>
620
+ </munit:execution>
621
+
622
+ <!-- Assert -->
623
+ <munit:validation>
624
+ <munit-tools:assert-that expression="#[payload.orderId]"
625
+ is="#[MunitTools::notNullValue()]"/>
626
+ </munit:validation>
627
+ </munit:test>
628
+ ```
629
+
630
+ ### Test Organization
631
+
632
+ ```
633
+ src/test/munit/
634
+ ├── orders-api-test-suite.xml # API endpoint tests
635
+ ├── orders-flows-test-suite.xml # Business logic tests
636
+ ├── error-handling-test-suite.xml # Error scenario tests
637
+ └── common-test-resources.xml # Shared mocks and utilities
638
+ ```
639
+
640
+ ### Key Principles
641
+
642
+ 1. **Mock external dependencies** - Don't call real systems in unit tests
643
+ 2. **Test error scenarios** - Verify all error handlers work correctly
644
+ 3. **Use descriptive test names** - Names should describe the scenario
645
+ 4. **Isolate tests** - Each test should be independent
646
+
647
+ ---
648
+
649
+ ## CI/CD Integration
650
+
651
+ Automate build, test, and deployment for consistent, reliable releases.
652
+
653
+ ### Recommended Pipeline Stages
654
+
655
+ ```
656
+ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐
657
+ │ Build │ → │ Lint │ → │ Test │ → │ Package │ → │ Deploy │
658
+ │ │ │ │ │ │ │ │ │ │
659
+ │ mvn │ │ mule- │ │ mvn test │ │ mvn │ │ anypoint │
660
+ │ compile │ │ lint │ │ │ │ package │ │ deploy │
661
+ └──────────┘ └──────────┘ └──────────┘ └──────────┘ └──────────┘
662
+ ```
663
+
664
+ ### GitHub Actions Example
665
+
666
+ ```yaml
667
+ # .github/workflows/mule-ci.yml
668
+ name: Mule CI/CD
669
+
670
+ on:
671
+ push:
672
+ branches: [main, develop]
673
+ pull_request:
674
+ branches: [main]
675
+
676
+ jobs:
677
+ build-and-test:
678
+ runs-on: ubuntu-latest
679
+ steps:
680
+ - uses: actions/checkout@v4
681
+
682
+ - name: Set up JDK 11
683
+ uses: actions/setup-java@v3
684
+ with:
685
+ java-version: '11'
686
+ distribution: 'adopt'
687
+
688
+ - name: Cache Maven packages
689
+ uses: actions/cache@v3
690
+ with:
691
+ path: ~/.m2
692
+ key: ${{ runner.os }}-m2-${{ hashFiles('**/pom.xml') }}
693
+
694
+ - name: Build with Maven
695
+ run: mvn -B clean compile
696
+
697
+ - name: Run mule-lint
698
+ run: npx @sfdxy/mule-lint ./src/main/mule -f sarif -o lint-results.sarif
699
+
700
+ - name: Run MUnit tests
701
+ run: mvn -B test
702
+
703
+ - name: Upload SARIF results
704
+ uses: github/codeql-action/upload-sarif@v2
705
+ with:
706
+ sarif_file: lint-results.sarif
707
+ ```
708
+
709
+ ### Git Branch Strategy
710
+
711
+ | Branch | Purpose | Deployment Target |
712
+ |--------|---------|-------------------|
713
+ | `main` | Production-ready code | Production |
714
+ | `develop` | Integration branch | QA/Staging |
715
+ | `feature/*` | New features | Development |
716
+ | `hotfix/*` | Production fixes | Production |
717
+
718
+ ---
719
+
720
+ ## API Versioning
721
+
722
+ Plan for API evolution from the start.
723
+
724
+ ### URL-Based Versioning (Recommended)
725
+
726
+ ```
727
+ /api/v1/orders
728
+ /api/v2/orders
729
+ ```
730
+
731
+ ### Implementation Pattern
732
+
733
+ ```xml
734
+ <!-- src/main/mule/orders-api-v1.xml -->
735
+ <flow name="orders-api-v1-main-flow">
736
+ <http:listener config-ref="HTTPS_Listener" path="/api/v1/orders/*"/>
737
+ <apikit:router config-ref="orders-v1-config"/>
738
+ </flow>
739
+
740
+ <!-- src/main/mule/orders-api-v2.xml -->
741
+ <flow name="orders-api-v2-main-flow">
742
+ <http:listener config-ref="HTTPS_Listener" path="/api/v2/orders/*"/>
743
+ <apikit:router config-ref="orders-v2-config"/>
744
+ </flow>
745
+ ```
746
+
747
+ ### Version Deprecation Strategy
748
+
749
+ 1. **Announce deprecation** - Communicate timeline to consumers
750
+ 2. **Add deprecation headers** - Return `Deprecation` header in responses
751
+ 3. **Monitor usage** - Track v1 vs v2 adoption
752
+ 4. **Sunset gracefully** - Remove only after consumer migration
753
+
754
+ ```xml
755
+ <!-- Add deprecation warning -->
756
+ <set-variable variableName="outboundHeaders" value="#[{
757
+ 'Deprecation': 'true',
758
+ 'Sunset': 'Sat, 01 Jan 2025 00:00:00 GMT',
759
+ 'Link': '&lt;/api/v2/orders&gt;; rel="successor-version"'
760
+ }]"/>
761
+ ```
762
+
763
+ ---
764
+
765
+ ## Deployment Practices
766
+
767
+ Deploy safely and consistently across environments.
768
+
769
+ ### Environment Promotion
770
+
771
+ ```
772
+ Development → QA → Staging → Production
773
+ ↓ ↓ ↓ ↓
774
+ dev.yaml qa.yaml stg.yaml prod.yaml
775
+ ```
776
+
777
+ ### Deployment Checklist
778
+
779
+ | Item | Description |
780
+ |------|-------------|
781
+ | ✅ All tests pass | MUnit and integration tests |
782
+ | ✅ Lint checks pass | No errors from mule-lint |
783
+ | ✅ Properties configured | Environment YAML verified |
784
+ | ✅ Secrets encrypted | No plaintext credentials |
785
+ | ✅ API Manager policies | Authentication, rate limiting |
786
+ | ✅ Monitoring configured | Dashboards and alerts ready |
787
+
788
+ ### Blue-Green Deployment
789
+
790
+ For zero-downtime deployments:
791
+
792
+ 1. Deploy new version to "green" workers
793
+ 2. Run smoke tests against green
794
+ 3. Switch load balancer to green
795
+ 4. Monitor for issues
796
+ 5. Decommission "blue" workers (or keep for rollback)
797
+
798
+ ### Rollback Strategy
799
+
800
+ ```bash
801
+ # Anypoint CLI rollback example
802
+ anypoint-cli runtime-mgr cloudhub-application modify \
803
+ --environment Production \
804
+ --applicationName orders-api \
805
+ --runtime 4.4.0 \
806
+ --artifact-id orders-api-1.2.0.jar
807
+ ```
808
+
809
+ ---
810
+
811
+ ## Monitoring and Observability
812
+
813
+ Production applications need comprehensive monitoring.
814
+
815
+ ### The Three Pillars
816
+
817
+ | Pillar | Tool | Purpose |
818
+ |--------|------|---------|
819
+ | **Logs** | Anypoint Monitoring, Splunk, ELK | Debug issues, audit trail |
820
+ | **Metrics** | Anypoint Monitoring, Grafana | Performance, health status |
821
+ | **Traces** | Anypoint Monitoring, Jaeger | Request flow, latency analysis |
822
+
823
+ ### Key Metrics to Monitor
824
+
825
+ ```
826
+ Application Health:
827
+ ├── Response time (p50, p95, p99)
828
+ ├── Error rate (%)
829
+ ├── Throughput (requests/sec)
830
+ ├── Active connections
831
+ └── Worker CPU/Memory usage
832
+
833
+ Business Metrics:
834
+ ├── Orders processed per hour
835
+ ├── Failed transactions
836
+ ├── API calls by consumer
837
+ └── Integration latency by backend
838
+ ```
839
+
840
+ ### Alerting Best Practices
841
+
842
+ | Alert Level | Condition | Response |
843
+ |-------------|-----------|----------|
844
+ | **Critical** | Error rate > 10%, App down | Immediate on-call response |
845
+ | **Warning** | Error rate > 5%, Latency > 5s | Investigate within 1 hour |
846
+ | **Info** | Unusual patterns, Resource > 70% | Review in daily standup |
847
+
848
+ ### Correlation ID Pattern
849
+
850
+ Ensure correlation IDs flow through all systems:
851
+
852
+ ```xml
853
+ <!-- Set correlation ID at entry point -->
854
+ <set-variable variableName="correlationId"
855
+ value="#[correlationId default uuid()]"/>
856
+
857
+ <!-- Include in all outbound requests -->
858
+ <http:request config-ref="HTTP_Config" path="/downstream">
859
+ <http:headers><![CDATA[#[{
860
+ 'X-Correlation-ID': vars.correlationId
861
+ }]]]></http:headers>
862
+ </http:request>
863
+
864
+ <!-- Include in all log messages -->
865
+ <logger category="com.myorg"
866
+ message="#['[' ++ vars.correlationId ++ '] Processing request...']"/>
867
+ ```
868
+
869
+ ### Health Check Endpoint
870
+
871
+ Expose a health endpoint for load balancers and monitoring:
872
+
873
+ ```xml
874
+ <flow name="health-check-flow">
875
+ <http:listener config-ref="HTTPS_Listener" path="/health"/>
876
+ <set-payload value='#[%dw 2.0
877
+ output application/json
878
+ ---
879
+ {
880
+ status: "UP",
881
+ timestamp: now(),
882
+ version: p("app.version"),
883
+ environment: p("mule.env")
884
+ }]'/>
885
+ </flow>
886
+ ```
887
+
888
+ ---
889
+
890
+ ## Summary
891
+
892
+ This guide covers both linter-enforced practices and general developer guidelines:
893
+
894
+ | Category | Linter Enforced | General Guidelines |
895
+ |----------|-----------------|-------------------|
896
+ | Code Quality | ✅ Naming, Structure, Complexity | Testing, Code Review |
897
+ | Security | ✅ Hardcoded secrets, TLS | Secrets Management, IAM |
898
+ | Operations | ✅ Error handling, Logging | CI/CD, Monitoring, Deployment |
899
+ | Architecture | ✅ API-Led patterns | Versioning, Documentation |
900
+
901
+ For linter rule details, see the [Rules Catalog](rules-catalog.md).
902
+