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.
Files changed (52) hide show
  1. package/CHANGELOG.md +192 -0
  2. package/README.md +606 -119
  3. package/SECURITY.md +25 -11
  4. package/dist/cli.js +54 -15
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.js +2 -0
  7. package/dist/lib/helm.js +28 -1
  8. package/dist/lib/helmChartWriter.js +27 -8
  9. package/dist/lib/policy/configurationLoader.d.ts +46 -0
  10. package/dist/lib/policy/configurationLoader.js +251 -0
  11. package/dist/lib/policy/errorContextGenerator.d.ts +63 -0
  12. package/dist/lib/policy/errorContextGenerator.js +302 -0
  13. package/dist/lib/policy/errors.d.ts +40 -0
  14. package/dist/lib/policy/errors.js +109 -0
  15. package/dist/lib/policy/index.d.ts +11 -0
  16. package/dist/lib/policy/index.js +10 -0
  17. package/dist/lib/policy/parallelExecutor.d.ts +58 -0
  18. package/dist/lib/policy/parallelExecutor.js +215 -0
  19. package/dist/lib/policy/pluginLoader.d.ts +41 -0
  20. package/dist/lib/policy/pluginLoader.js +220 -0
  21. package/dist/lib/policy/pluginRegistry.d.ts +14 -0
  22. package/dist/lib/policy/pluginRegistry.js +69 -0
  23. package/dist/lib/policy/policyEngine.d.ts +39 -0
  24. package/dist/lib/policy/policyEngine.js +495 -0
  25. package/dist/lib/policy/resultAggregator.d.ts +8 -0
  26. package/dist/lib/policy/resultAggregator.js +138 -0
  27. package/dist/lib/policy/resultFormatter.d.ts +25 -0
  28. package/dist/lib/policy/resultFormatter.js +217 -0
  29. package/dist/lib/policy/types.d.ts +111 -0
  30. package/dist/lib/policy/types.js +1 -0
  31. package/dist/lib/policy/validationCache.d.ts +58 -0
  32. package/dist/lib/policy/validationCache.js +289 -0
  33. package/dist/lib/resources/baseResourceProvider.js +5 -0
  34. package/dist/lib/resources/cloud/aws/awsResources.js +2 -1
  35. package/dist/lib/resources/cloud/aws/karpenterResources.js +16 -2
  36. package/dist/lib/rutter.d.ts +7 -2
  37. package/dist/lib/rutter.js +177 -8
  38. package/dist/lib/security.js +4 -4
  39. package/dist/lib/templates/flexible-subchart.js +18 -7
  40. package/dist/lib/templates/umbrella-chart.js +29 -18
  41. package/dist/lib/umbrellaRutter.d.ts +1 -1
  42. package/dist/lib/umbrellaRutter.js +21 -9
  43. package/dist/lib/utils/envVarsLoader.js +13 -7
  44. package/dist/lib/utils/helmHelpers.js +10 -2
  45. package/dist/lib/utils/helmYamlSerializer.js +19 -9
  46. package/dist/lib/utils/logger.js +54 -39
  47. package/dist/lib/utils/valuesRef.js +9 -0
  48. package/dist/lib/validation/inputValidator.d.ts +26 -0
  49. package/dist/lib/validation/inputValidator.js +176 -0
  50. package/dist/types/index.d.ts +27 -0
  51. package/dist/types/index.js +1 -0
  52. package/package.json +21 -19
package/README.md CHANGED
@@ -17,18 +17,107 @@ directory.
17
17
 
18
18
  ## ✨ Key Features
19
19
 
20
- - **šŸ”’ Type-safe API** with strict TypeScript and cdk8s constructs.
21
- - **šŸŽÆ Type-Safe Helm Helpers** with 9 composable template helpers (`helmIf`, `helmRange`,
22
- `helmWith`, `helmInclude`, etc.)
23
- - **šŸ”§ Flexible resource creation** with built-in methods and `addManifest()` for custom resources.
24
- - **šŸŒ Multi-environment support** with automatic values files generation.
25
- - **ā˜‚ļø Umbrella Charts** for managing multiple subcharts as a single unit.
26
- - **šŸ› ļø Enhanced Helm Helpers** with environment, GitOps, observability, and validation helpers.
27
- - **ā˜ļø Cloud integrations**:
28
- - **AWS**: EBS/EFS StorageClass, ALB Ingress, IRSA ServiceAccount, ECR, and Karpenter.
29
- - **šŸ›”ļø Security-first approach** with NetworkPolicies and best practices.
30
- - **⚔ Minimal CLI** (`tl`) for scaffolding and chart generation.
31
- - **šŸ“¦ Flexible subchart templates** supporting cdk8s and cdk8s-plus-33.
20
+ ### Core Capabilities
21
+
22
+ - **šŸ”’ Type-safe API** with strict TypeScript and cdk8s constructs
23
+ - **šŸ”§ Flexible resource creation** with built-in methods and `addManifest()` for custom resources
24
+ - **šŸŒ Multi-environment support** with automatic values files generation
25
+ - **ā˜‚ļø Umbrella Charts** for managing multiple subcharts as a single unit
26
+ - **⚔ Minimal CLI** (`tl`) for scaffolding, synthesis, validation, and deployment
27
+ - **šŸ“¦ Flexible subchart templates** supporting both cdk8s and cdk8s-plus-33
28
+
29
+ ### Type-Safe Helm Helpers (v3.0+)
30
+
31
+ #### ValuesRef System (NEW in v3.0 - RECOMMENDED)
32
+
33
+ Type-safe proxy-based values references with full IDE support:
34
+
35
+ - Import: `import { valuesRef } from 'timonel'`
36
+ - **Comparison operators**: `eq`, `ne`, `gt`, `ge`, `lt`, `le`
37
+ - **Logical operators**: `not`, `and`, `or`
38
+ - **String functions**: `quote`, `upper`, `lower`, `trim`, `replace`, `contains`
39
+ - **Default values**: `default()`
40
+ - **Type checking**: `kindIs`, `hasKey`
41
+ - **YAML functions**: `toYaml`, `toJson`, `nindent`, `indent`
42
+ - **Field-level conditionals**: `v.if()`, `v.ifElse()` - Complex conditional logic
43
+ - **Range loops**: `v.range()` - Type-safe iteration
44
+ - **Context switching**: `v.with()` - Scoped value access
45
+
46
+ #### Composable Helpers
47
+
48
+ Template definition and inclusion helpers:
49
+
50
+ - `helmInclude`, `helmDefine`, `helmVar`, `helmBlock`, `helmComment`, `helmFragment`
51
+ - `template`, `include`, `quote`, `indent`
52
+
53
+ #### Value Reference Helpers
54
+
55
+ Useful string-based utilities (no ValuesRef equivalent):
56
+
57
+ - `requiredValuesRef` - Required value with validation
58
+ - `numberRef`, `boolRef`, `floatRef` - Type-cast references (int, bool, float64)
59
+ - `base64Ref` - Base64 encoding
60
+
61
+ #### Legacy Helpers (NOT RECOMMENDED)
62
+
63
+ **āš ļø Use ValuesRef system instead:**
64
+
65
+ - `valuesRef(path)` → use `v.path` (ValuesRef system)
66
+ - `stringRef()` → use `v.quote()` (ValuesRef system)
67
+ - `defaultRef()` → use `v.default()` (ValuesRef system)
68
+ - `jsonRef()` → use `v.toJson()` (ValuesRef system)
69
+ - `conditionalRef()` → use `v.if()` (ValuesRef system)
70
+ - `helmIf`, `helmIfSimple` → use `v.if()` (ValuesRef system)
71
+ - `helmRange` → use `v.range()` (ValuesRef system)
72
+ - `helmWith` → use `v.with()` (ValuesRef system)
73
+ - `helmIfElseIf` → use `v.if()` with nested conditions
74
+
75
+ ### Enhanced Helm Helpers
76
+
77
+ - **Environment Helpers**: `envRef`, `envDefault`, `envRequired`, `envFromSecret`, `envFromConfigMap`
78
+ - **GitOps Helpers**: `gitBranch`, `gitCommit`, `gitTag`, `gitopsAnnotations`
79
+ - **Observability Helpers**: `prometheusAnnotations`, `datadogAnnotations`, `tracingAnnotations`
80
+ - **Validation Helpers**: `validateRequired`, `validatePattern`, `validateRange`, `validateEnum`
81
+ - **Standard Helpers**: 40+ built-in Helm helpers (chart.name, chart.fullname, chart.labels, etc.)
82
+
83
+ ### Cloud Integrations
84
+
85
+ - **AWS Resources**:
86
+ - EBS/EFS StorageClass with encryption and performance options
87
+ - ALB Ingress with SSL/TLS and health checks
88
+ - IRSA ServiceAccount for pod-level IAM roles
89
+ - ECR integration
90
+ - Karpenter NodePool, NodeClaim, and EC2NodeClass
91
+ - **Karpenter Features**:
92
+ - Disruption budgets and consolidation policies
93
+ - Instance type selection and requirements
94
+ - Spot instance support
95
+ - Custom AMI and user data
96
+
97
+ ### Security & Validation
98
+
99
+ - **šŸ›”ļø Security-first approach**:
100
+ - Input validation (CWE-20, CWE-22/23)
101
+ - Path traversal prevention
102
+ - Command injection prevention (CWE-78/77/88)
103
+ - Log injection protection (CWE-117)
104
+ - Code injection prevention (CWE-94)
105
+ - **šŸ” Policy Engine** (NEW):
106
+ - Extensible validation framework for Kubernetes manifests
107
+ - Plugin-based architecture for custom policy rules
108
+ - Zero-impact integration (completely optional)
109
+ - Support for security, compliance, and best practice policies
110
+ - **NetworkPolicy support** for pod-level network isolation
111
+ - **Helm chart validation** with `validateHelmYaml`
112
+ - **SecurityUtils** for path validation and sanitization
113
+
114
+ ### Developer Experience
115
+
116
+ - **Structured logging** with Pino (JSON format, performance tracking)
117
+ - **Environment variables loader** for external configuration
118
+ - **YAML serialization** with Helm template preservation
119
+ - **TypeScript strict mode** with all compiler checks enabled
120
+ - **Comprehensive error handling** with detailed messages
32
121
 
33
122
  ## šŸš€ Quick Start
34
123
 
@@ -128,6 +217,64 @@ chart.addManifest(
128
217
  chart.write('./dist');
129
218
  ```
130
219
 
220
+ ### Policy Engine Integration
221
+
222
+ ```typescript
223
+ import { Rutter, PolicyEngine } from 'timonel';
224
+ import { securityPolicies } from '@mycompany/k8s-security-policies';
225
+
226
+ // Create policy engine with custom plugins
227
+ const policyEngine = new PolicyEngine().use(securityPolicies).configure({
228
+ timeout: 5000,
229
+ parallel: true,
230
+ });
231
+
232
+ const chart = new Rutter({
233
+ meta: {
234
+ name: 'secure-app',
235
+ version: '1.0.0',
236
+ },
237
+ // Optional policy validation
238
+ policyEngine,
239
+ });
240
+
241
+ // Policies validate manifests before chart generation
242
+ chart.write('./dist'); // Fails if policy violations found
243
+ ```
244
+
245
+ ### Creating Custom Policy Plugins
246
+
247
+ ```typescript
248
+ import { PolicyPlugin, PolicyViolation } from 'timonel';
249
+
250
+ export const mySecurityPolicy: PolicyPlugin = {
251
+ name: 'my-security-policy',
252
+ version: '1.0.0',
253
+ description: 'Custom security validation rules',
254
+
255
+ async validate(manifests, context) {
256
+ const violations: PolicyViolation[] = [];
257
+
258
+ for (const manifest of manifests) {
259
+ if (manifest.kind === 'Deployment') {
260
+ // Check for security context
261
+ if (!manifest.spec?.template?.spec?.securityContext) {
262
+ violations.push({
263
+ plugin: this.name,
264
+ severity: 'error',
265
+ message: 'Deployment must specify securityContext',
266
+ resourcePath: `${manifest.kind}/${manifest.metadata?.name}`,
267
+ suggestion: 'Add spec.template.spec.securityContext to your Deployment',
268
+ });
269
+ }
270
+ }
271
+ }
272
+
273
+ return violations;
274
+ },
275
+ };
276
+ ```
277
+
131
278
  ### Umbrella Chart with Multiple Services
132
279
 
133
280
  ```typescript
@@ -153,146 +300,478 @@ const umbrellaConfig = {
153
300
  export const umbrella = new UmbrellaChartTemplate(umbrellaConfig);
154
301
  ```
155
302
 
156
- ### Type-Safe Helm Helpers
303
+ ### Using Type-Safe Helm Helpers
304
+
305
+ #### ValuesRef System (Recommended)
306
+
307
+ The new ValuesRef system provides a type-safe, proxy-based approach to Helm values with full IDE support.
157
308
 
158
- Timonel provides 9 composable, type-safe helpers for Helm template generation: `helmIf`,
159
- `helmRange`, `helmWith`, `helmInclude`, `helmDefine`, `helmVar`, `helmBlock`, `helmComment`, and
160
- `helmFragment`.
309
+ **āš ļø Important:** This is completely different from the legacy `valuesRef(path: string)` helper.
310
+ The new system uses generics and returns a proxy object with methods.
161
311
 
162
- **Benefits:**
312
+ ```typescript
313
+ import { valuesRef } from 'timonel';
163
314
 
164
- ## šŸ”§ Dynamic Environment Variables
315
+ interface MyValues {
316
+ replicaCount: number;
317
+ image: { repository: string; tag: string };
318
+ autoscaling: { enabled: boolean; minReplicas: number };
319
+ }
165
320
 
166
- Timonel supports flexible environment variable configuration that can be defined in code or
167
- loaded from external sources (e.g., Vault during CI/CD).
321
+ const v = valuesRef<MyValues>();
168
322
 
169
- ### Configuration Methods
323
+ // Type-safe value references with IDE autocomplete
324
+ const replicas = v.replicaCount; // {{ .Values.replicaCount }}
325
+ const imageTag = v.image.tag; // {{ .Values.image.tag }}
170
326
 
171
- **1. In-Code Defaults:**
327
+ // Comparison operators
328
+ const isProd = v.environment.eq('production'); // eq .Values.environment "production"
329
+ const hasReplicas = v.replicaCount.gt(1); // gt .Values.replicaCount 1
172
330
 
173
- ```typescript
174
- const envVars = [
175
- { name: 'VERSION', type: 'value', defaultValue: '1.0.0' },
176
- { name: 'DATABASE_URL', type: 'secret', secretName: 'app-secrets' },
177
- ];
331
+ // Logical operators
332
+ const notEnabled = v.autoscaling.enabled.not(); // not .Values.autoscaling.enabled
333
+
334
+ // String functions
335
+ const upperEnv = v.environment.upper(); // .Values.environment | upper
336
+ const quotedTag = v.image.tag.quote(); // .Values.image.tag | quote
337
+
338
+ // Default values
339
+ const port = v.port.default(8080); // {{ .Values.port | default 8080 }}
340
+
341
+ // Field-level conditionals
342
+ const deployment = {
343
+ spec: {
344
+ replicas: v.if(notEnabled, v.replicaCount), // Conditionally include field
345
+ },
346
+ };
347
+
348
+ // Range loops
349
+ const envVars = v.env.range((item, index) => ({
350
+ name: item.name,
351
+ value: item.value,
352
+ }));
353
+
354
+ // Context switching
355
+ const dbConfig = v.database.with((db) => ({
356
+ host: db.host,
357
+ port: db.port,
358
+ }));
178
359
  ```
179
360
 
180
- **2. External JSON/YAML (CI/CD):**
361
+ #### Template Composition Helpers
181
362
 
182
- ```bash
183
- # Load from Vault during CI
184
- vault kv get -format=json secret/app/env | jq '.data.data' > env-config.json
185
- pnpm run synth
363
+ Use these helpers for template definitions and inclusions:
364
+
365
+ ```typescript
366
+ import { helmInclude, helmDefine, helmFragment } from 'timonel';
367
+
368
+ // Template inclusion with pipe
369
+ const labels = helmInclude('chart.labels', '.', { pipe: 'nindent 4' });
370
+
371
+ // Define a named template
372
+ const myTemplate = helmDefine('myapp.config', {
373
+ key: 'value',
374
+ });
375
+
376
+ // Combine multiple constructs
377
+ const combined = helmFragment(helmInclude('chart.labels', '.'), { customKey: 'customValue' });
186
378
  ```
187
379
 
188
- **3. Generated Templates:**
380
+ #### Legacy Flow Control (NOT RECOMMENDED)
381
+
382
+ **āš ļø These are legacy and NOT RECOMMENDED. Use ValuesRef system (v.if, v.range, v.with)
383
+ instead:**
189
384
 
190
- ```yaml
191
- # Value variables
192
- - name: VERSION
193
- value: { { .Values.global.env.VERSION | default "1.0.0" } }
385
+ ```typescript
386
+ // āŒ OLD WAY - string-based valuesRef (no type safety)
387
+ const oldRef = valuesRef('.Values.production');
194
388
 
195
- # Secret variables
196
- - name: DATABASE_URL
197
- valueFrom:
198
- secretKeyRef:
199
- name: app-secrets
200
- key: DATABASE_URL
201
- optional: true
389
+ // āœ… NEW WAY - ValuesRef system (type-safe)
390
+ const v = valuesRef<MyValues>();
391
+ const newRef = v.production; // {{ .Values.production }}
392
+
393
+ // āŒ OLD WAY - helmIf, helmRange, helmWith (string-based)
394
+ const config = helmIf('.Values.production', { replicas: 5 }, { replicas: 1 });
395
+
396
+ // āœ… NEW WAY - v.if(), v.range(), v.with() (type-safe)
397
+ const config = v.if(v.production, { replicas: 5 });
202
398
  ```
203
399
 
400
+ **Why ValuesRef is Better:**
401
+
402
+ - āœ… **100% Type-Safe** - Catch errors at compile time with TypeScript generics
403
+ - āœ… **No Raw Strings** - Eliminate manual template interpolation and typos
404
+ - āœ… **Full IDE Support** - Autocomplete, type hints, and refactoring support
405
+ - āœ… **Proxy-based** - Chainable methods for complex logic
406
+ - āœ… **Composable** - Nest and combine operations naturally
407
+ - āŒ **Legacy helpers** - String-based, error-prone, no IDE support
408
+
409
+ **Migration:** Replace `valuesRef(path)` with `v.path`. Replace `helmIf`, `helmRange`, `helmWith`
410
+ with `v.if()`, `v.range()`, `v.with()`.
411
+
412
+ **Learn more:** See the
413
+ [Type-Safe Helm Helpers Guide](https://github.com/KenkoGeek/timonel/wiki/Helm-Helpers-System) for
414
+ complete documentation, examples, and best practices.
415
+
416
+ ## šŸ” Policy Engine
417
+
418
+ The Policy Engine provides extensible validation for Kubernetes manifests through a
419
+ plugin-based architecture. It's completely optional and has zero impact on existing users.
420
+
421
+ ### Key Features
422
+
423
+ - **šŸ”Œ Plugin Architecture**: Extensible through external npm packages
424
+ - **⚔ Zero Impact**: Completely optional with no performance overhead when unused
425
+ - **šŸ›”ļø Security Focus**: Built-in support for security and compliance policies
426
+ - **šŸ”„ Async Support**: Handles both synchronous and asynchronous validation plugins
427
+ - **šŸ“Š Rich Reporting**: Detailed violation reports with suggestions and context
428
+ - **ā±ļø Timeout Protection**: Configurable timeouts prevent hanging validations
429
+ - **šŸ”§ Configurable**: Environment-specific policy configuration support
430
+ - **šŸš€ Performance Optimized**: Parallel execution, caching, and resource monitoring
431
+ - **šŸ”„ Error Resilience**: Graceful degradation and retry mechanisms
432
+ - **šŸ“ˆ Observability**: Structured logging and performance metrics
433
+
434
+ ### Quick Start
435
+
204
436
  ```typescript
205
- import { Rutter, helmInclude, createHelmExpression as helm } from 'timonel';
437
+ import { Rutter, PolicyEngine } from 'timonel';
438
+
439
+ // Optional: Add policy validation
440
+ const policyEngine = new PolicyEngine({
441
+ timeout: 10000,
442
+ parallel: true,
443
+ gracefulDegradation: true,
444
+ });
445
+
446
+ // Register plugins
447
+ await policyEngine.use(await import('@mycompany/security-policies'));
448
+ await policyEngine.use(await import('@kubernetes/best-practices'));
206
449
 
207
450
  const chart = new Rutter({
208
- meta: {
209
- name: 'web-app',
210
- version: '1.0.0',
211
- description: 'Simple web application',
212
- },
213
- defaultValues: {
214
- replicas: 3,
215
- image: {
216
- repository: 'nginx',
217
- tag: 'latest',
218
- },
219
- },
451
+ meta: { name: 'my-app', version: '1.0.0' },
452
+ policyEngine, // ← Completely optional
220
453
  });
221
454
 
222
- // Add Deployment with type-safe helpers
223
- chart.addManifest(
224
- {
225
- apiVersion: 'apps/v1',
226
- kind: 'Deployment',
227
- metadata: {
228
- name: helmInclude('chart.fullname', '.'),
229
- labels: helmInclude('chart.labels', '.', { pipe: 'nindent 4' }),
455
+ chart.write('./dist'); // Validates before writing
456
+ ```
457
+
458
+ ### Available Policy Plugins
459
+
460
+ **Built-in Examples:**
461
+
462
+ - **Security Plugin** - Comprehensive security validation (security contexts, RBAC, network policies)
463
+ - **Best Practices Plugin** - Kubernetes best practices (resource limits, naming, probes)
464
+ - **AWS Plugin** - AWS-specific validations (EKS, ALB, IRSA, cost optimization)
465
+
466
+ **Community Plugins:**
467
+
468
+ - `@kubernetes/pod-security-standards` - Official Kubernetes PSS validation
469
+ - `@open-policy-agent/timonel-plugin` - OPA Rego policy integration
470
+ - `@falco/security-policies` - Falco runtime security rules
471
+
472
+ **Enterprise Plugins:**
473
+
474
+ - `@company/compliance-policies` - Organization-specific compliance rules
475
+ - `@aws/well-architected-policies` - AWS Well-Architected Framework validation
476
+ - `@security/cis-benchmarks` - CIS Kubernetes Benchmark validation
477
+
478
+ ### Creating Custom Policies
479
+
480
+ ```typescript
481
+ import { PolicyPlugin, PolicyViolation, ValidationContext } from 'timonel';
482
+
483
+ export const customSecurityPolicy: PolicyPlugin = {
484
+ name: 'custom-security-policy',
485
+ version: '1.0.0',
486
+ description: 'Custom security validation rules',
487
+
488
+ // Optional: Configuration schema for validation
489
+ configSchema: {
490
+ type: 'object',
491
+ properties: {
492
+ strictMode: { type: 'boolean', default: false },
493
+ allowedNamespaces: { type: 'array', items: { type: 'string' } },
230
494
  },
231
- spec: {
232
- replicas: helm('{{ .Values.replicas }}'),
233
- selector: {
234
- matchLabels: helmInclude('chart.selectorLabels', '.', { pipe: 'nindent 6' }),
235
- },
236
- template: {
237
- metadata: {
238
- labels: helmInclude('chart.selectorLabels', '.', { pipe: 'nindent 8' }),
239
- },
240
- spec: {
241
- containers: [
242
- {
243
- name: 'web',
244
- image: helm('{{ .Values.image.repository }}:{{ .Values.image.tag }}'),
245
- ports: [{ containerPort: 80, name: 'http' }],
495
+ },
496
+
497
+ async validate(manifests: unknown[], context: ValidationContext): Promise<PolicyViolation[]> {
498
+ const violations: PolicyViolation[] = [];
499
+ const config = context.config as { strictMode?: boolean; allowedNamespaces?: string[] };
500
+
501
+ for (const manifest of manifests) {
502
+ if (manifest.kind === 'Deployment') {
503
+ // Validate security context
504
+ if (!manifest.spec?.template?.spec?.securityContext) {
505
+ violations.push({
506
+ plugin: this.name,
507
+ severity: config?.strictMode ? 'error' : 'warning',
508
+ message: 'Deployment should specify securityContext',
509
+ resourcePath: `${manifest.kind}/${manifest.metadata?.name}`,
510
+ field: 'spec.template.spec.securityContext',
511
+ suggestion: 'Add securityContext with runAsNonRoot: true',
512
+ context: {
513
+ kubernetesVersion: context.kubernetesVersion,
514
+ environment: context.environment,
246
515
  },
247
- ],
248
- },
516
+ });
517
+ }
518
+
519
+ // Validate namespace restrictions
520
+ const namespace = manifest.metadata?.namespace || 'default';
521
+ if (config?.allowedNamespaces && !config.allowedNamespaces.includes(namespace)) {
522
+ violations.push({
523
+ plugin: this.name,
524
+ severity: 'error',
525
+ message: `Deployment in unauthorized namespace: ${namespace}`,
526
+ resourcePath: `${manifest.kind}/${manifest.metadata?.name}`,
527
+ field: 'metadata.namespace',
528
+ suggestion: `Deploy to allowed namespaces: ${config.allowedNamespaces.join(', ')}`,
529
+ });
530
+ }
531
+ }
532
+ }
533
+
534
+ return violations;
535
+ },
536
+ };
537
+ ```
538
+
539
+ ### Advanced Configuration
540
+
541
+ ```typescript
542
+ const policyEngine = new PolicyEngine({
543
+ // Execution settings
544
+ timeout: 15000, // 15 second timeout per plugin
545
+ parallel: true, // Run plugins in parallel for better performance
546
+ failFast: false, // Collect all violations before failing
547
+ gracefulDegradation: true, // Continue on plugin failures
548
+
549
+ // Performance optimization
550
+ cacheOptions: {
551
+ maxSize: 1000, // Cache up to 1000 validation results
552
+ ttl: 300000, // 5 minute cache TTL
553
+ enableStats: true, // Enable cache performance monitoring
554
+ },
555
+
556
+ // Parallel execution tuning
557
+ parallelOptions: {
558
+ maxConcurrency: 4, // Run up to 4 plugins concurrently
559
+ enableResourceMonitoring: true,
560
+ },
561
+
562
+ // Retry configuration
563
+ retryConfig: {
564
+ maxAttempts: 3,
565
+ baseDelay: 1000,
566
+ retryOnTimeout: true,
567
+ retryOnPluginError: false,
568
+ },
569
+
570
+ // Plugin-specific configuration
571
+ pluginConfig: {
572
+ 'security-plugin': {
573
+ strictMode: true,
574
+ allowedNamespaces: ['default', 'kube-system'],
575
+ securityContext: {
576
+ required: true,
577
+ runAsNonRoot: true,
578
+ },
579
+ },
580
+ 'best-practices-plugin': {
581
+ enforceResourceLimits: true,
582
+ requireLabels: ['app', 'version', 'environment'],
583
+ maxReplicas: 50,
584
+ },
585
+ 'aws-plugin': {
586
+ region: 'us-west-2',
587
+ enforceTagging: true,
588
+ costOptimization: {
589
+ enabled: true,
590
+ maxInstanceSize: 'xlarge',
249
591
  },
250
592
  },
251
593
  },
252
- 'deployment',
253
- );
594
+ });
254
595
 
255
- // Generate the chart
256
- chart.write('./dist');
596
+ // Register plugins
597
+ await policyEngine.use(securityPolicies);
598
+ await policyEngine.use(bestPracticesPolicies);
599
+ await policyEngine.use(awsPolicies);
257
600
  ```
258
601
 
259
- ```typescript
260
- import { UmbrellaChartTemplate } from 'timonel';
602
+ ### Environment-Specific Policies
261
603
 
262
- const umbrellaConfig = {
263
- name: 'my-umbrella-app',
264
- version: '1.0.0',
265
- subcharts: [
266
- {
267
- name: 'frontend',
268
- version: '1.0.0',
269
- chart: frontendChartFunction,
270
- },
271
- {
272
- name: 'backend',
273
- version: '1.0.0',
274
- chart: backendChartFunction,
604
+ ```typescript
605
+ // Load different policies based on environment
606
+ const createPolicyEngine = (environment: string) => {
607
+ const engine = new PolicyEngine({
608
+ environment,
609
+ configurationLoader: {
610
+ configurationFiles: ['config/policy-engine.json', `config/environments/${environment}.json`],
275
611
  },
276
- ],
612
+ });
613
+
614
+ // Base security policies for all environments
615
+ await engine.use(baseSecurity);
616
+
617
+ // Environment-specific policies
618
+ switch (environment) {
619
+ case 'production':
620
+ await engine.use(strictSecurity);
621
+ await engine.use(compliancePolicies);
622
+ await engine.use(awsPolicies);
623
+ break;
624
+ case 'staging':
625
+ await engine.use(moderateSecurity);
626
+ await engine.use(awsPolicies);
627
+ break;
628
+ case 'development':
629
+ // Minimal policies for development
630
+ await engine.use(basicSecurity);
631
+ break;
632
+ }
633
+
634
+ return engine;
277
635
  };
636
+ ```
278
637
 
279
- export const umbrella = new UmbrellaChartTemplate(umbrellaConfig);
638
+ ### Integration with CI/CD
639
+
640
+ ```typescript
641
+ // In your CI/CD pipeline
642
+ import { Rutter, PolicyEngine, PolicyEngineError } from 'timonel';
643
+
644
+ const validateChart = async (chartPath: string, environment: string) => {
645
+ const policyEngine = await createPolicyEngine(environment);
646
+
647
+ try {
648
+ const chart = new Rutter({
649
+ meta: { name: 'my-app', version: process.env.VERSION },
650
+ policyEngine,
651
+ });
652
+
653
+ await chart.write(chartPath);
654
+
655
+ // Log validation success with metrics
656
+ const stats = policyEngine.getCacheStats();
657
+ console.log('āœ… Chart validation passed', {
658
+ environment,
659
+ cacheHitRate: stats.hitRate,
660
+ pluginCount: policyEngine.getPluginCount(),
661
+ });
662
+ } catch (error) {
663
+ if (error instanceof PolicyEngineError) {
664
+ console.error('āŒ Policy violations found:');
665
+
666
+ // Group violations by severity
667
+ const errors = error.violations.filter((v) => v.severity === 'error');
668
+ const warnings = error.violations.filter((v) => v.severity === 'warning');
669
+
670
+ if (errors.length > 0) {
671
+ console.error(`\n🚨 Errors (${errors.length}):`);
672
+ errors.forEach((v) => {
673
+ console.error(` • ${v.resourcePath}: ${v.message}`);
674
+ if (v.suggestion) {
675
+ console.error(` šŸ’” ${v.suggestion}`);
676
+ }
677
+ });
678
+ }
679
+
680
+ if (warnings.length > 0) {
681
+ console.warn(`\nāš ļø Warnings (${warnings.length}):`);
682
+ warnings.forEach((v) => {
683
+ console.warn(` • ${v.resourcePath}: ${v.message}`);
684
+ });
685
+ }
686
+
687
+ // Fail CI/CD on errors, but allow warnings
688
+ if (errors.length > 0) {
689
+ process.exit(1);
690
+ }
691
+ } else {
692
+ throw error;
693
+ }
694
+ }
695
+ };
696
+
697
+ // Usage in GitHub Actions, GitLab CI, etc.
698
+ await validateChart('./dist', process.env.ENVIRONMENT || 'development');
280
699
  ```
281
700
 
282
- Timonel provides 9 composable, type-safe helpers for Helm template generation: `helmIf`,
283
- `helmRange`, `helmWith`, `helmInclude`, `helmDefine`, `helmVar`, `helmBlock`, `helmComment`, and
284
- `helmFragment`.
701
+ ### Plugin Ecosystem
285
702
 
286
- **Benefits:**
703
+ The Policy Engine supports a rich ecosystem of plugins for various use cases:
287
704
 
288
- - āœ… 100% Type-Safe - catch errors at compile time
289
- - āœ… No Raw Strings - eliminate manual template interpolation
290
- - āœ… Composable - nest and combine helpers freely
291
- - āœ… Full IDE Support - autocomplete and type hints
705
+ #### Security & Compliance
292
706
 
293
- **Learn more:** See the
294
- [Type-Safe Helm Helpers Guide](https://github.com/KenkoGeek/timonel/wiki/Helm-Helpers-System) for
295
- complete documentation, examples, and best practices.
707
+ - **Pod Security Standards** - Kubernetes PSS validation
708
+ - **CIS Benchmarks** - Center for Internet Security benchmarks
709
+ - **NIST Framework** - NIST Cybersecurity Framework compliance
710
+ - **PCI DSS** - Payment Card Industry compliance
711
+ - **SOC 2** - Service Organization Control 2 compliance
712
+
713
+ #### Cloud Provider Integrations
714
+
715
+ - **AWS Well-Architected** - AWS best practices and cost optimization
716
+ - **Azure Security Center** - Azure-specific security policies
717
+ - **GCP Security Command Center** - Google Cloud security validation
718
+
719
+ #### Development & Operations
720
+
721
+ - **GitOps Policies** - GitOps workflow validation
722
+ - **Resource Optimization** - Cost and performance optimization
723
+ - **Observability** - Monitoring and logging best practices
724
+ - **Backup & Recovery** - Data protection policies
725
+
726
+ #### Creating Plugin Packages
727
+
728
+ ```typescript
729
+ // package.json for a policy plugin
730
+ {
731
+ "name": "@mycompany/k8s-security-policies",
732
+ "version": "1.0.0",
733
+ "description": "Security policies for Kubernetes manifests",
734
+ "main": "dist/index.js",
735
+ "types": "dist/index.d.ts",
736
+ "keywords": ["timonel", "policy", "security", "kubernetes"],
737
+ "peerDependencies": {
738
+ "timonel": "^3.0.0"
739
+ }
740
+ }
741
+
742
+ // src/index.ts
743
+ export { SecurityPlugin } from './security-plugin.js';
744
+ export { CompliancePlugin } from './compliance-plugin.js';
745
+ export type { SecurityConfig, ComplianceConfig } from './types.js';
746
+ ```
747
+
748
+ ### Performance & Monitoring
749
+
750
+ The Policy Engine includes comprehensive performance monitoring:
751
+
752
+ ```typescript
753
+ // Monitor policy engine performance
754
+ const result = await policyEngine.validate(manifests, { name: 'example-chart', version: '1.0.0' });
755
+
756
+ console.log('Validation Performance:', {
757
+ executionTime: result.metadata.executionTime,
758
+ pluginCount: result.metadata.pluginCount,
759
+ manifestCount: result.metadata.manifestCount,
760
+ violationsFound: result.violations.length,
761
+ });
762
+
763
+ // Cache performance monitoring
764
+ const cacheStats = policyEngine.getCacheStats();
765
+ console.log('Cache Performance:', {
766
+ hitRate: cacheStats.hitRate,
767
+ totalHits: cacheStats.hits,
768
+ totalMisses: cacheStats.misses,
769
+ cacheSize: cacheStats.size,
770
+ });
771
+
772
+ // Clear cache when needed
773
+ policyEngine.invalidateCache({ all: true });
774
+ ```
296
775
 
297
776
  ## šŸ“š Documentation
298
777
 
@@ -300,6 +779,14 @@ complete documentation, examples, and best practices.
300
779
  documentation
301
780
  - **[CLI Reference](https://github.com/KenkoGeek/timonel/wiki/CLI-Reference)** - Command-line
302
781
  interface guide
782
+ - **[Policy Engine Guide](https://github.com/KenkoGeek/timonel/wiki/Policy-Engine)** -
783
+ Policy validation and plugin development
784
+ - **[Plugin Development Guide](https://github.com/KenkoGeek/timonel/wiki/Plugin-Development)** -
785
+ Creating custom policy plugins
786
+ - **[Configuration Reference](https://github.com/KenkoGeek/timonel/wiki/Policy-Configuration)** -
787
+ Policy engine configuration options
788
+ - **[Policy Examples](https://github.com/KenkoGeek/timonel/wiki/Policy-Examples)** - Example plugins
789
+ and usage patterns
303
790
  - **[Examples](https://github.com/KenkoGeek/timonel/wiki/Examples)** - Real-world usage examples
304
791
  - **[Best Practices](https://github.com/KenkoGeek/timonel/wiki/Best-Practices)** - Recommended
305
792
  patterns and practices
@@ -324,10 +811,10 @@ If you get `Error: Cannot find module 'cdk8s'` when running `tl umbrella synth`:
324
811
  "version": "1.0.0",
325
812
  "type": "module",
326
813
  "dependencies": {
327
- "cdk8s": "^2.70.16",
328
- "cdk8s-plus-33": "^2.3.8",
329
- "constructs": "^10.4.2",
330
- "timonel": "^2.11.0"
814
+ "cdk8s": "^2.70.28",
815
+ "cdk8s-plus-33": "^2.4.6",
816
+ "constructs": "^10.4.3",
817
+ "timonel": "^3.0.0-beta.1"
331
818
  },
332
819
  "devDependencies": {
333
820
  "@types/node": "^24.5.2",
@@ -362,7 +849,7 @@ MIT
362
849
  [security-url]: SECURITY.md
363
850
  [pnpm-badge]: https://img.shields.io/badge/pm-pnpm-ffd95a?logo=pnpm&logoColor=fff&labelColor=24292e
364
851
  [pnpm-url]: https://pnpm.io/
365
- [node-badge]: https://img.shields.io/badge/node-%3E%3D20-339933?logo=node.js&logoColor=fff
852
+ [node-badge]: https://img.shields.io/badge/node-%3E%3D22-339933?logo=node.js&logoColor=fff
366
853
  [node-url]: https://nodejs.org/
367
854
  [ts-badge]: https://img.shields.io/badge/TypeScript-5.x-3178C6?logo=typescript&logoColor=fff
368
855
  [ts-url]: https://www.typescriptlang.org/