timonel 3.1.1 → 3.1.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 (83) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/README.md +323 -695
  3. package/dist/cli.js +275 -15
  4. package/dist/index.d.ts +5 -1
  5. package/dist/index.js +12 -0
  6. package/dist/lib/helm.d.ts +471 -0
  7. package/dist/lib/helm.js +483 -0
  8. package/dist/lib/helmChartWriter.d.ts +157 -0
  9. package/dist/lib/helmChartWriter.js +171 -1
  10. package/dist/lib/policy/configurationLoader.d.ts +132 -0
  11. package/dist/lib/policy/configurationLoader.js +132 -0
  12. package/dist/lib/policy/errorContextGenerator.d.ts +89 -0
  13. package/dist/lib/policy/errorContextGenerator.js +99 -2
  14. package/dist/lib/policy/errors.d.ts +35 -0
  15. package/dist/lib/policy/errors.js +36 -0
  16. package/dist/lib/policy/index.d.ts +9 -0
  17. package/dist/lib/policy/index.js +16 -0
  18. package/dist/lib/policy/parallelExecutor.d.ts +90 -0
  19. package/dist/lib/policy/parallelExecutor.js +86 -3
  20. package/dist/lib/policy/pluginLoader.d.ts +92 -0
  21. package/dist/lib/policy/pluginLoader.js +92 -1
  22. package/dist/lib/policy/pluginRegistry.d.ts +54 -0
  23. package/dist/lib/policy/pluginRegistry.js +56 -0
  24. package/dist/lib/policy/policyEngine.d.ts +137 -0
  25. package/dist/lib/policy/policyEngine.js +191 -5
  26. package/dist/lib/policy/resultAggregator.d.ts +46 -0
  27. package/dist/lib/policy/resultAggregator.js +69 -1
  28. package/dist/lib/policy/resultFormatter.d.ts +88 -0
  29. package/dist/lib/policy/resultFormatter.js +101 -0
  30. package/dist/lib/policy/types.d.ts +136 -0
  31. package/dist/lib/policy/types.js +8 -0
  32. package/dist/lib/policy/validationCache.d.ts +146 -0
  33. package/dist/lib/policy/validationCache.js +142 -6
  34. package/dist/lib/resources/baseResourceProvider.d.ts +45 -0
  35. package/dist/lib/resources/baseResourceProvider.js +48 -1
  36. package/dist/lib/resources/cloud/aws/awsResources.d.ts +192 -0
  37. package/dist/lib/resources/cloud/aws/awsResources.js +163 -1
  38. package/dist/lib/resources/cloud/aws/karpenterResources.d.ts +131 -0
  39. package/dist/lib/resources/cloud/aws/karpenterResources.js +77 -0
  40. package/dist/lib/rutter.d.ts +381 -3
  41. package/dist/lib/rutter.js +439 -28
  42. package/dist/lib/security.d.ts +123 -0
  43. package/dist/lib/security.js +162 -4
  44. package/dist/lib/templates/flexible-subchart.d.ts +52 -0
  45. package/dist/lib/templates/flexible-subchart.js +70 -0
  46. package/dist/lib/templates/umbrella-chart.d.ts +27 -0
  47. package/dist/lib/templates/umbrella-chart.js +89 -0
  48. package/dist/lib/types.d.ts +26 -0
  49. package/dist/lib/umbrella.d.ts +23 -0
  50. package/dist/lib/umbrella.js +23 -0
  51. package/dist/lib/umbrellaRutter.d.ts +75 -0
  52. package/dist/lib/umbrellaRutter.js +82 -2
  53. package/dist/lib/utils/envVarsLoader.d.ts +49 -0
  54. package/dist/lib/utils/envVarsLoader.js +53 -0
  55. package/dist/lib/utils/helmConstructSerializer.d.ts +17 -0
  56. package/dist/lib/utils/helmConstructSerializer.js +22 -0
  57. package/dist/lib/utils/helmControlStructures.d.ts +194 -0
  58. package/dist/lib/utils/helmControlStructures.js +180 -0
  59. package/dist/lib/utils/helmHelpers/envHelpers.d.ts +13 -0
  60. package/dist/lib/utils/helmHelpers/envHelpers.js +13 -0
  61. package/dist/lib/utils/helmHelpers/gitopsHelpers.d.ts +13 -0
  62. package/dist/lib/utils/helmHelpers/gitopsHelpers.js +13 -0
  63. package/dist/lib/utils/helmHelpers/index.d.ts +74 -0
  64. package/dist/lib/utils/helmHelpers/index.js +85 -1
  65. package/dist/lib/utils/helmHelpers/observabilityHelpers.d.ts +13 -0
  66. package/dist/lib/utils/helmHelpers/observabilityHelpers.js +13 -0
  67. package/dist/lib/utils/helmHelpers/types.d.ts +23 -0
  68. package/dist/lib/utils/helmHelpers/types.js +4 -0
  69. package/dist/lib/utils/helmHelpers/validationHelpers.d.ts +13 -0
  70. package/dist/lib/utils/helmHelpers/validationHelpers.js +13 -0
  71. package/dist/lib/utils/helmHelpers.d.ts +62 -0
  72. package/dist/lib/utils/helmHelpers.js +77 -0
  73. package/dist/lib/utils/helmYamlSerializer.d.ts +77 -0
  74. package/dist/lib/utils/helmYamlSerializer.js +398 -21
  75. package/dist/lib/utils/logger.d.ts +153 -0
  76. package/dist/lib/utils/logger.js +170 -2
  77. package/dist/lib/utils/valuesRef.d.ts +181 -50
  78. package/dist/lib/utils/valuesRef.js +168 -170
  79. package/dist/lib/validation/inputValidator.d.ts +45 -0
  80. package/dist/lib/validation/inputValidator.js +67 -2
  81. package/dist/types/index.d.ts +34 -0
  82. package/dist/types/index.js +3 -0
  83. package/package.json +31 -38
@@ -1,5 +1,17 @@
1
+ /**
2
+ * Configuration Loader
3
+ *
4
+ * This module provides configuration loading and validation for policy plugins.
5
+ * It supports environment-specific configuration, schema validation, and
6
+ * configuration inheritance.
7
+ *
8
+ * @since 3.0.0
9
+ */
1
10
  import { createLogger } from '../utils/logger.js';
2
11
  import { PluginConfigurationError } from './errors.js';
12
+ /**
13
+ * Default configuration loader options
14
+ */
3
15
  const DEFAULT_LOADER_OPTIONS = {
4
16
  defaultEnvironment: 'development',
5
17
  validateSchemas: true,
@@ -7,12 +19,18 @@ const DEFAULT_LOADER_OPTIONS = {
7
19
  configurationFiles: [],
8
20
  environmentPrefix: 'TIMONEL_POLICY',
9
21
  };
22
+ /**
23
+ * Configuration priority levels
24
+ */
10
25
  const CONFIGURATION_PRIORITIES = {
11
26
  default: 0,
12
27
  file: 10,
13
28
  environment: 20,
14
29
  inline: 30,
15
30
  };
31
+ /**
32
+ * Configuration loader for policy plugins
33
+ */
16
34
  export class ConfigurationLoader {
17
35
  constructor(options = {}) {
18
36
  this.configurations = new Map();
@@ -24,6 +42,13 @@ export class ConfigurationLoader {
24
42
  operation: 'config_loader_init',
25
43
  });
26
44
  }
45
+ /**
46
+ * Loads configuration for a plugin
47
+ * @param plugin - Plugin to load configuration for
48
+ * @param environment - Target environment
49
+ * @param inlineConfig - Inline configuration to merge
50
+ * @returns Plugin configuration
51
+ */
27
52
  async loadPluginConfiguration(plugin, environment, inlineConfig) {
28
53
  const targetEnvironment = environment || this.options.defaultEnvironment;
29
54
  this.logger.debug('Loading plugin configuration', {
@@ -32,8 +57,11 @@ export class ConfigurationLoader {
32
57
  hasInlineConfig: inlineConfig !== undefined,
33
58
  operation: 'load_plugin_config',
34
59
  });
60
+ // Collect configuration entries from all sources
35
61
  const entries = await this.collectConfigurationEntries(plugin, targetEnvironment, inlineConfig);
62
+ // Merge configurations by priority
36
63
  const mergedConfig = this.mergeConfigurations(entries);
64
+ // Validate configuration if schema is provided
37
65
  const validationResult = this.validatePluginConfiguration(plugin, mergedConfig);
38
66
  const result = {
39
67
  pluginName: plugin.name,
@@ -54,8 +82,13 @@ export class ConfigurationLoader {
54
82
  });
55
83
  return result;
56
84
  }
85
+ /**
86
+ * Collects configuration entries from all sources
87
+ * @private
88
+ */
57
89
  async collectConfigurationEntries(plugin, targetEnvironment, inlineConfig) {
58
90
  const entries = [];
91
+ // 1. Default configuration (if plugin provides it)
59
92
  if (plugin.metadata?.defaultConfig) {
60
93
  entries.push({
61
94
  value: plugin.metadata.defaultConfig,
@@ -64,6 +97,7 @@ export class ConfigurationLoader {
64
97
  ...(plugin.configSchema && { schema: plugin.configSchema }),
65
98
  });
66
99
  }
100
+ // 2. File-based configuration
67
101
  const fileConfig = await this.loadFileConfiguration(plugin.name, targetEnvironment);
68
102
  if (fileConfig) {
69
103
  entries.push({
@@ -74,6 +108,7 @@ export class ConfigurationLoader {
74
108
  ...(plugin.configSchema && { schema: plugin.configSchema }),
75
109
  });
76
110
  }
111
+ // 3. Environment variable configuration
77
112
  const envConfig = this.loadEnvironmentVariableConfiguration(plugin.name);
78
113
  if (envConfig) {
79
114
  entries.push({
@@ -83,6 +118,7 @@ export class ConfigurationLoader {
83
118
  ...(plugin.configSchema && { schema: plugin.configSchema }),
84
119
  });
85
120
  }
121
+ // 4. Inline configuration (highest priority)
86
122
  if (inlineConfig) {
87
123
  entries.push({
88
124
  value: inlineConfig,
@@ -93,6 +129,10 @@ export class ConfigurationLoader {
93
129
  }
94
130
  return entries;
95
131
  }
132
+ /**
133
+ * Validates plugin configuration
134
+ * @private
135
+ */
96
136
  validatePluginConfiguration(plugin, mergedConfig) {
97
137
  let validated = false;
98
138
  let validationErrors;
@@ -112,6 +152,11 @@ export class ConfigurationLoader {
112
152
  }
113
153
  return { validated, ...(validationErrors && { validationErrors }) };
114
154
  }
155
+ /**
156
+ * Loads environment-specific configuration
157
+ * @param environment - Environment name
158
+ * @returns Environment configuration
159
+ */
115
160
  async loadEnvironmentConfiguration(environment) {
116
161
  if (this.environmentConfigs.has(environment)) {
117
162
  return this.environmentConfigs.get(environment);
@@ -120,6 +165,7 @@ export class ConfigurationLoader {
120
165
  environment,
121
166
  operation: 'load_env_config',
122
167
  });
168
+ // Load from configuration files
123
169
  const envConfig = await this.loadEnvironmentFromFiles(environment);
124
170
  if (envConfig) {
125
171
  this.environmentConfigs.set(environment, envConfig);
@@ -132,6 +178,13 @@ export class ConfigurationLoader {
132
178
  }
133
179
  return envConfig;
134
180
  }
181
+ /**
182
+ * Validates configuration against a JSON schema
183
+ * @param config - Configuration to validate
184
+ * @param schema - JSON schema to validate against
185
+ * @param pluginName - Plugin name for error reporting
186
+ * @throws {PluginConfigurationError} When validation fails
187
+ */
135
188
  validateConfiguration(config, schema, pluginName) {
136
189
  try {
137
190
  this.validateAgainstSchema(config, schema, []);
@@ -140,12 +193,18 @@ export class ConfigurationLoader {
140
193
  throw new PluginConfigurationError(`Configuration validation failed for plugin '${pluginName}': ${error instanceof Error ? error.message : String(error)}`, pluginName, undefined, { config, schema, validationError: error });
141
194
  }
142
195
  }
196
+ /**
197
+ * Adds a configuration entry for a plugin
198
+ * @param pluginName - Plugin name
199
+ * @param entry - Configuration entry to add
200
+ */
143
201
  addConfigurationEntry(pluginName, entry) {
144
202
  if (!this.configurations.has(pluginName)) {
145
203
  this.configurations.set(pluginName, []);
146
204
  }
147
205
  const entries = this.configurations.get(pluginName);
148
206
  entries.push(entry);
207
+ // Sort by priority (highest first)
149
208
  entries.sort((a, b) => b.priority - a.priority);
150
209
  this.logger.debug('Configuration entry added', {
151
210
  pluginName,
@@ -154,9 +213,17 @@ export class ConfigurationLoader {
154
213
  operation: 'config_entry_added',
155
214
  });
156
215
  }
216
+ /**
217
+ * Gets all configuration entries for a plugin
218
+ * @param pluginName - Plugin name
219
+ * @returns Array of configuration entries
220
+ */
157
221
  getConfigurationEntries(pluginName) {
158
222
  return this.configurations.get(pluginName) || [];
159
223
  }
224
+ /**
225
+ * Clears all cached configurations
226
+ */
160
227
  clearCache() {
161
228
  this.configurations.clear();
162
229
  this.environmentConfigs.clear();
@@ -164,9 +231,24 @@ export class ConfigurationLoader {
164
231
  operation: 'config_cache_cleared',
165
232
  });
166
233
  }
234
+ /**
235
+ * Loads file-based configuration for a plugin
236
+ * @param _pluginName - Plugin name (unused)
237
+ * @param _environment - Target environment (unused)
238
+ * @returns Configuration object or undefined
239
+ * @private
240
+ */
167
241
  async loadFileConfiguration(_pluginName, _environment) {
242
+ // For now, return undefined as file loading is not implemented
243
+ // This would typically load from JSON/YAML files
168
244
  return undefined;
169
245
  }
246
+ /**
247
+ * Loads environment variable configuration for a plugin
248
+ * @param pluginName - Plugin name
249
+ * @returns Configuration object or undefined
250
+ * @private
251
+ */
170
252
  loadEnvironmentVariableConfiguration(pluginName) {
171
253
  if (!pluginName) {
172
254
  return undefined;
@@ -174,19 +256,36 @@ export class ConfigurationLoader {
174
256
  const prefix = `${this.options.environmentPrefix}_${pluginName.toUpperCase().replace(/[^A-Z0-9]/g, '_')}`;
175
257
  const config = Object.create(null);
176
258
  let hasConfig = false;
259
+ // Scan environment variables with the plugin prefix
177
260
  for (const [key, value] of Object.entries(process.env)) {
178
261
  if (key.startsWith(prefix + '_')) {
179
262
  const configKey = key.substring(prefix.length + 1).toLowerCase();
263
+ // eslint-disable-next-line security/detect-object-injection
180
264
  config[configKey] = this.parseEnvironmentValue(value);
181
265
  hasConfig = true;
182
266
  }
183
267
  }
184
268
  return hasConfig ? config : undefined;
185
269
  }
270
+ /**
271
+ * Loads environment configuration from files
272
+ * @param _environment - Environment name (unused)
273
+ * @returns Environment configuration or undefined
274
+ * @private
275
+ */
186
276
  async loadEnvironmentFromFiles(_environment) {
277
+ // For now, return undefined as file loading is not implemented
278
+ // This would typically load from configuration files
187
279
  return undefined;
188
280
  }
281
+ /**
282
+ * Merges configuration entries by priority
283
+ * @param entries - Configuration entries to merge
284
+ * @returns Merged configuration
285
+ * @private
286
+ */
189
287
  mergeConfigurations(entries) {
288
+ // Sort by priority (lowest first for proper merging)
190
289
  const sortedEntries = [...entries].sort((a, b) => a.priority - b.priority);
191
290
  let merged = {};
192
291
  for (const entry of sortedEntries) {
@@ -196,20 +295,40 @@ export class ConfigurationLoader {
196
295
  }
197
296
  return merged;
198
297
  }
298
+ /**
299
+ * Parses environment variable value to appropriate type
300
+ * @param value - Environment variable value
301
+ * @returns Parsed value
302
+ * @private
303
+ */
199
304
  parseEnvironmentValue(value) {
200
305
  if (!value)
201
306
  return undefined;
307
+ // Try to parse as JSON first
202
308
  try {
203
309
  return JSON.parse(value);
204
310
  }
205
311
  catch {
312
+ // Return as string if not valid JSON
206
313
  return value;
207
314
  }
208
315
  }
316
+ /**
317
+ * Validates a configuration object against a JSON schema
318
+ * @param config - Configuration to validate
319
+ * @param schema - JSON schema
320
+ * @param path - Current path for error reporting
321
+ * @throws {Error} When validation fails
322
+ * @private
323
+ */
209
324
  validateAgainstSchema(config, schema, path) {
210
325
  this.validateBasicType(config, schema, path);
211
326
  this.validateObjectProperties(config, schema, path);
212
327
  }
328
+ /**
329
+ * Validates basic type constraints
330
+ * @private
331
+ */
213
332
  validateBasicType(config, schema, path) {
214
333
  if (schema.type) {
215
334
  const actualType = Array.isArray(config) ? 'array' : typeof config;
@@ -218,6 +337,10 @@ export class ConfigurationLoader {
218
337
  }
219
338
  }
220
339
  }
340
+ /**
341
+ * Validates object properties
342
+ * @private
343
+ */
221
344
  validateObjectProperties(config, schema, path) {
222
345
  if (schema.type === 'object' &&
223
346
  schema.properties &&
@@ -228,6 +351,10 @@ export class ConfigurationLoader {
228
351
  this.validateEachProperty(configObj, schema, path);
229
352
  }
230
353
  }
354
+ /**
355
+ * Validates required properties
356
+ * @private
357
+ */
231
358
  validateRequiredProperties(configObj, schema, path) {
232
359
  if (schema.required) {
233
360
  for (const requiredProp of schema.required) {
@@ -237,8 +364,13 @@ export class ConfigurationLoader {
237
364
  }
238
365
  }
239
366
  }
367
+ /**
368
+ * Validates each property in the object
369
+ * @private
370
+ */
240
371
  validateEachProperty(configObj, schema, path) {
241
372
  for (const [propName, propValue] of Object.entries(configObj)) {
373
+ // eslint-disable-next-line security/detect-object-injection
242
374
  const propSchema = schema.properties?.[propName];
243
375
  if (propSchema) {
244
376
  this.validateAgainstSchema(propValue, propSchema, [...path, propName]);
@@ -1,23 +1,40 @@
1
+ /**
2
+ * Error Context Generator
3
+ *
4
+ * This module provides utilities for generating detailed error context
5
+ * for policy violations, including stack traces, environment information,
6
+ * and debugging hints.
7
+ *
8
+ * @since 3.0.0
9
+ */
1
10
  import type { PolicyViolation, PolicyWarning, ValidationContext } from './types.js';
11
+ /**
12
+ * Enhanced error context information
13
+ */
2
14
  export interface ErrorContext {
15
+ /** Error timestamp */
3
16
  readonly timestamp: string;
17
+ /** Environment information */
4
18
  readonly environment: {
5
19
  readonly nodeVersion: string;
6
20
  readonly platform: string;
7
21
  readonly arch: string;
8
22
  readonly timonelVersion?: string;
9
23
  };
24
+ /** Validation context */
10
25
  readonly validationContext: {
11
26
  readonly chartName?: string;
12
27
  readonly chartVersion?: string;
13
28
  readonly kubernetesVersion?: string;
14
29
  readonly environment?: string;
15
30
  };
31
+ /** Plugin information */
16
32
  readonly plugin: {
17
33
  readonly name: string;
18
34
  readonly version?: string;
19
35
  readonly executionTime?: number;
20
36
  };
37
+ /** Error details */
21
38
  readonly error: {
22
39
  readonly message: string;
23
40
  readonly severity: 'error' | 'warning' | 'info';
@@ -27,15 +44,36 @@ export interface ErrorContext {
27
44
  readonly stackTrace?: string;
28
45
  readonly originalContext?: Record<string, unknown>;
29
46
  };
47
+ /** Debugging hints */
30
48
  readonly debuggingHints: string[];
49
+ /** Related violations */
31
50
  readonly relatedViolations?: Array<{
32
51
  readonly plugin: string;
33
52
  readonly message: string;
34
53
  readonly similarity: number;
35
54
  }>;
36
55
  }
56
+ /**
57
+ * Error context generator for policy violations
58
+ */
37
59
  export declare class ErrorContextGenerator {
60
+ /**
61
+ * Generates detailed error context for a policy violation
62
+ * @param violation - Policy violation to generate context for
63
+ * @param validationContext - Validation context
64
+ * @param allViolations - All violations for finding related issues
65
+ * @param executionTime - Plugin execution time
66
+ * @returns Enhanced error context
67
+ */
38
68
  generateContext(violation: PolicyViolation | PolicyWarning, validationContext?: ValidationContext, allViolations?: (PolicyViolation | PolicyWarning)[], executionTime?: number): ErrorContext;
69
+ /**
70
+ * Generates a formatted error report
71
+ * @param violation - Policy violation
72
+ * @param validationContext - Validation context
73
+ * @param allViolations - All violations
74
+ * @param executionTime - Plugin execution time
75
+ * @returns Formatted error report string
76
+ */
39
77
  generateErrorReport(violation: PolicyViolation | PolicyWarning, validationContext?: ValidationContext, allViolations?: (PolicyViolation | PolicyWarning)[], executionTime?: number): string;
40
78
  private addReportHeader;
41
79
  private addBasicInformation;
@@ -46,9 +84,32 @@ export declare class ErrorContextGenerator {
46
84
  private addDebuggingHints;
47
85
  private addRelatedViolations;
48
86
  private addOriginalContext;
87
+ /**
88
+ * Gets environment information
89
+ * @returns Environment information object
90
+ * @private
91
+ */
49
92
  private getEnvironmentInfo;
93
+ /**
94
+ * Gets Timonel version from package.json
95
+ * @returns Timonel version or undefined
96
+ * @private
97
+ */
50
98
  private getTimonelVersion;
99
+ /**
100
+ * Extracts validation context information
101
+ * @param validationContext - Validation context
102
+ * @returns Validation context information
103
+ * @private
104
+ */
51
105
  private getValidationContextInfo;
106
+ /**
107
+ * Generates debugging hints based on the violation
108
+ * @param violation - Policy violation
109
+ * @param validationContext - Validation context
110
+ * @returns Array of debugging hints
111
+ * @private
112
+ */
52
113
  private generateDebuggingHints;
53
114
  private addSeverityHints;
54
115
  private addResourcePathHints;
@@ -56,8 +117,36 @@ export declare class ErrorContextGenerator {
56
117
  private addPluginHints;
57
118
  private addEnvironmentHints;
58
119
  private addKubernetesVersionHints;
120
+ /**
121
+ * Finds violations related to the current one
122
+ * @param violation - Current violation
123
+ * @param allViolations - All violations to search through
124
+ * @returns Array of related violations with similarity scores
125
+ * @private
126
+ */
59
127
  private findRelatedViolations;
128
+ /**
129
+ * Calculates similarity between two violations
130
+ * @param violation1 - First violation
131
+ * @param violation2 - Second violation
132
+ * @returns Similarity score between 0 and 1
133
+ * @private
134
+ */
60
135
  private calculateSimilarity;
136
+ /**
137
+ * Calculates string similarity using a simple algorithm
138
+ * @param str1 - First string
139
+ * @param str2 - Second string
140
+ * @returns Similarity score between 0 and 1
141
+ * @private
142
+ */
61
143
  private calculateStringSimilarity;
144
+ /**
145
+ * Calculates Levenshtein distance between two strings
146
+ * @param str1 - First string
147
+ * @param str2 - Second string
148
+ * @returns Edit distance
149
+ * @private
150
+ */
62
151
  private calculateLevenshteinDistance;
63
152
  }
@@ -1,4 +1,24 @@
1
+ /**
2
+ * Error Context Generator
3
+ *
4
+ * This module provides utilities for generating detailed error context
5
+ * for policy violations, including stack traces, environment information,
6
+ * and debugging hints.
7
+ *
8
+ * @since 3.0.0
9
+ */
10
+ /**
11
+ * Error context generator for policy violations
12
+ */
1
13
  export class ErrorContextGenerator {
14
+ /**
15
+ * Generates detailed error context for a policy violation
16
+ * @param violation - Policy violation to generate context for
17
+ * @param validationContext - Validation context
18
+ * @param allViolations - All violations for finding related issues
19
+ * @param executionTime - Plugin execution time
20
+ * @returns Enhanced error context
21
+ */
2
22
  generateContext(violation, validationContext, allViolations, executionTime) {
3
23
  return {
4
24
  timestamp: new Date().toISOString(),
@@ -20,6 +40,14 @@ export class ErrorContextGenerator {
20
40
  relatedViolations: this.findRelatedViolations(violation, allViolations),
21
41
  };
22
42
  }
43
+ /**
44
+ * Generates a formatted error report
45
+ * @param violation - Policy violation
46
+ * @param validationContext - Validation context
47
+ * @param allViolations - All violations
48
+ * @param executionTime - Plugin execution time
49
+ * @returns Formatted error report string
50
+ */
23
51
  generateErrorReport(violation, validationContext, allViolations, executionTime) {
24
52
  const context = this.generateContext(violation, validationContext, allViolations, executionTime);
25
53
  const lines = [];
@@ -126,6 +154,11 @@ export class ErrorContextGenerator {
126
154
  lines.push('');
127
155
  }
128
156
  }
157
+ /**
158
+ * Gets environment information
159
+ * @returns Environment information object
160
+ * @private
161
+ */
129
162
  getEnvironmentInfo() {
130
163
  const timonelVersion = this.getTimonelVersion();
131
164
  return {
@@ -135,9 +168,23 @@ export class ErrorContextGenerator {
135
168
  ...(timonelVersion && { timonelVersion }),
136
169
  };
137
170
  }
171
+ /**
172
+ * Gets Timonel version from package.json
173
+ * @returns Timonel version or undefined
174
+ * @private
175
+ */
138
176
  getTimonelVersion() {
139
- return '3.0.0';
177
+ // Try to read package.json to get version
178
+ // This is a simplified approach - in a real implementation,
179
+ // you might want to read from a constants file or build-time injection
180
+ return '3.0.0'; // Placeholder
140
181
  }
182
+ /**
183
+ * Extracts validation context information
184
+ * @param validationContext - Validation context
185
+ * @returns Validation context information
186
+ * @private
187
+ */
141
188
  getValidationContextInfo(validationContext) {
142
189
  return {
143
190
  ...(validationContext?.chart?.name && { chartName: validationContext.chart.name }),
@@ -148,6 +195,13 @@ export class ErrorContextGenerator {
148
195
  ...(validationContext?.environment && { environment: validationContext.environment }),
149
196
  };
150
197
  }
198
+ /**
199
+ * Generates debugging hints based on the violation
200
+ * @param violation - Policy violation
201
+ * @param validationContext - Validation context
202
+ * @returns Array of debugging hints
203
+ * @private
204
+ */
151
205
  generateDebuggingHints(violation, validationContext) {
152
206
  const hints = [];
153
207
  this.addSeverityHints(hints, violation);
@@ -220,6 +274,13 @@ export class ErrorContextGenerator {
220
274
  }
221
275
  }
222
276
  }
277
+ /**
278
+ * Finds violations related to the current one
279
+ * @param violation - Current violation
280
+ * @param allViolations - All violations to search through
281
+ * @returns Array of related violations with similarity scores
282
+ * @private
283
+ */
223
284
  findRelatedViolations(violation, allViolations) {
224
285
  if (!allViolations || allViolations.length <= 1) {
225
286
  return [];
@@ -230,6 +291,7 @@ export class ErrorContextGenerator {
230
291
  continue;
231
292
  const similarity = this.calculateSimilarity(violation, other);
232
293
  if (similarity > 0.3) {
294
+ // 30% similarity threshold
233
295
  related.push({
234
296
  plugin: other.plugin,
235
297
  message: other.message,
@@ -237,34 +299,54 @@ export class ErrorContextGenerator {
237
299
  });
238
300
  }
239
301
  }
302
+ // Sort by similarity and return top 3
240
303
  return related.sort((a, b) => b.similarity - a.similarity).slice(0, 3);
241
304
  }
305
+ /**
306
+ * Calculates similarity between two violations
307
+ * @param violation1 - First violation
308
+ * @param violation2 - Second violation
309
+ * @returns Similarity score between 0 and 1
310
+ * @private
311
+ */
242
312
  calculateSimilarity(violation1, violation2) {
243
313
  let score = 0;
244
314
  let factors = 0;
315
+ // Same plugin
245
316
  if (violation1.plugin === violation2.plugin) {
246
317
  score += 0.4;
247
318
  }
248
319
  factors += 0.4;
320
+ // Same severity
249
321
  if (violation1.severity === violation2.severity) {
250
322
  score += 0.2;
251
323
  }
252
324
  factors += 0.2;
325
+ // Similar resource path
253
326
  if (violation1.resourcePath && violation2.resourcePath) {
254
327
  const pathSimilarity = this.calculateStringSimilarity(violation1.resourcePath, violation2.resourcePath);
255
328
  score += pathSimilarity * 0.2;
256
329
  }
257
330
  factors += 0.2;
331
+ // Similar field
258
332
  if (violation1.field && violation2.field) {
259
333
  const fieldSimilarity = this.calculateStringSimilarity(violation1.field, violation2.field);
260
334
  score += fieldSimilarity * 0.1;
261
335
  }
262
336
  factors += 0.1;
337
+ // Similar message
263
338
  const messageSimilarity = this.calculateStringSimilarity(violation1.message, violation2.message);
264
339
  score += messageSimilarity * 0.1;
265
340
  factors += 0.1;
266
341
  return factors > 0 ? score / factors : 0;
267
342
  }
343
+ /**
344
+ * Calculates string similarity using a simple algorithm
345
+ * @param str1 - First string
346
+ * @param str2 - Second string
347
+ * @returns Similarity score between 0 and 1
348
+ * @private
349
+ */
268
350
  calculateStringSimilarity(str1, str2) {
269
351
  if (str1 === str2)
270
352
  return 1;
@@ -277,23 +359,38 @@ export class ErrorContextGenerator {
277
359
  const editDistance = this.calculateLevenshteinDistance(longer, shorter);
278
360
  return (longer.length - editDistance) / longer.length;
279
361
  }
362
+ /**
363
+ * Calculates Levenshtein distance between two strings
364
+ * @param str1 - First string
365
+ * @param str2 - Second string
366
+ * @returns Edit distance
367
+ * @private
368
+ */
280
369
  calculateLevenshteinDistance(str1, str2) {
281
370
  const matrix = Array(str2.length + 1)
282
371
  .fill(null)
283
372
  .map(() => Array(str1.length + 1).fill(0));
284
373
  for (let i = 0; i <= str2.length; i++) {
374
+ // eslint-disable-next-line security/detect-object-injection
285
375
  matrix[i][0] = i;
286
376
  }
287
377
  for (let j = 0; j <= str1.length; j++) {
378
+ // eslint-disable-next-line security/detect-object-injection
288
379
  matrix[0][j] = j;
289
380
  }
290
381
  for (let i = 1; i <= str2.length; i++) {
291
382
  for (let j = 1; j <= str1.length; j++) {
292
383
  if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
384
+ // eslint-disable-next-line security/detect-object-injection
293
385
  matrix[i][j] = matrix[i - 1][j - 1];
294
386
  }
295
387
  else {
296
- matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
388
+ // eslint-disable-next-line security/detect-object-injection
389
+ matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution
390
+ // eslint-disable-next-line security/detect-object-injection
391
+ matrix[i][j - 1] + 1, // insertion
392
+ // eslint-disable-next-line security/detect-object-injection
393
+ matrix[i - 1][j] + 1);
297
394
  }
298
395
  }
299
396
  }