timonel 3.0.0-beta.1 → 3.1.0-beta.1
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/CHANGELOG.md +192 -0
- package/README.md +606 -119
- package/SECURITY.md +25 -11
- package/dist/cli.js +54 -15
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/lib/helm.js +28 -1
- package/dist/lib/helmChartWriter.js +27 -8
- package/dist/lib/policy/configurationLoader.d.ts +46 -0
- package/dist/lib/policy/configurationLoader.js +251 -0
- package/dist/lib/policy/errorContextGenerator.d.ts +63 -0
- package/dist/lib/policy/errorContextGenerator.js +302 -0
- package/dist/lib/policy/errors.d.ts +40 -0
- package/dist/lib/policy/errors.js +109 -0
- package/dist/lib/policy/index.d.ts +11 -0
- package/dist/lib/policy/index.js +10 -0
- package/dist/lib/policy/parallelExecutor.d.ts +58 -0
- package/dist/lib/policy/parallelExecutor.js +215 -0
- package/dist/lib/policy/pluginLoader.d.ts +41 -0
- package/dist/lib/policy/pluginLoader.js +220 -0
- package/dist/lib/policy/pluginRegistry.d.ts +14 -0
- package/dist/lib/policy/pluginRegistry.js +69 -0
- package/dist/lib/policy/policyEngine.d.ts +39 -0
- package/dist/lib/policy/policyEngine.js +495 -0
- package/dist/lib/policy/resultAggregator.d.ts +8 -0
- package/dist/lib/policy/resultAggregator.js +138 -0
- package/dist/lib/policy/resultFormatter.d.ts +25 -0
- package/dist/lib/policy/resultFormatter.js +217 -0
- package/dist/lib/policy/types.d.ts +111 -0
- package/dist/lib/policy/types.js +1 -0
- package/dist/lib/policy/validationCache.d.ts +58 -0
- package/dist/lib/policy/validationCache.js +289 -0
- package/dist/lib/resources/baseResourceProvider.js +5 -0
- package/dist/lib/resources/cloud/aws/awsResources.js +2 -1
- package/dist/lib/resources/cloud/aws/karpenterResources.js +16 -2
- package/dist/lib/rutter.d.ts +7 -2
- package/dist/lib/rutter.js +177 -8
- package/dist/lib/security.js +4 -4
- package/dist/lib/templates/flexible-subchart.js +18 -7
- package/dist/lib/templates/umbrella-chart.js +29 -18
- package/dist/lib/umbrellaRutter.d.ts +1 -1
- package/dist/lib/umbrellaRutter.js +21 -9
- package/dist/lib/utils/envVarsLoader.js +13 -7
- package/dist/lib/utils/helmHelpers.js +10 -2
- package/dist/lib/utils/helmYamlSerializer.js +19 -9
- package/dist/lib/utils/logger.js +54 -39
- package/dist/lib/utils/valuesRef.js +9 -0
- package/dist/lib/validation/inputValidator.d.ts +26 -0
- package/dist/lib/validation/inputValidator.js +176 -0
- package/dist/types/index.d.ts +27 -0
- package/dist/types/index.js +1 -0
- package/package.json +21 -19
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { PolicyViolation, PolicyWarning, ValidationContext } from './types.js';
|
|
2
|
+
export interface ErrorContext {
|
|
3
|
+
readonly timestamp: string;
|
|
4
|
+
readonly environment: {
|
|
5
|
+
readonly nodeVersion: string;
|
|
6
|
+
readonly platform: string;
|
|
7
|
+
readonly arch: string;
|
|
8
|
+
readonly timonelVersion?: string;
|
|
9
|
+
};
|
|
10
|
+
readonly validationContext: {
|
|
11
|
+
readonly chartName?: string;
|
|
12
|
+
readonly chartVersion?: string;
|
|
13
|
+
readonly kubernetesVersion?: string;
|
|
14
|
+
readonly environment?: string;
|
|
15
|
+
};
|
|
16
|
+
readonly plugin: {
|
|
17
|
+
readonly name: string;
|
|
18
|
+
readonly version?: string;
|
|
19
|
+
readonly executionTime?: number;
|
|
20
|
+
};
|
|
21
|
+
readonly error: {
|
|
22
|
+
readonly message: string;
|
|
23
|
+
readonly severity: 'error' | 'warning' | 'info';
|
|
24
|
+
readonly resourcePath?: string;
|
|
25
|
+
readonly field?: string;
|
|
26
|
+
readonly suggestion?: string;
|
|
27
|
+
readonly stackTrace?: string;
|
|
28
|
+
readonly originalContext?: Record<string, unknown>;
|
|
29
|
+
};
|
|
30
|
+
readonly debuggingHints: string[];
|
|
31
|
+
readonly relatedViolations?: Array<{
|
|
32
|
+
readonly plugin: string;
|
|
33
|
+
readonly message: string;
|
|
34
|
+
readonly similarity: number;
|
|
35
|
+
}>;
|
|
36
|
+
}
|
|
37
|
+
export declare class ErrorContextGenerator {
|
|
38
|
+
generateContext(violation: PolicyViolation | PolicyWarning, validationContext?: ValidationContext, allViolations?: (PolicyViolation | PolicyWarning)[], executionTime?: number): ErrorContext;
|
|
39
|
+
generateErrorReport(violation: PolicyViolation | PolicyWarning, validationContext?: ValidationContext, allViolations?: (PolicyViolation | PolicyWarning)[], executionTime?: number): string;
|
|
40
|
+
private addReportHeader;
|
|
41
|
+
private addBasicInformation;
|
|
42
|
+
private addResourceInformation;
|
|
43
|
+
private addSuggestion;
|
|
44
|
+
private addEnvironmentInfo;
|
|
45
|
+
private addValidationContextInfo;
|
|
46
|
+
private addDebuggingHints;
|
|
47
|
+
private addRelatedViolations;
|
|
48
|
+
private addOriginalContext;
|
|
49
|
+
private getEnvironmentInfo;
|
|
50
|
+
private getTimonelVersion;
|
|
51
|
+
private getValidationContextInfo;
|
|
52
|
+
private generateDebuggingHints;
|
|
53
|
+
private addSeverityHints;
|
|
54
|
+
private addResourcePathHints;
|
|
55
|
+
private addFieldHints;
|
|
56
|
+
private addPluginHints;
|
|
57
|
+
private addEnvironmentHints;
|
|
58
|
+
private addKubernetesVersionHints;
|
|
59
|
+
private findRelatedViolations;
|
|
60
|
+
private calculateSimilarity;
|
|
61
|
+
private calculateStringSimilarity;
|
|
62
|
+
private calculateLevenshteinDistance;
|
|
63
|
+
}
|
|
@@ -0,0 +1,302 @@
|
|
|
1
|
+
export class ErrorContextGenerator {
|
|
2
|
+
generateContext(violation, validationContext, allViolations, executionTime) {
|
|
3
|
+
return {
|
|
4
|
+
timestamp: new Date().toISOString(),
|
|
5
|
+
environment: this.getEnvironmentInfo(),
|
|
6
|
+
validationContext: this.getValidationContextInfo(validationContext),
|
|
7
|
+
plugin: {
|
|
8
|
+
name: violation.plugin,
|
|
9
|
+
...(executionTime !== undefined && { executionTime }),
|
|
10
|
+
},
|
|
11
|
+
error: {
|
|
12
|
+
message: violation.message,
|
|
13
|
+
severity: violation.severity,
|
|
14
|
+
...(violation.resourcePath && { resourcePath: violation.resourcePath }),
|
|
15
|
+
...(violation.field && { field: violation.field }),
|
|
16
|
+
...(violation.suggestion && { suggestion: violation.suggestion }),
|
|
17
|
+
...(violation.context && { originalContext: violation.context }),
|
|
18
|
+
},
|
|
19
|
+
debuggingHints: this.generateDebuggingHints(violation, validationContext),
|
|
20
|
+
relatedViolations: this.findRelatedViolations(violation, allViolations),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
generateErrorReport(violation, validationContext, allViolations, executionTime) {
|
|
24
|
+
const context = this.generateContext(violation, validationContext, allViolations, executionTime);
|
|
25
|
+
const lines = [];
|
|
26
|
+
this.addReportHeader(lines, violation);
|
|
27
|
+
this.addBasicInformation(lines, context);
|
|
28
|
+
this.addResourceInformation(lines, context);
|
|
29
|
+
this.addSuggestion(lines, context);
|
|
30
|
+
this.addEnvironmentInfo(lines, context);
|
|
31
|
+
this.addValidationContextInfo(lines, context);
|
|
32
|
+
this.addDebuggingHints(lines, context);
|
|
33
|
+
this.addRelatedViolations(lines, context);
|
|
34
|
+
this.addOriginalContext(lines, context);
|
|
35
|
+
return lines.join('\n');
|
|
36
|
+
}
|
|
37
|
+
addReportHeader(lines, violation) {
|
|
38
|
+
lines.push('='.repeat(80));
|
|
39
|
+
lines.push(`Policy Violation Report - ${violation.severity.toUpperCase()}`);
|
|
40
|
+
lines.push('='.repeat(80));
|
|
41
|
+
lines.push('');
|
|
42
|
+
}
|
|
43
|
+
addBasicInformation(lines, context) {
|
|
44
|
+
lines.push('Basic Information:');
|
|
45
|
+
lines.push(` Plugin: ${context.plugin.name}`);
|
|
46
|
+
lines.push(` Severity: ${context.error.severity}`);
|
|
47
|
+
lines.push(` Message: ${context.error.message}`);
|
|
48
|
+
lines.push(` Timestamp: ${context.timestamp}`);
|
|
49
|
+
if (context.plugin.executionTime !== undefined) {
|
|
50
|
+
lines.push(` Exec Time: ${context.plugin.executionTime}ms`);
|
|
51
|
+
}
|
|
52
|
+
lines.push('');
|
|
53
|
+
}
|
|
54
|
+
addResourceInformation(lines, context) {
|
|
55
|
+
if (context.error.resourcePath || context.error.field) {
|
|
56
|
+
lines.push('Resource Information:');
|
|
57
|
+
if (context.error.resourcePath) {
|
|
58
|
+
lines.push(` Path: ${context.error.resourcePath}`);
|
|
59
|
+
}
|
|
60
|
+
if (context.error.field) {
|
|
61
|
+
lines.push(` Field: ${context.error.field}`);
|
|
62
|
+
}
|
|
63
|
+
lines.push('');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
addSuggestion(lines, context) {
|
|
67
|
+
if (context.error.suggestion) {
|
|
68
|
+
lines.push('Suggested Fix:');
|
|
69
|
+
lines.push(` ${context.error.suggestion}`);
|
|
70
|
+
lines.push('');
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
addEnvironmentInfo(lines, context) {
|
|
74
|
+
lines.push('Environment:');
|
|
75
|
+
lines.push(` Node.js: ${context.environment.nodeVersion}`);
|
|
76
|
+
lines.push(` Platform: ${context.environment.platform} (${context.environment.arch})`);
|
|
77
|
+
if (context.environment.timonelVersion) {
|
|
78
|
+
lines.push(` Timonel: ${context.environment.timonelVersion}`);
|
|
79
|
+
}
|
|
80
|
+
lines.push('');
|
|
81
|
+
}
|
|
82
|
+
addValidationContextInfo(lines, context) {
|
|
83
|
+
const hasValidationContext = context.validationContext.chartName ||
|
|
84
|
+
context.validationContext.kubernetesVersion ||
|
|
85
|
+
context.validationContext.environment;
|
|
86
|
+
if (hasValidationContext) {
|
|
87
|
+
lines.push('Validation Context:');
|
|
88
|
+
if (context.validationContext.chartName) {
|
|
89
|
+
const version = context.validationContext.chartVersion || 'unknown';
|
|
90
|
+
lines.push(` Chart: ${context.validationContext.chartName}@${version}`);
|
|
91
|
+
}
|
|
92
|
+
if (context.validationContext.kubernetesVersion) {
|
|
93
|
+
lines.push(` Kubernetes: ${context.validationContext.kubernetesVersion}`);
|
|
94
|
+
}
|
|
95
|
+
if (context.validationContext.environment) {
|
|
96
|
+
lines.push(` Environment: ${context.validationContext.environment}`);
|
|
97
|
+
}
|
|
98
|
+
lines.push('');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
addDebuggingHints(lines, context) {
|
|
102
|
+
if (context.debuggingHints.length > 0) {
|
|
103
|
+
lines.push('Debugging Hints:');
|
|
104
|
+
context.debuggingHints.forEach((hint) => {
|
|
105
|
+
lines.push(` • ${hint}`);
|
|
106
|
+
});
|
|
107
|
+
lines.push('');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
addRelatedViolations(lines, context) {
|
|
111
|
+
if (context.relatedViolations && context.relatedViolations.length > 0) {
|
|
112
|
+
lines.push('Related Violations:');
|
|
113
|
+
for (const related of context.relatedViolations) {
|
|
114
|
+
lines.push(` • [${related.plugin}] ${related.message} (${Math.round(related.similarity * 100)}% similar)`);
|
|
115
|
+
}
|
|
116
|
+
lines.push('');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
addOriginalContext(lines, context) {
|
|
120
|
+
if (context.error.originalContext && Object.keys(context.error.originalContext).length > 0) {
|
|
121
|
+
lines.push('Additional Context:');
|
|
122
|
+
lines.push(JSON.stringify(context.error.originalContext, null, 2)
|
|
123
|
+
.split('\n')
|
|
124
|
+
.map((line) => ` ${line}`)
|
|
125
|
+
.join('\n'));
|
|
126
|
+
lines.push('');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
getEnvironmentInfo() {
|
|
130
|
+
const timonelVersion = this.getTimonelVersion();
|
|
131
|
+
return {
|
|
132
|
+
nodeVersion: process.version,
|
|
133
|
+
platform: process.platform,
|
|
134
|
+
arch: process.arch,
|
|
135
|
+
...(timonelVersion && { timonelVersion }),
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
getTimonelVersion() {
|
|
139
|
+
return '3.0.0';
|
|
140
|
+
}
|
|
141
|
+
getValidationContextInfo(validationContext) {
|
|
142
|
+
return {
|
|
143
|
+
...(validationContext?.chart?.name && { chartName: validationContext.chart.name }),
|
|
144
|
+
...(validationContext?.chart?.version && { chartVersion: validationContext.chart.version }),
|
|
145
|
+
...(validationContext?.kubernetesVersion && {
|
|
146
|
+
kubernetesVersion: validationContext.kubernetesVersion,
|
|
147
|
+
}),
|
|
148
|
+
...(validationContext?.environment && { environment: validationContext.environment }),
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
generateDebuggingHints(violation, validationContext) {
|
|
152
|
+
const hints = [];
|
|
153
|
+
this.addSeverityHints(hints, violation);
|
|
154
|
+
this.addResourcePathHints(hints, violation);
|
|
155
|
+
this.addFieldHints(hints, violation);
|
|
156
|
+
this.addPluginHints(hints, violation);
|
|
157
|
+
this.addEnvironmentHints(hints, validationContext);
|
|
158
|
+
this.addKubernetesVersionHints(hints, validationContext);
|
|
159
|
+
return hints;
|
|
160
|
+
}
|
|
161
|
+
addSeverityHints(hints, violation) {
|
|
162
|
+
if (violation.severity === 'error') {
|
|
163
|
+
hints.push('This error will prevent chart generation. Fix this violation to proceed.');
|
|
164
|
+
}
|
|
165
|
+
else if (violation.severity === 'warning') {
|
|
166
|
+
hints.push("This warning indicates a potential issue but won't block chart generation.");
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
addResourcePathHints(hints, violation) {
|
|
170
|
+
if (!violation.resourcePath)
|
|
171
|
+
return;
|
|
172
|
+
if (violation.resourcePath.includes('spec.containers')) {
|
|
173
|
+
hints.push('This violation is related to container specifications. Check container configuration.');
|
|
174
|
+
}
|
|
175
|
+
else if (violation.resourcePath.includes('metadata')) {
|
|
176
|
+
hints.push('This violation is related to resource metadata. Verify labels, annotations, and names.');
|
|
177
|
+
}
|
|
178
|
+
else if (violation.resourcePath.includes('spec.template')) {
|
|
179
|
+
hints.push('This violation is in a pod template. Check deployment or statefulset configuration.');
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
addFieldHints(hints, violation) {
|
|
183
|
+
if (!violation.field)
|
|
184
|
+
return;
|
|
185
|
+
if (violation.field.includes('securityContext')) {
|
|
186
|
+
hints.push('Security context violations often relate to privilege escalation or root access.');
|
|
187
|
+
}
|
|
188
|
+
else if (violation.field.includes('resources')) {
|
|
189
|
+
hints.push('Resource violations typically involve CPU/memory limits or requests.');
|
|
190
|
+
}
|
|
191
|
+
else if (violation.field.includes('image')) {
|
|
192
|
+
hints.push('Image violations may relate to image tags, registries, or security policies.');
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
addPluginHints(hints, violation) {
|
|
196
|
+
if (violation.plugin.includes('security')) {
|
|
197
|
+
hints.push('Security violations should be addressed promptly to maintain cluster security.');
|
|
198
|
+
hints.push("Consider reviewing your organization's security policies and best practices.");
|
|
199
|
+
}
|
|
200
|
+
else if (violation.plugin.includes('resource')) {
|
|
201
|
+
hints.push('Resource violations can impact cluster performance and cost.');
|
|
202
|
+
}
|
|
203
|
+
else if (violation.plugin.includes('network')) {
|
|
204
|
+
hints.push('Network violations may affect service connectivity and security.');
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
addEnvironmentHints(hints, validationContext) {
|
|
208
|
+
if (validationContext?.environment === 'production') {
|
|
209
|
+
hints.push('This is a production environment - ensure all violations are resolved before deployment.');
|
|
210
|
+
}
|
|
211
|
+
else if (validationContext?.environment === 'development') {
|
|
212
|
+
hints.push('Development environment detected - some violations may be acceptable for testing.');
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
addKubernetesVersionHints(hints, validationContext) {
|
|
216
|
+
if (validationContext?.kubernetesVersion) {
|
|
217
|
+
const version = validationContext.kubernetesVersion;
|
|
218
|
+
if (version.startsWith('1.2')) {
|
|
219
|
+
hints.push('Kubernetes 1.2x detected - ensure compatibility with newer API versions.');
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
findRelatedViolations(violation, allViolations) {
|
|
224
|
+
if (!allViolations || allViolations.length <= 1) {
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
const related = [];
|
|
228
|
+
for (const other of allViolations) {
|
|
229
|
+
if (other === violation)
|
|
230
|
+
continue;
|
|
231
|
+
const similarity = this.calculateSimilarity(violation, other);
|
|
232
|
+
if (similarity > 0.3) {
|
|
233
|
+
related.push({
|
|
234
|
+
plugin: other.plugin,
|
|
235
|
+
message: other.message,
|
|
236
|
+
similarity,
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return related.sort((a, b) => b.similarity - a.similarity).slice(0, 3);
|
|
241
|
+
}
|
|
242
|
+
calculateSimilarity(violation1, violation2) {
|
|
243
|
+
let score = 0;
|
|
244
|
+
let factors = 0;
|
|
245
|
+
if (violation1.plugin === violation2.plugin) {
|
|
246
|
+
score += 0.4;
|
|
247
|
+
}
|
|
248
|
+
factors += 0.4;
|
|
249
|
+
if (violation1.severity === violation2.severity) {
|
|
250
|
+
score += 0.2;
|
|
251
|
+
}
|
|
252
|
+
factors += 0.2;
|
|
253
|
+
if (violation1.resourcePath && violation2.resourcePath) {
|
|
254
|
+
const pathSimilarity = this.calculateStringSimilarity(violation1.resourcePath, violation2.resourcePath);
|
|
255
|
+
score += pathSimilarity * 0.2;
|
|
256
|
+
}
|
|
257
|
+
factors += 0.2;
|
|
258
|
+
if (violation1.field && violation2.field) {
|
|
259
|
+
const fieldSimilarity = this.calculateStringSimilarity(violation1.field, violation2.field);
|
|
260
|
+
score += fieldSimilarity * 0.1;
|
|
261
|
+
}
|
|
262
|
+
factors += 0.1;
|
|
263
|
+
const messageSimilarity = this.calculateStringSimilarity(violation1.message, violation2.message);
|
|
264
|
+
score += messageSimilarity * 0.1;
|
|
265
|
+
factors += 0.1;
|
|
266
|
+
return factors > 0 ? score / factors : 0;
|
|
267
|
+
}
|
|
268
|
+
calculateStringSimilarity(str1, str2) {
|
|
269
|
+
if (str1 === str2)
|
|
270
|
+
return 1;
|
|
271
|
+
if (str1.length === 0 || str2.length === 0)
|
|
272
|
+
return 0;
|
|
273
|
+
const longer = str1.length > str2.length ? str1 : str2;
|
|
274
|
+
const shorter = str1.length > str2.length ? str2 : str1;
|
|
275
|
+
if (longer.length === 0)
|
|
276
|
+
return 1;
|
|
277
|
+
const editDistance = this.calculateLevenshteinDistance(longer, shorter);
|
|
278
|
+
return (longer.length - editDistance) / longer.length;
|
|
279
|
+
}
|
|
280
|
+
calculateLevenshteinDistance(str1, str2) {
|
|
281
|
+
const matrix = Array(str2.length + 1)
|
|
282
|
+
.fill(null)
|
|
283
|
+
.map(() => Array(str1.length + 1).fill(0));
|
|
284
|
+
for (let i = 0; i <= str2.length; i++) {
|
|
285
|
+
matrix[i][0] = i;
|
|
286
|
+
}
|
|
287
|
+
for (let j = 0; j <= str1.length; j++) {
|
|
288
|
+
matrix[0][j] = j;
|
|
289
|
+
}
|
|
290
|
+
for (let i = 1; i <= str2.length; i++) {
|
|
291
|
+
for (let j = 1; j <= str1.length; j++) {
|
|
292
|
+
if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
|
|
293
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return matrix[str2.length][str1.length];
|
|
301
|
+
}
|
|
302
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export declare class PolicyEngineError extends Error {
|
|
2
|
+
readonly code?: string | undefined;
|
|
3
|
+
readonly context?: Record<string, unknown> | undefined;
|
|
4
|
+
constructor(message: string, code?: string | undefined, context?: Record<string, unknown> | undefined);
|
|
5
|
+
}
|
|
6
|
+
export declare class PluginError extends PolicyEngineError {
|
|
7
|
+
readonly pluginName: string;
|
|
8
|
+
constructor(message: string, pluginName: string, context?: Record<string, unknown>);
|
|
9
|
+
}
|
|
10
|
+
export declare class ValidationTimeoutError extends PolicyEngineError {
|
|
11
|
+
constructor(pluginName: string, timeout: number);
|
|
12
|
+
}
|
|
13
|
+
export declare class PluginRegistrationError extends PolicyEngineError {
|
|
14
|
+
readonly pluginName?: string | undefined;
|
|
15
|
+
constructor(message: string, pluginName?: string | undefined, context?: Record<string, unknown>);
|
|
16
|
+
}
|
|
17
|
+
export declare class PluginConfigurationError extends PolicyEngineError {
|
|
18
|
+
readonly pluginName: string;
|
|
19
|
+
readonly configPath?: string | undefined;
|
|
20
|
+
constructor(message: string, pluginName: string, configPath?: string | undefined, context?: Record<string, unknown>);
|
|
21
|
+
}
|
|
22
|
+
export declare class ValidationOrchestrationError extends PolicyEngineError {
|
|
23
|
+
readonly failedPlugins?: string[] | undefined;
|
|
24
|
+
constructor(message: string, failedPlugins?: string[] | undefined, context?: Record<string, unknown>);
|
|
25
|
+
}
|
|
26
|
+
export declare class PluginRetryExhaustedError extends PolicyEngineError {
|
|
27
|
+
readonly pluginName: string;
|
|
28
|
+
readonly attempts: number;
|
|
29
|
+
readonly lastError: Error;
|
|
30
|
+
constructor(message: string, pluginName: string, attempts: number, lastError: Error, context?: Record<string, unknown>);
|
|
31
|
+
}
|
|
32
|
+
export declare class GracefulDegradationError extends PolicyEngineError {
|
|
33
|
+
readonly degradedPlugins: string[];
|
|
34
|
+
readonly originalErrors: Error[];
|
|
35
|
+
constructor(message: string, degradedPlugins: string[], originalErrors: Error[], context?: Record<string, unknown>);
|
|
36
|
+
}
|
|
37
|
+
export declare class PolicyValidationError extends PolicyEngineError {
|
|
38
|
+
readonly field?: string | undefined;
|
|
39
|
+
constructor(message: string, field?: string | undefined, context?: Record<string, unknown>);
|
|
40
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
export class PolicyEngineError extends Error {
|
|
2
|
+
constructor(message, code, context) {
|
|
3
|
+
super(message);
|
|
4
|
+
this.code = code;
|
|
5
|
+
this.context = context;
|
|
6
|
+
this.name = 'PolicyEngineError';
|
|
7
|
+
if (Error.captureStackTrace) {
|
|
8
|
+
Error.captureStackTrace(this, PolicyEngineError);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class PluginError extends PolicyEngineError {
|
|
13
|
+
constructor(message, pluginName, context) {
|
|
14
|
+
super(message, 'PLUGIN_ERROR', { ...context, pluginName });
|
|
15
|
+
this.pluginName = pluginName;
|
|
16
|
+
this.name = 'PluginError';
|
|
17
|
+
if (Error.captureStackTrace) {
|
|
18
|
+
Error.captureStackTrace(this, PluginError);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class ValidationTimeoutError extends PolicyEngineError {
|
|
23
|
+
constructor(pluginName, timeout) {
|
|
24
|
+
super(`Plugin '${pluginName}' timed out after ${timeout}ms`, 'VALIDATION_TIMEOUT', {
|
|
25
|
+
pluginName,
|
|
26
|
+
timeout,
|
|
27
|
+
});
|
|
28
|
+
this.name = 'ValidationTimeoutError';
|
|
29
|
+
if (Error.captureStackTrace) {
|
|
30
|
+
Error.captureStackTrace(this, ValidationTimeoutError);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export class PluginRegistrationError extends PolicyEngineError {
|
|
35
|
+
constructor(message, pluginName, context) {
|
|
36
|
+
super(message, 'PLUGIN_REGISTRATION_ERROR', { ...context, pluginName });
|
|
37
|
+
this.pluginName = pluginName;
|
|
38
|
+
this.name = 'PluginRegistrationError';
|
|
39
|
+
if (Error.captureStackTrace) {
|
|
40
|
+
Error.captureStackTrace(this, PluginRegistrationError);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export class PluginConfigurationError extends PolicyEngineError {
|
|
45
|
+
constructor(message, pluginName, configPath, context) {
|
|
46
|
+
super(message, 'PLUGIN_CONFIGURATION_ERROR', { ...context, pluginName, configPath });
|
|
47
|
+
this.pluginName = pluginName;
|
|
48
|
+
this.configPath = configPath;
|
|
49
|
+
this.name = 'PluginConfigurationError';
|
|
50
|
+
if (Error.captureStackTrace) {
|
|
51
|
+
Error.captureStackTrace(this, PluginConfigurationError);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
export class ValidationOrchestrationError extends PolicyEngineError {
|
|
56
|
+
constructor(message, failedPlugins, context) {
|
|
57
|
+
super(message, 'VALIDATION_ORCHESTRATION_ERROR', { ...context, failedPlugins });
|
|
58
|
+
this.failedPlugins = failedPlugins;
|
|
59
|
+
this.name = 'ValidationOrchestrationError';
|
|
60
|
+
if (Error.captureStackTrace) {
|
|
61
|
+
Error.captureStackTrace(this, ValidationOrchestrationError);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
export class PluginRetryExhaustedError extends PolicyEngineError {
|
|
66
|
+
constructor(message, pluginName, attempts, lastError, context) {
|
|
67
|
+
super(message, 'PLUGIN_RETRY_EXHAUSTED', {
|
|
68
|
+
...context,
|
|
69
|
+
pluginName,
|
|
70
|
+
attempts,
|
|
71
|
+
lastError: lastError.message,
|
|
72
|
+
});
|
|
73
|
+
this.pluginName = pluginName;
|
|
74
|
+
this.attempts = attempts;
|
|
75
|
+
this.lastError = lastError;
|
|
76
|
+
this.name = 'PluginRetryExhaustedError';
|
|
77
|
+
if (Error.captureStackTrace) {
|
|
78
|
+
Error.captureStackTrace(this, PluginRetryExhaustedError);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
export class GracefulDegradationError extends PolicyEngineError {
|
|
83
|
+
constructor(message, degradedPlugins, originalErrors, context) {
|
|
84
|
+
super(message, 'GRACEFUL_DEGRADATION', {
|
|
85
|
+
...context,
|
|
86
|
+
degradedPlugins,
|
|
87
|
+
errorCount: originalErrors.length,
|
|
88
|
+
});
|
|
89
|
+
this.degradedPlugins = degradedPlugins;
|
|
90
|
+
this.originalErrors = originalErrors;
|
|
91
|
+
this.name = 'GracefulDegradationError';
|
|
92
|
+
if (Error.captureStackTrace) {
|
|
93
|
+
Error.captureStackTrace(this, GracefulDegradationError);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
export class PolicyValidationError extends PolicyEngineError {
|
|
98
|
+
constructor(message, field, context) {
|
|
99
|
+
super(message, 'POLICY_VALIDATION_ERROR', {
|
|
100
|
+
...context,
|
|
101
|
+
field,
|
|
102
|
+
});
|
|
103
|
+
this.field = field;
|
|
104
|
+
this.name = 'PolicyValidationError';
|
|
105
|
+
if (Error.captureStackTrace) {
|
|
106
|
+
Error.captureStackTrace(this, PolicyValidationError);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export { PolicyEngine } from './policyEngine.js';
|
|
2
|
+
export { PluginRegistry } from './pluginRegistry.js';
|
|
3
|
+
export { ConfigurationLoader } from './configurationLoader.js';
|
|
4
|
+
export { PluginLoader } from './pluginLoader.js';
|
|
5
|
+
export { ValidationCache, generateManifestHash, generatePluginHash, type CacheEntry, type CacheOptions, type CacheStats, } from './validationCache.js';
|
|
6
|
+
export { ParallelExecutor, calculateOptimalConcurrency, type ParallelExecutionOptions, type PluginExecutionResult, type ParallelExecutionStats, } from './parallelExecutor.js';
|
|
7
|
+
export { aggregateResults, generateResultSummary, filterViolationsBySeverity, groupViolationsByPlugin, sortViolationsBySeverity, createEmptyResult, mergeViolationContexts, } from './resultAggregator.js';
|
|
8
|
+
export { DefaultResultFormatter, JsonResultFormatter, CompactResultFormatter, GitHubActionsResultFormatter, SarifResultFormatter, createFormatter, getAvailableFormatters, } from './resultFormatter.js';
|
|
9
|
+
export { ErrorContextGenerator, type ErrorContext } from './errorContextGenerator.js';
|
|
10
|
+
export type { PolicyEngine as IPolicyEngine, PolicyPlugin, PolicyEngineOptions, PolicyResult, PolicyViolation, PolicyWarning, ValidationContext, ValidationMetadata, JSONSchema, PluginMetadata, ResultFormatter, ResultSummary, RetryConfig, ConfigurationLoaderOptions, } from './types.js';
|
|
11
|
+
export { PolicyEngineError, PluginError, ValidationTimeoutError, PluginRegistrationError, PluginConfigurationError, ValidationOrchestrationError, PluginRetryExhaustedError, GracefulDegradationError, } from './errors.js';
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { PolicyEngine } from './policyEngine.js';
|
|
2
|
+
export { PluginRegistry } from './pluginRegistry.js';
|
|
3
|
+
export { ConfigurationLoader } from './configurationLoader.js';
|
|
4
|
+
export { PluginLoader } from './pluginLoader.js';
|
|
5
|
+
export { ValidationCache, generateManifestHash, generatePluginHash, } from './validationCache.js';
|
|
6
|
+
export { ParallelExecutor, calculateOptimalConcurrency, } from './parallelExecutor.js';
|
|
7
|
+
export { aggregateResults, generateResultSummary, filterViolationsBySeverity, groupViolationsByPlugin, sortViolationsBySeverity, createEmptyResult, mergeViolationContexts, } from './resultAggregator.js';
|
|
8
|
+
export { DefaultResultFormatter, JsonResultFormatter, CompactResultFormatter, GitHubActionsResultFormatter, SarifResultFormatter, createFormatter, getAvailableFormatters, } from './resultFormatter.js';
|
|
9
|
+
export { ErrorContextGenerator } from './errorContextGenerator.js';
|
|
10
|
+
export { PolicyEngineError, PluginError, ValidationTimeoutError, PluginRegistrationError, PluginConfigurationError, ValidationOrchestrationError, PluginRetryExhaustedError, GracefulDegradationError, } from './errors.js';
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { PolicyPlugin, PolicyViolation, ValidationContext } from './types.js';
|
|
2
|
+
export interface ParallelExecutionOptions {
|
|
3
|
+
maxConcurrency?: number;
|
|
4
|
+
useWorkerThreads?: boolean;
|
|
5
|
+
pluginTimeout?: number;
|
|
6
|
+
failFast?: boolean;
|
|
7
|
+
resourceLimits?: {
|
|
8
|
+
maxMemoryMB?: number;
|
|
9
|
+
maxCpuTimeMs?: number;
|
|
10
|
+
};
|
|
11
|
+
priorityConfig?: {
|
|
12
|
+
highPriority?: string[];
|
|
13
|
+
lowPriority?: string[];
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export interface PluginExecutionResult {
|
|
17
|
+
plugin: PolicyPlugin;
|
|
18
|
+
violations: PolicyViolation[];
|
|
19
|
+
executionTime: number;
|
|
20
|
+
error?: Error;
|
|
21
|
+
resourceUsage?: {
|
|
22
|
+
memoryUsageMB: number;
|
|
23
|
+
cpuTimeMs: number;
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export interface ParallelExecutionStats {
|
|
27
|
+
totalExecutionTime: number;
|
|
28
|
+
averagePluginTime: number;
|
|
29
|
+
maxPluginTime: number;
|
|
30
|
+
parallelPluginCount: number;
|
|
31
|
+
concurrencyUtilization: number;
|
|
32
|
+
resourceUsage: {
|
|
33
|
+
totalMemoryMB: number;
|
|
34
|
+
totalCpuTimeMs: number;
|
|
35
|
+
peakConcurrentPlugins: number;
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
export declare class ParallelExecutor {
|
|
39
|
+
private readonly options;
|
|
40
|
+
private readonly logger;
|
|
41
|
+
private activeExecutions;
|
|
42
|
+
private executionQueue;
|
|
43
|
+
constructor(options?: ParallelExecutionOptions);
|
|
44
|
+
executePlugins(plugins: PolicyPlugin[], manifests: unknown[], validationContext: ValidationContext): Promise<{
|
|
45
|
+
results: PluginExecutionResult[];
|
|
46
|
+
stats: ParallelExecutionStats;
|
|
47
|
+
}>;
|
|
48
|
+
private executePlugin;
|
|
49
|
+
private executeWithTimeout;
|
|
50
|
+
private executeConcurrently;
|
|
51
|
+
private sortPluginsByPriority;
|
|
52
|
+
private calculateStats;
|
|
53
|
+
}
|
|
54
|
+
export declare function calculateOptimalConcurrency(pluginCount: number, systemInfo?: {
|
|
55
|
+
cpuCount?: number;
|
|
56
|
+
availableMemoryMB?: number;
|
|
57
|
+
isContainerized?: boolean;
|
|
58
|
+
}): number;
|