private/localization/Get-CtManagedService.ps1
|
<#
.SYNOPSIS Resolve, para um achado REPROVADO, o texto de "Serviços Gerenciados Cloud Target". .DESCRIPTION Combina duas fontes (carregadas dos assets do módulo): - assets/managed-service-ct.json : texto 'ct' por TestId (como a Cloud Target apoia aquele achado específico). - assets/offer-rules.json + assets/offers.json : mapeia o pilar/categoria do teste para uma oferta (projeto/serviço gerenciado) e traz o pitch dela. Só produz conteúdo para achados com status reprovado (offer-rules.mappedStatuses), pois a recomendação comercial só faz sentido quando o controle falhou. Retorna markdown pronto para um card, ou $null quando não há oferta aplicável. #> $script:CtOffers = $null $script:CtOfferRules = $null $script:CtServiceText = $null $script:CtOffersLoaded = $false function Initialize-CtManagedService { [CmdletBinding()] param() $assets = Join-Path $script:ModuleRoot 'assets' $offersPath = Join-Path $assets 'offers.json' $rulesPath = Join-Path $assets 'offer-rules.json' $ctPath = Join-Path $assets 'managed-service-ct.json' $script:CtOffers = @{} if (Test-Path $offersPath) { foreach ($o in (Get-Content $offersPath -Raw -Encoding UTF8 | ConvertFrom-Json).offers) { $script:CtOffers[$o.id] = $o } } $script:CtOfferRules = if (Test-Path $rulesPath) { Get-Content $rulesPath -Raw -Encoding UTF8 | ConvertFrom-Json } else { $null } $script:CtServiceText = if (Test-Path $ctPath) { Get-Content $ctPath -Raw -Encoding UTF8 | ConvertFrom-Json } else { $null } $script:CtOffersLoaded = $true } function Get-CtManagedService { [CmdletBinding()] param( [string]$TestId, [string]$Pillar, [string]$Category, [string]$Status ) if (-not $script:CtOffersLoaded) { Initialize-CtManagedService } if (-not $script:CtOfferRules) { return $null } # Apenas achados reprovados (mappedStatuses = 'fail'). if ([string]::IsNullOrWhiteSpace($Status) -or $Status -notmatch '(?i)fail') { return $null } if ([string]::IsNullOrWhiteSpace($Pillar)) { return $null } $pillarRule = $script:CtOfferRules.byPillar.$Pillar if (-not $pillarRule) { return $null } $offerId = $pillarRule.primary # categoryOverrides refinam a oferta por categoria dentro do pilar. if ($Category -and $script:CtOfferRules.categoryOverrides) { foreach ($ov in $script:CtOfferRules.categoryOverrides) { if ($ov.pillar -eq $Pillar -and $ov.categoryMatch -and $Category -like "*$($ov.categoryMatch)*" -and $ov.primary) { $offerId = $ov.primary break } } } $offer = $script:CtOffers[$offerId] # Texto especifico do achado (por TestId), quando existir. $ctText = $null if ($TestId -and $script:CtServiceText) { $prop = $script:CtServiceText.PSObject.Properties[$TestId] if ($prop) { $ctText = $prop.Value } } if (-not $offer -and -not $ctText) { return $null } $sb = [System.Text.StringBuilder]::new() if ($ctText) { [void]$sb.AppendLine($ctText) [void]$sb.AppendLine() } if ($offer) { $tipo = if ($offer.type) { " ($($offer.type))" } else { '' } [void]$sb.AppendLine("**Oferta recomendada: $($offer.name)$tipo**") [void]$sb.AppendLine() if ($offer.pitch) { [void]$sb.AppendLine($offer.pitch) } } return $sb.ToString().TrimEnd() } |