# Example Declarative Plugin

This plugin demonstrates the **declarative pattern** where all logic is defined in TOML with a minimal PowerShell stub.

## Pattern Overview

| File | Purpose |
|------|---------|
| `plugin.ps1` | PowerShell stub for plugin discovery |
| `declarative.toml` | TOML template with all actions, groups, and conditions |

The stub provides the required plugin contract (`Test-Applicable`, `Invoke-Seal`, `Invoke-Engage`) while the template defines WHAT actions to perform. Metadata is declared in `plugin.toml`, not in code. This separation enables:

- Non-developers to maintain plugin configuration
- Easy auditing and review of changes
- Version control friendly diffs
- Template reuse across similar plugins

## When to Use Declarative Pattern

**Use when:**

- Actions are standard (registry, service, task, command)
- Conditions are straightforward (OS version, existence checks)
- No custom logic is needed during execution
- Configuration changes are more frequent than logic changes

**Consider hybrid or imperative instead when:**

- Custom Analyze logic is needed (e.g., reading actual system state)
- Complex rollback validation is required
- External APIs must be called
- Conditional logic exceeds simple existence/value checks

## How It Works

```
1. Plugin discovery finds plugin.ps1
2. Invoke-Seal is called during Seal phase
3. Stub loads adjacent declarative.toml via Import-vSEALTemplate
4. Each group is executed via Invoke-vSEALActionGroup
5. Group processor handles:
   - Condition evaluation (group and per-action)
   - Action dispatch to type-specific executors
   - Baseline capture for rollback
   - Error handling (continue/stop/rollback strategies)
```

## Template Structure

### Template Metadata Section (`declarative.toml`)

This section is part of the TOML template file (`declarative.toml`), not `plugin.toml`. The `plugin.toml` metadata uses a `[plugin]` section with different fields (name, version, category, phases, priority, description).

```toml
[template]
name = "VDI System Hardening"       # Required: Display name
version = "1.0.0"                    # Required: Semantic version
description = "..."                  # Optional: Description
min_build = 22000                    # Optional: Minimum Windows build
tags = ["vdi", "hardening"]          # Optional: Categorization tags

[template.author]                    # Optional: Author block
name = "Author Name"
```

### Groups and Actions

```toml
[[groups]]
name = "Group Name"                  # Required: Display name
description = "What this does"       # Optional: Documentation
on_error = "continue"                # continue | stop | rollback

# Group-level conditions (AND logic - all must pass)
[[groups.conditions]]
type = "globals"
path = "OS.Build"
operator = ">="
value = 22000

# Actions in this group
[[groups.actions]]
type = "registry"
action = "set"
key = 'HKLM:\SOFTWARE\...'
name = "ValueName"
data = 1
datatype = "dword"

# Per-action conditions (optional)
[[groups.actions.conditions]]
type = "registry"
key = 'HKLM:\SOFTWARE\Prerequisite'
operator = "exists"
```

## Action Types

| Type | Purpose | Key Fields |
|------|---------|------------|
| `registry` | Set/delete registry values | `action`, `key`, `name`, `data`, `datatype` |
| `service` | Disable services | `action`, `name`, `start_mode` |
| `task` | Disable scheduled tasks | `action`, `name` |
| `command` | Run commands | `action`, `command`, `description`, `timeout` |

## Condition Types

| Type | Purpose | Fields | Operators |
|------|---------|--------|-----------|
| `globals` | Check OS/platform info | `path`, `operator`, `value` | `=`, `!=`, `>`, `>=`, `<`, `<=`, `in`, `not_in`, `contains` |
| `registry` | Check registry key/value | `key`, `operator` | `exists`, `not_exists` |
| `service` | Check service existence | `name`, `operator` | `exists`, `not_exists` |
| `task` | Check task existence | `name`, `operator` | `exists`, `not_exists` (supports wildcards) |

## Template in This Plugin

The `declarative.toml` template includes 6 groups demonstrating:

1. **Registry Hardening** - DWord, String, MultiString values with conditions
2. **Service Management** - Service disable with existence condition (skips)
3. **Task Management** - Task disable with task condition
4. **Command Execution** - Commands with timeout and rollback_command
5. **Conditional Logic Demo** - Multiple conditions, not_exists checks
6. **Engage Preparation** - Registry condition at group level

**Action Distribution:**
- Registry: 9 actions
- Service: 2 actions
- Task: 3 actions
- Command: 4 actions

**Condition Coverage:**
- All 4 types at group level (globals, registry, service, task)
- Action-level conditions for registry and task

## Testing

```powershell
# Verify plugin is discoverable
Import-Module ./src/vSEAL/vSEAL.psd1 -Force
Get-vSEALPlugin -Name 'Example Declarative'

# Verify template loads via the stub pattern
$plugin = Get-vSEALPlugin -Name 'Example Declarative'
. $plugin.Path
$templatePath = Join-Path (Split-Path $plugin.Path) 'declarative.toml'
$template = Import-vSEALTemplate -Path $templatePath
Write-Host "Template: $($template.Template.Name) with $($template.Groups.Count) groups"

# Validate template structure
$result = Import-vSEALTemplate -Path $templatePath -ValidateOnly
$result.IsValid  # Should be True
$result.Groups.Count  # Should be 6
```

## Key Points

- Template is validated at load time (Import-vSEALTemplate throws on errors)
- Conditions are evaluated before action execution
- Failed conditions skip the action/group gracefully
- Actions targeting non-existent resources return "Skipped" (not error)
- on_error = "continue" allows other groups to proceed on failure
- Baseline entries are automatically captured for each successful action
- PluginId is the plugin folder name (e.g., "example-declarative")

## Related Patterns

- **Hybrid**: `example-hybrid/plugin.ps1` - TOML for Seal + custom Rollback
- **Imperative**: `example-imperative/plugin.ps1` - Full PowerShell with direct executor calls
