Private/Add-SqlSpnProvenance.ps1
|
# ============================================================================= # Script : Add-SqlSpnProvenance.ps1 # Author : Keith Ramsey # Created : 2026-05-28 # ============================================================================= # Change Log # ----------------------------------------------------------------------------- # 2026-05-28 cross-suite meta Claude Initial: provenance helper per DR-312 # (in the internal companion). Stamps the suite- # standard five fields (ModuleVersion / SchemaVersion # / CommitSha / RunId / Timestamp) on any # [pscustomobject] before it leaves a Public command. # Matches the cross-suite factory pattern used by # SqlInstanceForge New-SqlForgeResult, SqlCertForge # New-SqlCertResult, ClusterValidator Add-ClvResult. # ============================================================================= function Add-SqlSpnProvenance { <# .SYNOPSIS Stamp the suite-standard provenance fields on a result object. .DESCRIPTION Adds ModuleVersion, SchemaVersion, CommitSha, RunId, and Timestamp to a [pscustomobject] in place and returns the same object. The first three fields are captured once at module load (see SqlSpnManager.psm1) so a single invocation pays no per-call manifest-read cost. RunId is a per-call GUID; Timestamp is per-call UTC ISO 8601. If a caller already attached one of these fields by name (defensive — the helper supports being called twice on the same object), the existing value is replaced. Never throws; if a captured script-scope provenance variable is missing (e.g. the module was dot-sourced standalone in a test), the field gets a sentinel string ('unknown') so the shape is preserved. .PARAMETER Result The result object to stamp. Mutated in place AND returned, so the caller may simply `return $Result | Add-SqlSpnProvenance` or `Add-SqlSpnProvenance -Result $r ; $r`. .OUTPUTS The same [pscustomobject] passed in, with the five fields added. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Mutates the result object in place; no external state. ShouldProcess would be noise.')] [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [pscustomobject] $Result ) process { $mv = if (Test-Path variable:script:moduleVersion) { $script:moduleVersion } else { 'unknown' } $sv = if (Test-Path variable:script:schemaVersion) { $script:schemaVersion } else { 'unknown' } $sh = if (Test-Path variable:script:commitSha) { $script:commitSha } else { $null } $stamp = [ordered]@{ ModuleVersion = $mv SchemaVersion = $sv CommitSha = $sh RunId = [guid]::NewGuid().ToString() Timestamp = [datetime]::UtcNow.ToString('o') } foreach ($k in $stamp.Keys) { if ($Result.PSObject.Properties.Match($k).Count -gt 0) { $Result.$k = $stamp[$k] } else { $Result | Add-Member -MemberType NoteProperty -Name $k -Value $stamp[$k] } } $Result } } |