diff --git a/CHANGELOG.md b/CHANGELOG.md index 1b3e18e..195510d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,28 @@ -## Preview documentation refresh (unreleased) +# IT-ToolBox - Change History + +## 3.0.0-beta1 - 2026-10-05 + +The modernization review is complete. This beta retains the 29-command API and +PowerShell 7.4 baseline. Live AD, remote CIM and service authentication still +require integration validation. This entry does not announce a GitHub release +or PowerShell Gallery publication. + +### Beta release preparation + +- Promote manifest prerelease metadata from alpha1 to beta1. +- Improve project documentation, command help and code formatting. +- Add contributor templates and a security policy. +- Include the contributing guide and security policy in installable archives. +- Restore explicit four-space indentation and branch-selection instructions. +- Consolidate completed modernization history below and retain older releases. + +### Preview documentation refresh - Document cloning, local import, updates, command help and platform requirements. - Clarify v2 migration boundaries and supported preview commands. - Add contributing instructions for feature branches, four-space style and CI. -## Supported module packaging (unreleased) +### Supported module packaging - Add a local ZIP builder with conventional IT-ToolBox/version module layout. - Package supported code and documentation only; exclude legacy and development files. @@ -12,7 +30,7 @@ - Add real archive-content and isolated import/logger tests to the three-platform CI. - Document preview installation; retain alpha1 metadata without publishing or signing. -## Integration boundary review (unreleased) +### Integration boundary review - Remove the obsolete Close-AzureSession helper and document service-specific authentication ownership. - Remove the process-wide certificate-validation bypass snippet; retain Git history. @@ -23,7 +41,7 @@ - Add isolated import/reload regression coverage for TLS, sessions and archive exclusion. - Retain the 29-command supported API and alpha1 preview version. -## Script-context helper restoration (unreleased) +### Script-context helper restoration - Restore Get-ScriptDirectory and Get-ScriptName; export twenty-nine commands. - Resolve the immediately calling script rather than module-scoped invocation data. @@ -32,7 +50,7 @@ - Remove dependence on the externally supplied hostinvocation variable. - Add real script, nested/dot-sourced caller and isolated interactive regression tests. -## AD helper restoration (unreleased) +### AD helper restoration - Restore Test-IsValidDn, Test-IsValidUpn and Get-ReportChain; export twenty-seven commands. - Replace DN/UPN regexes with documented practical syntax policies and pipeline support. @@ -43,7 +61,7 @@ - Keep ActiveDirectory optional at import; add mocked query and syntax regression tests. - Complete migration of all former Staging/v3 candidates. -## Filesystem naming and registry restoration (unreleased) +### Filesystem naming and registry restoration - Restore Remove-SpecialCharacters and Test-RegistryValue; export twenty-four commands. - Preserve the historical punctuation policy; return a rename preview by default. @@ -54,7 +72,7 @@ - Propagate operational failures and document platform and non-transactional behavior. - Add real filesystem tests and Windows-only temporary HKCU integration tests. -## Timestamp and uptime restoration (unreleased) +### Timestamp and uptime restoration - Restore Convert-LogonTimestamp and Get-OsUpTime; export twenty-two supported commands. - Preserve local DateTime and default date formatting; add UTC and pipeline conversion. @@ -65,7 +83,7 @@ - Propagate errors without changing caller preferences; document remote Windows requirements. - Add boundary, culture, local uptime and mocked CIM regression tests. -## Email and URL validation restoration (unreleased) +### Email and URL validation restoration - Restore Test-IsEmail and Test-IsUrl; export twenty supported commands. - Preserve email parameter aliases and the HTTP/HTTPS/FTP/FTPS scheme set. @@ -75,7 +93,7 @@ - Document intentional validation-policy changes and reduce staged candidates to seven. - Add 96 validator cases covering boundaries, Unicode, IPv6 and malformed inputs. -## Logging and timer audit fixes (unreleased) +### Logging and timer audit fixes - Treat redaction replacement text literally, preventing regex substitutions from reinserting secrets. - Serialize buffer snapshot/write/removal; retain entries after failed writes and preserve appended entries. @@ -84,7 +102,7 @@ - Require a non-null stopwatch in every Get-ElapsedTime parameter set. - Add regression tests and concurrent-process file-write coverage. -## String utilities restoration (unreleased) +### String utilities restoration - Restore character conversion, string checksums and SHA-256 hashing. - Preserve the character map while fixing index leakage and default space handling. @@ -93,7 +111,7 @@ - Default SHA-256 output to hexadecimal; expose LegacyFormat for old comparisons. - Add behavioral and known-vector tests. -## API request restoration (unreleased) +### API request restoration - Restore New-ApiRequest with independent optional-parameter handling. - Accept header dictionaries; correctly serialize JSON or form authentication fields. @@ -101,7 +119,7 @@ - Disable automatic redirects and expose a connection timeout. - Propagate request failures; add mocked tests with no network or credentials. -## Password-generation restoration (unreleased) +### Password-generation restoration - Restore New-RandomString, New-RandomPassword and New-PhoneticPassword. - Use secure unbiased integer selection and Fisher-Yates composition shuffling. @@ -110,20 +128,20 @@ - Validate lengths/counts and remove the old random-password alphabet-length cap. - Add behavioral tests with mocked console and clipboard operations. -## Authenticated string encryption (unreleased) +### Authenticated string encryption - Restore New-StringEncryption/New-StringDecryption with AES-256-GCM and PBKDF2-HMAC-SHA256. - Require explicit passphrases, generate random salts/nonces, authenticate ciphertext. - Add a bounded versioned format and independent interoperability/tampering tests. - Preserve original legacy decoding code; document intentional ciphertext/API changes. -## Validation restoration (unreleased) +### Validation restoration - Restore filename/path, IP and date validators with documented semantics and tests. - Correct filename character scanning; add Windows-compatible device-name checks. - Reject ambiguous IPv4 shorthand; allow explicit date culture and exact format. -# 3.0.0-alpha1 (unreleased) +### Module foundation - Establish a PowerShell 7.4 Core module foundation with five explicit exports. - Adopt the tested New-LogEntry implementation and private helpers. @@ -133,7 +151,6 @@ - Retain other candidate utilities in Staging/v3 and historical helpers in Legacy. - Remove obsolete CLR/.NET Framework constraints and stale FileList entries. -# IT-ToolBox - Change History ## Version 2.2.3.3 - 10.10.2020 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d521106..c15a25c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,14 +49,34 @@ Invoke-Pester ./Tests ## Contribution workflow -1. Create a branch from the current working branch. +1. Preserve local changes, update master, and create a dedicated feature branch. 2. Keep changes focused on one concern or feature area. 3. Preserve existing behavior unless the change explicitly updates documented semantics. 4. Validate the changed code with the relevant Pester tests and syntax checks. 5. Update documentation if behavior, usage, or compatibility changes. +Start work with explicit branch selection: + +```bash +git switch master +git pull --ff-only +git switch -c feature/your-change +``` + +Before committing, select the same branch and stage only intended files: + +```bash +git switch feature/your-change +git diff --check +git add +git commit -m "Describe the change" +git push -u origin feature/your-change +``` + ## Coding expectations +- Use four spaces for indentation, never tabs. Preserve intentional tabs in data. + - Prefer clear, readable PowerShell idioms over clever shortcuts. - Maintain explicit error handling and avoid silently swallowing operational failures. - Preserve cross-platform compatibility where feasible. diff --git a/IT-ToolBox.psd1 b/IT-ToolBox.psd1 index 9d61882..8185658 100644 --- a/IT-ToolBox.psd1 +++ b/IT-ToolBox.psd1 @@ -47,7 +47,7 @@ Tags = @('Infrastructure', 'Automation', 'Logging') LicenseUri = 'https://github.com/PsCustomObject/IT-ToolBox/blob/master/LICENSE' ProjectUri = 'https://github.com/PsCustomObject/IT-ToolBox' - Prerelease = 'alpha1' + Prerelease = 'beta1' } } } diff --git a/IT-ToolBox.psm1 b/IT-ToolBox.psm1 index 99eeb1c..9c132ef 100644 --- a/IT-ToolBox.psm1 +++ b/IT-ToolBox.psm1 @@ -14,28 +14,28 @@ Export-ModuleMember -Function @( 'Get-TimerStatus' 'Stop-Timer' 'Get-ElapsedTime' - 'Get-ScriptDirectory' - 'Get-ScriptName' - 'Test-FileName' - 'Test-IsValidPath' - 'Test-IsIP' - 'Test-IsDate' - 'Test-IsEmail' - 'Test-IsUrl' - 'Convert-LogonTimestamp' - 'Get-OsUpTime' - 'Remove-SpecialCharacters' - 'Test-RegistryValue' - 'Test-IsValidDn' - 'Test-IsValidUpn' - 'Get-ReportChain' - 'New-StringEncryption' - 'New-StringDecryption' - 'New-RandomString' - 'New-RandomPassword' - 'New-PhoneticPassword' - 'New-ApiRequest' - 'New-StringConversion' - 'Get-StringCheckSum' - 'Get-StringHashCode' + 'Get-ScriptDirectory' + 'Get-ScriptName' + 'Test-FileName' + 'Test-IsValidPath' + 'Test-IsIP' + 'Test-IsDate' + 'Test-IsEmail' + 'Test-IsUrl' + 'Convert-LogonTimestamp' + 'Get-OsUpTime' + 'Remove-SpecialCharacters' + 'Test-RegistryValue' + 'Test-IsValidDn' + 'Test-IsValidUpn' + 'Get-ReportChain' + 'New-StringEncryption' + 'New-StringDecryption' + 'New-RandomString' + 'New-RandomPassword' + 'New-PhoneticPassword' + 'New-ApiRequest' + 'New-StringConversion' + 'Get-StringCheckSum' + 'Get-StringHashCode' ) diff --git a/Public/Get-ScriptDirectory.ps1 b/Public/Get-ScriptDirectory.ps1 index 74a8e40..7d40968 100644 --- a/Public/Get-ScriptDirectory.ps1 +++ b/Public/Get-ScriptDirectory.ps1 @@ -39,4 +39,3 @@ function Get-ScriptDirectory } } } - diff --git a/Public/New-StringConversion.ps1 b/Public/New-StringConversion.ps1 index 2d93e22..d60e6cb 100644 --- a/Public/New-StringConversion.ps1 +++ b/Public/New-StringConversion.ps1 @@ -24,7 +24,7 @@ function New-StringConversion [Parameter(ParameterSetName = 'ReplaceSpaces')][AllowEmptyString()][ValidateNotNull()][string]$ReplaceSpaces = '-', [ValidateNotNullOrEmpty()][string]$UnknownCharacter = '?' ) - + if ($PSBoundParameters.ContainsKey('UnicodeHashTable')) { # Normalize a private copy so the caller's map remains unchanged. @@ -61,10 +61,10 @@ function New-StringConversion # Canonicalize equivalent Unicode sequences so character-map lookups are consistent. $normalized = $StringToConvert.Normalize([System.Text.NormalizationForm]::FormC) - + # Enumerate text elements, such as surrogate pairs and combining sequences, as units. $elements = [System.Globalization.StringInfo]::GetTextElementEnumerator($normalized) - + # Accumulate converted text without repeatedly creating longer strings. $result = [System.Text.StringBuilder]::new() diff --git a/README.md b/README.md index 08e5d84..0c40ff0 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ [![PowerShell 7.4+](https://img.shields.io/badge/PowerShell-7.4%2B-5391FE?logo=powershell)](https://github.com/PowerShell/PowerShell) [![License: MIT](https://img.shields.io/badge/License-MIT-green.svg)](./LICENSE) -[![Status: Alpha Preview](https://img.shields.io/badge/status-alpha%20preview-orange.svg)](./CHANGELOG.md) +[![Status: Beta Preview](https://img.shields.io/badge/status-beta%20preview-orange.svg)](./CHANGELOG.md) PowerShell utilities for enterprise automation, secure logging, identity validation, and cross-platform operational tooling. @@ -89,8 +89,9 @@ Current roadmap focus: ## Status and requirements -This is the **3.0.0-alpha1 modernization preview**, not the completed -modernization release. Requires PowerShell 7.4 or later (Core edition). Windows +This is the **3.0.0-beta1 modernization preview**. The modernization review is +complete; live AD, remote CIM and service authentication remain unverified. +Requires PowerShell 7.4 or later (Core edition). Windows PowerShell 5.1 is not supported. The module imports without WinSCP, GnuPG, Active Directory or Exchange diff --git a/SECURITY.md b/SECURITY.md index 91236c2..6655f71 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -4,7 +4,12 @@ Please do not open a public issue for security-sensitive problems. -Instead, contact the project maintainer privately through the repository's preferred security reporting path and provide the following details: +Use [GitHub private vulnerability reporting](https://github.com/PsCustomObject/IT-ToolBox/security/advisories/new). +Sign in to GitHub to submit a private report. If private reporting is unavailable, +open a general issue asking the maintainer to enable it, without including +vulnerability details, secrets or reproduction steps. + +Include the following details in the private report: - a clear description of the issue - the affected command, script, or workflow diff --git a/Tests/Packaging.Tests.ps1 b/Tests/Packaging.Tests.ps1 index 3b15afa..ebb0d44 100644 --- a/Tests/Packaging.Tests.ps1 +++ b/Tests/Packaging.Tests.ps1 @@ -9,10 +9,12 @@ BeforeAll { Describe 'Installable module packaging' { It 'uses the manifest preview version and conventional module layout' { - $package.Version | Should -Be '3.0.0-alpha1' - [IO.Path]::GetFileName($package.ArchivePath) | Should -Be 'IT-ToolBox-3.0.0-alpha1.zip' + $package.Version | Should -Be '3.0.0-beta1' + [IO.Path]::GetFileName($package.ArchivePath) | Should -Be 'IT-ToolBox-3.0.0-beta1.zip' Test-ModuleManifest (Join-Path $moduleRoot 'IT-ToolBox.psd1') -ErrorAction Stop | Should -Not -BeNullOrEmpty - Test-Path -LiteralPath (Join-Path $moduleRoot 'LICENSE') | Should -BeTrue + foreach ($name in @('LICENSE', 'CONTRIBUTING.md', 'SECURITY.md')) { + Test-Path -LiteralPath (Join-Path $moduleRoot $name) | Should -BeTrue + } } It 'ships only supported code and documentation, excluding development and legacy files' { @@ -23,12 +25,21 @@ Describe 'Installable module packaging' { $files.Count | Should -Be $package.FileCount foreach ($file in $files) { $relative = [IO.Path]::GetRelativePath($moduleRoot, $file.FullName).Replace('\', '/') - $relative | Should -Match '^(IT-ToolBox\.psd1|IT-ToolBox\.psm1|LICENSE|README\.md|CHANGELOG\.md|(Public|Private)/[^/]+\.ps1|docs/[^/]+\.md)$' + $relative | Should -Match '^(IT-ToolBox\.psd1|IT-ToolBox\.psm1|LICENSE|README\.md|CHANGELOG\.md|CONTRIBUTING\.md|SECURITY\.md|(Public|Private)/[^/]+\.ps1|docs/[^/]+\.md)$' $original = Join-Path $sourceRoot $relative (Get-FileHash -LiteralPath $file.FullName).Hash | Should -Be (Get-FileHash -LiteralPath $original).Hash } } + It 'resolves relative documentation links in the packaged README' { + $readme = Get-Content -LiteralPath (Join-Path $moduleRoot 'README.md') -Raw + $links = [regex]::Matches($readme, '\]\((\./[^)#]+)(?:#[^)]*)?\)') + $links.Count | Should -BeGreaterThan 0 + foreach ($link in $links) { + Test-Path -LiteralPath (Join-Path $moduleRoot $link.Groups[1].Value) | Should -BeTrue + } + } + It 'imports the extracted module by name and exercises logging in a fresh process' { $escapedRoot = $extractRoot.Replace("'", "''") $code = @" diff --git a/docs/Packaging.md b/docs/Packaging.md index b8eeb82..e4c39fb 100644 --- a/docs/Packaging.md +++ b/docs/Packaging.md @@ -7,13 +7,14 @@ Invoke-Pester ./Tests ./scripts/Build-Module.ps1 ``` -The script creates artifacts/IT-ToolBox-3.0.0-alpha1.zip and returns its path, +The script creates artifacts/IT-ToolBox-3.0.0-beta1.zip and returns its path, version and file count. It takes the version from the manifest without modifying it. Use -OutputDirectory to choose another local destination. An existing archive causes a terminating error; use a different destination for another build. The ZIP contains IT-ToolBox/3.0.0/ with the manifest, loader, Public and Private -implementation files, license, README, changelog and Markdown documents in docs/. +implementation files, license, README, changelog, contributing guide, security policy and Markdown +documents in docs/. Tests, build scripts, Legacy, Staging, Git metadata and external binaries are excluded. Historical encryption migration requires the original repository source in a separate session; the old decoder is not distributed in this archive. @@ -21,7 +22,7 @@ in a separate session; the old decoder is not distributed in this archive. Extract into a new directory, then verify or import the extracted manifest: ```powershell -Expand-Archive -LiteralPath './artifacts/IT-ToolBox-3.0.0-alpha1.zip' -DestinationPath './preview-install' +Expand-Archive -LiteralPath './artifacts/IT-ToolBox-3.0.0-beta1.zip' -DestinationPath './preview-install' Import-Module './preview-install/IT-ToolBox/3.0.0/IT-ToolBox.psd1' -Force Get-Command -Module IT-ToolBox ``` @@ -33,5 +34,5 @@ this script does not install or replace a module for you. CI runs archive-content and fresh-process import tests on Windows, Linux and macOS, then builds the archive locally. No publishing, release creation or signing is performed. ZIP timestamps are not normalized, so identical source builds need not -have identical archive hashes. This remains an alpha preview; the package process +have identical archive hashes. This remains a beta preview; the package process does not establish live AD, remote CIM or service authentication compatibility. diff --git a/scripts/Build-Module.ps1 b/scripts/Build-Module.ps1 index 13b475c..4650bb2 100644 --- a/scripts/Build-Module.ps1 +++ b/scripts/Build-Module.ps1 @@ -57,7 +57,7 @@ try { $null = [IO.Directory]::CreateDirectory($moduleRoot) - $files = @(foreach ($name in @('IT-ToolBox.psd1', 'IT-ToolBox.psm1', 'LICENSE', 'README.md', 'CHANGELOG.md')) + $files = @(foreach ($name in @('IT-ToolBox.psd1', 'IT-ToolBox.psm1', 'LICENSE', 'README.md', 'CHANGELOG.md', 'CONTRIBUTING.md', 'SECURITY.md')) { Get-Item -LiteralPath (Join-Path $sourceRoot $name) })