diff --git a/docs/reference/steps/step-create-identity.md b/docs/reference/steps/step-create-identity.md index 83cc4ab9..0bb9f0a5 100644 --- a/docs/reference/steps/step-create-identity.md +++ b/docs/reference/steps/step-create-identity.md @@ -9,8 +9,7 @@ - **Module**: `IdLE.Steps.Common` - **Implementation**: `Invoke-IdleStepCreateIdentity` - **Idempotent**: `Yes` -- **Contracts**: `Unknown` -- **Events**: Unknown +- **Required Capabilities**: `IdLE.Identity.Create` ## Synopsis @@ -18,7 +17,7 @@ Creates a new identity in the target system. ## Description -This is a provider-agnostic step. The host must supply a provider instance via +The host must supply a provider instance via Context.Providers[<ProviderAlias>] that implements CreateIdentity(identityKey, attributes) and returns an object with properties 'IdentityKey' and 'Changed'. @@ -38,7 +37,27 @@ Authentication: ## Inputs (With.*) -| Key | Required | -| --- | --- | -| IdentityKey | Yes | -| Attributes | Yes | +The following keys are required in the step's ``With`` configuration: + +| Key | Required | Description | +| --- | --- | --- | +| `Attributes` | Yes | Hashtable of attributes to set | +| `IdentityKey` | Yes | Unique identifier for the identity | + +## Example + +```powershell +@{ + Name = 'CreateIdentity Example' + Type = 'IdLE.Step.CreateIdentity' + With = @{ + Attributes = @{ GivenName = 'First'; Surname = 'Last' } + IdentityKey = 'user.name' + } +} +``` + +## See Also + +- [Capabilities Reference](../capabilities.md) - Details on required capabilities +- [Providers](../providers.md) - Available provider implementations diff --git a/docs/reference/steps/step-delete-identity.md b/docs/reference/steps/step-delete-identity.md index f090ffbc..c4b01633 100644 --- a/docs/reference/steps/step-delete-identity.md +++ b/docs/reference/steps/step-delete-identity.md @@ -9,8 +9,7 @@ - **Module**: `IdLE.Steps.Common` - **Implementation**: `Invoke-IdleStepDeleteIdentity` - **Idempotent**: `Yes` -- **Contracts**: `Unknown` -- **Events**: Unknown +- **Required Capabilities**: `IdLE.Identity.Delete` ## Synopsis @@ -18,7 +17,7 @@ Deletes an identity from the target system. ## Description -This is a provider-agnostic step. The host must supply a provider instance via +The host must supply a provider instance via Context.Providers[<ProviderAlias>] that implements DeleteIdentity(identityKey) and returns an object with properties 'IdentityKey' and 'Changed'. @@ -42,4 +41,25 @@ Authentication: ## Inputs (With.*) -_Unknown (not detected automatically). Document required With.* keys in the step help and/or use a supported pattern._ +The following keys are required in the step's ``With`` configuration: + +| Key | Required | Description | +| --- | --- | --- | +| `IdentityKey` | Yes | Unique identifier for the identity | + +## Example + +```powershell +@{ + Name = 'DeleteIdentity Example' + Type = 'IdLE.Step.DeleteIdentity' + With = @{ + IdentityKey = 'user.name' + } +} +``` + +## See Also + +- [Capabilities Reference](../capabilities.md) - Details on required capabilities +- [Providers](../providers.md) - Available provider implementations diff --git a/docs/reference/steps/step-disable-identity.md b/docs/reference/steps/step-disable-identity.md index cf5ee16b..35f00476 100644 --- a/docs/reference/steps/step-disable-identity.md +++ b/docs/reference/steps/step-disable-identity.md @@ -9,8 +9,7 @@ - **Module**: `IdLE.Steps.Common` - **Implementation**: `Invoke-IdleStepDisableIdentity` - **Idempotent**: `Yes` -- **Contracts**: `Unknown` -- **Events**: Unknown +- **Required Capabilities**: `IdLE.Identity.Disable` ## Synopsis @@ -18,7 +17,7 @@ Disables an identity in the target system. ## Description -This is a provider-agnostic step. The host must supply a provider instance via +The host must supply a provider instance via Context.Providers[<ProviderAlias>] that implements DisableIdentity(identityKey) and returns an object with properties 'IdentityKey' and 'Changed'. @@ -38,4 +37,25 @@ Authentication: ## Inputs (With.*) -_Unknown (not detected automatically). Document required With.* keys in the step help and/or use a supported pattern._ +The following keys are required in the step's ``With`` configuration: + +| Key | Required | Description | +| --- | --- | --- | +| `IdentityKey` | Yes | Unique identifier for the identity | + +## Example + +```powershell +@{ + Name = 'DisableIdentity Example' + Type = 'IdLE.Step.DisableIdentity' + With = @{ + IdentityKey = 'user.name' + } +} +``` + +## See Also + +- [Capabilities Reference](../capabilities.md) - Details on required capabilities +- [Providers](../providers.md) - Available provider implementations diff --git a/docs/reference/steps/step-emit-event.md b/docs/reference/steps/step-emit-event.md index dcde656f..61bbaeb3 100644 --- a/docs/reference/steps/step-emit-event.md +++ b/docs/reference/steps/step-emit-event.md @@ -9,8 +9,6 @@ - **Module**: `IdLE.Steps.Common` - **Implementation**: `Invoke-IdleStepEmitEvent` - **Idempotent**: `Unknown` -- **Contracts**: `Unknown` -- **Events**: Unknown ## Synopsis @@ -24,4 +22,22 @@ to write structured events. ## Inputs (With.*) -_Unknown (not detected automatically). Document required With.* keys in the step help and/or use a supported pattern._ +The required input keys could not be detected automatically. +Please refer to the step description and examples for usage details. + +## Example + +```powershell +@{ + Name = 'EmitEvent Example' + Type = 'IdLE.Step.EmitEvent' + With = @{ + # See step description for available options + } +} +``` + +## See Also + +- [Capabilities Reference](../capabilities.md) - Overview of IdLE capabilities +- [Providers](../providers.md) - Available provider implementations diff --git a/docs/reference/steps/step-enable-identity.md b/docs/reference/steps/step-enable-identity.md index 771ddcba..90051687 100644 --- a/docs/reference/steps/step-enable-identity.md +++ b/docs/reference/steps/step-enable-identity.md @@ -9,8 +9,7 @@ - **Module**: `IdLE.Steps.Common` - **Implementation**: `Invoke-IdleStepEnableIdentity` - **Idempotent**: `Yes` -- **Contracts**: `Unknown` -- **Events**: Unknown +- **Required Capabilities**: `IdLE.Identity.Enable` ## Synopsis @@ -18,7 +17,7 @@ Enables an identity in the target system. ## Description -This is a provider-agnostic step. The host must supply a provider instance via +The host must supply a provider instance via Context.Providers[<ProviderAlias>] that implements EnableIdentity(identityKey) and returns an object with properties 'IdentityKey' and 'Changed'. @@ -38,4 +37,25 @@ Authentication: ## Inputs (With.*) -_Unknown (not detected automatically). Document required With.* keys in the step help and/or use a supported pattern._ +The following keys are required in the step's ``With`` configuration: + +| Key | Required | Description | +| --- | --- | --- | +| `IdentityKey` | Yes | Unique identifier for the identity | + +## Example + +```powershell +@{ + Name = 'EnableIdentity Example' + Type = 'IdLE.Step.EnableIdentity' + With = @{ + IdentityKey = 'user.name' + } +} +``` + +## See Also + +- [Capabilities Reference](../capabilities.md) - Details on required capabilities +- [Providers](../providers.md) - Available provider implementations diff --git a/docs/reference/steps/step-ensure-attribute.md b/docs/reference/steps/step-ensure-attribute.md index a569a1e1..84edda1d 100644 --- a/docs/reference/steps/step-ensure-attribute.md +++ b/docs/reference/steps/step-ensure-attribute.md @@ -9,8 +9,7 @@ - **Module**: `IdLE.Steps.Common` - **Implementation**: `Invoke-IdleStepEnsureAttribute` - **Idempotent**: `Yes` -- **Contracts**: `Provider must implement method: EnsureAttribute` -- **Events**: Unknown +- **Required Capabilities**: `IdLE.Identity.Attribute.Ensure` ## Synopsis @@ -18,7 +17,7 @@ Ensures that an identity attribute matches the desired value. ## Description -This is a provider-agnostic step. The host must supply a provider instance via +The host must supply a provider instance via Context.Providers[<ProviderAlias>]. The provider must implement an EnsureAttribute method with the signature (IdentityKey, Name, Value) and return an object that contains a boolean property 'Changed'. @@ -38,8 +37,29 @@ Authentication: ## Inputs (With.*) -| Key | Required | -| --- | --- | -| IdentityKey | Yes | -| Name | Yes | -| Value | Yes | +The following keys are required in the step's ``With`` configuration: + +| Key | Required | Description | +| --- | --- | --- | +| `IdentityKey` | Yes | Unique identifier for the identity | +| `Name` | Yes | Name of the attribute or property | +| `Value` | Yes | Desired value to set | + +## Example + +```powershell +@{ + Name = 'EnsureAttribute Example' + Type = 'IdLE.Step.EnsureAttribute' + With = @{ + IdentityKey = 'user.name' + Name = 'AttributeName' + Value = 'AttributeValue' + } +} +``` + +## See Also + +- [Capabilities Reference](../capabilities.md) - Details on required capabilities +- [Providers](../providers.md) - Available provider implementations diff --git a/docs/reference/steps/step-ensure-entitlement.md b/docs/reference/steps/step-ensure-entitlement.md index 63dbbe96..80d36180 100644 --- a/docs/reference/steps/step-ensure-entitlement.md +++ b/docs/reference/steps/step-ensure-entitlement.md @@ -9,8 +9,7 @@ - **Module**: `IdLE.Steps.Common` - **Implementation**: `Invoke-IdleStepEnsureEntitlement` - **Idempotent**: `Yes` -- **Contracts**: `Unknown` -- **Events**: Unknown +- **Required Capabilities**: `IdLE.Entitlement.List`, `IdLE.Entitlement.Grant`, `IdLE.Entitlement.Revoke` ## Synopsis @@ -44,8 +43,29 @@ Authentication: ## Inputs (With.*) -| Key | Required | -| --- | --- | -| IdentityKey | Yes | -| Entitlement | Yes | -| State | Yes | +The following keys are required in the step's ``With`` configuration: + +| Key | Required | Description | +| --- | --- | --- | +| `Entitlement` | Yes | Entitlement identifier or object | +| `IdentityKey` | Yes | Unique identifier for the identity | +| `State` | Yes | Desired state for the entitlement | + +## Example + +```powershell +@{ + Name = 'EnsureEntitlement Example' + Type = 'IdLE.Step.EnsureEntitlement' + With = @{ + Entitlement = @{ Kind = 'Group'; Id = 'GroupId'; DisplayName = 'Example Group' } + IdentityKey = 'user.name' + State = 'Present' + } +} +``` + +## See Also + +- [Capabilities Reference](../capabilities.md) - Details on required capabilities +- [Providers](../providers.md) - Available provider implementations diff --git a/docs/reference/steps/step-move-identity.md b/docs/reference/steps/step-move-identity.md index 48134535..a69d8266 100644 --- a/docs/reference/steps/step-move-identity.md +++ b/docs/reference/steps/step-move-identity.md @@ -9,8 +9,7 @@ - **Module**: `IdLE.Steps.Common` - **Implementation**: `Invoke-IdleStepMoveIdentity` - **Idempotent**: `Yes` -- **Contracts**: `Unknown` -- **Events**: Unknown +- **Required Capabilities**: `IdLE.Identity.Move` ## Synopsis @@ -18,7 +17,7 @@ Moves an identity to a different container/OU in the target system. ## Description -This is a provider-agnostic step. The host must supply a provider instance via +The host must supply a provider instance via Context.Providers[<ProviderAlias>] that implements MoveIdentity(identityKey, targetContainer) and returns an object with properties 'IdentityKey' and 'Changed'. @@ -38,7 +37,27 @@ Authentication: ## Inputs (With.*) -| Key | Required | -| --- | --- | -| IdentityKey | Yes | -| TargetContainer | Yes | +The following keys are required in the step's ``With`` configuration: + +| Key | Required | Description | +| --- | --- | --- | +| `IdentityKey` | Yes | Unique identifier for the identity | +| `TargetContainer` | Yes | See step description for details | + +## Example + +```powershell +@{ + Name = 'MoveIdentity Example' + Type = 'IdLE.Step.MoveIdentity' + With = @{ + IdentityKey = 'user.name' + TargetContainer = '' + } +} +``` + +## See Also + +- [Capabilities Reference](../capabilities.md) - Details on required capabilities +- [Providers](../providers.md) - Available provider implementations diff --git a/docs/reference/steps/step-trigger-directory-sync.md b/docs/reference/steps/step-trigger-directory-sync.md index 8edaa1b7..c80813e2 100644 --- a/docs/reference/steps/step-trigger-directory-sync.md +++ b/docs/reference/steps/step-trigger-directory-sync.md @@ -9,8 +9,7 @@ - **Module**: `IdLE.Steps.DirectorySync` - **Implementation**: `Invoke-IdleStepTriggerDirectorySync` - **Idempotent**: `Unknown` -- **Contracts**: `Unknown` -- **Events**: Unknown +- **Required Capabilities**: `IdLE.DirectorySync.Trigger`, `IdLE.DirectorySync.Status` ## Synopsis @@ -18,7 +17,7 @@ Triggers a directory sync cycle and optionally waits for completion. ## Description -This is a provider-agnostic step. The host must supply a provider instance via +The host must supply a provider instance via Context.Providers[<ProviderAlias>] that implements: - StartSyncCycle(PolicyType, AuthSession) @@ -38,4 +37,27 @@ Authentication: ## Inputs (With.*) -_Unknown (not detected automatically). Document required With.* keys in the step help and/or use a supported pattern._ +The following keys are required in the step's ``With`` configuration: + +| Key | Required | Description | +| --- | --- | --- | +| `AuthSessionName` | Yes | Name of auth session to use (optional) | +| `PolicyType` | Yes | Type of policy (e.g., Delta, Initial) | + +## Example + +```powershell +@{ + Name = 'TriggerDirectorySync Example' + Type = 'IdLE.Step.TriggerDirectorySync' + With = @{ + AuthSessionName = 'AdminSession' + PolicyType = 'Delta' + } +} +``` + +## See Also + +- [Capabilities Reference](../capabilities.md) - Details on required capabilities +- [Providers](../providers.md) - Available provider implementations diff --git a/tools/Generate-IdleStepReference.ps1 b/tools/Generate-IdleStepReference.ps1 index 6a999277..8bd1e362 100644 --- a/tools/Generate-IdleStepReference.ps1 +++ b/tools/Generate-IdleStepReference.ps1 @@ -206,6 +206,7 @@ function Get-IdleRequiredWithKeysFromSource { # Best-effort heuristic: detect patterns like: # foreach ($key in @('IdentityKey','Name','Value')) { ... } + # OR throw messages like: "StepName requires With.KeyName." $filePath = $null if ($CommandInfo.ScriptBlock -and $CommandInfo.ScriptBlock.File) { $filePath = $CommandInfo.ScriptBlock.File @@ -216,21 +217,48 @@ function Get-IdleRequiredWithKeysFromSource { } $content = Get-Content -Path $filePath -Raw -ErrorAction Stop + $keys = @() + # Pattern 1: foreach loop with key array $m = [regex]::Match( $content, 'foreach\s*\(\s*\$key\s+in\s+@\((?[^)]*)\)\s*\)', 'IgnoreCase' ) - if (-not $m.Success) { - return @() + if ($m.Success) { + $listText = $m.Groups['List'].Value + $foreachKeys = [regex]::Matches($listText, "'(?[^']+)'") | ForEach-Object { $_.Groups['Key'].Value } + $keys += $foreachKeys + } + + # Pattern 2: throw messages like "requires With.KeyName" + $throwMatches = [regex]::Matches( + $content, + 'throw\s+[^"]*"[^"]*requires\s+With\.(?[A-Za-z][A-Za-z0-9]*)', + 'IgnoreCase' + ) + foreach ($match in $throwMatches) { + $keys += $match.Groups['Key'].Value } - $listText = $m.Groups['List'].Value - $keys = [regex]::Matches($listText, "'(?[^']+)'") | ForEach-Object { $_.Groups['Key'].Value } + # Pattern 3: ContainsKey checks followed by throw + $containsMatches = [regex]::Matches( + $content, + '\$with\.ContainsKey\(''(?[^'']+)''\)', + 'IgnoreCase' + ) + foreach ($match in $containsMatches) { + $keyName = $match.Groups['Key'].Value + # Only include if there's a throw statement nearby (within next 100 chars) + $matchPos = $match.Index + $nextChunk = $content.Substring($matchPos, [Math]::Min(150, $content.Length - $matchPos)) + if ($nextChunk -match 'throw') { + $keys += $keyName + } + } - return @($keys | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique) + return @($keys | Where-Object { -not [string]::IsNullOrWhiteSpace($_) } | Select-Object -Unique | Sort-Object) } function Get-IdleProviderMethodHintFromDescription { @@ -332,6 +360,53 @@ function Get-IdleCommandModuleName { return 'Unknown' } +function Get-IdleStepRequiredCapabilities { + [CmdletBinding()] + param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $StepType, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $ModuleName + ) + + # Try to load metadata catalog from the step's module to get required capabilities + try { + # Disambiguate in case multiple versions of the module are loaded + $module = Get-Module -Name $ModuleName -All -ErrorAction SilentlyContinue | Select-Object -First 1 + if ($null -ne $module) { + # Call Get-IdleStepMetadataCatalog in the context of the specific module + $catalog = & $module { Get-IdleStepMetadataCatalog -ErrorAction SilentlyContinue } + if ($catalog -is [System.Collections.IDictionary]) { + $fullStepTypeName = "IdLE.Step.$StepType" + if ($catalog.Contains($fullStepTypeName)) { + $metadata = $catalog[$fullStepTypeName] + if ($metadata) { + $requiredCapabilities = $null + if ($metadata -is [System.Collections.IDictionary] -and $metadata.Contains('RequiredCapabilities')) { + $requiredCapabilities = $metadata['RequiredCapabilities'] + } + elseif ($metadata.PSObject -and $metadata.PSObject.Properties['RequiredCapabilities']) { + $requiredCapabilities = $metadata.RequiredCapabilities + } + + if ($null -ne $requiredCapabilities) { + return @($requiredCapabilities) + } + } + } + } + } + } + catch { + # Metadata catalog not available or error loading it + } + + return @() +} + function New-IdleStepDocModel { [CmdletBinding()] param( @@ -367,6 +442,9 @@ function New-IdleStepDocModel { $synopsis = 'No synopsis available (missing comment-based help).' } + # Remove redundant "This is a provider-agnostic step." sentence + $description = $description -replace '(?i)This\s+is\s+a\s+provider-agnostic\s+step\.\s*', '' + $requiredWithKeys = @(Get-IdleRequiredWithKeysFromSource -CommandInfo $CommandInfo) $idempotent = 'Unknown' @@ -374,21 +452,21 @@ function New-IdleStepDocModel { $idempotent = 'Yes' } - $providerMethod = Get-IdleProviderMethodHintFromDescription -DescriptionText $description - $contracts = if ($providerMethod) { "Provider must implement method: $providerMethod" } else { 'Unknown' } + # Get required capabilities from metadata catalog + $requiredCapabilities = @(Get-IdleStepRequiredCapabilities -StepType $stepType -ModuleName $moduleName) $slug = ConvertTo-IdleStepSlug -StepType $stepType return [pscustomobject]@{ - StepType = $stepType - Slug = $slug - ModuleName = $moduleName - CommandName = $commandName - Synopsis = $synopsis - Description = $description - RequiredWithKeys = $requiredWithKeys - Idempotent = $idempotent - Contracts = $contracts + StepType = $stepType + Slug = $slug + ModuleName = $moduleName + CommandName = $commandName + Synopsis = $synopsis + Description = $description + RequiredWithKeys = $requiredWithKeys + Idempotent = $idempotent + RequiredCapabilities = $requiredCapabilities } } @@ -414,8 +492,12 @@ function New-IdleStepDetailPageContent { [void]$sb.AppendLine(("- **Module**: ``{0}``" -f $Model.ModuleName)) [void]$sb.AppendLine(("- **Implementation**: ``{0}``" -f $Model.CommandName)) [void]$sb.AppendLine(("- **Idempotent**: ``{0}``" -f $Model.Idempotent)) - [void]$sb.AppendLine(("- **Contracts**: ``{0}``" -f $Model.Contracts)) - [void]$sb.AppendLine(("- **Events**: Unknown")) + + # Only show Required Capabilities if we have any + if ($Model.RequiredCapabilities -and $Model.RequiredCapabilities.Count -gt 0) { + $capsFormatted = ($Model.RequiredCapabilities | ForEach-Object { "``$_``" }) -join ', ' + [void]$sb.AppendLine(("- **Required Capabilities**: {0}" -f $capsFormatted)) + } [void]$sb.AppendLine() [void]$sb.AppendLine('## Synopsis') @@ -434,18 +516,93 @@ function New-IdleStepDetailPageContent { [void]$sb.AppendLine() if ($Model.RequiredWithKeys.Count -eq 0) { - [void]$sb.AppendLine('_Unknown (not detected automatically). Document required With.* keys in the step help and/or use a supported pattern._') + [void]$sb.AppendLine('The required input keys could not be detected automatically.') + [void]$sb.AppendLine('Please refer to the step description and examples for usage details.') [void]$sb.AppendLine() } else { - [void]$sb.AppendLine('| Key | Required |') - [void]$sb.AppendLine('| --- | --- |') + [void]$sb.AppendLine('The following keys are required in the step''s ``With`` configuration:') + [void]$sb.AppendLine() + [void]$sb.AppendLine('| Key | Required | Description |') + [void]$sb.AppendLine('| --- | --- | --- |') foreach ($k in $Model.RequiredWithKeys) { - [void]$sb.AppendLine("| $k | Yes |") + # Add basic description based on common key patterns + $keyDescription = switch ($k) { + 'IdentityKey' { 'Unique identifier for the identity' } + 'Name' { 'Name of the attribute or property' } + 'Value' { 'Desired value to set' } + 'Attributes' { 'Hashtable of attributes to set' } + 'DestinationPath' { 'Target location or path' } + 'Message' { 'Message text to emit (optional for EmitEvent step)' } + 'EntitlementType' { 'Type of entitlement (e.g., Group, License)' } + 'EntitlementValue' { 'Specific entitlement identifier' } + 'Entitlement' { 'Entitlement identifier or object' } + 'State' { 'Desired state for the entitlement' } + 'Ensure' { 'Desired state (Present or Absent)' } + 'Provider' { 'Provider alias (optional, defaults vary by step)' } + 'AuthSessionName' { 'Name of auth session to use (optional)' } + 'PolicyType' { 'Type of policy (e.g., Delta, Initial)' } + 'Wait' { 'Whether to wait for completion' } + default { 'See step description for details' } + } + [void]$sb.AppendLine("| ``$k`` | Yes | $keyDescription |") } [void]$sb.AppendLine() } + # Add examples section + [void]$sb.AppendLine('## Example') + [void]$sb.AppendLine() + [void]$sb.AppendLine('```powershell') + [void]$sb.AppendLine('@{') + [void]$sb.AppendLine((" Name = '{0} Example'" -f $Model.StepType)) + [void]$sb.AppendLine((" Type = 'IdLE.Step.{0}'" -f $Model.StepType)) + [void]$sb.AppendLine(' With = @{') + + if ($Model.RequiredWithKeys.Count -gt 0) { + foreach ($k in $Model.RequiredWithKeys) { + $exampleValue = switch ($k) { + 'IdentityKey' { '''user.name''' } + 'Name' { '''AttributeName''' } + 'Value' { '''AttributeValue''' } + 'Attributes' { "@{ GivenName = 'First'; Surname = 'Last' }" } + 'DestinationPath' { '''OU=Users,DC=domain,DC=com''' } + 'Message' { '''Custom event message''' } + 'EntitlementType' { '''Group''' } + 'EntitlementValue' { '''CN=GroupName,OU=Groups,DC=domain,DC=com''' } + 'Entitlement' { "@{ Kind = 'Group'; Id = 'GroupId'; DisplayName = 'Example Group' }" } + 'State' { '''Present''' } + 'Ensure' { '''Present''' } + 'Provider' { '''Identity''' } + 'AuthSessionName' { '''AdminSession''' } + 'PolicyType' { '''Delta''' } + 'Wait' { '$true' } + default { '''''' } + } + [void]$sb.AppendLine((" {0,-20} = {1}" -f $k, $exampleValue)) + } + } + else { + [void]$sb.AppendLine(' # See step description for available options') + } + + [void]$sb.AppendLine(' }') + [void]$sb.AppendLine('}') + [void]$sb.AppendLine('```') + [void]$sb.AppendLine() + + # Add "See Also" section for consistency across all step pages + [void]$sb.AppendLine('## See Also') + [void]$sb.AppendLine() + if ($Model.RequiredCapabilities -and $Model.RequiredCapabilities.Count -gt 0) { + [void]$sb.AppendLine('- [Capabilities Reference](../capabilities.md) - Details on required capabilities') + } + else { + [void]$sb.AppendLine('- [Capabilities Reference](../capabilities.md) - Overview of IdLE capabilities') + } + [void]$sb.AppendLine('- [Providers](../providers.md) - Available provider implementations') + [void]$sb.AppendLine() + # Normalize output: ensure exactly one LF at EOF. return ($sb.ToString().TrimEnd()) + "`n" }