Prerequisites
💡 Summary
Several internal helper functions across ScubaGear modules still use hardcoded [ValidateSet] attributes for the -M365Environment parameter rather than deriving valid values dynamically from ScubaConfigDefaults.json via [ScubaConfig]::GetSupportedEnvironments(). This issue tracks updating those functions so that adding a new environment to the JSON schema is the single source of truth with no code changes required in multiple files.
Motivation and context
ScubaGear is designed so that ScubaConfigDefaults.json is the single source of truth for supported
M365 environments and Products. Adding a new environment (e.g., a new sovereign cloud) should require only a
JSON update; not code changes scattered across multiple .psm1 files.
Today that goal is not fully realized. Six internal helper functions each maintain their own
hardcoded copy of the environment list, both in [ValidateSet] parameter declarations and in
switch statements that map environment names to endpoint URLs and OAuth scopes. A developer
adding a new environment to the schema must know to find and update all of these locations manually.
Miss one and the result is either a confusing internal validation error or silent misbehavior
(wrong endpoint, null URL) that is difficult to trace back to the root cause.
Implementation notes
- Add
using module for ScubaConfig
At the top of each affected file, add:
using module '..\ScubaConfig\ScubaConfig.psm1'
- Replace
[ValidateSet] on -M365Environment
Before:
[ValidateSet('commercial', 'gcc', 'gcchigh', 'dod')]
[string]$M365Environment
After:
powershell [ValidateScript({ $_ -in [ScubaConfig]::GetSupportedEnvironments() })] [string]$M365Environment
- Replace
[ValidateSet] on -ProductNames
Before:
[ValidateSet('aad', 'exo', 'powerplatform', 'sharepoint', 'teams', 'powerbi', 'securitysuite', '*')]
[string[]]$ProductNames
After:
[ValidateScript({
$valid = @([ScubaConfig]::ScubaDefault('AllProductNames')) + '*'
$_ | ForEach-Object {
if ($_ -notin $valid) {
throw "Invalid ProductName '$_'. Valid values: $($valid -join ', ')"
}
}
$true
})]
[string[]]$ProductNames
- Update hardcoded wildcard expansion
Before:
if ($ProductNames -contains '*') {
$ProductNames = @('aad', 'exo', 'powerplatform', 'sharepoint', 'teams', 'powerbi', 'securitysuite')
}
After:
if ($ProductNames -contains '*') {
$ProductNames = [ScubaConfig]::ScubaDefault('AllProductNames')
}
- Register tab completers in
ScubaGear.psm1
Add the following block at the bottom of ScubaGear.psm1 (after all Import-Module calls):
$m365Completer = {
param($cmd, $param, $word, $ast, $fakeBound)
[ScubaConfig]::GetSupportedEnvironments() | Where-Object { $_ -like "$word*" }
}
$productCompleter = {
param($cmd, $param, $word, $ast, $fakeBound)
(@([ScubaConfig]::ScubaDefault('AllProductNames')) + '*') | Where-Object { $_ -like "$word*" }
}
$scubaModules = Get-Module | Where-Object { $_.Path -like "$PSScriptRoot*" }
$m365Functions = Get-Command -Module $scubaModules |
Where-Object { $_.Parameters.ContainsKey('M365Environment') } |
Select-Object -ExpandProperty Name
$productFunctions = Get-Command -Module $scubaModules |
Where-Object { $_.Parameters.ContainsKey('ProductNames') } |
Select-Object -ExpandProperty Name
foreach ($fn in $m365Functions) {
Register-ArgumentCompleter -CommandName $fn -ParameterName 'M365Environment' -ScriptBlock $m365Completer
}
foreach ($fn in $productFunctions) {
Register-ArgumentCompleter -CommandName $fn -ParameterName 'ProductNames' -ScriptBlock $productCompleter
}
Register-ArgumentCompleter handles tab completion. [ValidateScript] handles
runtime validation. Both are needed — neither replaces the other.
Acceptance criteria
Prerequisites
💡 Summary
Several internal helper functions across ScubaGear modules still use hardcoded
[ValidateSet]attributes for the-M365Environmentparameter rather than deriving valid values dynamically fromScubaConfigDefaults.jsonvia[ScubaConfig]::GetSupportedEnvironments(). This issue tracks updating those functions so that adding a new environment to the JSON schema is the single source of truth with no code changes required in multiple files.Motivation and context
ScubaGear is designed so that
ScubaConfigDefaults.jsonis the single source of truth for supportedM365 environments and Products. Adding a new environment (e.g., a new sovereign cloud) should require only a
JSON update; not code changes scattered across multiple
.psm1files.Today that goal is not fully realized. Six internal helper functions each maintain their own
hardcoded copy of the environment list, both in
[ValidateSet]parameter declarations and inswitchstatements that map environment names to endpoint URLs and OAuth scopes. A developeradding a new environment to the schema must know to find and update all of these locations manually.
Miss one and the result is either a confusing internal validation error or silent misbehavior
(wrong endpoint, null URL) that is difficult to trace back to the root cause.
Implementation notes
using modulefor ScubaConfigAt the top of each affected file, add:
using module '..\ScubaConfig\ScubaConfig.psm1'[ValidateSet]on-M365EnvironmentBefore:
After:
powershell [ValidateScript({ $_ -in [ScubaConfig]::GetSupportedEnvironments() })] [string]$M365Environment [ValidateSet]on-ProductNamesBefore:
After:
Before:
After:
ScubaGear.psm1Add the following block at the bottom of
ScubaGear.psm1(after allImport-Modulecalls):Acceptance criteria
[ValidateSet]remains on-M365Environmentin any of thelisted files.
[ScubaConfig]rather than matching against a hardcoded list.ScubaConfigDefaults.jsonrequires no changesto any of the listed files.
supported environments.