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,21 +1,144 @@
1
+ /**
2
+ * @fileoverview Security utilities for input validation and sanitization
3
+ * Focused on CLI tool security concerns: path traversal, injection prevention
4
+ * @since 2.8.0+
5
+ */
6
+ /** Options controlling path validation behaviour. */
1
7
  export interface PathValidationOptions {
8
+ /**
9
+ * When true, accepts absolute destinations even if they fall outside the allowed base.
10
+ * @since 2.12.2 Enables secure chart writes to system-level directories.
11
+ */
2
12
  allowAbsolute?: boolean;
3
13
  }
14
+ /**
15
+ * Security utilities for input validation and sanitization
16
+ * Focused on CLI tool security concerns: path traversal, injection prevention
17
+ *
18
+ * @since 2.8.0+
19
+ */
4
20
  export declare class SecurityUtils {
21
+ /**
22
+ * Validates and sanitizes file paths to prevent path traversal attacks
23
+ * @param inputPath - The path to validate
24
+ * @param allowedBasePath - The base path that the input should be within
25
+ * @returns Sanitized path if valid
26
+ * @throws Error if path is invalid or contains traversal sequences
27
+ *
28
+ * @since 2.8.0+
29
+ */
5
30
  static validatePath(inputPath: string, allowedBasePath: string, options?: PathValidationOptions): string;
31
+ /**
32
+ * Sanitizes log messages to prevent log injection attacks
33
+ * @param message - The message to sanitize
34
+ * @returns Sanitized message with control characters removed
35
+ *
36
+ * @since 2.8.0+
37
+ */
6
38
  static sanitizeLogMessage(message: string): string;
39
+ /**
40
+ * Sanitizes environment names to prevent path traversal (CWE-22)
41
+ * @param env - Environment name to sanitize
42
+ * @returns Sanitized environment name
43
+ * @throws Error if environment name is invalid
44
+ *
45
+ * @since 2.8.0+
46
+ */
7
47
  static sanitizeEnvironmentName(env: string): string;
48
+ /**
49
+ * Validates TypeScript file extensions for dynamic imports
50
+ * @param filePath - The file path to validate
51
+ * @returns True if the file has a valid TypeScript extension
52
+ *
53
+ * @since 2.8.0+
54
+ */
8
55
  static isValidTypeScriptFile(filePath: string): boolean;
56
+ /**
57
+ * Validates if a path is safe for use in Helm templates
58
+ * Enhanced validation with better security checks and Helm best practices
59
+ * @param templatePath - The template path to validate
60
+ * @returns True if the path is valid for Helm templates
61
+ *
62
+ * @since 2.8.0+
63
+ */
9
64
  static isValidHelmTemplatePath(templatePath: string): boolean;
65
+ /**
66
+ * Validates chart names according to Helm conventions
67
+ * @param chartName - Chart name to validate
68
+ * @returns True if chart name follows Helm naming rules
69
+ *
70
+ * @since 2.8.0+
71
+ */
10
72
  static isValidChartName(chartName: string): boolean;
73
+ /**
74
+ * Validates subchart names according to Helm conventions
75
+ * @param subchartName - Subchart name to validate
76
+ * @returns True if subchart name is valid
77
+ *
78
+ * @since 2.8.0+
79
+ */
11
80
  static isValidSubchartName(subchartName: string): boolean;
81
+ /**
82
+ * Sanitizes environment variable names and values for Kubernetes security
83
+ * Prevents injection attacks and ensures compliance with Kubernetes naming rules
84
+ * @param name - Environment variable name to sanitize
85
+ * @param value - Environment variable value to sanitize
86
+ * @returns Object with sanitized name and value
87
+ * @throws Error if name or value contains dangerous patterns
88
+ *
89
+ * @since 2.8.0+
90
+ */
12
91
  static sanitizeEnvVar(name: string, value: string): {
13
92
  name: string;
14
93
  value: string;
15
94
  };
95
+ /**
96
+ * Validates container image tags for security best practices
97
+ * Prevents use of dangerous tags and ensures proper versioning
98
+ * @param tag - Image tag to validate
99
+ * @returns True if tag is valid and secure
100
+ * @throws Error if tag violates security policies
101
+ *
102
+ * @since 2.8.0+
103
+ */
16
104
  static validateImageTag(tag: string): boolean;
105
+ /**
106
+ * Generates secure names for Kubernetes secrets
107
+ * Ensures names follow RFC 1123 and are safe for Kubernetes
108
+ * @param baseName - Base name for the secret
109
+ * @param suffix - Optional suffix to append
110
+ * @returns Secure secret name
111
+ * @throws Error if generated name is invalid
112
+ *
113
+ * @since 2.8.0+
114
+ */
17
115
  static generateSecretName(baseName: string, suffix?: string): string;
116
+ /**
117
+ * Sanitizes the base name for secret generation using safe string methods
118
+ * @param baseName - Base name to sanitize
119
+ * @returns Sanitized base name
120
+ * @throws Error if no valid characters remain
121
+ *
122
+ * @since 2.8.0+
123
+ */
18
124
  private static sanitizeBaseName;
125
+ /**
126
+ * Appends suffix to sanitized base name using safe string methods
127
+ * @param baseName - Sanitized base name
128
+ * @param suffix - Suffix to append
129
+ * @returns Base name with suffix
130
+ * @throws Error if suffix is invalid
131
+ *
132
+ * @since 2.8.0+
133
+ */
19
134
  private static appendSuffix;
135
+ /**
136
+ * Truncates name if it exceeds length limits
137
+ * @param name - Name to potentially truncate
138
+ * @param suffix - Original suffix for preservation
139
+ * @returns Truncated name if needed
140
+ *
141
+ * @since 2.8.0+
142
+ */
20
143
  private static truncateIfNeeded;
21
144
  }
@@ -1,5 +1,25 @@
1
+ /**
2
+ * @fileoverview Security utilities for input validation and sanitization
3
+ * Focused on CLI tool security concerns: path traversal, injection prevention
4
+ * @since 2.8.0+
5
+ */
1
6
  import * as path from 'path';
7
+ /**
8
+ * Security utilities for input validation and sanitization
9
+ * Focused on CLI tool security concerns: path traversal, injection prevention
10
+ *
11
+ * @since 2.8.0+
12
+ */
2
13
  export class SecurityUtils {
14
+ /**
15
+ * Validates and sanitizes file paths to prevent path traversal attacks
16
+ * @param inputPath - The path to validate
17
+ * @param allowedBasePath - The base path that the input should be within
18
+ * @returns Sanitized path if valid
19
+ * @throws Error if path is invalid or contains traversal sequences
20
+ *
21
+ * @since 2.8.0+
22
+ */
3
23
  static validatePath(inputPath, allowedBasePath, options) {
4
24
  if (!inputPath || typeof inputPath !== 'string') {
5
25
  throw new Error('Invalid path: path must be a non-empty string');
@@ -24,6 +44,7 @@ export class SecurityUtils {
24
44
  registerCandidate(normalized);
25
45
  }
26
46
  catch {
47
+ // Ignore normalization errors and continue with existing candidates.
27
48
  }
28
49
  };
29
50
  addCandidate(inputPath);
@@ -58,6 +79,7 @@ export class SecurityUtils {
58
79
  throw new Error('Invalid path: path traversal sequences detected');
59
80
  }
60
81
  }
82
+ // Resolve and normalize paths
61
83
  const resolvedInput = path.resolve(inputPath);
62
84
  const resolvedBase = path.resolve(allowedBasePath);
63
85
  const relativePath = path.relative(resolvedBase, resolvedInput);
@@ -67,21 +89,39 @@ export class SecurityUtils {
67
89
  }
68
90
  return resolvedInput;
69
91
  }
92
+ /**
93
+ * Sanitizes log messages to prevent log injection attacks
94
+ * @param message - The message to sanitize
95
+ * @returns Sanitized message with control characters removed
96
+ *
97
+ * @since 2.8.0+
98
+ */
70
99
  static sanitizeLogMessage(message) {
71
100
  if (typeof message !== 'string') {
72
101
  return String(message);
73
102
  }
103
+ // Remove control characters (ASCII 0-31 and 127) and normalize line endings
74
104
  return (message
75
- .replace(/\r\n/g, '\n')
76
- .replace(/[\x00-\x09\x0B-\x0C\x0E-\x1F\x7F]/g, '')
77
- .replace(/[\r\n]/g, ' ')
78
- .replace(/\s+/g, ' ')
105
+ .replace(/\r\n/g, '\n') // Normalize CRLF to LF
106
+ // eslint-disable-next-line no-control-regex -- Intentionally removing control characters for security
107
+ .replace(/[\x00-\x09\x0B-\x0C\x0E-\x1F\x7F]/g, '') // Strip control chars except LF/CR
108
+ .replace(/[\r\n]/g, ' ') // Normalize remaining line breaks
109
+ .replace(/\s+/g, ' ') // Collapse repeated whitespace
79
110
  .trim());
80
111
  }
112
+ /**
113
+ * Sanitizes environment names to prevent path traversal (CWE-22)
114
+ * @param env - Environment name to sanitize
115
+ * @returns Sanitized environment name
116
+ * @throws Error if environment name is invalid
117
+ *
118
+ * @since 2.8.0+
119
+ */
81
120
  static sanitizeEnvironmentName(env) {
82
121
  if (!env || typeof env !== 'string') {
83
122
  throw new Error('Environment name must be a non-empty string');
84
123
  }
124
+ // Allow only alphanumeric, hyphens, and underscores
85
125
  const sanitized = env.replace(/[^a-zA-Z0-9-_]/g, '');
86
126
  if (sanitized !== env) {
87
127
  throw new Error(`Invalid environment name: ${SecurityUtils.sanitizeLogMessage(env)}`);
@@ -91,52 +131,105 @@ export class SecurityUtils {
91
131
  }
92
132
  return sanitized;
93
133
  }
134
+ /**
135
+ * Validates TypeScript file extensions for dynamic imports
136
+ * @param filePath - The file path to validate
137
+ * @returns True if the file has a valid TypeScript extension
138
+ *
139
+ * @since 2.8.0+
140
+ */
94
141
  static isValidTypeScriptFile(filePath) {
95
142
  const allowedExtensions = ['.ts', '.tsx', '.cts', '.mts'];
96
143
  const ext = path.extname(filePath);
97
144
  return allowedExtensions.includes(ext);
98
145
  }
146
+ /**
147
+ * Validates if a path is safe for use in Helm templates
148
+ * Enhanced validation with better security checks and Helm best practices
149
+ * @param templatePath - The template path to validate
150
+ * @returns True if the path is valid for Helm templates
151
+ *
152
+ * @since 2.8.0+
153
+ */
99
154
  static isValidHelmTemplatePath(templatePath) {
100
155
  if (!templatePath || typeof templatePath !== 'string') {
101
156
  return false;
102
157
  }
158
+ // Check length limits (reasonable for Helm paths)
103
159
  if (templatePath.length > 253) {
104
160
  return false;
105
161
  }
162
+ // Enhanced validation following Kubernetes naming conventions
163
+ // Check if starts and ends with alphanumeric
106
164
  if (!/^[a-zA-Z0-9]/.test(templatePath) || !/[a-zA-Z0-9]$/.test(templatePath)) {
107
165
  return false;
108
166
  }
167
+ // Check for valid characters only (safe regex)
109
168
  if (!/^[a-zA-Z0-9._\-/]+$/.test(templatePath)) {
110
169
  return false;
111
170
  }
171
+ // Additional security checks
172
+ // Prevent path traversal attempts
112
173
  if (templatePath.includes('..') || templatePath.includes('//')) {
113
174
  return false;
114
175
  }
176
+ // Prevent reserved words that could cause issues
115
177
  const reservedWords = ['nil', 'null', 'undefined', 'true', 'false'];
178
+ // Split by directory separators first
116
179
  const pathParts = templatePath.split('/');
117
180
  for (const part of pathParts) {
181
+ // Then split by dots for file extensions/parts
118
182
  const segments = part.split('.');
119
183
  for (const segment of segments) {
120
184
  if (reservedWords.includes(segment.toLowerCase())) {
121
185
  return false;
122
186
  }
187
+ // Each segment should not be empty (except possibly for leading dot files, but split handles that)
123
188
  if (segment.length === 0 && segments.length > 1) {
189
+ // Allow .gitignore (empty first segment)
124
190
  continue;
125
191
  }
126
192
  }
127
193
  }
128
194
  return true;
129
195
  }
196
+ /**
197
+ * Validates chart names according to Helm conventions
198
+ * @param chartName - Chart name to validate
199
+ * @returns True if chart name follows Helm naming rules
200
+ *
201
+ * @since 2.8.0+
202
+ */
130
203
  static isValidChartName(chartName) {
131
204
  if (!chartName || typeof chartName !== 'string') {
132
205
  return false;
133
206
  }
207
+ // Helm chart name validation (RFC 1123 subdomain) - safe regex
208
+ // Must start with a letter, can contain letters, numbers, and hyphens
209
+ // eslint-disable-next-line security/detect-unsafe-regex -- Simple character class regex is safe
134
210
  const chartNameRegex = /^[a-z]([-a-z0-9]*[a-z0-9])?$/;
135
211
  return chartNameRegex.test(chartName) && chartName.length <= 63;
136
212
  }
213
+ /**
214
+ * Validates subchart names according to Helm conventions
215
+ * @param subchartName - Subchart name to validate
216
+ * @returns True if subchart name is valid
217
+ *
218
+ * @since 2.8.0+
219
+ */
137
220
  static isValidSubchartName(subchartName) {
138
221
  return this.isValidChartName(subchartName);
139
222
  }
223
+ /**
224
+ * Sanitizes environment variable names and values for Kubernetes security
225
+ * Prevents injection attacks and ensures compliance with Kubernetes naming rules
226
+ * @param name - Environment variable name to sanitize
227
+ * @param value - Environment variable value to sanitize
228
+ * @returns Object with sanitized name and value
229
+ * @throws Error if name or value contains dangerous patterns
230
+ *
231
+ * @since 2.8.0+
232
+ */
140
233
  static sanitizeEnvVar(name, value) {
141
234
  if (!name || typeof name !== 'string') {
142
235
  throw new Error('Environment variable name must be a non-empty string');
@@ -144,7 +237,9 @@ export class SecurityUtils {
144
237
  if (typeof value !== 'string') {
145
238
  throw new Error('Environment variable value must be a string');
146
239
  }
240
+ // Kubernetes env var name validation (RFC 1123 compatible)
147
241
  let sanitizedName = name.toUpperCase().replace(/[^A-Z0-9_]/g, '_');
242
+ // Ensure name starts with letter or underscore
148
243
  if (/^[0-9]/.test(sanitizedName)) {
149
244
  sanitizedName = `_${sanitizedName}`;
150
245
  }
@@ -152,6 +247,7 @@ export class SecurityUtils {
152
247
  if (!nameRegex.test(sanitizedName)) {
153
248
  throw new Error(`Invalid environment variable name: ${SecurityUtils.sanitizeLogMessage(name)}`);
154
249
  }
250
+ // Check for dangerous patterns in value using safer string methods
155
251
  const hasDangerousPattern = (val) => {
156
252
  if (val.includes('$(') && val.includes(')'))
157
253
  return 'command substitution';
@@ -159,6 +255,7 @@ export class SecurityUtils {
159
255
  return 'backtick execution';
160
256
  if (val.includes('${') && val.includes('}'))
161
257
  return 'variable expansion';
258
+ // Check for control characters
162
259
  for (let i = 0; i < val.length; i++) {
163
260
  const code = val.charCodeAt(i);
164
261
  if ((code >= 0x00 && code <= 0x08) ||
@@ -175,6 +272,7 @@ export class SecurityUtils {
175
272
  if (dangerousPattern) {
176
273
  throw new Error(`Environment variable value contains dangerous pattern (${dangerousPattern}): ${SecurityUtils.sanitizeLogMessage(value)}`);
177
274
  }
275
+ // Limit value length to prevent DoS
178
276
  if (value.length > 32768) {
179
277
  throw new Error('Environment variable value exceeds maximum length (32KB)');
180
278
  }
@@ -183,31 +281,58 @@ export class SecurityUtils {
183
281
  value: value.trim(),
184
282
  };
185
283
  }
284
+ /**
285
+ * Validates container image tags for security best practices
286
+ * Prevents use of dangerous tags and ensures proper versioning
287
+ * @param tag - Image tag to validate
288
+ * @returns True if tag is valid and secure
289
+ * @throws Error if tag violates security policies
290
+ *
291
+ * @since 2.8.0+
292
+ */
186
293
  static validateImageTag(tag) {
187
294
  if (!tag || typeof tag !== 'string') {
188
295
  throw new Error('Image tag must be a non-empty string');
189
296
  }
190
297
  const trimmedTag = tag.trim();
298
+ // Reject dangerous or non-specific tags
191
299
  const dangerousTags = ['latest', 'master', 'main', 'dev', 'development', 'test', 'staging'];
192
300
  if (dangerousTags.includes(trimmedTag.toLowerCase())) {
193
301
  throw new Error(`Insecure image tag detected: '${trimmedTag}'. Use specific version tags for security.`);
194
302
  }
303
+ // Validate tag format (Docker tag rules)
195
304
  const tagRegex = /^[a-zA-Z0-9._-]+$/;
196
305
  if (!tagRegex.test(trimmedTag)) {
197
306
  throw new Error(`Invalid image tag format: ${SecurityUtils.sanitizeLogMessage(trimmedTag)}`);
198
307
  }
308
+ // Check length limits
199
309
  if (trimmedTag.length > 128) {
200
310
  throw new Error('Image tag exceeds maximum length (128 characters)');
201
311
  }
312
+ // Prefer semantic versioning patterns
313
+ // eslint-disable-next-line security/detect-unsafe-regex -- Simple regex patterns are safe for validation
202
314
  const semverPattern = /^v?\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?$/;
203
315
  const hashPattern = /^[a-f0-9]{7,64}$/;
316
+ // eslint-disable-next-line security/detect-unsafe-regex -- Simple date pattern is safe for validation
204
317
  const datePattern = /^\d{4}-\d{2}-\d{2}(-[a-zA-Z0-9.-]+)?$/;
205
318
  if (!semverPattern.test(trimmedTag) &&
206
319
  !hashPattern.test(trimmedTag) &&
207
320
  !datePattern.test(trimmedTag)) {
321
+ // Warning for non-standard tags but don't fail
322
+ // Note: Non-standard tag pattern detected but allowing it
208
323
  }
209
324
  return true;
210
325
  }
326
+ /**
327
+ * Generates secure names for Kubernetes secrets
328
+ * Ensures names follow RFC 1123 and are safe for Kubernetes
329
+ * @param baseName - Base name for the secret
330
+ * @param suffix - Optional suffix to append
331
+ * @returns Secure secret name
332
+ * @throws Error if generated name is invalid
333
+ *
334
+ * @since 2.8.0+
335
+ */
211
336
  static generateSecretName(baseName, suffix) {
212
337
  if (!baseName || typeof baseName !== 'string') {
213
338
  throw new Error('Base name must be a non-empty string');
@@ -216,16 +341,27 @@ export class SecurityUtils {
216
341
  if (suffix) {
217
342
  sanitizedBase = this.appendSuffix(sanitizedBase, suffix);
218
343
  }
344
+ // Ensure name starts with letter (not number)
219
345
  if (/^[0-9]/.test(sanitizedBase)) {
220
346
  sanitizedBase = `s${sanitizedBase}`;
221
347
  }
222
348
  sanitizedBase = this.truncateIfNeeded(sanitizedBase, suffix);
349
+ // Final validation
223
350
  if (!this.isValidChartName(sanitizedBase)) {
224
351
  throw new Error(`Generated secret name is invalid: ${sanitizedBase}`);
225
352
  }
226
353
  return sanitizedBase;
227
354
  }
355
+ /**
356
+ * Sanitizes the base name for secret generation using safe string methods
357
+ * @param baseName - Base name to sanitize
358
+ * @returns Sanitized base name
359
+ * @throws Error if no valid characters remain
360
+ *
361
+ * @since 2.8.0+
362
+ */
228
363
  static sanitizeBaseName(baseName) {
364
+ // Use character-by-character processing instead of regex
229
365
  let sanitized = '';
230
366
  for (const char of baseName.toLowerCase()) {
231
367
  if ((char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char === '-') {
@@ -235,6 +371,7 @@ export class SecurityUtils {
235
371
  sanitized += '-';
236
372
  }
237
373
  }
374
+ // Collapse multiple hyphens using split/filter/join
238
375
  const parts = sanitized.split('-').filter((part) => part.length > 0);
239
376
  sanitized = parts.join('-');
240
377
  if (!sanitized) {
@@ -242,10 +379,20 @@ export class SecurityUtils {
242
379
  }
243
380
  return sanitized;
244
381
  }
382
+ /**
383
+ * Appends suffix to sanitized base name using safe string methods
384
+ * @param baseName - Sanitized base name
385
+ * @param suffix - Suffix to append
386
+ * @returns Base name with suffix
387
+ * @throws Error if suffix is invalid
388
+ *
389
+ * @since 2.8.0+
390
+ */
245
391
  static appendSuffix(baseName, suffix) {
246
392
  if (typeof suffix !== 'string') {
247
393
  throw new Error('Suffix must be a string');
248
394
  }
395
+ // Use character-by-character processing instead of regex
249
396
  let sanitizedSuffix = '';
250
397
  for (const char of suffix.toLowerCase()) {
251
398
  if ((char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char === '-') {
@@ -255,6 +402,7 @@ export class SecurityUtils {
255
402
  sanitizedSuffix += '-';
256
403
  }
257
404
  }
405
+ // Collapse multiple hyphens using split/filter/join
258
406
  const parts = sanitizedSuffix.split('-').filter((part) => part.length > 0);
259
407
  sanitizedSuffix = parts.join('-');
260
408
  if (sanitizedSuffix) {
@@ -262,12 +410,22 @@ export class SecurityUtils {
262
410
  }
263
411
  return baseName;
264
412
  }
413
+ /**
414
+ * Truncates name if it exceeds length limits
415
+ * @param name - Name to potentially truncate
416
+ * @param suffix - Original suffix for preservation
417
+ * @returns Truncated name if needed
418
+ *
419
+ * @since 2.8.0+
420
+ */
265
421
  static truncateIfNeeded(name, suffix) {
266
422
  const maxLength = 63;
267
423
  if (name.length <= maxLength) {
268
424
  return name;
269
425
  }
426
+ // Truncate but preserve suffix if possible
270
427
  if (suffix) {
428
+ // Use safe character processing instead of regex
271
429
  let safeSuffix = '';
272
430
  for (const char of suffix.toLowerCase()) {
273
431
  if ((char >= 'a' && char <= 'z') || (char >= '0' && char <= '9') || char === '-') {
@@ -1,4 +1,12 @@
1
+ /**
2
+ * @fileoverview Flexible subchart template that supports any cdk8s/cdk8s-plus-33 construct
3
+ * @since 2.8.4
4
+ */
1
5
  import { Chart } from 'cdk8s';
6
+ /**
7
+ * Flexible subchart that can accept any cdk8s construct or function
8
+ * @since 2.8.4
9
+ */
2
10
  export declare class FlexibleSubchart extends Chart {
3
11
  private readonly config;
4
12
  private _constructs;
@@ -11,18 +19,62 @@ export declare class FlexibleSubchart extends Chart {
11
19
  manifest?: unknown;
12
20
  [key: string]: unknown;
13
21
  });
22
+ /**
23
+ * Add any cdk8s construct
24
+ * @param construct - Any cdk8s construct
25
+ * @param id - Unique identifier
26
+ */
14
27
  addConstruct(construct: unknown, id?: string): void;
28
+ /**
29
+ * Add any manifest (for addManifest compatibility)
30
+ * @param manifest - Any manifest object
31
+ * @param id - Unique identifier
32
+ */
15
33
  addManifest(manifest: unknown, id?: string): void;
34
+ /**
35
+ * Configure the subchart with any provided construct or manifest
36
+ * @private
37
+ */
16
38
  private configure;
39
+ /**
40
+ * Write Helm chart files for this subchart
41
+ * @param outputDir - Directory to write the Helm chart files
42
+ */
17
43
  writeHelmChart(outputDir: string): void;
44
+ /**
45
+ * Generate Helm template for a manifest
46
+ * @param manifest - The manifest object
47
+ * @param id - Template identifier
48
+ * @returns Generated template content
49
+ * @private
50
+ */
18
51
  private _generateManifestTemplate;
52
+ /**
53
+ * Get all constructs added to this subchart
54
+ */
19
55
  getConstructs(): unknown[];
56
+ /**
57
+ * Get all manifests added to this subchart
58
+ */
20
59
  getManifests(): unknown[];
21
60
  }
61
+ /**
62
+ * Create a flexible subchart that can accept any construct
63
+ * @param scope - Parent chart scope
64
+ * @param id - Unique identifier
65
+ * @param config - Subchart configuration
66
+ * @returns FlexibleSubchart instance
67
+ */
22
68
  export declare function createFlexibleSubchart(scope: Chart, id: string, config: {
23
69
  name: string;
24
70
  version?: string;
25
71
  description?: string;
26
72
  [key: string]: unknown;
27
73
  }): FlexibleSubchart;
74
+ /**
75
+ * Generate a simple subchart template using Rutter addManifest()
76
+ * @param name Subchart name
77
+ * @returns Template string for chart.ts with simple Rutter implementation
78
+ * @since 2.11.0
79
+ */
28
80
  export declare function generateFlexibleSubchartTemplate(name: string): string;