# Provisioning Extension System

The provisioning system supports extensions to add custom providers, task services, and access control without forking the main codebase.

## Extension Architecture

### Extension Discovery Paths

Extensions are loaded from multiple locations in priority order:

1. **Project-specific**: `.provisioning/extensions/` (highest priority)
2. **User-specific**: `~/.provisioning-extensions/`
3. **System-wide**: `/opt/provisioning-extensions/`
4. **Environment**: `$PROVISIONING_EXTENSIONS_PATH`

### Extension Types

#### 1. **Providers**
Custom cloud providers or infrastructure backends.

```
~/.provisioning-extensions/providers/
├── digitalocean/
│   ├── manifest.yaml
│   └── nulib/digitalocean/
│       ├── servers.nu
│       ├── env.nu
│       └── cache.nu
└── internal-cloud/
    ├── manifest.yaml
    └── nulib/internal-cloud/
        └── servers.nu
```

#### 2. **TaskServs**
Custom task services for application deployment or system configuration.

```
~/.provisioning-extensions/taskservs/
├── custom-app/
│   ├── manifest.yaml
│   ├── production/
│   │   └── install-custom-app.sh
│   ├── staging/
│   │   └── install-custom-app.sh
│   └── development/
│       └── install-custom-app.sh
└── monitoring/
    ├── manifest.yaml
    └── default/
        └── install-monitoring.sh
```

#### 3. **Profiles**
Access control profiles for restricted environments.

```
~/.provisioning-extensions/profiles/
├── cicd.yaml
├── developer.yaml
└── readonly.yaml
```

## Extension Configuration

### Environment Variables

| Variable | Description | Default |
|----------|-------------|---------|
| `PROVISIONING_EXTENSION_MODE` | Extension loading mode: `full`, `restricted`, `disabled` | `full` |
| `PROVISIONING_PROFILE` | Active access control profile | `""` (unrestricted) |
| `PROVISIONING_EXTENSIONS_PATH` | Custom extension base path | `""` |
| `PROVISIONING_ALLOWED_EXTENSIONS` | Comma-separated allowlist | `""` |
| `PROVISIONING_BLOCKED_EXTENSIONS` | Comma-separated blocklist | `""` |

### Configuration via Context

Add to `~/.provisioning/context.yaml`:

```yaml
extension_mode: restricted
profile: cicd
allowed_extensions: "digitalocean,custom-app"
blocked_extensions: "aws,dangerous-taskserv"
extensions_path: "/custom/path/to/extensions"
```

## Creating Extensions

### Provider Extension

1. **Create directory structure**:
   ```bash
   mkdir -p ~/.provisioning-extensions/providers/myprovider/nulib/myprovider
   ```

2. **Create manifest.yaml**:
   ```yaml
   name: myprovider
   version: 1.0.0
   type: provider
   description: My custom cloud provider
   requires:
     - mycloud-cli
   permissions:
     - network
     - compute
   hooks:
     pre_create: validate.nu
     post_create: notify.nu
   ```

3. **Implement provider functions** in `nulib/myprovider/servers.nu`:
   ```nushell
   export def myprovider_create_servers [settings: record, servers: table, check: bool, wait: bool] {
       # Implementation here
   }

   export def myprovider_delete_servers [settings: record, servers: table, check: bool] {
       # Implementation here
   }

   export def myprovider_query_servers [find: string, cols: string] {
       # Implementation here
   }

   export def myprovider_get_ip [settings: record, server: record, ip_type: string, fallback: bool] {
       # Implementation here
   }
   ```

### TaskServ Extension

1. **Create directory structure**:
   ```bash
   mkdir -p ~/.provisioning-extensions/taskservs/mytask/{production,staging,development}
   ```

2. **Create manifest.yaml**:
   ```yaml
   name: mytask
   version: 2.0.0
   type: taskserv
   description: My custom task service
   requires:
     - docker
     - kubectl
   profiles:
     - production
     - staging
     - development
   ```

3. **Create installation scripts**:
   ```bash
   # ~/.provisioning-extensions/taskservs/mytask/production/install-mytask.sh
   #!/bin/bash
   echo "Installing mytask in production mode"
   # Implementation here
   ```

### Profile Extension

Create `~/.provisioning-extensions/profiles/myprofile.yaml`:

```yaml
profile: myprofile
description: Custom access profile
restricted: true
allowed:
  commands: ["server list", "taskserv status"]
  providers: ["local", "myprovider"]
  taskservs: ["kubernetes", "mytask"]
blocked:
  commands: ["server delete", "sops"]
  providers: ["aws"]
  taskservs: ["postgres"]
```

## Usage Examples

### Using Custom Provider

```bash
# Enable extensions
export PROVISIONING_EXTENSION_MODE=full

# Use custom provider in settings.k
servers = [
    {
        hostname: "web-01"
        provider: "digitalocean"  # Custom provider
        region: "nyc1"
        size: "s-1vcpu-1gb"
    }
]
```

### Restricted CI/CD Environment

```bash
# Set CI/CD profile
export PROVISIONING_PROFILE=cicd
export PROVISIONING_EXTENSION_MODE=restricted

# These commands work
provisioning server list          ✅
provisioning taskserv status      ✅

# These commands are blocked
provisioning server delete        ❌
provisioning sops edit secrets    ❌
```

### Project-Specific Extensions

```bash
# In your project directory
mkdir -p .provisioning/extensions/taskservs/project-deploy/default
echo '#!/bin/bash\necho "Deploying project"' > .provisioning/extensions/taskservs/project-deploy/default/install-project-deploy.sh

# Use in taskservs
taskservs = [
    {
        name: "project-deploy"  # Automatically discovered
        profile: "default"
    }
]
```

## Extension Management Commands

```bash
# List available extensions
provisioning extensions list

# Show extension details
provisioning extensions show digitalocean

# Validate extension
provisioning extensions validate ~/.provisioning-extensions/providers/myprovider

# Create example profiles
provisioning profiles create-examples

# Show current profile
provisioning profile show
```

## Security Considerations

1. **Profile Enforcement**: Use profiles in CI/CD to limit capabilities
2. **Extension Validation**: Check manifests and requirements before loading
3. **Path Isolation**: Extensions can't access core provisioning internals
4. **Permission System**: Extensions declare required permissions
5. **Allowlist/Blocklist**: Control which extensions can be loaded

## Migration Guide

### From Forked Provisioning

1. **Extract Custom Code**: Move custom providers/taskservs to extension directories
2. **Create Manifests**: Add `manifest.yaml` for each extension
3. **Update Configuration**: Use environment variables instead of code changes
4. **Test Extensions**: Verify functionality with extension system

### Gradual Adoption

1. **Start Small**: Begin with profile-based access control
2. **Move TaskServs**: Migrate custom task services to extensions
3. **Add Providers**: Create provider extensions as needed
4. **Full Migration**: Remove forks and use pure extension system

This extension system allows the main provisioning project to remain clean and focused while providing unlimited customization capabilities.