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

1176 lines
25 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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](#overview)
2. [Goals & Non-Goals](#goals--non-goals)
3. [Configuration File Format](#configuration-file-format)
4. [Preset System](#preset-system)
5. [Rule Configuration](#rule-configuration)
6. [Layer Customization](#layer-customization)
7. [Ignore & Exclude Patterns](#ignore--exclude-patterns)
8. [CLI Integration](#cli-integration)
9. [Migration Guide](#migration-guide)
10. [Implementation Plan](#implementation-plan)
11. [Testing Strategy](#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
```typescript
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
}
```
### Example: guardian.config.js (Recommended)
```javascript
// 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)
```json
{
"preset": "clean-architecture",
"rules": {
"hardcode/magic-numbers": "error",
"hardcode/magic-strings": "warn"
},
"exclude": ["**/*.test.ts", "**/*.spec.ts"]
}
```
### Example: package.json
```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:
```javascript
// 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:
```javascript
// 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:
```javascript
// 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:
```javascript
// 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:
```javascript
// 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:
```javascript
// 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:
```javascript
// 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
```bash
npm install @mycompany/guardian-preset
```
```javascript
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
```javascript
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:
```javascript
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
```javascript
layers: {
domain: 'src/domain',
application: 'src/application',
infrastructure: 'src/infrastructure',
shared: 'src/shared',
}
```
### Custom Paths (Single)
```javascript
layers: {
domain: 'src/core/domain',
application: 'src/core/application',
infrastructure: 'src/adapters',
shared: 'src/common',
}
```
### Multiple Paths per Layer
```javascript
layers: {
domain: ['src/core/domain', 'src/modules/*/domain'],
application: ['src/core/application', 'src/modules/*/application'],
infrastructure: ['src/adapters', 'src/modules/*/adapters'],
}
```
### Monorepo Support
```javascript
// Root guardian.config.js
layers: {
domain: 'packages/*/src/domain',
application: 'packages/*/src/application',
infrastructure: 'packages/*/src/infrastructure',
}
```
---
## Ignore & Exclude Patterns
### Global Excludes
```javascript
exclude: [
'**/*.test.ts',
'**/*.spec.ts',
'**/__tests__/**',
'scripts/**',
'migrations/**',
'node_modules/**',
'dist/**',
'build/**',
]
```
### Per-Rule Ignores
#### Ignore Specific Values
```javascript
ignore: {
'hardcode/magic-numbers': {
'src/config/constants.ts': [3000, 8080, 5000],
'src/config/defaults.ts': [10, 20, 30],
}
}
```
#### Ignore All Violations
```javascript
ignore: {
'naming-convention': {
'src/legacy/**': '*', // Ignore all naming in legacy
}
}
```
#### Ignore Entire Directories
```javascript
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:
```bash
# 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)
```bash
# 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:
```bash
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:
```javascript
// guardian.config.js
{
rules: {
'hardcode/magic-numbers': 'error'
}
}
```
```bash
# 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):**
```bash
# All rules enabled, hardcoded paths
guardian check ./src
```
**After (v0.6.0):**
```bash
# 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:**
```bash
# This still works exactly the same
guardian check ./src
# Default config is applied automatically
```
**Default config (when no config file found):**
```javascript
{
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
```typescript
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
```typescript
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
```javascript
// guardian.config.js
export default {
preset: 'clean-architecture',
}
```
### Example 2: Custom Paths
```javascript
// guardian.config.js
export default {
preset: 'clean-architecture',
layers: {
domain: 'src/core/domain',
application: 'src/core/application',
infrastructure: 'src/adapters',
},
}
```
### Example 3: Rule Customization
```javascript
// 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
```javascript
// 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
```javascript
// guardian.config.js
export default {
preset: 'nestjs-clean-architecture',
exclude: [
'**/*.spec.ts',
'test/**',
],
}
```
### Example 6: Monorepo
```javascript
// 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)
```typescript
// No configuration support
const result = await analyzeProject({
rootDir: './src',
exclude: ['node_modules'],
})
```
### After (v0.6.0)
```typescript
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
```bash
npm install @mycompany/guardian-config
```
```javascript
export default {
extends: '@mycompany/guardian-config'
}
```
### v0.8.0 - Remote Configs
```javascript
export default {
extends: 'https://example.com/guardian-config.js'
}
```
### v1.0.0 - GUI Config Editor
```bash
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
- 📧 Email: fozilbek.samiyev@gmail.com
- 🐙 GitHub: https://github.com/samiyev/puaros/issues
- 💬 Discuss: https://github.com/samiyev/puaros/discussions
---
**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