diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 3178dff..495f808 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -30,7 +30,7 @@ powershell -ExecutionPolicy Bypass -File Tests\pssa-check.ps1
## Pull Request Checklist
-- [ ] All 5,032 tests pass (`Run-Tests.ps1` exits with code 0)
+- [ ] All 5,040 tests pass (`Run-Tests.ps1` exits with code 0)
- [ ] PSScriptAnalyzer reports 0 errors (`pssa-check.ps1`)
- [ ] Monolithic synced (`sync-to-monolithic.ps1` shows 0 parse errors)
- [ ] New functions follow PowerShell verb-noun naming (`Get-`, `Set-`, `Test-`, `Show-`)
diff --git a/Changelog.md b/Changelog.md
index 2851e0a..55819f4 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -1,5 +1,13 @@
# Changelog
+## v1.110.0
+
+Enable AD Recycle Bin — added to **AD DS Domain Controller Promotion** (`[6] Enable AD Recycle Bin`) and via the `ADRecycleBin` CLI action. Turns on Active Directory object recovery so deleted users/groups/OUs can be restored with their attributes intact.
+
+It checks the forest, warns that enabling is **permanent** (the AD Recycle Bin cannot be disabled once on) and requires a forest functional level of 2008 R2 or higher, confirms, then runs `Enable-ADOptionalFeature`. The action is Dry-Run-aware and queued as **one-way** (no undo, matching the irreversibility). `-Action ADRecycleBin -OutputFormat JSON` reports the current enabled state without changing anything.
+
+Addition to 61-ActiveDirectory (no new module). CLI actions: 192 → 193.
+
## v1.109.0
VHDX encryption-at-rest verification — added to **BitLocker Management** (`[7] VHDX Encryption-at-Rest Audit`) and via the `VHDXEncryptionAudit` CLI action. A **read-only** check that reports whether each Hyper-V VM's virtual disk (VHD/VHDX) sits on a BitLocker-protected volume — so you can confirm VM storage is encrypted at rest.
diff --git a/Header.ps1 b/Header.ps1
index 99932c0..4aa5ece 100644
--- a/Header.ps1
+++ b/Header.ps1
@@ -30,7 +30,7 @@
7h3 4b1d3r
.VERSION
- 1.109.0
+ 1.110.0
.LAST UPDATED
05/23/2026
@@ -1391,7 +1391,7 @@
param(
# CLI headless mode: run a specific action without interactive menus
# Usage: RackStack.exe -Action Cleanup [-Tier Standard] [-Silent] [-OutputFormat JSON]
- [ValidateSet('Cleanup', 'Debloat', 'HealthCheck', 'Batch', 'QuickScan', 'Inventory', 'DriftCheck', 'Snapshot', 'Compliance', 'Harden', 'Remediate', 'Aggregate', 'Compare', 'Export', 'Trend', 'CertCheck', 'ReportHTML', 'ListeningPorts', 'SoftwareList', 'Uptime', 'ServiceAudit', 'EventAudit', 'NetInfo', 'ScheduledExport', 'ValidateConfig', 'Watch', 'Query', 'Diff', 'Baseline', 'Alert', 'FleetScan', 'PatchStatus', 'UserAudit', 'FirewallAudit', 'TaskAudit', 'DiskAudit', 'TLSAudit', 'SMBAudit', 'DriverAudit', 'TimeAudit', 'BootAudit', 'GPOAudit', 'MemoryAudit', 'ProcessAudit', 'BackupAudit', 'ShareAudit', 'DNSAudit', 'PowerAudit', 'RegistryAudit', 'ProfileAudit', 'HyperVAudit', 'NetworkAudit', 'StorageAudit', 'FeatureAudit', 'AutoStartAudit', 'BIOSAudit', 'ClusterAudit', 'AuditPolicyAudit', 'EnvAudit', 'CrashAudit', 'LocalGroupAudit', 'WMIAudit', 'TempAudit', 'UpdatePolicyAudit', 'IISAudit', 'SSHAudit', 'BitLockerAudit', 'PrintAudit', 'CredGuardAudit', 'PortAudit', 'AntivirusAudit', 'DotNetAudit', 'RDPAudit', 'VPNAudit', 'HostsFileAudit', 'NetStatAudit', 'LicenseAudit', 'USBDeviceAudit', 'AppLockerAudit', 'EventSubAudit', 'HotfixAudit', 'SysInfoAudit', 'LogonAudit', 'ACLAudit', 'RecoveryAudit', 'ServiceAccountAudit', 'ProxyAudit', 'PendingRebootAudit', 'PageFileAudit', 'CPUAudit', 'DefenderExclusionAudit', 'KerberosAudit', 'DHCPAudit', 'NUMAAudit', 'SymlinkAudit', 'StartupScriptAudit', 'SecureChannelAudit', 'ComObjectAudit', 'FirewallLogAudit', 'ScheduledRebootAudit', 'PowerShellAudit', 'RouteTableAudit', 'TokenPrivilegeAudit', 'WindowsCapabilityAudit', 'ARPTableAudit', 'LocaleAudit', 'TaskHistoryAudit', 'NTFSAudit', 'Win11Cleanup', 'DarkMode', 'LightMode', 'iSCSIAudit', 'NICTeamAudit', 'SMBSessionAudit', 'WindowsUpdateAudit', 'ClusterQuorumAudit', 'S2DAudit', 'VirtualSwitchAudit', 'MPIOPathAudit', 'ServiceRecoveryAudit', 'VMOvercommitAudit', 'DedupAudit', 'ClusterNetworkAudit', 'ReplicaLagAudit', 'HandleLeakAudit', 'ShadowCopyAudit', 'QoSPolicyAudit', 'LiveMigrationAudit', 'DomainTrustAudit', 'DiskLatencyAudit', 'NICOffloadAudit', 'StorageTimeoutAudit', 'EventLogCapacityAudit', 'TcpSettingsAudit', 'WinRMAudit', 'ClusterHealthScore', 'VMInventoryExport', 'VMSnapshotAudit', 'StorageHealthScore', 'CSVSpaceAudit', 'SMBConnectionAudit', 'VolumeLabelAudit', 'NICErrorAudit', 'VMResourceWaste', 'HealthDashboard', 'SCCMClientAudit', 'SCOMAgentAudit', 'WACConnectivityAudit', 'AzureADAudit', 'ServerScore', 'FleetReport', 'PasswordPolicy', 'FirewallRuleAudit', 'GPResultAudit', 'DNSCacheAudit', 'TPMAudit', 'SecureBootAudit', 'TimeSkewAudit', 'NetworkProfileAudit', 'InsecureServiceAudit', 'SelfTest', 'CheckForUpdate', 'ExportLogs', 'UpdateSelf', 'Rollback', 'ScheduleUpdateCheck', 'Dashboard', 'History', 'Replay', 'AzureArcEnroll', 'DefenderEndpointOnboard', 'WSUSSetup', 'ADCSSetup', 'StorageMigrationSetup', 'GPOBackup', 'GPODrift', 'JEAList', 'NPSSetup', 'AlwaysOnVPNSetup', 'CISScan', 'SIEMSetup', 'SIEMStatus', 'WACSetup', 'WACStatus', 'VHDXEncryptionAudit')]
+ [ValidateSet('Cleanup', 'Debloat', 'HealthCheck', 'Batch', 'QuickScan', 'Inventory', 'DriftCheck', 'Snapshot', 'Compliance', 'Harden', 'Remediate', 'Aggregate', 'Compare', 'Export', 'Trend', 'CertCheck', 'ReportHTML', 'ListeningPorts', 'SoftwareList', 'Uptime', 'ServiceAudit', 'EventAudit', 'NetInfo', 'ScheduledExport', 'ValidateConfig', 'Watch', 'Query', 'Diff', 'Baseline', 'Alert', 'FleetScan', 'PatchStatus', 'UserAudit', 'FirewallAudit', 'TaskAudit', 'DiskAudit', 'TLSAudit', 'SMBAudit', 'DriverAudit', 'TimeAudit', 'BootAudit', 'GPOAudit', 'MemoryAudit', 'ProcessAudit', 'BackupAudit', 'ShareAudit', 'DNSAudit', 'PowerAudit', 'RegistryAudit', 'ProfileAudit', 'HyperVAudit', 'NetworkAudit', 'StorageAudit', 'FeatureAudit', 'AutoStartAudit', 'BIOSAudit', 'ClusterAudit', 'AuditPolicyAudit', 'EnvAudit', 'CrashAudit', 'LocalGroupAudit', 'WMIAudit', 'TempAudit', 'UpdatePolicyAudit', 'IISAudit', 'SSHAudit', 'BitLockerAudit', 'PrintAudit', 'CredGuardAudit', 'PortAudit', 'AntivirusAudit', 'DotNetAudit', 'RDPAudit', 'VPNAudit', 'HostsFileAudit', 'NetStatAudit', 'LicenseAudit', 'USBDeviceAudit', 'AppLockerAudit', 'EventSubAudit', 'HotfixAudit', 'SysInfoAudit', 'LogonAudit', 'ACLAudit', 'RecoveryAudit', 'ServiceAccountAudit', 'ProxyAudit', 'PendingRebootAudit', 'PageFileAudit', 'CPUAudit', 'DefenderExclusionAudit', 'KerberosAudit', 'DHCPAudit', 'NUMAAudit', 'SymlinkAudit', 'StartupScriptAudit', 'SecureChannelAudit', 'ComObjectAudit', 'FirewallLogAudit', 'ScheduledRebootAudit', 'PowerShellAudit', 'RouteTableAudit', 'TokenPrivilegeAudit', 'WindowsCapabilityAudit', 'ARPTableAudit', 'LocaleAudit', 'TaskHistoryAudit', 'NTFSAudit', 'Win11Cleanup', 'DarkMode', 'LightMode', 'iSCSIAudit', 'NICTeamAudit', 'SMBSessionAudit', 'WindowsUpdateAudit', 'ClusterQuorumAudit', 'S2DAudit', 'VirtualSwitchAudit', 'MPIOPathAudit', 'ServiceRecoveryAudit', 'VMOvercommitAudit', 'DedupAudit', 'ClusterNetworkAudit', 'ReplicaLagAudit', 'HandleLeakAudit', 'ShadowCopyAudit', 'QoSPolicyAudit', 'LiveMigrationAudit', 'DomainTrustAudit', 'DiskLatencyAudit', 'NICOffloadAudit', 'StorageTimeoutAudit', 'EventLogCapacityAudit', 'TcpSettingsAudit', 'WinRMAudit', 'ClusterHealthScore', 'VMInventoryExport', 'VMSnapshotAudit', 'StorageHealthScore', 'CSVSpaceAudit', 'SMBConnectionAudit', 'VolumeLabelAudit', 'NICErrorAudit', 'VMResourceWaste', 'HealthDashboard', 'SCCMClientAudit', 'SCOMAgentAudit', 'WACConnectivityAudit', 'AzureADAudit', 'ServerScore', 'FleetReport', 'PasswordPolicy', 'FirewallRuleAudit', 'GPResultAudit', 'DNSCacheAudit', 'TPMAudit', 'SecureBootAudit', 'TimeSkewAudit', 'NetworkProfileAudit', 'InsecureServiceAudit', 'SelfTest', 'CheckForUpdate', 'ExportLogs', 'UpdateSelf', 'Rollback', 'ScheduleUpdateCheck', 'Dashboard', 'History', 'Replay', 'AzureArcEnroll', 'DefenderEndpointOnboard', 'WSUSSetup', 'ADCSSetup', 'StorageMigrationSetup', 'GPOBackup', 'GPODrift', 'JEAList', 'NPSSetup', 'AlwaysOnVPNSetup', 'CISScan', 'SIEMSetup', 'SIEMStatus', 'WACSetup', 'WACStatus', 'VHDXEncryptionAudit', 'ADRecycleBin')]
[string]$Action,
[ValidateSet('Light', 'Standard', 'Aggressive')]
diff --git a/Modules/00-Initialization.ps1 b/Modules/00-Initialization.ps1
index 8d35193..514b839 100644
--- a/Modules/00-Initialization.ps1
+++ b/Modules/00-Initialization.ps1
@@ -225,7 +225,7 @@ if (-not $PSCommandPath -and $script:ScriptPath) {
if (-not $script:ModuleRoot -and $script:ScriptPath) {
$script:ModuleRoot = [System.IO.Path]::GetDirectoryName($script:ScriptPath)
}
-$script:ScriptVersion = "1.109.0"
+$script:ScriptVersion = "1.110.0"
$script:ScriptStartTime = Get-Date
# Post-update cleanup: UpdateSelf / Rollback leave a `.pending-delete` sibling next to RackStack.exe.
diff --git a/Modules/34-Help.ps1 b/Modules/34-Help.ps1
index f18b7b3..b1a469e 100644
--- a/Modules/34-Help.ps1
+++ b/Modules/34-Help.ps1
@@ -253,7 +253,7 @@ function Search-HelpTopics {
@{ Title = "Performance"; Keywords = @("performance", "cpu", "memory", "disk", "io", "bandwidth", "dashboard", "process"); Description = "Live performance dashboard with CPU, memory, disk I/O, and network bandwidth monitoring" }
@{ Title = "Licensing & NTP"; Keywords = @("license", "activation", "kms", "avma", "ntp", "time", "timezone", "clock"); Description = "Windows licensing status (KMS/AVMA/Retail), NTP configuration, time sync, and timezone setup" }
@{ Title = "VM Management"; Keywords = @("checkpoint", "snapshot", "export", "import", "migration", "vhd", "iso"); Description = "VM checkpoints, export/import, migration readiness, VHD health, and ISO inventory" }
- @{ Title = "CLI Actions"; Keywords = @("cli", "action", "headless", "automation", "fleet", "json", "audit", "scan", "score", "dashboard", "monitor", "policy", "sla", "netmap", "validate"); Description = "192 CLI actions for headless automation. Run -ListActions to see all. JSON output via -OutputFormat JSON. Key: ServerScore, HealthDashboard, FleetReport, CISScan, NPSSetup, AlwaysOnVPNSetup, SIEMStatus." }
+ @{ Title = "CLI Actions"; Keywords = @("cli", "action", "headless", "automation", "fleet", "json", "audit", "scan", "score", "dashboard", "monitor", "policy", "sla", "netmap", "validate"); Description = "193 CLI actions for headless automation. Run -ListActions to see all. JSON output via -OutputFormat JSON. Key: ServerScore, HealthDashboard, FleetReport, CISScan, NPSSetup, AlwaysOnVPNSetup, SIEMStatus." }
@{ Title = "SelfTest Action"; Keywords = @("selftest", "self-test", "diagnose", "diagnostic", "verify", "healthcheck", "sanity"); Description = "Internal diagnostic. -Action SelfTest checks PS version, elevation, module count, version consistency, defaults.json validity, temp path writability, FileServer reachability, and agent installer config. Exit 1 on any failure. Use -OutputFormat JSON for structured output." }
@{ Title = "Security Audits"; Keywords = @("security", "audit", "hardening", "compliance", "tls", "smb", "kerberos", "credguard", "applocker", "bitlockeraudit", "defenderexclusionaudit", "audit-policy", "secureboot", "tpm"); Description = "Security-focused CLI audits: TLSAudit, SMBAudit, KerberosAudit, CredGuardAudit, AppLockerAudit, BitLockerAudit, DefenderExclusionAudit, AuditPolicyAudit, SecureBootAudit, TPMAudit, UserAudit, LogonAudit, InsecureServiceAudit, RegistryAudit. All support -OutputFormat JSON." }
@{ Title = "Network Audits"; Keywords = @("netaudit", "dns", "firewall-audit", "firewalllog", "arp", "route", "tcp", "netstat", "dhcp", "netprofile", "winrm", "qos", "nicoffload"); Description = "Network audits: DNSAudit, DNSCacheAudit, FirewallAudit, FirewallRuleAudit, FirewallLogAudit, ARPTableAudit, RouteTableAudit, TcpSettingsAudit, NetStatAudit, DHCPAudit, NetworkProfileAudit, WinRMAudit, QoSPolicyAudit, NICOffloadAudit, NICErrorAudit, HostsFileAudit, VPNAudit, ProxyAudit." }
diff --git a/Modules/50-EntryPoint.ps1 b/Modules/50-EntryPoint.ps1
index f1c1d55..8b9a636 100644
--- a/Modules/50-EntryPoint.ps1
+++ b/Modules/50-EntryPoint.ps1
@@ -410,6 +410,7 @@ function Assert-Elevation {
@{ Action = 'WACSetup'; Description = 'Install + configure the Windows Admin Center gateway (verified MSI, port, certificate)' }
@{ Action = 'WACStatus'; Description = 'Show Windows Admin Center gateway status (service, port, listening)' }
@{ Action = 'VHDXEncryptionAudit'; Description = 'Read-only: report whether each VM virtual disk sits on a BitLocker-protected volume' }
+ @{ Action = 'ADRecycleBin'; Description = 'Show AD Recycle Bin status (JSON) or enable it interactively (irreversible)' }
@{ Action = 'Batch'; Description = 'JSON-driven full configuration' }
)
if ($script:CLIOutputFormat -eq 'JSON') {
@@ -2047,6 +2048,11 @@ footer{text-align:center;color:#999;font-size:12px;padding:16px}
$vhdxOk = Start-VHDXEncryptionAudit
[Environment]::Exit([int](-not $vhdxOk))
}
+ 'ADRecycleBin' {
+ # AD Recycle Bin status (JSON) / interactive enable (console).
+ $adrbOk = Start-ADRecycleBin
+ [Environment]::Exit([int](-not $adrbOk))
+ }
'Batch' {
if (-not $script:CLIConfig) {
Write-OutputColor " ERROR: -Action Batch requires -Config " -color "Error"
diff --git a/Modules/61-ActiveDirectory.ps1 b/Modules/61-ActiveDirectory.ps1
index 836a92e..b674a95 100644
--- a/Modules/61-ActiveDirectory.ps1
+++ b/Modules/61-ActiveDirectory.ps1
@@ -717,6 +717,7 @@ function Show-ADDSPromotionMenu {
Write-MenuItem -Text "[3] Read-Only Domain Controller (RODC)"
Write-MenuItem -Text "[4] Check AD DS Status"
Write-MenuItem -Text "[5] Replication Health Monitor"
+ Write-MenuItem -Text "[6] Enable AD Recycle Bin"
Write-OutputColor " └────────────────────────────────────────────────────────────────────────┘" -color "Info"
Write-OutputColor "" -color "Info"
Write-OutputColor " [B] ◄ Back" -color "Info"
@@ -732,8 +733,9 @@ function Show-ADDSPromotionMenu {
"3" { Install-ReadOnlyDC }
"4" { Show-ADDSStatus }
"5" { Show-ReplicationMonitor }
+ "6" { Enable-ADRecycleBinFeature }
default {
- Write-OutputColor " Invalid choice. Enter 1-5 or B." -color "Error"
+ Write-OutputColor " Invalid choice. Enter 1-6 or B." -color "Error"
Start-Sleep -Seconds 1
}
}
@@ -1472,4 +1474,78 @@ function Show-ADDSStatus {
Write-OutputColor "" -color "Info"
Write-PressEnter
}
+
+# Read-only: is the AD Recycle Bin optional feature enabled in this forest?
+function Test-ADRecycleBinStatus {
+ try {
+ if ($null -eq (Get-Command -Name Get-ADOptionalFeature -ErrorAction SilentlyContinue)) {
+ return [PSCustomObject]@{ Available = $false; Enabled = $false; Forest = ''; ForestMode = '' }
+ }
+ $forest = Get-ADForest -ErrorAction Stop
+ $feat = Get-ADOptionalFeature -Filter "Name -eq 'Recycle Bin Feature'" -ErrorAction Stop
+ $enabled = ($null -ne $feat -and @($feat.EnabledScopes).Count -gt 0)
+ return [PSCustomObject]@{ Available = $true; Enabled = $enabled; Forest = "$($forest.Name)"; ForestMode = "$($forest.ForestMode)" }
+ }
+ catch {
+ return [PSCustomObject]@{ Available = $false; Enabled = $false; Forest = ''; ForestMode = '' }
+ }
+}
+
+# Interactive: enable the AD Recycle Bin. IRREVERSIBLE once enabled.
+function Enable-ADRecycleBinFeature {
+ Clear-Host
+ Write-CenteredOutput "Enable AD Recycle Bin" -color "Info"
+ $s = Test-ADRecycleBinStatus
+ if (-not $s.Available) {
+ Write-OutputColor " Active Directory module unavailable (not a DC, or RSAT-AD-PowerShell missing)." -color "Error"; return
+ }
+ if ($s.Enabled) {
+ Write-OutputColor " AD Recycle Bin is already enabled for forest '$($s.Forest)'." -color "Info"; return
+ }
+ Write-OutputColor " Forest: $($s.Forest) (functional level: $($s.ForestMode))" -color "Info"
+ Write-OutputColor " WARNING: Enabling the AD Recycle Bin is PERMANENT — it cannot be disabled" -color "Warning"
+ Write-OutputColor " afterward, and requires a forest functional level of 2008 R2 or higher." -color "Warning"
+ if (-not (Confirm-UserAction -Message "Enable the AD Recycle Bin for '$($s.Forest)' (irreversible)?")) {
+ Write-OutputColor " Cancelled." -color "Info"; return
+ }
+
+ if ($script:DryRunMode -and -not $script:ApplyingDryRunQueue) {
+ $capForest = $s.Forest
+ Push-DryRunStep -Label "Enable AD Recycle Bin ($capForest)" -Category "ActiveDirectory" -OneWay $true `
+ -Params @{ Forest = $capForest } `
+ -Preflight { if ((Test-ADRecycleBinStatus).Enabled) { "AD Recycle Bin already enabled" } else { $true } }.GetNewClosure() `
+ -Apply {
+ Enable-ADOptionalFeature -Identity 'Recycle Bin Feature' -Scope ForestOrConfigurationSet -Target $capForest -Confirm:$false -ErrorAction Stop | Out-Null
+ }.GetNewClosure() `
+ -Undo { Write-OutputColor " AD Recycle Bin cannot be disabled once enabled — no undo." -color "Info" }.GetNewClosure()
+ Write-OutputColor " Queued (Dry-Run, ONE-WAY): enable AD Recycle Bin." -color "Warning"
+ Add-SessionChange -Category "DryRun" -Description "Queued AD Recycle Bin enable ($capForest)"
+ return
+ }
+
+ try {
+ Enable-ADOptionalFeature -Identity 'Recycle Bin Feature' -Scope ForestOrConfigurationSet -Target $s.Forest -Confirm:$false -ErrorAction Stop | Out-Null
+ Write-OutputColor " AD Recycle Bin enabled for forest '$($s.Forest)'." -color "Success"
+ Add-SessionChange -Category "ActiveDirectory" -Description "Enabled AD Recycle Bin ($($s.Forest))"
+ Clear-MenuCache
+ }
+ catch {
+ Write-OutputColor " Failed to enable AD Recycle Bin: $($_.Exception.Message)" -color "Error"
+ }
+}
+
+# CLI: ADRecycleBin — JSON status (read-only); interactive enable on console.
+function Start-ADRecycleBin {
+ if ($script:CLIOutputFormat -eq 'JSON') {
+ $s = Test-ADRecycleBinStatus
+ Write-Output (@{
+ Tool = $script:ToolFullName; Version = $script:ScriptVersion; Action = 'ADRecycleBin'
+ Timestamp = (Get-Date -Format "yyyy-MM-ddTHH:mm:ss"); Hostname = $env:COMPUTERNAME
+ Available = $s.Available; Enabled = $s.Enabled; Forest = $s.Forest; ForestMode = $s.ForestMode
+ } | ConvertTo-Json)
+ return $true
+ }
+ Enable-ADRecycleBinFeature
+ return $true
+}
#endregion
diff --git a/README.md b/README.md
index fac6c91..ac22b6d 100644
--- a/README.md
+++ b/README.md
@@ -28,7 +28,7 @@
-
+
@@ -37,7 +37,7 @@
---
-RackStack is a menu-driven PowerShell tool that automates everything between "Windows is installed" and "server is in production." Where sconfig gives you 15 options, RackStack gives you 192 CLI actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, clustering, VM deployment, cloud onboarding, and batch automation, all with undo, transaction rollback, and audit logging.
+RackStack is a menu-driven PowerShell tool that automates everything between "Windows is installed" and "server is in production." Where sconfig gives you 15 options, RackStack gives you 193 CLI actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, clustering, VM deployment, cloud onboarding, and batch automation, all with undo, transaction rollback, and audit logging.
Built for MSPs, sysadmins, and infrastructure teams who build servers repeatedly and want it done right every time.
@@ -61,7 +61,7 @@ Built for MSPs, sysadmins, and infrastructure teams who build servers repeatedly
**Automation** -- JSON-driven batch mode (24 idempotent steps with transaction rollback), Quick Setup Wizard, configuration export/import, HTML reports, JSON audit logging with rotation
-**Monitoring** -- 192 CLI actions with JSON output for fleet automation, `ServerScore` (unified 0-100 health grade), `HealthDashboard` (all-in-one monitoring endpoint), `ClusterHealthScore`, `StorageHealthScore`, System Center (SCCM/SCOM/WAC) + Azure AD/Intune integration
+**Monitoring** -- 193 CLI actions with JSON output for fleet automation, `ServerScore` (unified 0-100 health grade), `HealthDashboard` (all-in-one monitoring endpoint), `ClusterHealthScore`, `StorageHealthScore`, System Center (SCCM/SCOM/WAC) + Azure AD/Intune integration
**Cloud & Security** -- Azure Arc server onboarding (install the Connected Machine Agent, connect the host to Azure's hybrid management plane via service-principal auth); Microsoft Defender for Endpoint onboarding (activate the built-in EDR sensor against your tenant, with a built-in detection test)
@@ -439,7 +439,7 @@ $report.Issues
**Tiers:** `Light` (minimal, safe for prod), `Standard` (recommended), `Aggressive` (maximum cleanup/debloat).
-### 192 CLI Actions
+### 193 CLI Actions
| Category | Actions |
|----------|---------|
@@ -487,7 +487,7 @@ RackStack/
│ ├── ... # 75 more modules
│ └── 77-WindowsAdminCenter.ps1
├── Tests/
-│ ├── Run-Tests.ps1 # 5,032 automated tests
+│ ├── Run-Tests.ps1 # 5,040 automated tests
│ ├── Validate-Release.ps1 # Pre-release validation suite
│ └── ...
└── docs/
@@ -525,7 +525,7 @@ RackStack/
## Testing
```powershell
-# Full test suite (5,032 tests, ~4 minutes)
+# Full test suite (5,040 tests, ~4 minutes)
powershell -ExecutionPolicy Bypass -File Tests\Run-Tests.ps1
# PSScriptAnalyzer (0 errors on all 78 modules + monolithic)
diff --git a/RackStack.ps1 b/RackStack.ps1
index 92a450e..1411ebc 100644
--- a/RackStack.ps1
+++ b/RackStack.ps1
@@ -13,7 +13,7 @@
Environment-specific settings are configured via defaults.json.
.VERSION
- 1.109.0
+ 1.110.0
.NOTES
- Requires Windows Server 2012 R2 or later (or Windows 10/11 for testing)
diff --git a/RackStack.psd1 b/RackStack.psd1
index 437f641..74d06ad 100644
--- a/RackStack.psd1
+++ b/RackStack.psd1
@@ -1,6 +1,6 @@
-@{
+@{
RootModule = 'RackStack.psm1'
- ModuleVersion = '1.109.0'
+ ModuleVersion = '1.110.0'
GUID = 'c19b8e71-4a35-4f2b-9d06-8a24f7bc0e91'
Author = 'TheAbider'
CompanyName = 'TheAbider'
diff --git a/Tests/Run-Tests.ps1 b/Tests/Run-Tests.ps1
index 471e0e0..912b8dd 100644
--- a/Tests/Run-Tests.ps1
+++ b/Tests/Run-Tests.ps1
@@ -9045,6 +9045,29 @@ catch {
Write-TestResult "VHDX Encryption Audit Tests" $false $_.Exception.Message
}
+# ============================================================================
+# SECTION 177: AD DS RECYCLE BIN (v1.110.0, addition to 61-ActiveDirectory)
+# ============================================================================
+Write-SectionHeader "SECTION 177: AD DS RECYCLE BIN (61-ActiveDirectory)"
+
+try {
+ $adC = Get-Content "$modulesPath\61-ActiveDirectory.ps1" -Raw
+ Write-TestResult "61-AD: Test-ADRecycleBinStatus exists" ($adC -match 'function\s+Test-ADRecycleBinStatus\b')
+ Write-TestResult "61-AD: Enable-ADRecycleBinFeature exists" ($adC -match 'function\s+Enable-ADRecycleBinFeature\b')
+ Write-TestResult "61-AD: Start-ADRecycleBin exists" ($adC -match 'function\s+Start-ADRecycleBin\b')
+ # Enabling the Recycle Bin is irreversible -> dry-run step must be OneWay.
+ Write-TestResult "61-AD: AD Recycle Bin enable is OneWay in Dry-Run" ($adC -match 'Enable AD Recycle Bin[\s\S]{0,200}-OneWay \$true')
+ Write-TestResult "61-AD: uses Enable-ADOptionalFeature" ($adC -match "Enable-ADOptionalFeature -Identity 'Recycle Bin Feature'")
+ Write-TestResult "61-AD: menu routes [6] to Enable-ADRecycleBinFeature" ($adC -match '"6"\s*\{\s*Enable-ADRecycleBinFeature')
+ $adEntry = Get-Content "$modulesPath\50-EntryPoint.ps1" -Raw
+ Write-TestResult "50-EntryPoint: ADRecycleBin dispatch case" ($adEntry -match "'ADRecycleBin'\s*\{")
+ $adHeader = Get-Content (Join-Path $script:ModuleRoot "Header.ps1") -Raw
+ Write-TestResult "Header.ps1: ADRecycleBin in -Action ValidateSet" ($adHeader -match "'ADRecycleBin'")
+}
+catch {
+ Write-TestResult "AD Recycle Bin Tests" $false $_.Exception.Message
+}
+
# ============================================================================
# SECTION 174: DOCUMENTATION FRESHNESS (counts must match the codebase)
# ============================================================================
@@ -9391,7 +9414,7 @@ Write-TestResult "58-NetworkDiagnostics: specific invalid msg" ($ndContent -matc
# AD DS promotion menu — no double Write-PressEnter (sub-functions have their own)
$adContent = Get-Content -LiteralPath "$modulesPath\61-ActiveDirectory.ps1" -Raw
Write-TestResult "61-AD: no inline Write-PressEnter on sub-function calls" (-not ($adContent -match 'Install-NewForest;\s*Write-PressEnter'))
-Write-TestResult "61-AD: specific invalid msg" ($adContent -match 'Enter 1-5 or B')
+Write-TestResult "61-AD: specific invalid msg" ($adContent -match 'Enter 1-6 or B')
# No generic "Invalid choice." left in codebase
$genericInvalidCount = 0
@@ -13056,7 +13079,7 @@ try {
# Action list in -ListActions block has 160 entries
$listBlock = [regex]::Match($ep5, '\$actionList = @\([\s\S]*?\)[\s\S]{0,50}CLIOutputFormat').Value
$listActionCount = @([regex]::Matches($listBlock, "Action\s*=\s*'")).Count
- Write-TestResult "50-EntryPoint: action list has 192 entries" ($listActionCount -eq 192) "Found $listActionCount"
+ Write-TestResult "50-EntryPoint: action list has 193 entries" ($listActionCount -eq 193) "Found $listActionCount"
} catch {
Write-TestResult "v1.91.0 Tests" $false $_.Exception.Message
}
@@ -13089,7 +13112,7 @@ try {
# Action list count (should be 167 now)
$listBlock2 = [regex]::Match($ep6, '\$actionList = @\([\s\S]*?\)[\s\S]{0,50}CLIOutputFormat').Value
$actionCount2 = @([regex]::Matches($listBlock2, "Action\s*=\s*'")).Count
- Write-TestResult "50-EntryPoint: action list has 192 entries" ($actionCount2 -eq 192) "Found $actionCount2"
+ Write-TestResult "50-EntryPoint: action list has 193 entries" ($actionCount2 -eq 193) "Found $actionCount2"
} catch {
Write-TestResult "v1.92.0 Tests" $false $_.Exception.Message
}
@@ -13115,7 +13138,7 @@ try {
# Action count updated
$listBlock3 = [regex]::Match($ep7, '\$actionList = @\([\s\S]*?\)[\s\S]{0,50}CLIOutputFormat').Value
$actionCount3 = @([regex]::Matches($listBlock3, "Action\s*=\s*'")).Count
- Write-TestResult "50-EntryPoint: action list has 192 entries" ($actionCount3 -eq 192) "Found $actionCount3"
+ Write-TestResult "50-EntryPoint: action list has 193 entries" ($actionCount3 -eq 193) "Found $actionCount3"
} catch {
Write-TestResult "v1.93.0 Tests" $false $_.Exception.Message
}
@@ -13153,7 +13176,7 @@ try {
# Action list count
$listBlock4 = [regex]::Match($ep8, '\$actionList = @\([\s\S]*?\)[\s\S]{0,50}CLIOutputFormat').Value
$actionCount4 = @([regex]::Matches($listBlock4, "Action\s*=\s*'")).Count
- Write-TestResult "50-EntryPoint: action list has 192 entries" ($actionCount4 -eq 192) "Found $actionCount4"
+ Write-TestResult "50-EntryPoint: action list has 193 entries" ($actionCount4 -eq 193) "Found $actionCount4"
} catch {
Write-TestResult "v1.94.1 Tests" $false $_.Exception.Message
}
diff --git a/dist/chocolatey/rackstack.nuspec b/dist/chocolatey/rackstack.nuspec
index 222a123..3339524 100644
--- a/dist/chocolatey/rackstack.nuspec
+++ b/dist/chocolatey/rackstack.nuspec
@@ -18,7 +18,7 @@
windows-server hyper-v iscsi clustering powershell sysadmin automation msp admin-tools
PowerShell automation toolkit for configuring Windows Server hosts
-RackStack is a menu-driven PowerShell tool that automates everything between "Windows is installed" and "server is in production." 192 CLI actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, clustering, VM deployment, and batch automation, all with undo, transaction rollback, and audit logging.
+RackStack is a menu-driven PowerShell tool that automates everything between "Windows is installed" and "server is in production." 193 CLI actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI, clustering, VM deployment, and batch automation, all with undo, transaction rollback, and audit logging.
Built for MSPs, sysadmins, and infrastructure teams who build servers repeatedly and want it done right every time.
diff --git a/dist/scoop/rackstack.json b/dist/scoop/rackstack.json
index 4ae3c3f..639712f 100644
--- a/dist/scoop/rackstack.json
+++ b/dist/scoop/rackstack.json
@@ -1,7 +1,7 @@
{
"$schema": "https://raw.githubusercontent.com/ScoopInstaller/Scoop/master/schema.json",
"version": "0.0.0",
- "description": "PowerShell automation toolkit for configuring Windows Server hosts — Hyper-V virtualization hosts, failover cluster nodes, iSCSI storage clients, Active Directory members, and standalone servers. Ships as a code-signed EXE plus a PowerShell Gallery wrapper module exposing 192 structured CLI actions.",
+ "description": "PowerShell automation toolkit for configuring Windows Server hosts — Hyper-V virtualization hosts, failover cluster nodes, iSCSI storage clients, Active Directory members, and standalone servers. Ships as a code-signed EXE plus a PowerShell Gallery wrapper module exposing 193 structured CLI actions.",
"homepage": "https://github.com/TheAbider/RackStack",
"license": "MIT",
"url": "https://github.com/TheAbider/RackStack/releases/download/v0.0.0/RackStack.exe",
diff --git a/dist/winget/1.99.1/TheAbider.RackStack.locale.en-US.yaml b/dist/winget/1.99.1/TheAbider.RackStack.locale.en-US.yaml
index e85a82f..dee1fe9 100644
--- a/dist/winget/1.99.1/TheAbider.RackStack.locale.en-US.yaml
+++ b/dist/winget/1.99.1/TheAbider.RackStack.locale.en-US.yaml
@@ -13,7 +13,7 @@ Copyright: Copyright (c) 2026 TheAbider
ShortDescription: PowerShell automation toolkit for configuring Windows Server hosts.
Description: |-
RackStack is a menu-driven PowerShell tool that automates everything between
- "Windows is installed" and "server is in production." It provides 192 CLI
+ "Windows is installed" and "server is in production." It provides 193 CLI
actions and 60+ interactive menus covering networking, Hyper-V, SAN/iSCSI,
clustering, VM deployment, cloud onboarding, and batch automation, all with
undo, transaction rollback, and audit logging. Built for MSPs, sysadmins,