@tamyla/clodo-framework 4.5.1 → 4.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ # [4.6.0](https://github.com/tamylaa/clodo-framework/compare/v4.5.1...v4.6.0) (2026-02-18)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * **config:** add Zod schema validation for CLI config files ([3c25c88](https://github.com/tamylaa/clodo-framework/commit/3c25c88626fa5e4bc48c874a25ff89b8f75fb236))
7
+ * **secrets:** integrate secret scanning CLI with existing SecretGenerator infrastructure ([f72f70f](https://github.com/tamylaa/clodo-framework/commit/f72f70f8fd3a0dd8da552c15e8b34bc459584870))
8
+
9
+
10
+ ### Features
11
+
12
+ * **doctor:** implement clodo doctor command with token scope validation, secrets baseline scanning, and comprehensive test stabilization ([9b1fe00](https://github.com/tamylaa/clodo-framework/commit/9b1fe00f77bd7167cb8c836637caae68b9e8cd1c))
13
+
1
14
  ## [4.5.1](https://github.com/tamylaa/clodo-framework/compare/v4.5.0...v4.5.1) (2026-02-11)
2
15
 
3
16
 
@@ -5,6 +18,14 @@
5
18
 
6
19
  * resolve e2e test failures for validate and deploy commands ([97fd564](https://github.com/tamylaa/clodo-framework/commit/97fd5648211d13f46004b9e69c9b6face546d86d))
7
20
 
21
+ ### Features (post-4.5.1)
22
+
23
+ * **doctor**: add `clodo-service doctor` preflight command — automated environment, dependency, and connectivity checks before deployment. Integrates with deploy via `--skip-doctor` / `--doctor-strict` flags. ([f72f70f](https://github.com/tamylaa/clodo-framework/commit/f72f70f))
24
+
25
+ * **secrets**: add `clodo-service secrets` command — source code secret scanning with 15+ built-in patterns (AWS, Stripe, GitHub, JWT, etc.), baseline management (`baseline show`/`baseline update`), and `SecretsManager` programmatic API. 42 unit + 19 E2E tests. ([f72f70f](https://github.com/tamylaa/clodo-framework/commit/f72f70f))
26
+
27
+ * **config**: add `clodo-service config-schema` command — Zod-powered schema validation for all CLI config files (create, deploy, validate, update). Includes `show`, `validate`, `types` subcommands, semantic warnings (env var placeholders, duplicate features, production without security). `ConfigSchemaValidator` programmatic API. 77 unit + 21 E2E tests. ([3c25c88](https://github.com/tamylaa/clodo-framework/commit/3c25c88))
28
+
8
29
  # [4.5.0](https://github.com/tamylaa/clodo-framework/compare/v4.4.1...v4.5.0) (2026-02-11)
9
30
 
10
31
 
package/README.md CHANGED
@@ -7,7 +7,7 @@
7
7
  **Framework Status: ✅ VALIDATED & PRODUCTION-READY**
8
8
  **Validation: 10/10 Phases Passed**
9
9
  **Service Generation: 28+ Files Per Service**
10
- **Test Coverage:** (Latest CI run 2026-02-04) — **115 test suites passed; 4 tests skipped; 2113 passed, 2117 total**
10
+ **Test Coverage:** (Latest CI run 2026-02-18) — **124 test suites passed; 1 skipped; 2328 passed, 2352 total**
11
11
 
12
12
  A comprehensive framework for building enterprise-grade software architecture on Cloudflare Workers + D1. This framework enables rapid development of autonomous, domain-specific services while maintaining consistency and reusability across your entire ecosystem.
13
13
 
@@ -234,11 +234,23 @@ const zones = await api.listZones();
234
234
  Run framework commands in your terminal:
235
235
 
236
236
  ```bash
237
+ # Create a new service
238
+ clodo-service create
239
+
237
240
  # Deploy your service
238
241
  clodo-service deploy
239
242
 
240
- # Create a new service
241
- clodo-create-service my-service
243
+ # Validate service configuration
244
+ clodo-service validate
245
+
246
+ # Preflight health checks before deployment
247
+ clodo-service doctor
248
+
249
+ # Scan for leaked secrets
250
+ clodo-service secrets scan
251
+
252
+ # Validate config files against schemas
253
+ clodo-service config-schema validate clodo-deploy.json
242
254
 
243
255
  # Security auditing
244
256
  clodo-security audit
@@ -293,7 +305,7 @@ clodo-framework/
293
305
  │ ├── analysis/ # Technical analysis
294
306
  │ └── licensing/ # License information
295
307
  ├── src/ # 💻 Source code
296
- ├── test/ # ✅ Test suites (Latest CI: 115 suites; 2113 tests passed, 4 skipped)
308
+ ├── test/ # ✅ Test suites (Latest CI: 124 suites; 2328 tests passed, 24 skipped)
297
309
  ├── cli/ # 🔧 CLI tools & commands
298
310
  ├── examples/ # 📚 Usage examples & demos
299
311
  ├── config/ # ⚙️ Configuration files & examples
@@ -311,7 +323,7 @@ clodo-framework/
311
323
  ```
312
324
 
313
325
  **Quality Metrics:**
314
- - ✅ **Latest CI (2026-02-04): 115 test suites passed; 4 tests skipped; 2113/2117 tests passed**
326
+ - ✅ **Latest CI (2026-02-18): 124 test suites passed; 1 skipped; 2328/2352 tests passed**
315
327
  - ✅ **CLI tests:** passing (all CLI-specific tests passed in the latest run)
316
328
  - ✅ **Clean architecture** (organized file structure, no clutter in root)
317
329
  - ✅ **Configuration-based** (no hard-coded values in source)
@@ -369,6 +381,15 @@ npx @tamyla/clodo-framework security generate-key api content-skimmer
369
381
  # Validate configuration security
370
382
  npx @tamyla/clodo-framework security validate customer production
371
383
 
384
+ # Scan source code for leaked secrets
385
+ clodo-service secrets scan
386
+
387
+ # Validate secrets against baseline
388
+ clodo-service secrets validate
389
+
390
+ # Run preflight security checks
391
+ clodo-service doctor
392
+
372
393
  # Deploy with automatic security validation
373
394
  npx @tamyla/clodo-framework security deploy customer production
374
395
  ```
@@ -388,6 +409,9 @@ npx @tamyla/clodo-framework security deploy customer production
388
409
  - ✅ **🔒 Security Validation Framework**: Automated security validation and deployment blocking
389
410
  - ✅ **🛡️ Cryptographic Key Generation**: Secure API key and JWT secret generation
390
411
  - ✅ **🚫 Deployment Security**: Pre-deployment validation that blocks insecure configurations
412
+ - ✅ **🩺 Doctor / Preflight Checks**: Automated environment, dependency, and connectivity validation before deploy
413
+ - ✅ **🔍 Secret Scanning & Baseline**: Detect leaked secrets in source code with baseline management
414
+ - ✅ **📋 Config Schema Validation**: Zod-powered schema validation for all CLI config files (create, deploy, validate, update)
391
415
  - ✅ **👥 Customer Configuration Management**: Multi-environment, multi-customer configuration system
392
416
  - ✅ **🏗️ Template-Based Customer Onboarding**: Automated customer setup from reusable templates
393
417
  - ✅ **🔗 Framework Integration**: Customer configs integrate with domain and feature flag systems
@@ -404,6 +428,9 @@ npx @tamyla/clodo-framework security deploy customer production
404
428
  - **🔒 Security-by-Default**: Automatic detection and prevention of insecure configurations
405
429
  - **🛡️ Production Security**: Environment-specific security requirements and validation
406
430
  - **🔐 Cryptographic Utilities**: Secure key generation and secret management
431
+ - **🩺 Doctor / Preflight**: Automated pre-deployment environment checks with `--skip-doctor` / `--doctor-strict` flags
432
+ - **🔍 Secret Scanning**: Source code secret detection, pattern matching, and baseline management
433
+ - **📋 Config Schema Validation**: Zod schemas for all config file types with semantic warnings
407
434
  - **Production Testing**: Health checks, authentication flows, performance monitoring
408
435
  - **Audit & Compliance**: Detailed deployment logging and reporting
409
436
  - **👥 Customer Configuration Management**: Multi-environment customer isolation and management
@@ -413,10 +440,84 @@ npx @tamyla/clodo-framework security deploy customer production
413
440
  - **⚡ Performance Optimized**: Intelligent caching system for schemas, SQL queries, and validation results
414
441
  - **🔄 Advanced Data Operations**: Enhanced CRUD with relationships, advanced pagination, and query optimization
415
442
 
416
- ## 🎉 What's New in v2.0.7
443
+ ## 🎉 What's New in v4.5.x
444
+
445
+ ### 🩺 Doctor / Preflight Command (v4.5.x)
446
+ Run comprehensive pre-deployment health checks to catch issues before they reach production:
447
+
448
+ ```bash
449
+ # Run all preflight checks
450
+ clodo-service doctor
451
+
452
+ # Skip doctor during deploy
453
+ clodo-service deploy --skip-doctor
454
+
455
+ # Fail deploy on doctor warnings
456
+ clodo-service deploy --doctor-strict
457
+ ```
458
+
459
+ **Checks performed:**
460
+ - ✅ Node.js version compatibility
461
+ - ✅ Required dependencies installed (wrangler, etc.)
462
+ - ✅ Environment variables set
463
+ - ✅ Cloudflare API connectivity
464
+ - ✅ Config file schema validation
465
+ - ✅ Secret baseline compliance
466
+
467
+ ### 🔍 Secret Scanning & Baseline Management (v4.5.x)
468
+ Detect leaked secrets in your codebase before they reach version control:
469
+
470
+ ```bash
471
+ # Scan for secrets in source code
472
+ clodo-service secrets scan [directory]
473
+
474
+ # Validate against a known baseline
475
+ clodo-service secrets validate
476
+
477
+ # Show current baseline
478
+ clodo-service secrets baseline show
479
+
480
+ # Update baseline after review
481
+ clodo-service secrets baseline update
482
+
483
+ # List known secret patterns
484
+ clodo-service secrets patterns
485
+ ```
486
+
487
+ **Features:**
488
+ - 15+ built-in secret patterns (AWS, Stripe, GitHub, JWT, etc.)
489
+ - Baseline management for known/accepted findings
490
+ - Integration with doctor preflight checks
491
+ - Programmatic API via `SecretsManager`
492
+
493
+ ### 📋 Config Schema Validation (v4.5.x)
494
+ Validate your CLI config files against Zod schemas with semantic warnings:
495
+
496
+ ```bash
497
+ # Validate a config file
498
+ clodo-service config-schema validate clodo-deploy.json
499
+
500
+ # Strict mode (exit code 1 on any error)
501
+ clodo-service config-schema validate clodo-create.json --strict
502
+
503
+ # Show schema for a config type
504
+ clodo-service config-schema show deploy
505
+
506
+ # List all supported config types
507
+ clodo-service config-schema types
508
+ ```
509
+
510
+ **Supported config types:** `create`, `deploy`, `validate`, `update`
511
+
512
+ **Semantic warnings detect:**
513
+ - Environment variable placeholders left in values
514
+ - Duplicate features
515
+ - Production configs without security features
516
+ - Missing backup strategy with migrations enabled
517
+ - Name mismatches between config fields
417
518
 
418
519
  ### 🔧 Enhanced Customer Configuration System
419
- The customer configuration CLI now **reads directly from your wrangler.toml** file, providing a single source of truth for deployment configuration:
520
+ The customer configuration CLI **reads directly from your wrangler.toml** file, providing a single source of truth for deployment configuration:
420
521
 
421
522
  ```bash
422
523
  # List all customers with complete deployment metadata
@@ -1200,15 +1301,58 @@ npx clodo-db sync --portfolio
1200
1301
  npx clodo-db backup my-domain
1201
1302
  ```
1202
1303
 
1203
- #### `clodo-secrets` - Secret Generation Utility
1204
- Cryptographically secure secret generation for production deployments.
1304
+ #### `clodo-secrets` - Secret Scanning & Baseline Management
1305
+ Detect leaked secrets in source code and manage baselines for known findings.
1205
1306
 
1206
1307
  ```bash
1207
- # Generate secrets for domain
1208
- npx clodo-secrets --domain my-domain --environment production
1308
+ # Scan current directory for secrets
1309
+ clodo-service secrets scan
1310
+
1311
+ # Scan a specific directory
1312
+ clodo-service secrets scan ./src
1313
+
1314
+ # Validate against baseline
1315
+ clodo-service secrets validate
1316
+
1317
+ # Show current baseline
1318
+ clodo-service secrets baseline show
1319
+
1320
+ # Update baseline after review
1321
+ clodo-service secrets baseline update
1322
+
1323
+ # List known secret patterns
1324
+ clodo-service secrets patterns
1325
+ ```
1326
+
1327
+ #### `clodo doctor` - Preflight Health Checks
1328
+ Run comprehensive environment and configuration checks before deployment.
1329
+
1330
+ ```bash
1331
+ # Run all checks
1332
+ clodo-service doctor
1333
+
1334
+ # Skip during deploy
1335
+ clodo-service deploy --skip-doctor
1336
+
1337
+ # Strict mode (fail on warnings)
1338
+ clodo-service deploy --doctor-strict
1339
+ ```
1340
+
1341
+ #### `clodo config-schema` - Config File Validation
1342
+ Validate CLI config files against Zod schemas with semantic analysis.
1343
+
1344
+ ```bash
1345
+ # Validate a config file
1346
+ clodo-service config-schema validate clodo-deploy.json
1347
+
1348
+ # Show schema for a config type
1349
+ clodo-service config-schema show create
1350
+
1351
+ # List all supported config types
1352
+ clodo-service config-schema types
1209
1353
 
1210
- # Generate specific secret types
1211
- npx clodo-secrets --types database,api-keys,jwt --persist
1354
+ # Strict mode
1355
+ clodo-service config-schema validate config.json --strict
1212
1356
  ```
1213
1357
 
1214
1358
  ## Quick Start
@@ -14,6 +14,7 @@
14
14
  * - diagnose Diagnose and report issues with an existing service
15
15
  * - assess Run intelligent capability assessment
16
16
  * - list-types List available service types and their features
17
+ * - secrets Secret scanning and baseline management for leak prevention
17
18
  */
18
19
  import { Command } from 'commander';
19
20
  import { join, dirname } from 'path';
@@ -51,6 +52,10 @@ async function registerAvailableCommands() {
51
52
  name: 'diagnose',
52
53
  path: pathToFileURL(join(commandsDir, 'diagnose.js')).href,
53
54
  register: 'registerDiagnoseCommand'
55
+ }, {
56
+ name: 'doctor',
57
+ path: pathToFileURL(join(commandsDir, 'doctor.js')).href,
58
+ register: 'registerDoctorCommand'
54
59
  }, {
55
60
  name: 'assess',
56
61
  path: pathToFileURL(join(commandsDir, 'assess.js')).href,
@@ -59,6 +64,14 @@ async function registerAvailableCommands() {
59
64
  name: 'init-config',
60
65
  path: pathToFileURL(join(commandsDir, 'init-config.js')).href,
61
66
  register: 'registerInitConfigCommand'
67
+ }, {
68
+ name: 'secrets',
69
+ path: pathToFileURL(join(commandsDir, 'secrets.js')).href,
70
+ register: 'registerSecretsCommand'
71
+ }, {
72
+ name: 'config-schema',
73
+ path: pathToFileURL(join(commandsDir, 'config-schema.js')).href,
74
+ register: 'registerConfigSchemaCommand'
62
75
  }];
63
76
  for (const cmd of commands) {
64
77
  try {
@@ -0,0 +1,144 @@
1
+ /**
2
+ * Config Schema CLI Command
3
+ * Provides schema inspection, validation, and documentation for config files
4
+ *
5
+ * Subcommands:
6
+ * clodo config-schema show <type> - Show schema for a command type
7
+ * clodo config-schema validate <file> - Validate a config file
8
+ * clodo config-schema types - List all config types
9
+ */
10
+
11
+ import chalk from 'chalk';
12
+ import { readFileSync } from 'fs';
13
+ import { ConfigSchemaValidator } from '../../src/validation/ConfigSchemaValidator.js';
14
+ export function registerConfigSchemaCommand(program) {
15
+ const cmd = program.command('config-schema').description('Inspect and validate configuration file schemas');
16
+
17
+ // ─── show ──────────────────────────────────────────────────────────────
18
+ cmd.command('show <type>').description('Show the schema definition for a config type (create, deploy, validate, update)').option('--json', 'Output as JSON').action((type, options) => {
19
+ const validator = new ConfigSchemaValidator();
20
+ const definition = validator.getSchemaDefinition(type);
21
+ if (!definition) {
22
+ console.error(chalk.red(`Unknown config type: '${type}'`));
23
+ console.log(`Valid types: ${validator.getRegisteredTypes().join(', ')}`);
24
+ process.exit(1);
25
+ }
26
+ if (options.json) {
27
+ console.log(JSON.stringify(definition, null, 2));
28
+ return;
29
+ }
30
+ console.log(chalk.cyan(`\n📋 Config Schema: ${type}`));
31
+ console.log(chalk.gray('═'.repeat(60)));
32
+ console.log(chalk.white(definition.description));
33
+ console.log('');
34
+ console.log(chalk.bold('Fields:'));
35
+ for (const [name, field] of Object.entries(definition.fields)) {
36
+ const required = field.required ? chalk.red('*') : ' ';
37
+ const type = chalk.gray(`(${field.type})`);
38
+ console.log(` ${required} ${chalk.white(name)} ${type}`);
39
+ if (field.description) {
40
+ console.log(` ${chalk.gray(field.description)}`);
41
+ }
42
+ }
43
+ console.log('');
44
+ console.log(chalk.bold('Valid Service Types:'));
45
+ console.log(` ${definition.validServiceTypes.join(', ')}`);
46
+ console.log('');
47
+ console.log(chalk.bold('Valid Features:'));
48
+ console.log(` ${definition.validFeatures.join(', ')}`);
49
+ console.log('');
50
+ console.log(chalk.gray(`Total fields: ${definition.fieldCount}`));
51
+ console.log(chalk.gray(`Usage: npx clodo-service ${type} --config-file your-config.json`));
52
+ });
53
+
54
+ // ─── validate ──────────────────────────────────────────────────────────
55
+ cmd.command('validate <file>').description('Validate a config file against its schema').option('--type <type>', 'Config type (auto-detected if not specified)').option('--strict', 'Exit with error code on validation failures').option('--json', 'Output as JSON').action((file, options) => {
56
+ const validator = new ConfigSchemaValidator();
57
+
58
+ // Determine command type
59
+ let commandType = options.type;
60
+ if (!commandType) {
61
+ // Try to auto-detect from filename or content
62
+ const filenameLower = file.toLowerCase();
63
+ if (filenameLower.includes('create')) commandType = 'create';else if (filenameLower.includes('deploy')) commandType = 'deploy';else if (filenameLower.includes('validate')) commandType = 'validate';else if (filenameLower.includes('update')) commandType = 'update';else {
64
+ // Try content-based detection
65
+ try {
66
+ const content = JSON.parse(readFileSync(file, 'utf8'));
67
+ const detection = validator.detectConfigType(content);
68
+ if (detection.detected) {
69
+ commandType = detection.commandType;
70
+ if (!options.json) {
71
+ console.log(chalk.gray(`Auto-detected config type: ${commandType} (confidence: ${Math.round(detection.confidence * 100)}%)`));
72
+ }
73
+ }
74
+ } catch {
75
+ // Fall through
76
+ }
77
+ }
78
+ if (!commandType) {
79
+ console.error(chalk.red('Could not detect config type. Use --type to specify.'));
80
+ console.log(`Valid types: ${validator.getRegisteredTypes().join(', ')}`);
81
+ process.exit(1);
82
+ }
83
+ }
84
+ const result = validator.validateConfigFile(file, commandType);
85
+ if (options.json) {
86
+ console.log(JSON.stringify(result, null, 2));
87
+ } else {
88
+ console.log(chalk.cyan(`\n🔍 Config Validation: ${file}`));
89
+ console.log(chalk.gray(`Type: ${commandType}`));
90
+ console.log(chalk.gray('═'.repeat(60)));
91
+ if (result.valid) {
92
+ console.log(chalk.green(`✅ Valid configuration (${result.fieldCount} fields)`));
93
+ } else {
94
+ console.log(chalk.red(`❌ Invalid configuration — ${result.errors.length} error(s)`));
95
+ }
96
+ if (result.errors.length > 0) {
97
+ console.log('');
98
+ console.log(chalk.bold('Errors:'));
99
+ for (const err of result.errors) {
100
+ console.log(chalk.red(` ✗ ${err.field}: ${err.message}`));
101
+ }
102
+ }
103
+ if (result.warnings.length > 0) {
104
+ console.log('');
105
+ console.log(chalk.bold('Warnings:'));
106
+ for (const warn of result.warnings) {
107
+ console.log(chalk.yellow(` ⚠ ${warn.field}: ${warn.message}`));
108
+ }
109
+ }
110
+ }
111
+
112
+ // Exit with error code for file-level errors (always) or validation errors (when --strict)
113
+ if (!result.valid) {
114
+ const hasFileError = result.errors.some(e => e.code === 'FILE_NOT_FOUND' || e.code === 'INVALID_JSON');
115
+ if (hasFileError || options.strict) {
116
+ process.exit(1);
117
+ }
118
+ }
119
+ });
120
+
121
+ // ─── types ─────────────────────────────────────────────────────────────
122
+ cmd.command('types').description('List all available config types').option('--json', 'Output as JSON').action(options => {
123
+ const validator = new ConfigSchemaValidator();
124
+ const types = validator.getRegisteredTypes();
125
+ if (options.json) {
126
+ const details = {};
127
+ for (const type of types) {
128
+ details[type] = validator.getSchemaDefinition(type);
129
+ }
130
+ console.log(JSON.stringify(details, null, 2));
131
+ return;
132
+ }
133
+ console.log(chalk.cyan('\n📋 Available Config Types'));
134
+ console.log(chalk.gray('═'.repeat(60)));
135
+ for (const type of types) {
136
+ const def = validator.getSchemaDefinition(type);
137
+ console.log(` ${chalk.white(type)} — ${def.fieldCount} fields`);
138
+ console.log(chalk.gray(` Example: config/clodo-${type}.example.json`));
139
+ console.log(chalk.gray(` Usage: npx clodo-service ${type} --config-file config.json`));
140
+ }
141
+ console.log('');
142
+ console.log(chalk.gray('Run `clodo config-schema show <type>` for detailed field info'));
143
+ });
144
+ }
@@ -8,6 +8,7 @@
8
8
  import chalk from 'chalk';
9
9
  import { Clodo, ConfigLoader } from '@tamyla/clodo-framework';
10
10
  import { StandardOptions } from '../../lib/shared/utils/cli-options.js';
11
+ import { ConfigSchemaValidator } from '../../src/validation/ConfigSchemaValidator.js';
11
12
  export function registerCreateCommand(program) {
12
13
  const command = program.command('create').description('Create a new Clodo service with conversational setup').option('-n, --non-interactive', 'Run in non-interactive mode with all required parameters').option('--service-name <name>', 'Service name (required in non-interactive mode)').option('--service-type <type>', 'Service type: data-service, auth-service, content-service, api-gateway, generic', 'generic').option('--domain-name <domain>', 'Domain name (required in non-interactive mode)').option('--cloudflare-token <token>', 'Cloudflare API token (required in non-interactive mode)').option('--cloudflare-account-id <id>', 'Cloudflare account ID (required in non-interactive mode)').option('--cloudflare-zone-id <id>', 'Cloudflare zone ID (required in non-interactive mode)').option('--environment <env>', 'Target environment: development, staging, production', 'development').option('--output-path <path>', 'Output directory for generated service', '.').option('--template-path <path>', 'Path to service templates', './templates').option('--middleware-strategy <strategy>', 'Middleware generation strategy: contract|legacy', 'contract').option('--force', 'Skip confirmation prompts').option('--validate', 'Validate service after creation');
13
14
 
@@ -21,10 +22,26 @@ export function registerCreateCommand(program) {
21
22
  json: options.json
22
23
  });
23
24
 
24
- // Load config from file if specified
25
+ // Load config from file if specified (with schema validation)
25
26
  let configFileData = {};
26
27
  if (options.configFile) {
27
28
  configFileData = configLoader.loadSafe(options.configFile, {});
29
+ // Validate against create schema
30
+ const schemaValidator = new ConfigSchemaValidator({
31
+ verbose: options.verbose
32
+ });
33
+ const validation = schemaValidator.validateConfig(configFileData, 'create');
34
+ if (!validation.valid && options.verbose) {
35
+ output.warning(`Config file has ${validation.errors.length} schema validation issue(s):`);
36
+ for (const err of validation.errors) {
37
+ output.warning(` ${err.field}: ${err.message}`);
38
+ }
39
+ }
40
+ if (validation.warnings.length > 0 && options.verbose) {
41
+ for (const warn of validation.warnings) {
42
+ output.info(` ⚠ ${warn.field}: ${warn.message}`);
43
+ }
44
+ }
28
45
  if (options.verbose && !options.quiet) {
29
46
  output.info(`Loaded configuration from: ${options.configFile}`);
30
47
  }
@@ -1,10 +1,11 @@
1
1
  import chalk from 'chalk';
2
2
  import { Clodo, ConfigLoader, InteractiveDeploymentCoordinator, OutputFormatter } from '@tamyla/clodo-framework';
3
3
  import { StandardOptions } from '../../lib/shared/utils/cli-options.js';
4
+ import { ConfigSchemaValidator } from '../../src/validation/ConfigSchemaValidator.js';
4
5
  export function registerDeployCommand(program) {
5
6
  const command = program.command('deploy').description('Deploy a Clodo service with interactive configuration and validation')
6
7
  // Cloudflare-specific options
7
- .option('--token <token>', 'Cloudflare API token (or set CLOUDFLARE_API_TOKEN env var)').option('--account-id <id>', 'Cloudflare account ID (or set CLOUDFLARE_ACCOUNT_ID env var)').option('--zone-id <id>', 'Cloudflare zone ID (or set CLOUDFLARE_ZONE_ID env var)').option('--domain <domain>', 'Specific domain to deploy to').option('--service-name <name>', 'Service name for URL generation (e.g., data-service, auth-service)', 'data-service').option('--environment <env>', 'Target environment (development, staging, production)', 'production').option('--development', 'Deploy to development environment (shorthand for --environment development)').option('--staging', 'Deploy to staging environment (shorthand for --environment staging)').option('--production', 'Deploy to production environment (shorthand for --environment production)').option('--dry-run', 'Simulate deployment without making changes').option('-y, --yes', 'Skip confirmation prompts (for CI/CD)').option('--service-path <path>', 'Path to service directory', '.').option('--check-prereqs', 'Check deployment prerequisites before starting').option('--check-auth', 'Check Wrangler authentication status').option('--check-network', 'Check network connectivity to Cloudflare');
8
+ .option('--token <token>', 'Cloudflare API token (or set CLOUDFLARE_API_TOKEN env var)').option('--account-id <id>', 'Cloudflare account ID (or set CLOUDFLARE_ACCOUNT_ID env var)').option('--zone-id <id>', 'Cloudflare zone ID (or set CLOUDFLARE_ZONE_ID env var)').option('--domain <domain>', 'Specific domain to deploy to').option('--service-name <name>', 'Service name for URL generation (e.g., data-service, auth-service)', 'data-service').option('--environment <env>', 'Target environment (development, staging, production)', 'production').option('--development', 'Deploy to development environment (shorthand for --environment development)').option('--staging', 'Deploy to staging environment (shorthand for --environment staging)').option('--production', 'Deploy to production environment (shorthand for --environment production)').option('--dry-run', 'Simulate deployment without making changes').option('-y, --yes', 'Skip confirmation prompts (for CI/CD)').option('--service-path <path>', 'Path to service directory', '.').option('--check-prereqs', 'Check deployment prerequisites before starting').option('--check-auth', 'Check Wrangler authentication status').option('--check-network', 'Check network connectivity to Cloudflare').option('--skip-doctor', 'Skip preflight doctor checks').option('--doctor-strict', 'Fail deployment if doctor finds warnings (default: fail only on errors)');
8
9
 
9
10
  // Add standard options (--verbose, --quiet, --json, --no-color, --config-file)
10
11
  StandardOptions.define(command).action(async options => {
@@ -25,10 +26,26 @@ export function registerDeployCommand(program) {
25
26
  options.environment = 'production';
26
27
  }
27
28
 
28
- // Load config from file if specified
29
+ // Load config from file if specified (with schema validation)
29
30
  let configFileData = {};
30
31
  if (options.configFile) {
31
32
  configFileData = configLoader.loadSafe(options.configFile, {});
33
+ // Validate against deploy schema
34
+ const schemaValidator = new ConfigSchemaValidator({
35
+ verbose: options.verbose
36
+ });
37
+ const validation = schemaValidator.validateConfig(configFileData, 'deploy');
38
+ if (!validation.valid && options.verbose) {
39
+ output.warning(`Config file has ${validation.errors.length} schema validation issue(s):`);
40
+ for (const err of validation.errors) {
41
+ output.warning(` ${err.field}: ${err.message}`);
42
+ }
43
+ }
44
+ if (validation.warnings.length > 0 && options.verbose) {
45
+ for (const warn of validation.warnings) {
46
+ output.info(` ⚠ ${warn.field}: ${warn.message}`);
47
+ }
48
+ }
32
49
  if (options.verbose && !options.quiet) {
33
50
  output.info(`Loaded configuration from: ${options.configFile}`);
34
51
  }
@@ -37,6 +54,48 @@ export function registerDeployCommand(program) {
37
54
  // Merge config file defaults with CLI options (CLI takes precedence)
38
55
  const mergedOptions = configLoader.merge(configFileData, options);
39
56
 
57
+ // Run doctor preflight checks (unless skipped)
58
+ if (!mergedOptions.skipDoctor) {
59
+ const {
60
+ ValidationHandler
61
+ } = await import('../../src/service-management/handlers/ValidationHandler.js');
62
+ const doctor = new ValidationHandler();
63
+ if (!mergedOptions.quiet) {
64
+ output.info('🔍 Running preflight doctor checks...');
65
+ }
66
+ const doctorResults = await doctor.runDoctor({
67
+ servicePath: mergedOptions.servicePath || '.',
68
+ strict: mergedOptions.doctorStrict || false,
69
+ json: false // Always use human-readable for deploy context
70
+ });
71
+ if (doctorResults.exitCode !== 0) {
72
+ output.error('❌ Preflight checks failed!');
73
+ output.error(`Found ${doctorResults.summary.errors} errors and ${doctorResults.summary.warnings} warnings`);
74
+
75
+ // Show details of failed checks
76
+ doctorResults.checks.forEach(check => {
77
+ if (check.status !== 'passed') {
78
+ const color = check.severity === 'error' ? 'red' : check.severity === 'warning' ? 'yellow' : 'gray';
79
+ console.log(chalk[color](` ${check.name}: ${check.message}`));
80
+ check.details.forEach(detail => {
81
+ console.log(chalk.gray(` ${detail}`));
82
+ });
83
+ }
84
+ });
85
+ if (doctorResults.fixSuggestions.length > 0) {
86
+ output.info('\n💡 Fix suggestions:');
87
+ doctorResults.fixSuggestions.forEach(suggestion => {
88
+ output.log(chalk.blue(` • ${suggestion}`));
89
+ });
90
+ }
91
+ output.info('\nTo skip these checks, use --skip-doctor');
92
+ output.info('To run checks manually, use: clodo doctor');
93
+ process.exit(1);
94
+ } else if (!mergedOptions.quiet) {
95
+ output.success(`✅ Preflight checks passed (${doctorResults.summary.passed}/${doctorResults.summary.total})`);
96
+ }
97
+ }
98
+
40
99
  // Determine if interactive mode should be enabled
41
100
  const interactive = !mergedOptions.nonInteractive && !mergedOptions.yes;
42
101
  if (interactive) {