Files
puaros/packages/guardian/docs/v0.6.0-CONFIGURATION-SPEC.md

25 KiB
Raw Blame History

Guardian v0.6.0 - Configuration & Presets Specification

Version: 0.6.0 Target Release: Q1 2026 (January-February) Status: 📋 Specification Priority: 🔥 CRITICAL


📋 Table of Contents

  1. Overview
  2. Goals & Non-Goals
  3. Configuration File Format
  4. Preset System
  5. Rule Configuration
  6. Layer Customization
  7. Ignore & Exclude Patterns
  8. CLI Integration
  9. Migration Guide
  10. Implementation Plan
  11. Testing Strategy

Overview

Problem Statement

Currently, Guardian uses hardcoded rules and layer paths. This prevents:

  • Customization for different project structures
  • Disabling specific rules
  • Per-file or per-directory overrides
  • Team-specific configurations
  • Framework-specific presets (NestJS, Express, etc.)

Without configuration support, Guardian cannot scale to enterprise adoption.

Solution

Add comprehensive configuration system with:

  • Multiple file format support
  • Zero-config presets
  • Rule-level customization
  • Custom layer paths
  • Ignore patterns
  • CLI overrides

Success Criteria

  • Support 5+ configuration file formats
  • Provide 4+ built-in presets
  • Enable/disable any rule via config
  • Custom layer path mapping
  • Per-file/directory ignore patterns
  • CLI can override any config option
  • 100% backward compatible (default config)
  • Complete documentation with examples
  • 95%+ test coverage

Goals & Non-Goals

Goals

Configuration Discovery

  • Support multiple file formats
  • Auto-discover config in project root
  • Clear precedence order

Zero-Config Experience

  • Works without config (sensible defaults)
  • Presets for common architectures

Flexibility

  • Enable/disable any rule
  • Custom severity levels
  • Per-file ignores

Developer Experience

  • guardian init command
  • Config validation
  • Helpful error messages

Non-Goals

Remote Configuration

  • No fetching config from URLs (v1.0+ maybe)

Shareable Config Packages

  • No @company/guardian-config packages (v0.7+ maybe)

GUI Config Editor

  • CLI/text-based only (v1.0+ maybe)

Configuration File Format

Supported File Formats

Guardian will discover configuration in this order:

  1. guardian.config.js (ES modules) - Recommended
  2. guardian.config.cjs (CommonJS)
  3. guardian.config.mjs (ES modules, explicit)
  4. .guardianrc (JSON)
  5. .guardianrc.json (JSON, explicit)
  6. .guardianrc.js (JS)
  7. package.json (in guardian field)

Precedence: First found wins.

Configuration Schema

interface GuardianConfig {
    // Preset (optional, zero-config)
    preset?: 'clean-architecture' | 'ddd' | 'hexagonal' | 'onion' | 'minimal' | string

    // Extends another config (optional)
    extends?: string | string[]

    // Root directory (optional, default: process.cwd())
    root?: string

    // File includes (optional, default: ['**/*.ts', '**/*.tsx', '**/*.js', '**/*.jsx'])
    include?: string[]

    // File excludes (optional)
    exclude?: string[]

    // Rule configuration
    rules?: {
        [ruleName: string]: RuleConfig
    }

    // Layer path mapping
    layers?: {
        domain?: string | string[]
        application?: string | string[]
        infrastructure?: string | string[]
        shared?: string | string[]
    }

    // Per-rule ignore patterns
    ignore?: {
        [ruleName: string]: IgnorePattern
    }

    // Output format (optional, default: 'text')
    format?: 'text' | 'json' | 'markdown' | 'ai-prompt'

    // Fail on severity (optional, default: 'error')
    failOn?: 'error' | 'warning' | 'off'
}

type RuleConfig = 'error' | 'warn' | 'off' | [RuleSeverity, RuleOptions]
type RuleSeverity = 'error' | 'warn' | 'off'
type RuleOptions = Record<string, unknown>

interface IgnorePattern {
    [filePattern: string]: unknown[]  // Specific values to ignore
}
// guardian.config.js
export default {
    // Use built-in preset
    preset: 'clean-architecture',

    // Custom layer paths
    layers: {
        domain: 'src/core/domain',
        application: 'src/core/application',
        infrastructure: 'src/adapters',
        shared: 'src/shared',
    },

    // Rule customization
    rules: {
        'hardcode/magic-numbers': 'error',
        'hardcode/magic-strings': 'warn',
        'architecture/layer-violation': 'error',
        'architecture/framework-leak': 'error',
        'architecture/entity-exposure': 'error',
        'circular-dependency': 'error',
        'naming-convention': 'warn',
        'dependency-direction': 'error',
        'repository-pattern': 'error',
    },

    // Exclusions
    exclude: [
        '**/*.test.ts',
        '**/*.spec.ts',
        'scripts/**',
        'migrations/**',
        'node_modules/**',
        'dist/**',
    ],

    // Per-rule ignores
    ignore: {
        'hardcode/magic-numbers': {
            'src/config/constants.ts': [3000, 8080, 5000],  // Allow these specific values
            'src/database/migrations/**': '*',  // Ignore all in migrations
        },
        'naming-convention': {
            'src/legacy/**': '*',  // Ignore all legacy code
        },
    },

    // Output format
    format: 'text',

    // Fail on errors only (warnings don't fail CI)
    failOn: 'error',
}

Example: .guardianrc (JSON)

{
    "preset": "clean-architecture",
    "rules": {
        "hardcode/magic-numbers": "error",
        "hardcode/magic-strings": "warn"
    },
    "exclude": ["**/*.test.ts", "**/*.spec.ts"]
}

Example: package.json

{
    "name": "my-app",
    "version": "1.0.0",
    "guardian": {
        "preset": "clean-architecture",
        "rules": {
            "hardcode/magic-numbers": "error"
        }
    }
}

Preset System

Built-in Presets

1. clean-architecture (Default)

Enforces Clean Architecture principles:

// Equivalent to:
{
    rules: {
        'architecture/layer-violation': 'error',
        'architecture/framework-leak': 'error',
        'architecture/entity-exposure': 'error',
        'dependency-direction': 'error',
        'circular-dependency': 'error',
        'hardcode/magic-numbers': 'error',
        'hardcode/magic-strings': 'error',
        'naming-convention': 'warn',
        'repository-pattern': 'error',
    },
    layers: {
        domain: 'src/domain',
        application: 'src/application',
        infrastructure: 'src/infrastructure',
        shared: 'src/shared',
    }
}

When to use: Most TypeScript projects following Clean Architecture

2. ddd (Domain-Driven Design)

All DDD pattern detectors enabled:

// Equivalent to:
{
    extends: 'clean-architecture',
    rules: {
        // All v0.11-v0.32 DDD features enabled
        'aggregate-boundaries': 'error',
        'anemic-domain-model': 'warn',
        'domain-events': 'error',
        'value-object-immutability': 'error',
        // ... all 30+ DDD rules
    }
}

When to use: Projects strictly following DDD

3. hexagonal (Ports & Adapters)

Validates hexagonal architecture:

// Equivalent to:
{
    rules: {
        'architecture/layer-violation': 'error',
        'port-adapter-pattern': 'error',  // v0.17.0
        'dependency-direction': 'error',
    },
    layers: {
        domain: 'src/domain',
        application: 'src/application',  // Ports here
        infrastructure: 'src/adapters',  // Adapters here
    }
}

When to use: Projects using Ports & Adapters pattern

4. minimal (Prototyping)

Only critical rules for fast iteration:

// Equivalent to:
{
    rules: {
        'hardcode/magic-numbers': 'warn',
        'circular-dependency': 'error',
        'architecture/framework-leak': 'warn',
    }
}

When to use: Prototypes, MVPs, learning projects

5. nestjs-clean-architecture

NestJS-specific preset:

// Equivalent to:
{
    extends: 'clean-architecture',
    layers: {
        domain: 'src/domain',
        application: 'src/application',
        infrastructure: 'src/infrastructure',
    },
    ignore: {
        'naming-convention': {
            '**/*.module.ts': '*',  // NestJS modules
            '**/*.controller.ts': '*',  // Already has suffix
        },
        'architecture/framework-leak': {
            'src/infrastructure/**': ['@nestjs/*'],  // Allow NestJS in infra
        }
    }
}

When to use: NestJS projects

6. express-clean-architecture

Express-specific preset:

// Equivalent to:
{
    extends: 'clean-architecture',
    ignore: {
        'architecture/framework-leak': {
            'src/infrastructure/http/**': ['express'],
        }
    }
}

When to use: Express projects

Custom Presets

Users can create custom presets:

// guardian.config.js
export default {
    preset: './presets/my-company-preset.js'
}

// presets/my-company-preset.js
export default {
    extends: 'clean-architecture',
    rules: {
        // Company-specific rules
    }
}

Future (v0.7+): Shareable preset packages

npm install @mycompany/guardian-preset
export default {
    preset: '@mycompany/guardian-preset'
}

Rule Configuration

Available Rules

Rule ID Default Description
hardcode/magic-numbers error Detect magic numbers
hardcode/magic-strings error Detect magic strings
architecture/layer-violation error Layer dependency violations
architecture/framework-leak error Framework imports in domain
architecture/entity-exposure error Domain entities in API
circular-dependency error Circular imports
naming-convention warn File naming conventions
dependency-direction error Wrong dependency direction
repository-pattern error Repository pattern violations

Future rules (v0.11+):

  • aggregate-boundaries (v0.11)
  • anemic-domain-model (v0.12)
  • domain-events (v0.13)
  • value-object-immutability (v0.14)
  • ... (25+ more)

Rule Severity Levels

rules: {
    'hardcode/magic-numbers': 'error',   // Fail CI, block PR
    'naming-convention': 'warn',         // Show warning, don't fail
    'some-future-rule': 'off',           // Completely disabled
}

Rule Options (Advanced)

Some rules accept options:

rules: {
    'hardcode/magic-numbers': ['error', {
        allowedNumbers: [-1, 0, 1, 2, 10, 100, 1000],
        ignoreEnums: true,
        ignoreReadonly: true,
    }],

    'naming-convention': ['warn', {
        useCaseVerbs: ['Create', 'Update', 'Delete', 'Get', 'List'],
        entityPattern: /^[A-Z][a-zA-Z]+$/,
    }],

    'circular-dependency': ['error', {
        maxDepth: 5,  // Only report cycles up to depth 5
    }],
}

Layer Customization

Default Layer Paths

layers: {
    domain: 'src/domain',
    application: 'src/application',
    infrastructure: 'src/infrastructure',
    shared: 'src/shared',
}

Custom Paths (Single)

layers: {
    domain: 'src/core/domain',
    application: 'src/core/application',
    infrastructure: 'src/adapters',
    shared: 'src/common',
}

Multiple Paths per Layer

layers: {
    domain: ['src/core/domain', 'src/modules/*/domain'],
    application: ['src/core/application', 'src/modules/*/application'],
    infrastructure: ['src/adapters', 'src/modules/*/adapters'],
}

Monorepo Support

// Root guardian.config.js
layers: {
    domain: 'packages/*/src/domain',
    application: 'packages/*/src/application',
    infrastructure: 'packages/*/src/infrastructure',
}

Ignore & Exclude Patterns

Global Excludes

exclude: [
    '**/*.test.ts',
    '**/*.spec.ts',
    '**/__tests__/**',
    'scripts/**',
    'migrations/**',
    'node_modules/**',
    'dist/**',
    'build/**',
]

Per-Rule Ignores

Ignore Specific Values

ignore: {
    'hardcode/magic-numbers': {
        'src/config/constants.ts': [3000, 8080, 5000],
        'src/config/defaults.ts': [10, 20, 30],
    }
}

Ignore All Violations

ignore: {
    'naming-convention': {
        'src/legacy/**': '*',  // Ignore all naming in legacy
    }
}

Ignore Entire Directories

ignore: {
    'hardcode/magic-numbers': {
        'migrations/**': '*',
        'scripts/**': '*',
    }
}

Pattern Syntax

Supports glob patterns:

  • * - matches any characters except /
  • ** - matches any characters including /
  • ? - matches single character
  • [abc] - matches a, b, or c
  • {a,b} - matches a or b

CLI Integration

Commands

guardian init

Generate configuration file:

# Interactive mode
guardian init

# With preset
guardian init --preset clean-architecture

# Specific format
guardian init --format js
guardian init --format json

# Output to custom location
guardian init --output custom-config.js

Interactive prompts:

? Which preset would you like to use? (Use arrow keys)
 clean-architecture (Recommended)
  ddd (Domain-Driven Design)
  hexagonal (Ports & Adapters)
  minimal (Prototyping)
  nestjs-clean-architecture
  express-clean-architecture
  custom (Configure manually)

? Where are your domain files? (src/domain)
? Where are your application files? (src/application)
? Where are your infrastructure files? (src/infrastructure)

? Configuration file format? (Use arrow keys)
 JavaScript (guardian.config.js) - Recommended
  JSON (.guardianrc)
  package.json

✅ Created guardian.config.js

guardian check (with config)

# Use config from default locations
guardian check ./src

# Specify config file
guardian check ./src --config custom-config.js

# Override rules via CLI
guardian check ./src --rule hardcode/magic-numbers=off
guardian check ./src --rule naming-convention=error

# Override preset
guardian check ./src --preset minimal

# Override fail-on
guardian check ./src --fail-on warning

guardian validate-config

Validate configuration file:

guardian validate-config
guardian validate-config --config custom-config.js

# Output:
# ✅ Configuration is valid
# or
# ❌ Configuration errors:
#    - Unknown rule: 'invalid-rule'
#    - Invalid severity: 'critical' (must be error/warn/off)

CLI Overrides

CLI options take precedence over config file:

// guardian.config.js
{
    rules: {
        'hardcode/magic-numbers': 'error'
    }
}
# Override to 'off' for this run
guardian check ./src --rule hardcode/magic-numbers=off

Precedence order:

  1. CLI flags (highest)
  2. Config file
  3. Preset
  4. Default config (lowest)

Migration Guide

From No Config → With Config

Before (v0.5.1):

# All rules enabled, hardcoded paths
guardian check ./src

After (v0.6.0):

# Generate config
guardian init --preset clean-architecture

# Customize guardian.config.js
# Run with config
guardian check ./src

Backward Compatibility

v0.6.0 is 100% backward compatible:

# This still works exactly the same
guardian check ./src

# Default config is applied automatically

Default config (when no config file found):

{
    preset: 'clean-architecture',
    layers: {
        domain: 'src/domain',
        application: 'src/application',
        infrastructure: 'src/infrastructure',
        shared: 'src/shared',
    },
    rules: {
        'hardcode/magic-numbers': 'error',
        'hardcode/magic-strings': 'error',
        'architecture/layer-violation': 'error',
        'architecture/framework-leak': 'error',
        'architecture/entity-exposure': 'error',
        'circular-dependency': 'error',
        'naming-convention': 'warn',
        'dependency-direction': 'error',
        'repository-pattern': 'error',
    }
}

Implementation Plan

Phase 1: Core Configuration (Week 1-2)

Tasks:

  • Create GuardianConfig TypeScript interface
  • Implement config file discovery
  • Implement config parser (JS, JSON)
  • Implement config validator
  • Add config merging (extends, overrides)
  • Update AnalyzeProject to accept config
  • Tests for config loading

Deliverable: Config files are discovered and parsed

Phase 2: Rule Configuration (Week 2-3)

Tasks:

  • Implement rule severity system (error/warn/off)
  • Update each detector to check rule config
  • Implement per-rule options
  • Tests for rule configuration

Deliverable: Rules can be enabled/disabled/configured

Phase 3: Preset System (Week 3-4)

Tasks:

  • Implement preset loader
  • Create built-in presets (clean-architecture, ddd, etc.)
  • Implement preset extends
  • Implement custom preset loading
  • Tests for preset system

Deliverable: Presets work and can be extended

Phase 4: Ignore Patterns (Week 4-5)

Tasks:

  • Implement ignore pattern matching
  • Update detectors to check ignore patterns
  • Add global exclude support
  • Tests for ignore patterns

Deliverable: Files and values can be ignored

Phase 5: CLI Integration (Week 5-6)

Tasks:

  • Implement guardian init command
  • Add --config flag
  • Add --rule override flag
  • Add --preset override flag
  • Implement guardian validate-config
  • Tests for CLI integration

Deliverable: CLI fully supports configuration

Phase 6: Documentation & Testing (Week 6-7)

Tasks:

  • Write configuration documentation
  • Create example configs for each preset
  • Add migration guide
  • Comprehensive integration tests
  • Update README

Deliverable: Complete docs and 95%+ coverage

Phase 7: Beta Testing & Release (Week 7-8)

Tasks:

  • Beta release (v0.6.0-beta.1)
  • Community testing
  • Bug fixes
  • Final release (v0.6.0)

Deliverable: Stable v0.6.0 release


Testing Strategy

Unit Tests

describe('ConfigLoader', () => {
    it('should discover guardian.config.js', async () => {
        // Test config file discovery
    })

    it('should parse JavaScript config', async () => {
        // Test JS config parsing
    })

    it('should parse JSON config', async () => {
        // Test JSON config parsing
    })

    it('should merge configs with extends', async () => {
        // Test config merging
    })

    it('should validate config schema', async () => {
        // Test validation
    })
})

describe('PresetLoader', () => {
    it('should load built-in preset', async () => {
        // Test preset loading
    })

    it('should extend preset', async () => {
        // Test preset extending
    })
})

describe('RuleConfiguration', () => {
    it('should disable rule when set to off', async () => {
        // Test rule disabling
    })

    it('should apply rule options', async () => {
        // Test rule options
    })
})

Integration Tests

describe('Configuration Integration', () => {
    it('should run with custom config', async () => {
        // Create temp config file
        // Run guardian check
        // Verify rules are applied
    })

    it('should apply preset correctly', async () => {
        // Test preset application
    })

    it('should ignore files matching pattern', async () => {
        // Test ignore patterns
    })

    it('should override config from CLI', async () => {
        // Test CLI overrides
    })
})

Test Coverage Goals

  • Configuration loading: 100%
  • Preset system: 100%
  • Rule configuration: 100%
  • Ignore patterns: 95%+
  • CLI integration: 95%+
  • Overall: 95%+

Examples

Example 1: Minimal Config

// guardian.config.js
export default {
    preset: 'clean-architecture',
}

Example 2: Custom Paths

// guardian.config.js
export default {
    preset: 'clean-architecture',
    layers: {
        domain: 'src/core/domain',
        application: 'src/core/application',
        infrastructure: 'src/adapters',
    },
}

Example 3: Rule Customization

// guardian.config.js
export default {
    preset: 'clean-architecture',
    rules: {
        'hardcode/magic-numbers': 'warn',  // Downgrade to warning
        'naming-convention': 'off',        // Disable completely
    },
}

Example 4: Ignore Patterns

// guardian.config.js
export default {
    preset: 'clean-architecture',
    ignore: {
        'hardcode/magic-numbers': {
            'src/config/**': '*',           // Ignore all hardcode in config
            'src/constants.ts': [3000, 8080], // Allow specific values
        },
        'naming-convention': {
            'src/legacy/**': '*',           // Ignore legacy code
        },
    },
}

Example 5: NestJS Project

// guardian.config.js
export default {
    preset: 'nestjs-clean-architecture',
    exclude: [
        '**/*.spec.ts',
        'test/**',
    ],
}

Example 6: Monorepo

// guardian.config.js (root)
export default {
    preset: 'clean-architecture',
    layers: {
        domain: 'packages/*/src/domain',
        application: 'packages/*/src/application',
        infrastructure: 'packages/*/src/infrastructure',
    },
    exclude: [
        'packages/legacy/**',
    ],
}

API Changes

Before (v0.5.1)

// No configuration support
const result = await analyzeProject({
    rootDir: './src',
    exclude: ['node_modules'],
})

After (v0.6.0)

import { loadConfig } from '@samiyev/guardian'

// Load config
const config = await loadConfig('./guardian.config.js')

// Use config
const result = await analyzeProject({
    rootDir: './src',
    config,  // New: Pass config
})

// Or auto-discover:
const result = await analyzeProject({
    rootDir: './src',
    // Config auto-discovered if not provided
})

Documentation Updates

New Documentation Pages

  1. Configuration Guide

    • How to create config
    • All options explained
    • Examples for each preset
  2. Preset Reference

    • Description of each preset
    • When to use which preset
    • How to customize presets
  3. Rule Reference

    • Complete list of rules
    • Rule options
    • Examples for each rule
  4. Migration Guide

    • From v0.5.x to v0.6.0
    • Adding config to existing projects

Updated Pages

  • README.md - Add configuration section
  • Quick Start - Show guardian init
  • CLI Reference - New commands and flags

Success Metrics

Release Criteria

  • All tests passing (95%+ coverage)
  • Documentation complete
  • 5+ example configs
  • Beta tested by 10+ users
  • Zero critical bugs
  • Backward compatible

Adoption Metrics (3 months post-release)

  • Target: 50%+ of users create config files
  • Target: 100+ GitHub repos with guardian.config.js
  • Target: <5 config-related issues on GitHub

Future Enhancements (Post-v0.6.0)

v0.7.0 - Shareable Configs

npm install @mycompany/guardian-config
export default {
    extends: '@mycompany/guardian-config'
}

v0.8.0 - Remote Configs

export default {
    extends: 'https://example.com/guardian-config.js'
}

v1.0.0 - GUI Config Editor

guardian config-editor
# Opens web-based config editor

Questions & Answers

Q: Will this be a breaking change?

A: No, v0.6.0 is 100% backward compatible. If no config file exists, Guardian uses the same default behavior as v0.5.1.

Q: Can I migrate incrementally?

A: Yes! Start with preset: 'clean-architecture' and customize one rule at a time.

Q: Will presets be updateable?

A: Presets are versioned with Guardian. When you update Guardian, presets update too. You can pin to a specific preset version in future versions.

Q: Can I use TypeScript for config?

A: Yes, in v0.7.0+ we'll add guardian.config.ts support. For v0.6.0, use .js with JSDoc types.


Timeline

Week Phase Deliverable
1-2 Core Configuration Config loading works
2-3 Rule Configuration Rules configurable
3-4 Preset System Presets work
4-5 Ignore Patterns Ignores work
5-6 CLI Integration CLI supports config
6-7 Documentation Complete docs
7-8 Beta & Release v0.6.0 stable

Target Release Date: End of Q1 2026 (February-March)


Feedback & Questions


Status: This specification is ready for implementation.

Next Steps:

  1. Review and approve this spec
  2. Create implementation tasks in GitHub
  3. Start Phase 1 development
  4. Weekly progress updates