@sfdxy/mule-lint 1.20.0 → 1.22.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.
- package/README.md +63 -17
- package/dist/package.json +1 -1
- package/dist/src/core/XPathHelper.d.ts.map +1 -1
- package/dist/src/core/XPathHelper.js +8 -0
- package/dist/src/core/XPathHelper.js.map +1 -1
- package/dist/src/engine/LintEngine.d.ts +22 -0
- package/dist/src/engine/LintEngine.d.ts.map +1 -1
- package/dist/src/engine/LintEngine.js +105 -18
- package/dist/src/engine/LintEngine.js.map +1 -1
- package/dist/src/mcp/prompts/index.d.ts +1 -1
- package/dist/src/mcp/prompts/index.d.ts.map +1 -1
- package/dist/src/mcp/prompts/index.js +62 -1
- package/dist/src/mcp/prompts/index.js.map +1 -1
- package/dist/src/mcp/resources/index.js +114 -16
- package/dist/src/mcp/resources/index.js.map +1 -1
- package/dist/src/mcp/tools/getRuleDetails.d.ts.map +1 -1
- package/dist/src/mcp/tools/getRuleDetails.js +30 -1
- package/dist/src/mcp/tools/getRuleDetails.js.map +1 -1
- package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts +22 -0
- package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts.map +1 -0
- package/dist/src/rules/api-led/ApikitConsoleProductionRule.js +43 -0
- package/dist/src/rules/api-led/ApikitConsoleProductionRule.js.map +1 -0
- package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts +24 -0
- package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts.map +1 -0
- package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js +53 -0
- package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js.map +1 -0
- package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts +25 -0
- package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts.map +1 -0
- package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js +59 -0
- package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js.map +1 -0
- package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts +24 -0
- package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts.map +1 -0
- package/dist/src/rules/connector/EventListenerNullGuardRule.js +58 -0
- package/dist/src/rules/connector/EventListenerNullGuardRule.js.map +1 -0
- package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts +23 -0
- package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts.map +1 -0
- package/dist/src/rules/connector/ReplayChannelConfigRule.js +52 -0
- package/dist/src/rules/connector/ReplayChannelConfigRule.js.map +1 -0
- package/dist/src/rules/dataweave/DataWeaveRules.d.ts +11 -4
- package/dist/src/rules/dataweave/DataWeaveRules.d.ts.map +1 -1
- package/dist/src/rules/dataweave/DataWeaveRules.js +20 -20
- package/dist/src/rules/dataweave/DataWeaveRules.js.map +1 -1
- package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts +25 -0
- package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts.map +1 -0
- package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js +63 -0
- package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js.map +1 -0
- package/dist/src/rules/error-handling/CatchAllLastRule.d.ts +24 -0
- package/dist/src/rules/error-handling/CatchAllLastRule.d.ts.map +1 -0
- package/dist/src/rules/error-handling/CatchAllLastRule.js +65 -0
- package/dist/src/rules/error-handling/CatchAllLastRule.js.map +1 -0
- package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts +28 -0
- package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts.map +1 -0
- package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js +70 -0
- package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js.map +1 -0
- package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts +23 -0
- package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts.map +1 -0
- package/dist/src/rules/error-handling/ErrorResponseStructureRule.js +73 -0
- package/dist/src/rules/error-handling/ErrorResponseStructureRule.js.map +1 -0
- package/dist/src/rules/error-handling/GenericErrorRule.d.ts +15 -3
- package/dist/src/rules/error-handling/GenericErrorRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/GenericErrorRule.js +58 -18
- package/dist/src/rules/error-handling/GenericErrorRule.js.map +1 -1
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts +14 -15
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js +59 -38
- package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js.map +1 -1
- package/dist/src/rules/error-handling/TryScopeRule.d.ts +5 -0
- package/dist/src/rules/error-handling/TryScopeRule.d.ts.map +1 -1
- package/dist/src/rules/error-handling/TryScopeRule.js +30 -7
- package/dist/src/rules/error-handling/TryScopeRule.js.map +1 -1
- package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts +27 -0
- package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts.map +1 -0
- package/dist/src/rules/http/ConnectionIdleTimeoutRule.js +46 -0
- package/dist/src/rules/http/ConnectionIdleTimeoutRule.js.map +1 -0
- package/dist/src/rules/index.d.ts +1 -1
- package/dist/src/rules/index.d.ts.map +1 -1
- package/dist/src/rules/index.js +50 -8
- package/dist/src/rules/index.js.map +1 -1
- package/dist/src/rules/logging/LoggerPayloadRule.d.ts +15 -0
- package/dist/src/rules/logging/LoggerPayloadRule.d.ts.map +1 -1
- package/dist/src/rules/logging/LoggerPayloadRule.js +48 -4
- package/dist/src/rules/logging/LoggerPayloadRule.js.map +1 -1
- package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts +23 -0
- package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts.map +1 -0
- package/dist/src/rules/operations/FlowRefTargetExistsRule.js +58 -0
- package/dist/src/rules/operations/FlowRefTargetExistsRule.js.map +1 -0
- package/dist/src/rules/operations/UnusedFlowRule.d.ts +20 -0
- package/dist/src/rules/operations/UnusedFlowRule.d.ts.map +1 -1
- package/dist/src/rules/operations/UnusedFlowRule.js +73 -7
- package/dist/src/rules/operations/UnusedFlowRule.js.map +1 -1
- package/dist/src/rules/operations/UnusedVariableRule.d.ts +31 -0
- package/dist/src/rules/operations/UnusedVariableRule.d.ts.map +1 -0
- package/dist/src/rules/operations/UnusedVariableRule.js +103 -0
- package/dist/src/rules/operations/UnusedVariableRule.js.map +1 -0
- package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts +28 -0
- package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts.map +1 -0
- package/dist/src/rules/performance/ListenerReconnectForeverRule.js +56 -0
- package/dist/src/rules/performance/ListenerReconnectForeverRule.js.map +1 -0
- package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts +7 -4
- package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts.map +1 -1
- package/dist/src/rules/performance/ReconnectionStrategyRule.js +44 -24
- package/dist/src/rules/performance/ReconnectionStrategyRule.js.map +1 -1
- package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts +36 -0
- package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts.map +1 -0
- package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js +124 -0
- package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js.map +1 -0
- package/dist/src/rules/security/HardcodedCredentialsRule.d.ts +4 -0
- package/dist/src/rules/security/HardcodedCredentialsRule.d.ts.map +1 -1
- package/dist/src/rules/security/HardcodedCredentialsRule.js +15 -0
- package/dist/src/rules/security/HardcodedCredentialsRule.js.map +1 -1
- package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts +25 -0
- package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts.map +1 -0
- package/dist/src/rules/security/SecurePropertiesEncryptionRule.js +59 -0
- package/dist/src/rules/security/SecurePropertiesEncryptionRule.js.map +1 -0
- package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts +23 -0
- package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts.map +1 -0
- package/dist/src/rules/security/SecurePropertiesKeyRule.js +45 -0
- package/dist/src/rules/security/SecurePropertiesKeyRule.js.map +1 -0
- package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts +25 -0
- package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts.map +1 -0
- package/dist/src/rules/security/TlsKeystorePasswordRule.js +63 -0
- package/dist/src/rules/security/TlsKeystorePasswordRule.js.map +1 -0
- package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts +26 -0
- package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts.map +1 -0
- package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js +61 -0
- package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js.map +1 -0
- package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts +34 -0
- package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts.map +1 -0
- package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js +76 -0
- package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js.map +1 -0
- package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts +25 -0
- package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts.map +1 -0
- package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js +111 -0
- package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js.map +1 -0
- package/dist/src/rules/yaml/YamlRules.d.ts +6 -2
- package/dist/src/rules/yaml/YamlRules.d.ts.map +1 -1
- package/dist/src/rules/yaml/YamlRules.js +15 -11
- package/dist/src/rules/yaml/YamlRules.js.map +1 -1
- package/dist/src/types/Rule.d.ts +13 -0
- package/dist/src/types/Rule.d.ts.map +1 -1
- package/docs/README.md +87 -27
- package/docs/best-practices/ci-cd.md +135 -0
- package/docs/best-practices/connector-patterns.md +253 -0
- package/docs/best-practices/dataweave-patterns.md +370 -0
- package/docs/best-practices/deployment-2026.md +171 -0
- package/docs/best-practices/error-handling.md +277 -0
- package/docs/best-practices/event-driven-patterns.md +424 -0
- package/docs/best-practices/logging.md +163 -0
- package/docs/best-practices/mulesoft-best-practices.md +72 -865
- package/docs/best-practices/performance.md +273 -0
- package/docs/best-practices/rules-catalog.md +337 -29
- package/docs/best-practices/security.md +181 -0
- package/docs/best-practices/testing.md +190 -0
- package/docs/best-practices/variable-contracts.md +191 -0
- package/docs/linter/architecture.md +119 -64
- package/package.json +1 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SecurePropertiesEncryptionRule = void 0;
|
|
4
|
+
const BaseRule_1 = require("../base/BaseRule");
|
|
5
|
+
/**
|
|
6
|
+
* SEC-010: Secure Properties Encryption Algorithm
|
|
7
|
+
*
|
|
8
|
+
* When `<secure-properties:config>` specifies an encryption algorithm, it
|
|
9
|
+
* should use a strong algorithm (AES, Blowfish) and not a weak or
|
|
10
|
+
* deprecated one (DES, RC2, RC4).
|
|
11
|
+
*
|
|
12
|
+
* Also validates that when secure properties are used, the `encrypt`
|
|
13
|
+
* element exists (i.e., properties are actually encrypted, not just
|
|
14
|
+
* marked as "secure" with no encryption).
|
|
15
|
+
*/
|
|
16
|
+
class SecurePropertiesEncryptionRule extends BaseRule_1.BaseRule {
|
|
17
|
+
id = 'SEC-010';
|
|
18
|
+
name = 'Secure Properties Encryption';
|
|
19
|
+
description = 'Secure properties must use strong encryption algorithms';
|
|
20
|
+
severity = 'warning';
|
|
21
|
+
category = 'security';
|
|
22
|
+
issueType = 'vulnerability';
|
|
23
|
+
WEAK_ALGORITHMS = ['DES', 'DESede', 'RC2', 'RC4'];
|
|
24
|
+
STRONG_ALGORITHMS = ['AES', 'Blowfish'];
|
|
25
|
+
validate(doc, _context) {
|
|
26
|
+
const issues = [];
|
|
27
|
+
// Match secure-properties:config or secure-configuration-properties
|
|
28
|
+
const secureConfigs = this.select('//*[local-name()="config" and contains(namespace-uri(), "secure-properties")] | ' +
|
|
29
|
+
'//*[local-name()="secure-configuration-properties"]', doc);
|
|
30
|
+
for (const config of secureConfigs) {
|
|
31
|
+
// Check for encrypt element presence
|
|
32
|
+
const encryptElements = this.select('.//*[local-name()="encrypt"]', config);
|
|
33
|
+
if (encryptElements.length === 0) {
|
|
34
|
+
const docName = this.getDocName(config) ?? 'Secure Properties Config';
|
|
35
|
+
issues.push(this.createIssue(config, `"${docName}" has no <encrypt> element — properties may not be encrypted`, {
|
|
36
|
+
severity: 'warning',
|
|
37
|
+
suggestion: 'Add <secure-properties:encrypt algorithm="AES" mode="CBC"/> to enable encryption',
|
|
38
|
+
}));
|
|
39
|
+
continue;
|
|
40
|
+
}
|
|
41
|
+
// Check encryption algorithm
|
|
42
|
+
for (const encrypt of encryptElements) {
|
|
43
|
+
const algorithm = this.getAttribute(encrypt, 'algorithm');
|
|
44
|
+
if (!algorithm) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (this.WEAK_ALGORITHMS.includes(algorithm)) {
|
|
48
|
+
issues.push(this.createIssue(encrypt, `Weak encryption algorithm "${algorithm}" — use ${this.STRONG_ALGORITHMS.join(' or ')} instead`, {
|
|
49
|
+
severity: 'error',
|
|
50
|
+
suggestion: `Replace algorithm="${algorithm}" with algorithm="AES"`,
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return issues;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.SecurePropertiesEncryptionRule = SecurePropertiesEncryptionRule;
|
|
59
|
+
//# sourceMappingURL=SecurePropertiesEncryptionRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecurePropertiesEncryptionRule.js","sourceRoot":"","sources":["../../../../src/rules/security/SecurePropertiesEncryptionRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;;GAUG;AACH,MAAa,8BAA+B,SAAQ,mBAAQ;IAC1D,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,8BAA8B,CAAC;IACtC,WAAW,GAAG,yDAAyD,CAAC;IACxE,QAAQ,GAAG,SAAkB,CAAC;IAC9B,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAc,eAAe,CAAC;IAEtB,eAAe,GAAG,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAClD,iBAAiB,GAAG,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAEzD,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,oEAAoE;QACpE,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAC/B,kFAAkF;YAChF,qDAAqD,EACvD,GAAG,CACJ,CAAC;QAEF,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;YACnC,qCAAqC;YACrC,MAAM,eAAe,GAAG,IAAI,CAAC,MAAM,CAAC,8BAA8B,EAAE,MAAkB,CAAC,CAAC;YAExF,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,0BAA0B,CAAC;gBACtE,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,MAAM,EACN,IAAI,OAAO,8DAA8D,EACzE;oBACE,QAAQ,EAAE,SAAS;oBACnB,UAAU,EACR,kFAAkF;iBACrF,CACF,CACF,CAAC;gBACF,SAAS;YACX,CAAC;YAED,6BAA6B;YAC7B,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;gBACtC,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC;gBAC1D,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,SAAS;gBACX,CAAC;gBAED,IAAI,IAAI,CAAC,eAAe,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;oBAC7C,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,OAAO,EACP,8BAA8B,SAAS,WAAW,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,EAC/F;wBACE,QAAQ,EAAE,OAAO;wBACjB,UAAU,EAAE,sBAAsB,SAAS,wBAAwB;qBACpE,CACF,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAjED,wEAiEC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ValidationContext, Issue, IssueType } from '../../types';
|
|
2
|
+
import { BaseRule } from '../base/BaseRule';
|
|
3
|
+
/**
|
|
4
|
+
* SEC-008: Secure Properties Key Configuration
|
|
5
|
+
*
|
|
6
|
+
* The `<secure-properties:config>` element's `key` attribute must use a
|
|
7
|
+
* property placeholder (`${...}`) — never a hardcoded encryption key.
|
|
8
|
+
*
|
|
9
|
+
* A hardcoded key in the XML defeats the purpose of encryption because
|
|
10
|
+
* anyone with access to the source code can decrypt all secure properties.
|
|
11
|
+
* The key should be injected via a system property or environment variable
|
|
12
|
+
* at deployment time (e.g., `-Dsecure.key=...` in the Mule runtime args).
|
|
13
|
+
*/
|
|
14
|
+
export declare class SecurePropertiesKeyRule extends BaseRule {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
severity: "error";
|
|
19
|
+
category: "security";
|
|
20
|
+
issueType: IssueType;
|
|
21
|
+
validate(doc: Document, _context: ValidationContext): Issue[];
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=SecurePropertiesKeyRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecurePropertiesKeyRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/security/SecurePropertiesKeyRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,qBAAa,uBAAwB,SAAQ,QAAQ;IACnD,EAAE,SAAa;IACf,IAAI,SAA2B;IAC/B,WAAW,SAA4D;IACvE,QAAQ,EAAG,OAAO,CAAU;IAC5B,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,SAAS,CAAmB;IAEvC,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;CAkC9D"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SecurePropertiesKeyRule = void 0;
|
|
4
|
+
const BaseRule_1 = require("../base/BaseRule");
|
|
5
|
+
/**
|
|
6
|
+
* SEC-008: Secure Properties Key Configuration
|
|
7
|
+
*
|
|
8
|
+
* The `<secure-properties:config>` element's `key` attribute must use a
|
|
9
|
+
* property placeholder (`${...}`) — never a hardcoded encryption key.
|
|
10
|
+
*
|
|
11
|
+
* A hardcoded key in the XML defeats the purpose of encryption because
|
|
12
|
+
* anyone with access to the source code can decrypt all secure properties.
|
|
13
|
+
* The key should be injected via a system property or environment variable
|
|
14
|
+
* at deployment time (e.g., `-Dsecure.key=...` in the Mule runtime args).
|
|
15
|
+
*/
|
|
16
|
+
class SecurePropertiesKeyRule extends BaseRule_1.BaseRule {
|
|
17
|
+
id = 'SEC-008';
|
|
18
|
+
name = 'Secure Properties Key';
|
|
19
|
+
description = 'Secure properties encryption key must not be hardcoded';
|
|
20
|
+
severity = 'error';
|
|
21
|
+
category = 'security';
|
|
22
|
+
issueType = 'vulnerability';
|
|
23
|
+
validate(doc, _context) {
|
|
24
|
+
const issues = [];
|
|
25
|
+
// Match secure-properties:config or secure-configuration-properties
|
|
26
|
+
const secureConfigs = this.select('//*[local-name()="config" and contains(namespace-uri(), "secure-properties")] | ' +
|
|
27
|
+
'//*[local-name()="secure-configuration-properties"]', doc);
|
|
28
|
+
for (const config of secureConfigs) {
|
|
29
|
+
const key = this.getAttribute(config, 'key');
|
|
30
|
+
if (!key) {
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
// Key must be a property placeholder
|
|
34
|
+
if (!key.includes('${')) {
|
|
35
|
+
const docName = this.getDocName(config) ?? 'Secure Properties Config';
|
|
36
|
+
issues.push(this.createIssue(config, `"${docName}" has hardcoded encryption key — defeats the purpose of property encryption`, {
|
|
37
|
+
suggestion: 'Use a property placeholder: key="${secure.key}" and inject via -Dsecure.key=... at runtime',
|
|
38
|
+
}));
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return issues;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
exports.SecurePropertiesKeyRule = SecurePropertiesKeyRule;
|
|
45
|
+
//# sourceMappingURL=SecurePropertiesKeyRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"SecurePropertiesKeyRule.js","sourceRoot":"","sources":["../../../../src/rules/security/SecurePropertiesKeyRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;;GAUG;AACH,MAAa,uBAAwB,SAAQ,mBAAQ;IACnD,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,uBAAuB,CAAC;IAC/B,WAAW,GAAG,wDAAwD,CAAC;IACvE,QAAQ,GAAG,OAAgB,CAAC;IAC5B,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAc,eAAe,CAAC;IAEvC,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,oEAAoE;QACpE,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAC/B,kFAAkF;YAChF,qDAAqD,EACvD,GAAG,CACJ,CAAC;QAEF,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;YACnC,MAAM,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC7C,IAAI,CAAC,GAAG,EAAE,CAAC;gBACT,SAAS;YACX,CAAC;YAED,qCAAqC;YACrC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxB,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,0BAA0B,CAAC;gBACtE,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,MAAM,EACN,IAAI,OAAO,6EAA6E,EACxF;oBACE,UAAU,EACR,4FAA4F;iBAC/F,CACF,CACF,CAAC;YACJ,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA1CD,0DA0CC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ValidationContext, Issue, IssueType } from '../../types';
|
|
2
|
+
import { BaseRule } from '../base/BaseRule';
|
|
3
|
+
/**
|
|
4
|
+
* SEC-009: TLS Keystore/Truststore Passwords Secured
|
|
5
|
+
*
|
|
6
|
+
* TLS context keystore and truststore passwords must use secure property
|
|
7
|
+
* placeholders (`${secure::...}`) rather than plain-text placeholders or
|
|
8
|
+
* hardcoded values.
|
|
9
|
+
*
|
|
10
|
+
* These passwords protect the private keys and certificates used for
|
|
11
|
+
* mutual TLS (mTLS) authentication. Leaking them enables impersonation
|
|
12
|
+
* attacks and man-in-the-middle interception.
|
|
13
|
+
*/
|
|
14
|
+
export declare class TlsKeystorePasswordRule extends BaseRule {
|
|
15
|
+
id: string;
|
|
16
|
+
name: string;
|
|
17
|
+
description: string;
|
|
18
|
+
severity: "error";
|
|
19
|
+
category: "security";
|
|
20
|
+
issueType: IssueType;
|
|
21
|
+
private readonly PASSWORD_ATTRS;
|
|
22
|
+
validate(doc: Document, _context: ValidationContext): Issue[];
|
|
23
|
+
private extractPropName;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=TlsKeystorePasswordRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TlsKeystorePasswordRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/security/TlsKeystorePasswordRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;GAUG;AACH,qBAAa,uBAAwB,SAAQ,QAAQ;IACnD,EAAE,SAAa;IACf,IAAI,SAAmC;IACvC,WAAW,SAAyE;IACpF,QAAQ,EAAG,OAAO,CAAU;IAC5B,QAAQ,EAAG,UAAU,CAAU;IAC/B,SAAS,EAAE,SAAS,CAAmB;IAEvC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+B;IAE9D,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;IAoD7D,OAAO,CAAC,eAAe;CAIxB"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TlsKeystorePasswordRule = void 0;
|
|
4
|
+
const BaseRule_1 = require("../base/BaseRule");
|
|
5
|
+
/**
|
|
6
|
+
* SEC-009: TLS Keystore/Truststore Passwords Secured
|
|
7
|
+
*
|
|
8
|
+
* TLS context keystore and truststore passwords must use secure property
|
|
9
|
+
* placeholders (`${secure::...}`) rather than plain-text placeholders or
|
|
10
|
+
* hardcoded values.
|
|
11
|
+
*
|
|
12
|
+
* These passwords protect the private keys and certificates used for
|
|
13
|
+
* mutual TLS (mTLS) authentication. Leaking them enables impersonation
|
|
14
|
+
* attacks and man-in-the-middle interception.
|
|
15
|
+
*/
|
|
16
|
+
class TlsKeystorePasswordRule extends BaseRule_1.BaseRule {
|
|
17
|
+
id = 'SEC-009';
|
|
18
|
+
name = 'TLS Keystore Password Secured';
|
|
19
|
+
description = 'TLS keystore/truststore passwords must use ${secure::} placeholders';
|
|
20
|
+
severity = 'error';
|
|
21
|
+
category = 'security';
|
|
22
|
+
issueType = 'vulnerability';
|
|
23
|
+
PASSWORD_ATTRS = ['password', 'keyPassword'];
|
|
24
|
+
validate(doc, _context) {
|
|
25
|
+
const issues = [];
|
|
26
|
+
// Select all key-store and trust-store elements
|
|
27
|
+
const stores = this.select('//*[local-name()="key-store" or local-name()="trust-store"]', doc);
|
|
28
|
+
for (const store of stores) {
|
|
29
|
+
for (const attrName of this.PASSWORD_ATTRS) {
|
|
30
|
+
const value = this.getAttribute(store, attrName);
|
|
31
|
+
if (!value || value.trim() === '') {
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
// DataWeave expressions are OK
|
|
35
|
+
if (value.startsWith('#[')) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
// Must use ${secure::...}
|
|
39
|
+
if (value.includes('${') && !value.includes('${secure::')) {
|
|
40
|
+
const storeName = store.localName;
|
|
41
|
+
issues.push(this.createIssue(store, `TLS ${storeName} "${attrName}" uses plain property placeholder — must use \${secure::}`, {
|
|
42
|
+
suggestion: `Replace ${value} with \${secure::${this.extractPropName(value)}}`,
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
// Hardcoded value
|
|
46
|
+
if (!value.includes('${') && !value.startsWith('#[')) {
|
|
47
|
+
const storeName = store.localName;
|
|
48
|
+
issues.push(this.createIssue(store, `TLS ${storeName} "${attrName}" is hardcoded — must use \${secure::} placeholder`, {
|
|
49
|
+
severity: 'error',
|
|
50
|
+
suggestion: `Use \${secure::tls.${storeName}.${attrName}} instead of the hardcoded value`,
|
|
51
|
+
}));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return issues;
|
|
56
|
+
}
|
|
57
|
+
extractPropName(placeholder) {
|
|
58
|
+
const match = /\$\{([^}]+)\}/.exec(placeholder);
|
|
59
|
+
return match ? match[1] : placeholder;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.TlsKeystorePasswordRule = TlsKeystorePasswordRule;
|
|
63
|
+
//# sourceMappingURL=TlsKeystorePasswordRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TlsKeystorePasswordRule.js","sourceRoot":"","sources":["../../../../src/rules/security/TlsKeystorePasswordRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;;GAUG;AACH,MAAa,uBAAwB,SAAQ,mBAAQ;IACnD,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,+BAA+B,CAAC;IACvC,WAAW,GAAG,qEAAqE,CAAC;IACpF,QAAQ,GAAG,OAAgB,CAAC;IAC5B,QAAQ,GAAG,UAAmB,CAAC;IAC/B,SAAS,GAAc,eAAe,CAAC;IAEtB,cAAc,GAAG,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;IAE9D,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,gDAAgD;QAChD,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,6DAA6D,EAAE,GAAG,CAAC,CAAC;QAE/F,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC;gBAC3C,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;gBACjD,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC;oBAClC,SAAS;gBACX,CAAC;gBAED,+BAA+B;gBAC/B,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC3B,SAAS;gBACX,CAAC;gBAED,0BAA0B;gBAC1B,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;oBAC1D,MAAM,SAAS,GAAI,KAAiB,CAAC,SAAS,CAAC;oBAC/C,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,KAAK,EACL,OAAO,SAAS,KAAK,QAAQ,2DAA2D,EACxF;wBACE,UAAU,EAAE,WAAW,KAAK,oBAAoB,IAAI,CAAC,eAAe,CAAC,KAAK,CAAC,GAAG;qBAC/E,CACF,CACF,CAAC;gBACJ,CAAC;gBAED,kBAAkB;gBAClB,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;oBACrD,MAAM,SAAS,GAAI,KAAiB,CAAC,SAAS,CAAC;oBAC/C,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,KAAK,EACL,OAAO,SAAS,KAAK,QAAQ,oDAAoD,EACjF;wBACE,QAAQ,EAAE,OAAO;wBACjB,UAAU,EAAE,sBAAsB,SAAS,IAAI,QAAQ,kCAAkC;qBAC1F,CACF,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,eAAe,CAAC,WAAmB;QACzC,MAAM,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChD,OAAO,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC;IACxC,CAAC;CACF;AAlED,0DAkEC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ValidationContext, Issue, IssueType } from '../../types';
|
|
2
|
+
import { BaseRule } from '../base/BaseRule';
|
|
3
|
+
/**
|
|
4
|
+
* STD-001: APIKit Route Variable Consistency
|
|
5
|
+
*
|
|
6
|
+
* In APIKit projects, implementation flows (get:\resource:config, etc.)
|
|
7
|
+
* should follow a consistent pattern for setting response variables.
|
|
8
|
+
* For example, if some flows set httpStatus but others don't, this
|
|
9
|
+
* inconsistency can lead to unexpected HTTP responses.
|
|
10
|
+
*
|
|
11
|
+
* This rule flags APIKit implementation flows that deviate from the
|
|
12
|
+
* most common pattern in the file (e.g., if 4/5 flows set httpStatus
|
|
13
|
+
* but one doesn't, the outlier is flagged).
|
|
14
|
+
*/
|
|
15
|
+
export declare class ApikitRouteVariableConsistencyRule extends BaseRule {
|
|
16
|
+
id: string;
|
|
17
|
+
name: string;
|
|
18
|
+
description: string;
|
|
19
|
+
severity: "info";
|
|
20
|
+
category: "standards";
|
|
21
|
+
issueType: IssueType;
|
|
22
|
+
/** Pattern for APIKit-generated flow names */
|
|
23
|
+
private readonly APIKIT_FLOW_PATTERN;
|
|
24
|
+
validate(doc: Document, _context: ValidationContext): Issue[];
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=ApikitRouteVariableConsistencyRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApikitRouteVariableConsistencyRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/standards/ApikitRouteVariableConsistencyRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;;GAWG;AACH,qBAAa,kCAAmC,SAAQ,QAAQ;IAC9D,EAAE,SAAa;IACf,IAAI,SAAuC;IAC3C,WAAW,SAC8E;IACzF,QAAQ,EAAG,MAAM,CAAU;IAC3B,QAAQ,EAAG,WAAW,CAAU;IAChC,SAAS,EAAE,SAAS,CAAgB;IAEpC,8CAA8C;IAC9C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAkD;IAEtF,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;CAoD9D"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ApikitRouteVariableConsistencyRule = void 0;
|
|
4
|
+
const BaseRule_1 = require("../base/BaseRule");
|
|
5
|
+
/**
|
|
6
|
+
* STD-001: APIKit Route Variable Consistency
|
|
7
|
+
*
|
|
8
|
+
* In APIKit projects, implementation flows (get:\resource:config, etc.)
|
|
9
|
+
* should follow a consistent pattern for setting response variables.
|
|
10
|
+
* For example, if some flows set httpStatus but others don't, this
|
|
11
|
+
* inconsistency can lead to unexpected HTTP responses.
|
|
12
|
+
*
|
|
13
|
+
* This rule flags APIKit implementation flows that deviate from the
|
|
14
|
+
* most common pattern in the file (e.g., if 4/5 flows set httpStatus
|
|
15
|
+
* but one doesn't, the outlier is flagged).
|
|
16
|
+
*/
|
|
17
|
+
class ApikitRouteVariableConsistencyRule extends BaseRule_1.BaseRule {
|
|
18
|
+
id = 'STD-001';
|
|
19
|
+
name = 'APIKit Route Variable Consistency';
|
|
20
|
+
description = 'APIKit implementation flows should follow consistent patterns for response variables';
|
|
21
|
+
severity = 'info';
|
|
22
|
+
category = 'standards';
|
|
23
|
+
issueType = 'code-smell';
|
|
24
|
+
/** Pattern for APIKit-generated flow names */
|
|
25
|
+
APIKIT_FLOW_PATTERN = /^(get|post|put|patch|delete|head|options):\\/;
|
|
26
|
+
validate(doc, _context) {
|
|
27
|
+
const issues = [];
|
|
28
|
+
const flows = this.select('//mule:flow', doc);
|
|
29
|
+
// Collect APIKit implementation flows
|
|
30
|
+
const apikitFlows = [];
|
|
31
|
+
for (const flow of flows) {
|
|
32
|
+
const flowName = this.getAttribute(flow, 'name') ?? '';
|
|
33
|
+
if (!this.APIKIT_FLOW_PATTERN.test(flowName)) {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
const setsHttpStatus = this.exists('.//*[local-name()="set-variable" and @variableName="httpStatus"]', flow);
|
|
37
|
+
apikitFlows.push({ name: flowName, node: flow, setsHttpStatus });
|
|
38
|
+
}
|
|
39
|
+
// Need at least 3 flows to detect a meaningful pattern
|
|
40
|
+
if (apikitFlows.length < 3) {
|
|
41
|
+
return issues;
|
|
42
|
+
}
|
|
43
|
+
// Determine the majority pattern
|
|
44
|
+
const withStatus = apikitFlows.filter((f) => f.setsHttpStatus).length;
|
|
45
|
+
const withoutStatus = apikitFlows.length - withStatus;
|
|
46
|
+
// Only flag if there's a clear majority (>60%) and at least one outlier
|
|
47
|
+
if (withStatus > withoutStatus && withoutStatus > 0 && withStatus / apikitFlows.length > 0.6) {
|
|
48
|
+
// Majority sets httpStatus — flag those that don't
|
|
49
|
+
for (const flow of apikitFlows) {
|
|
50
|
+
if (!flow.setsHttpStatus) {
|
|
51
|
+
issues.push(this.createIssue(flow.node, `APIKit flow "${flow.name}" does not set httpStatus, but ${withStatus}/${apikitFlows.length} other flows do`, {
|
|
52
|
+
suggestion: 'Add a set-variable for httpStatus to maintain consistency across all APIKit implementation flows',
|
|
53
|
+
}));
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return issues;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
exports.ApikitRouteVariableConsistencyRule = ApikitRouteVariableConsistencyRule;
|
|
61
|
+
//# sourceMappingURL=ApikitRouteVariableConsistencyRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ApikitRouteVariableConsistencyRule.js","sourceRoot":"","sources":["../../../../src/rules/standards/ApikitRouteVariableConsistencyRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;;;GAWG;AACH,MAAa,kCAAmC,SAAQ,mBAAQ;IAC9D,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,mCAAmC,CAAC;IAC3C,WAAW,GACT,sFAAsF,CAAC;IACzF,QAAQ,GAAG,MAAe,CAAC;IAC3B,QAAQ,GAAG,WAAoB,CAAC;IAChC,SAAS,GAAc,YAAY,CAAC;IAEpC,8CAA8C;IAC7B,mBAAmB,GAAG,8CAA8C,CAAC;IAEtF,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,EAAE,GAAG,CAAC,CAAC;QAE9C,sCAAsC;QACtC,MAAM,WAAW,GAAiE,EAAE,CAAC;QAErF,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;YACvD,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;gBAC7C,SAAS;YACX,CAAC;YAED,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAChC,kEAAkE,EAClE,IAAI,CACL,CAAC;YAEF,WAAW,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAC;QACnE,CAAC;QAED,uDAAuD;QACvD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,iCAAiC;QACjC,MAAM,UAAU,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC;QACtE,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,GAAG,UAAU,CAAC;QAEtD,wEAAwE;QACxE,IAAI,UAAU,GAAG,aAAa,IAAI,aAAa,GAAG,CAAC,IAAI,UAAU,GAAG,WAAW,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;YAC7F,mDAAmD;YACnD,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;gBAC/B,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC;oBACzB,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,IAAI,CAAC,IAAI,EACT,gBAAgB,IAAI,CAAC,IAAI,kCAAkC,UAAU,IAAI,WAAW,CAAC,MAAM,iBAAiB,EAC5G;wBACE,UAAU,EACR,kGAAkG;qBACrG,CACF,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AAhED,gFAgEC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { ValidationContext, Issue } from '../../types';
|
|
2
|
+
import { BaseRule } from '../base/BaseRule';
|
|
3
|
+
/**
|
|
4
|
+
* CFG-001: Configuration Properties Ordering
|
|
5
|
+
*
|
|
6
|
+
* Mule configuration-properties elements should be loaded in the correct
|
|
7
|
+
* order: global defaults first, then environment-specific overrides, then
|
|
8
|
+
* secure properties. This ensures predictable property resolution (Mule
|
|
9
|
+
* uses last-wins for overlapping keys).
|
|
10
|
+
*
|
|
11
|
+
* Expected ordering pattern:
|
|
12
|
+
* 1. config/global.yaml (or common.yaml, defaults.yaml)
|
|
13
|
+
* 2. config/${mule.env}.yaml (environment-specific)
|
|
14
|
+
* 3. secure-properties:config (encrypted secrets)
|
|
15
|
+
* 4. entity-config/*.yaml (optional, additive)
|
|
16
|
+
*
|
|
17
|
+
* This rule flags when env-specific properties appear before global
|
|
18
|
+
* defaults, which would cause globals to override env-specific values.
|
|
19
|
+
*/
|
|
20
|
+
export declare class ConfigPropertiesOrderingRule extends BaseRule {
|
|
21
|
+
id: string;
|
|
22
|
+
name: string;
|
|
23
|
+
description: string;
|
|
24
|
+
severity: "info";
|
|
25
|
+
category: "standards";
|
|
26
|
+
/** Patterns that identify global/default property files */
|
|
27
|
+
private readonly GLOBAL_PATTERNS;
|
|
28
|
+
/** Patterns that identify env-specific property files */
|
|
29
|
+
private readonly ENV_PATTERNS;
|
|
30
|
+
validate(doc: Document, _context: ValidationContext): Issue[];
|
|
31
|
+
private isGlobalFile;
|
|
32
|
+
private isEnvSpecificFile;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=ConfigPropertiesOrderingRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigPropertiesOrderingRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/standards/ConfigPropertiesOrderingRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAE5C;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,4BAA6B,SAAQ,QAAQ;IACxD,EAAE,SAAa;IACf,IAAI,SAAuC;IAC3C,WAAW,SACwF;IACnG,QAAQ,EAAG,MAAM,CAAU;IAC3B,QAAQ,EAAG,WAAW,CAAU;IAEhC,2DAA2D;IAC3D,OAAO,CAAC,QAAQ,CAAC,eAAe,CAO9B;IAEF,yDAAyD;IACzD,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAoD;IAEjF,QAAQ,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,iBAAiB,GAAG,KAAK,EAAE;IA6C7D,OAAO,CAAC,YAAY;IAIpB,OAAO,CAAC,iBAAiB;CAG1B"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConfigPropertiesOrderingRule = void 0;
|
|
4
|
+
const BaseRule_1 = require("../base/BaseRule");
|
|
5
|
+
/**
|
|
6
|
+
* CFG-001: Configuration Properties Ordering
|
|
7
|
+
*
|
|
8
|
+
* Mule configuration-properties elements should be loaded in the correct
|
|
9
|
+
* order: global defaults first, then environment-specific overrides, then
|
|
10
|
+
* secure properties. This ensures predictable property resolution (Mule
|
|
11
|
+
* uses last-wins for overlapping keys).
|
|
12
|
+
*
|
|
13
|
+
* Expected ordering pattern:
|
|
14
|
+
* 1. config/global.yaml (or common.yaml, defaults.yaml)
|
|
15
|
+
* 2. config/${mule.env}.yaml (environment-specific)
|
|
16
|
+
* 3. secure-properties:config (encrypted secrets)
|
|
17
|
+
* 4. entity-config/*.yaml (optional, additive)
|
|
18
|
+
*
|
|
19
|
+
* This rule flags when env-specific properties appear before global
|
|
20
|
+
* defaults, which would cause globals to override env-specific values.
|
|
21
|
+
*/
|
|
22
|
+
class ConfigPropertiesOrderingRule extends BaseRule_1.BaseRule {
|
|
23
|
+
id = 'CFG-001';
|
|
24
|
+
name = 'Configuration Properties Ordering';
|
|
25
|
+
description = 'Configuration properties should be loaded in correct order: global before environment-specific';
|
|
26
|
+
severity = 'info';
|
|
27
|
+
category = 'standards';
|
|
28
|
+
/** Patterns that identify global/default property files */
|
|
29
|
+
GLOBAL_PATTERNS = [
|
|
30
|
+
'global.yaml',
|
|
31
|
+
'global.properties',
|
|
32
|
+
'common.yaml',
|
|
33
|
+
'common.properties',
|
|
34
|
+
'defaults.yaml',
|
|
35
|
+
'defaults.properties',
|
|
36
|
+
];
|
|
37
|
+
/** Patterns that identify env-specific property files */
|
|
38
|
+
ENV_PATTERNS = ['${mule.env}', '${env}', '${mule.environment}'];
|
|
39
|
+
validate(doc, _context) {
|
|
40
|
+
const issues = [];
|
|
41
|
+
// Find all configuration-properties elements in document order
|
|
42
|
+
const configProps = this.select('//*[local-name()="configuration-properties"]', doc);
|
|
43
|
+
if (configProps.length < 2) {
|
|
44
|
+
return issues; // Not enough elements to have ordering issues
|
|
45
|
+
}
|
|
46
|
+
let globalIndex = -1;
|
|
47
|
+
let envIndex = -1;
|
|
48
|
+
for (let i = 0; i < configProps.length; i++) {
|
|
49
|
+
const file = this.getAttribute(configProps[i], 'file') ?? '';
|
|
50
|
+
const fileLower = file.toLowerCase();
|
|
51
|
+
if (this.isGlobalFile(fileLower)) {
|
|
52
|
+
globalIndex = i;
|
|
53
|
+
}
|
|
54
|
+
if (this.isEnvSpecificFile(file)) {
|
|
55
|
+
if (envIndex === -1) {
|
|
56
|
+
envIndex = i; // Track the first env-specific file
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
// Flag if env-specific appears before global defaults
|
|
61
|
+
if (globalIndex >= 0 && envIndex >= 0 && envIndex < globalIndex) {
|
|
62
|
+
issues.push(this.createIssue(configProps[envIndex], 'Environment-specific properties file is loaded before global defaults', {
|
|
63
|
+
suggestion: 'Load global/common properties first (e.g., config/global.yaml) before environment-specific files (e.g., config/${mule.env}.yaml) to ensure correct override behavior',
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
return issues;
|
|
67
|
+
}
|
|
68
|
+
isGlobalFile(fileLower) {
|
|
69
|
+
return this.GLOBAL_PATTERNS.some((p) => fileLower.includes(p));
|
|
70
|
+
}
|
|
71
|
+
isEnvSpecificFile(file) {
|
|
72
|
+
return this.ENV_PATTERNS.some((p) => file.includes(p));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
exports.ConfigPropertiesOrderingRule = ConfigPropertiesOrderingRule;
|
|
76
|
+
//# sourceMappingURL=ConfigPropertiesOrderingRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ConfigPropertiesOrderingRule.js","sourceRoot":"","sources":["../../../../src/rules/standards/ConfigPropertiesOrderingRule.ts"],"names":[],"mappings":";;;AACA,+CAA4C;AAE5C;;;;;;;;;;;;;;;;GAgBG;AACH,MAAa,4BAA6B,SAAQ,mBAAQ;IACxD,EAAE,GAAG,SAAS,CAAC;IACf,IAAI,GAAG,mCAAmC,CAAC;IAC3C,WAAW,GACT,gGAAgG,CAAC;IACnG,QAAQ,GAAG,MAAe,CAAC;IAC3B,QAAQ,GAAG,WAAoB,CAAC;IAEhC,2DAA2D;IAC1C,eAAe,GAAG;QACjC,aAAa;QACb,mBAAmB;QACnB,aAAa;QACb,mBAAmB;QACnB,eAAe;QACf,qBAAqB;KACtB,CAAC;IAEF,yDAAyD;IACxC,YAAY,GAAG,CAAC,aAAa,EAAE,QAAQ,EAAE,qBAAqB,CAAC,CAAC;IAEjF,QAAQ,CAAC,GAAa,EAAE,QAA2B;QACjD,MAAM,MAAM,GAAY,EAAE,CAAC;QAE3B,+DAA+D;QAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,8CAA8C,EAAE,GAAG,CAAC,CAAC;QAErF,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3B,OAAO,MAAM,CAAC,CAAC,8CAA8C;QAC/D,CAAC;QAED,IAAI,WAAW,GAAG,CAAC,CAAC,CAAC;QACrB,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;QAElB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC5C,MAAM,IAAI,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;YAC7D,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;YAErC,IAAI,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,EAAE,CAAC;gBACjC,WAAW,GAAG,CAAC,CAAC;YAClB,CAAC;YAED,IAAI,IAAI,CAAC,iBAAiB,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjC,IAAI,QAAQ,KAAK,CAAC,CAAC,EAAE,CAAC;oBACpB,QAAQ,GAAG,CAAC,CAAC,CAAC,oCAAoC;gBACpD,CAAC;YACH,CAAC;QACH,CAAC;QAED,sDAAsD;QACtD,IAAI,WAAW,IAAI,CAAC,IAAI,QAAQ,IAAI,CAAC,IAAI,QAAQ,GAAG,WAAW,EAAE,CAAC;YAChE,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,WAAW,CAAC,QAAQ,CAAC,EACrB,uEAAuE,EACvE;gBACE,UAAU,EACR,sKAAsK;aACzK,CACF,CACF,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,YAAY,CAAC,SAAiB;QACpC,OAAO,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACjE,CAAC;IAEO,iBAAiB,CAAC,IAAY;QACpC,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;CACF;AAzED,oEAyEC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { ValidationContext, Issue, IssueType } from '../../types';
|
|
2
|
+
import { ProjectRule } from '../base/ProjectRule';
|
|
3
|
+
/**
|
|
4
|
+
* CFG-002: Missing Environment Properties Declaration
|
|
5
|
+
*
|
|
6
|
+
* Projects using configuration-properties with environment placeholders
|
|
7
|
+
* (e.g., ${mule.env}.yaml) should have at least dev and prod property files.
|
|
8
|
+
* Missing environment files cause deployment failures.
|
|
9
|
+
*
|
|
10
|
+
* Checks that for each pattern like `${mule.env}.yaml`, the project has
|
|
11
|
+
* at minimum: dev.yaml and prod.yaml (or the equivalent with the pattern).
|
|
12
|
+
*/
|
|
13
|
+
export declare class MissingEnvPropertiesDeclarationRule extends ProjectRule {
|
|
14
|
+
id: string;
|
|
15
|
+
name: string;
|
|
16
|
+
description: string;
|
|
17
|
+
severity: "warning";
|
|
18
|
+
category: "standards";
|
|
19
|
+
issueType: IssueType;
|
|
20
|
+
/** Required environments */
|
|
21
|
+
private readonly REQUIRED_ENVS;
|
|
22
|
+
protected validateProject(context: ValidationContext): Issue[];
|
|
23
|
+
private listFiles;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=MissingEnvPropertiesDeclarationRule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MissingEnvPropertiesDeclarationRule.d.ts","sourceRoot":"","sources":["../../../../src/rules/standards/MissingEnvPropertiesDeclarationRule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAIlD;;;;;;;;;GASG;AACH,qBAAa,mCAAoC,SAAQ,WAAW;IAClE,EAAE,SAAa;IACf,IAAI,SAAoC;IACxC,WAAW,SAC+E;IAC1F,QAAQ,EAAG,SAAS,CAAU;IAC9B,QAAQ,EAAG,WAAW,CAAU;IAChC,SAAS,EAAE,SAAS,CAAS;IAE7B,4BAA4B;IAC5B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAmB;IAEjD,SAAS,CAAC,eAAe,CAAC,OAAO,EAAE,iBAAiB,GAAG,KAAK,EAAE;IA6D9D,OAAO,CAAC,SAAS;CAOlB"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MissingEnvPropertiesDeclarationRule = void 0;
|
|
37
|
+
const ProjectRule_1 = require("../base/ProjectRule");
|
|
38
|
+
const fs = __importStar(require("fs"));
|
|
39
|
+
const path = __importStar(require("path"));
|
|
40
|
+
/**
|
|
41
|
+
* CFG-002: Missing Environment Properties Declaration
|
|
42
|
+
*
|
|
43
|
+
* Projects using configuration-properties with environment placeholders
|
|
44
|
+
* (e.g., ${mule.env}.yaml) should have at least dev and prod property files.
|
|
45
|
+
* Missing environment files cause deployment failures.
|
|
46
|
+
*
|
|
47
|
+
* Checks that for each pattern like `${mule.env}.yaml`, the project has
|
|
48
|
+
* at minimum: dev.yaml and prod.yaml (or the equivalent with the pattern).
|
|
49
|
+
*/
|
|
50
|
+
class MissingEnvPropertiesDeclarationRule extends ProjectRule_1.ProjectRule {
|
|
51
|
+
id = 'CFG-002';
|
|
52
|
+
name = 'Missing Environment Properties';
|
|
53
|
+
description = 'Projects with environment-parameterized configs must have dev and prod property files';
|
|
54
|
+
severity = 'warning';
|
|
55
|
+
category = 'standards';
|
|
56
|
+
issueType = 'bug';
|
|
57
|
+
/** Required environments */
|
|
58
|
+
REQUIRED_ENVS = ['dev', 'prod'];
|
|
59
|
+
validateProject(context) {
|
|
60
|
+
const issues = [];
|
|
61
|
+
const resourceDir = path.join(context.projectRoot, 'src', 'main', 'resources');
|
|
62
|
+
if (!fs.existsSync(resourceDir)) {
|
|
63
|
+
return issues; // Not a standard Mule project layout
|
|
64
|
+
}
|
|
65
|
+
// Look for YAML files in the resources directory
|
|
66
|
+
const files = this.listFiles(resourceDir);
|
|
67
|
+
const yamlFiles = files.filter((f) => f.endsWith('.yaml') || f.endsWith('.yml'));
|
|
68
|
+
// Check if any file looks like an env-parameterized name
|
|
69
|
+
// Common patterns: dev.yaml, prod.yaml, local.yaml, sandbox.yaml
|
|
70
|
+
const envFilePattern = /^(dev|prod|local|sandbox|qa|staging|uat|sit)\.(yaml|yml)$/;
|
|
71
|
+
const envFilesFound = yamlFiles
|
|
72
|
+
.map((f) => path.basename(f))
|
|
73
|
+
.filter((f) => envFilePattern.test(f));
|
|
74
|
+
// If there are env files, check that both dev and prod exist
|
|
75
|
+
if (envFilesFound.length > 0) {
|
|
76
|
+
for (const requiredEnv of this.REQUIRED_ENVS) {
|
|
77
|
+
const hasEnv = envFilesFound.some((f) => f.startsWith(`${requiredEnv}.`));
|
|
78
|
+
if (!hasEnv) {
|
|
79
|
+
issues.push(this.createProjectIssue(`Missing ${requiredEnv}.yaml property file — project has environment-specific configs but no ${requiredEnv} environment`, {
|
|
80
|
+
suggestion: `Create src/main/resources/${requiredEnv}.yaml with environment-specific properties`,
|
|
81
|
+
}));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
// Also check for secure property files if secure-*.yaml pattern is used
|
|
86
|
+
const secureFiles = yamlFiles
|
|
87
|
+
.map((f) => path.basename(f))
|
|
88
|
+
.filter((f) => f.startsWith('secure-'));
|
|
89
|
+
if (secureFiles.length > 0) {
|
|
90
|
+
for (const requiredEnv of this.REQUIRED_ENVS) {
|
|
91
|
+
const hasSecureEnv = secureFiles.some((f) => f === `secure-${requiredEnv}.yaml` || f === `secure-${requiredEnv}.yml`);
|
|
92
|
+
if (!hasSecureEnv) {
|
|
93
|
+
issues.push(this.createProjectIssue(`Missing secure-${requiredEnv}.yaml — project uses secure properties but no ${requiredEnv} secure config`, {
|
|
94
|
+
suggestion: `Create src/main/resources/secure-${requiredEnv}.yaml with encrypted secrets for the ${requiredEnv} environment`,
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return issues;
|
|
100
|
+
}
|
|
101
|
+
listFiles(dir) {
|
|
102
|
+
try {
|
|
103
|
+
return fs.readdirSync(dir).map((f) => path.join(dir, f));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return [];
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
exports.MissingEnvPropertiesDeclarationRule = MissingEnvPropertiesDeclarationRule;
|
|
111
|
+
//# sourceMappingURL=MissingEnvPropertiesDeclarationRule.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"MissingEnvPropertiesDeclarationRule.js","sourceRoot":"","sources":["../../../../src/rules/standards/MissingEnvPropertiesDeclarationRule.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,17 +1,21 @@
|
|
|
1
1
|
import { ValidationContext, Issue, IssueType } from '../../types';
|
|
2
2
|
import { BaseRule } from '../base/BaseRule';
|
|
3
|
+
import { ProjectRule } from '../base/ProjectRule';
|
|
3
4
|
/**
|
|
4
5
|
* YAML-001: Environment Properties Files
|
|
5
6
|
*
|
|
6
7
|
* Checks that environment-specific YAML files exist.
|
|
8
|
+
*
|
|
9
|
+
* This is a ProjectRule — it runs once per scan to avoid producing
|
|
10
|
+
* N identical issues (one per XML file).
|
|
7
11
|
*/
|
|
8
|
-
export declare class EnvironmentFilesRule extends
|
|
12
|
+
export declare class EnvironmentFilesRule extends ProjectRule {
|
|
9
13
|
id: string;
|
|
10
14
|
name: string;
|
|
11
15
|
description: string;
|
|
12
16
|
severity: "warning";
|
|
13
17
|
category: "standards";
|
|
14
|
-
|
|
18
|
+
protected validateProject(context: ValidationContext): Issue[];
|
|
15
19
|
}
|
|
16
20
|
/**
|
|
17
21
|
* YAML-003: Property Naming Convention
|