# ADR-020: Command Handler Domain Splitting\n\n**Status**: Proposed\n**Date**: 2026-01-13\n**Author**: Architecture Team\n**Supersedes**: Monolithic command handlers in `main_provisioning/commands/`\n\n## Context\n\nTwo large monolithic command handler files mix disparate domains:\n\n**commands/utilities.nu** (1112 lines):\n- SSH operations (150 lines)\n- SOPS secret editing (200 lines)\n- Cache management (180 lines)\n- Provider listing (100 lines)\n- Plugin operations (150 lines)\n- Shell information (80 lines)\n- Guide system (120 lines)\n- QR code generation (50 lines)\n\n**commands/integrations.nu** (1184 lines):\n- prov-ecosystem bridge (400 lines)\n- provctl integration (350 lines)\n- External API calls (434 lines)\n\n**Problem Statement**:\n\n1. **Mixed Concerns**: Each file handles 7-10 unrelated domains\n2. **Navigation Difficulty**: Hard to find specific functionality\n3. **Testing Complexity**: Can't test SSH without SOPS setup\n4. **Reusability**: Command logic locked in monolithic files\n5. **Maintenance Burden**: Changes in one domain affect entire file\n\n## Decision\n\nImplement **Domain-Based Command Modules**: split monolithic handlers into focused domain modules organized by responsibility.\n\n### Target Architecture\n\n```\nmain_provisioning/commands/\n├── dispatcher.nu               # Routes commands to domain handlers\n├── utilities/                  # Split by domain\n│   ├── ssh.nu                 # SSH operations (150 lines)\n│   ├── sops.nu                # SOPS editing (200 lines)\n│   ├── cache.nu               # Cache management (180 lines)\n│   ├── providers.nu           # Provider listing (100 lines)\n│   ├── plugins.nu             # Plugin operations (150 lines)\n│   ├── shell.nu               # Shell information (80 lines)\n│   ├── guides.nu              # Guide system (120 lines)\n│   └── qr.nu                  # QR code generation (50 lines)\n└── integrations/               # Split by integration\n    ├── prov_ecosystem.nu      # Prov-ecosystem bridge (400 lines)\n    ├── provctl.nu             # Provctl integration (350 lines)\n    └── external_apis.nu       # External API calls (434 lines)\n```\n\n### Module Organization\n\n**utilities/ssh.nu**:\n- SSH connection management\n- Key management\n- Remote command execution\n- Connection pooling\n\n**utilities/sops.nu**:\n- SOPS secret file editing\n- Encryption/decryption\n- Key rotation\n- Secret validation\n\n**utilities/cache.nu**:\n- Cache lookup\n- Cache invalidation\n- Cache statistics\n- Cleanup operations\n\n**utilities/providers.nu**:\n- List available providers\n- Provider capabilities\n- Provider health check\n- Provider registration\n\n**utilities/plugins.nu**:\n- Plugin discovery\n- Plugin loading\n- Plugin execution\n- Plugin management\n\n**utilities/shell.nu**:\n- Nushell info\n- Shell configuration\n- Environment variables\n- Shell capabilities\n\n**utilities/guides.nu**:\n- Guide listing\n- Guide rendering\n- Guide search\n- Interactive guides\n\n**utilities/qr.nu**:\n- QR code generation\n- QR code display\n- Code formatting\n- Error handling\n\n**integrations/prov_ecosystem.nu**:\n- Prov-ecosystem API calls\n- Data synchronization\n- Registry integration\n- Extension discovery\n\n**integrations/provctl.nu**:\n- Provctl command bridge\n- Orchestrator integration\n- Workflow execution\n- Status monitoring\n\n**integrations/external_apis.nu**:\n- Third-party API integration\n- HTTP calls\n- Data transformation\n- Error handling\n\n## Consequences\n\n### Positive\n\n- **Single Responsibility**: Each module handles one domain\n- **Easier Navigation**: Find functionality by domain name\n- **Testable**: Can test SSH independently from SOPS\n- **Maintainable**: Changes isolated to domain module\n- **Reusable**: Modules can be imported by other components\n- **Scalable**: Easy to add new domains\n\n### Negative\n\n- **More Files**: 11 modules vs 2 monolithic files\n- **Import Overhead**: More module imports needed\n- **Coordination Complexity**: Dispatcher must route correctly\n\n## Implementation Strategy\n\n### Phase 1: Extract Utilities Domain\n\nCreate `utilities/` directory with 8 modules:\n\n1. **utilities/ssh.nu** - Extract SSH operations\n2. **utilities/sops.nu** - Extract SOPS operations\n3. **utilities/cache.nu** - Extract cache operations\n4. **utilities/providers.nu** - Extract provider operations\n5. **utilities/plugins.nu** - Extract plugin operations\n6. **utilities/shell.nu** - Extract shell operations\n7. **utilities/guides.nu** - Extract guide operations\n8. **utilities/qr.nu** - Extract QR operations\n\n### Phase 2: Extract Integrations Domain\n\nCreate `integrations/` directory with 3 modules:\n\n1. **integrations/prov_ecosystem.nu** - Extract prov-ecosystem\n2. **integrations/provctl.nu** - Extract provctl\n3. **integrations/external_apis.nu** - Extract external APIs\n\n### Phase 3: Create Dispatcher\n\nImplement `dispatcher.nu`:\n\n```\nexport def provision-ssh [args] {\n    use ./utilities/ssh.nu *\n    handle-ssh-command $args\n}\n\nexport def provision-sops [args] {\n    use ./utilities/sops.nu *\n    handle-sops-command $args\n}\n\nexport def provision-cache [args] {\n    use ./utilities/cache.nu *\n    handle-cache-command $args\n}\n```\n\n### Phase 4: Maintain Backward Compatibility\n\nKeep public exports in original files for compatibility:\n\n```\n# commands/utilities.nu (compatibility layer)\nuse ./utilities/ssh.nu *\nuse ./utilities/sops.nu *\nuse ./utilities/cache.nu *\n\n# Re-export all functions (unchanged public API)\nexport use ./utilities/ssh.nu\nexport use ./utilities/sops.nu\n```\n\n### Phase 5: Testing\n\nCreate test structure:\n\n```\ntests/commands/\n├── utilities/\n│   ├── test_ssh.nu\n│   ├── test_sops.nu\n│   ├── test_cache.nu\n│   ├── test_providers.nu\n│   ├── test_plugins.nu\n│   ├── test_shell.nu\n│   ├── test_guides.nu\n│   └── test_qr.nu\n└── integrations/\n    ├── test_prov_ecosystem.nu\n    ├── test_provctl.nu\n    └── test_external_apis.nu\n```\n\n## Module Interface Example\n\n**utilities/ssh.nu**:\n\n```\n# Connect to remote host\nexport def ssh-connect [host: string --port: int = 22] {\n    # Implementation\n}\n\n# Execute remote command\nexport def ssh-exec [host: string command: string] {\n    # Implementation\n}\n\n# Close SSH connection\nexport def ssh-close [host: string] {\n    # Implementation\n}\n```\n\n## File Structure\n\n```\nmain_provisioning/commands/\n├── dispatcher.nu              # Route to domain handlers\n├── utilities/\n│   ├── mod.nu                # Utilities module index\n│   ├── ssh.nu                # 150 lines\n│   ├── sops.nu               # 200 lines\n│   ├── cache.nu              # 180 lines\n│   ├── providers.nu          # 100 lines\n│   ├── plugins.nu            # 150 lines\n│   ├── shell.nu              # 80 lines\n│   ├── guides.nu             # 120 lines\n│   └── qr.nu                 # 50 lines\n├── integrations/\n│   ├── mod.nu                # Integrations module index\n│   ├── prov_ecosystem.nu     # 400 lines\n│   ├── provctl.nu            # 350 lines\n│   └── external_apis.nu      # 434 lines\n└── README.md                 # Command routing guide\n```\n\n## CLI Interface (Unchanged)\n\nUsers see no change in CLI:\n\n```\nprovisioning ssh host.example.com\nprovisioning sops edit config.yaml\nprovisioning cache clear\nprovisioning list providers\nprovisioning guide from-scratch\n```\n\n## Backward Compatibility Strategy\n\n**Import Path Options**:\n\n```\n# Option 1: Import from domain module (new way)\nuse ./utilities/ssh.nu *\nconnect $host\n\n# Option 2: Import from compatibility layer (old way)\nuse ./utilities.nu *\nconnect $host\n```\n\nBoth paths work without breaking existing code.\n\n## Related ADRs\n\n- **ADR-006**: Provisioning CLI Refactoring\n- **ADR-012**: Nushell/Nickel Plugin CLI Wrapper\n\n## Open Questions\n\n1. Should we create a module registry for discoverability?\n2. Should domain modules be loadable as plugins?\n3. How do we handle shared utilities between domains?\n4. Should we implement hot-reloading for domain modules?\n\n## References\n\n- Current Implementation: `provisioning/core/nulib/main_provisioning/commands/`\n- Nushell 0.109 Guidelines: `.claude/guidelines/nushell.md`\n- Module System: Nushell module documentation\n
