diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..46344a7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,60 @@ +# Build output +bin/ +obj/ +out/ +publish/ +artifacts/ + +# Visual Studio / Rider / VS Code +.vs/ +.idea/ +.vscode/.ropeproject +*.user +*.suo +*.rsuser +*.sln.docstates +*.csproj.user +*.csproj.lscache + +# .NET / test artifacts +TestResults/ +coverage/ +coverage.xml +coverage.cobertura.xml +*.trx +*.coverage +*.coveragexml + +# Logs / temp +*.log +*.tmp +*.temp +*.cache +*.bak +*.orig + +# Local configuration / secrets +appsettings.Local.json +appsettings.*.local.json +appsettings.*.Local.json +*.secrets.json +secrets.json + +# EF / local tooling noise +.ef/ + +# OS files +.DS_Store +Thumbs.db +desktop.ini + +# Node/Web artifacts if frontend files ever land here +node_modules/ +dist/ +.env +.env.local +.env.*.local +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* \ No newline at end of file diff --git a/.tests/BgwMerge.Api.Tests.ps1 b/.tests/BgwMerge.Api.Tests.ps1 new file mode 100644 index 0000000..aa9798a --- /dev/null +++ b/.tests/BgwMerge.Api.Tests.ps1 @@ -0,0 +1,421 @@ +param( + [string]$ApiBaseUrl = 'http://localhost:5286/api', + + [string]$BgwRoot = ('F:\Kunden Auftr' + [char]0x00E4 + 'ge\BGW'), + + [string]$DeploymentBatchId = '80000000-0000-0000-0000-000000000101', + + [string]$MergeModulePath = 'F:\Projekte\Coding\PowerShell\Merge-DSCConfigurationData\Merge-DSCConfigurationData.psd1', + + [string]$ResolveModulePath = 'F:\Projekte\Coding\PowerShell\Resolve-DSCConfigurationData\Resolve-DSCConfigurationData.psd1', + + [int]$ApiTimeoutSec = 30, + + [bool]$UseDefaultCredentials = $true +) + +$ErrorActionPreference = 'Stop' + +function Invoke-TestBgwMergeApiJson { + param( + [ValidateSet('GET', 'POST', 'PUT', 'DELETE')] + [string]$Method, + + [string]$Path + ) + + $uri = ('{0}/{1}' -f $ApiBaseUrl.TrimEnd('/'), $Path.TrimStart('/')) + $parameters = @{ + Method = $Method + Uri = $uri + TimeoutSec = $ApiTimeoutSec + ErrorAction = 'Stop' + } + + if ($UseDefaultCredentials) { + $parameters.UseDefaultCredentials = $true + } + + try { + Invoke-RestMethod @parameters + } + catch { + $responseBody = '' + if ($_.Exception.Response) { + try { + $stream = $_.Exception.Response.GetResponseStream() + if ($stream) { + $reader = [System.IO.StreamReader]::new($stream) + $text = $reader.ReadToEnd() + if (-not [string]::IsNullOrWhiteSpace($text)) { + $responseBody = $text + } + } + } + catch { + $responseBody = '' + } + } + + throw "API request failed. Method=[$Method], Uri=[$uri], Response=[$responseBody]. $($_.Exception.Message)" + } +} + +function ConvertTo-TestBgwMergeConfigurationValue { + param([object]$Value) + + if ($null -eq $Value) { + return $null + } + + if ($Value -is [string] -or $Value -is [bool] -or $Value -is [int] -or $Value -is [long] -or $Value -is [double] -or $Value -is [decimal]) { + return $Value + } + + if ($Value -is [System.Collections.IDictionary]) { + $result = [ordered]@{} + foreach ($key in $Value.Keys) { + $result[[string]$key] = ConvertTo-TestBgwMergeConfigurationValue -Value $Value[$key] + } + + Write-Output -NoEnumerate $result + return + } + + if ($Value -is [pscustomobject]) { + $result = [ordered]@{} + foreach ($property in $Value.PSObject.Properties) { + $result[$property.Name] = ConvertTo-TestBgwMergeConfigurationValue -Value $property.Value + } + + Write-Output -NoEnumerate $result + return + } + + if ($Value -is [System.Collections.IEnumerable] -and $Value -isnot [string]) { + $items = New-Object System.Collections.Generic.List[object] + foreach ($item in $Value) { + $items.Add((ConvertTo-TestBgwMergeConfigurationValue -Value $item)) + } + + Write-Output -NoEnumerate $items.ToArray() + return + } + + return $Value +} + +function ConvertFrom-TestBgwMergeTemplateJson { + param([string]$JsonData) + + $document = $JsonData | ConvertFrom-Json + $metadata = ConvertTo-TestBgwMergeConfigurationValue -Value $document.metadata + if ($null -eq $metadata) { + $metadata = [ordered]@{} + } + + if (-not $metadata.Contains('TemplateType')) { + $metadata['TemplateType'] = $document.templateType + } + + [ordered]@{ + Metadata = $metadata + Parameters = ConvertTo-TestBgwMergeConfigurationValue -Value $document.parameters + Variables = ConvertTo-TestBgwMergeConfigurationValue -Value $document.variables + Resources = ConvertTo-TestBgwMergeConfigurationValue -Value $document.resources + } +} + +function ConvertFrom-TestBgwMergeTargetAssignments { + param([object[]]$TargetAssignments) + + @($TargetAssignments | Sort-Object sortOrder | ForEach-Object { + $nodeData = ConvertTo-TestBgwMergeConfigurationValue -Value ($_.nodeDataJson | ConvertFrom-Json) + $node = @{} + + foreach ($key in $nodeData.Keys) { + if ($key -eq 'nodeName') { + $node.NodeName = $nodeData[$key] + } + else { + $node[$key] = $nodeData[$key] + } + } + + $node + }) +} + +function ConvertTo-TestBgwMergeStableValue { + param([object]$Value) + + if ($null -eq $Value) { + return $null + } + + if ($Value -is [string] -or $Value -is [bool] -or $Value -is [int] -or $Value -is [long] -or $Value -is [double] -or $Value -is [decimal]) { + return $Value + } + + if ($Value -is [System.Collections.IDictionary]) { + $result = [ordered]@{} + foreach ($key in @($Value.Keys | Sort-Object)) { + $result[[string]$key] = ConvertTo-TestBgwMergeStableValue -Value $Value[$key] + } + + Write-Output -NoEnumerate $result + return + } + + if ($Value -is [pscustomobject]) { + $result = [ordered]@{} + foreach ($property in @($Value.PSObject.Properties | Sort-Object Name)) { + $result[$property.Name] = ConvertTo-TestBgwMergeStableValue -Value $property.Value + } + + Write-Output -NoEnumerate $result + return + } + + if ($Value -is [System.Collections.IEnumerable] -and $Value -isnot [string]) { + $items = New-Object System.Collections.Generic.List[object] + foreach ($item in $Value) { + $items.Add((ConvertTo-TestBgwMergeStableValue -Value $item)) + } + + Write-Output -NoEnumerate $items.ToArray() + return + } + + return $Value +} + +function ConvertTo-TestBgwMergeStableJson { + param([object]$Value) + + (ConvertTo-TestBgwMergeStableValue -Value $Value) | ConvertTo-Json -Depth 100 -Compress +} + +function Invoke-TestBgwMergeSnapshotScript { + param([string]$Script) + + $encodedCommand = [Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($Script)) + $output = & powershell.exe -NoProfile -ExecutionPolicy Bypass -EncodedCommand $encodedCommand + + if ($LASTEXITCODE -ne 0) { + throw "Snapshot PowerShell process failed with exit code [$LASTEXITCODE]. Output: $($output -join [Environment]::NewLine)" + } + + $json = ($output | Where-Object { -not [string]::IsNullOrWhiteSpace($_) }) -join [Environment]::NewLine + if ([string]::IsNullOrWhiteSpace($json)) { + throw 'Snapshot PowerShell process returned no JSON output.' + } + + $json | ConvertFrom-Json +} + +function New-TestBgwMergeSnapshotScript { + param( + [string]$ConfigurationDataPath, + [switch]$BuildLocalBaseline + ) + + $escapedBgwRoot = $BgwRoot.Replace("'", "''") + $escapedMergeModulePath = $MergeModulePath.Replace("'", "''") + $escapedResolveModulePath = $ResolveModulePath.Replace("'", "''") + $escapedConfigurationDataPath = if ($ConfigurationDataPath) { $ConfigurationDataPath.Replace("'", "''") } else { '' } + $buildLocalBaselineText = if ($BuildLocalBaseline) { 'True' } else { 'False' } + +@" +`$ErrorActionPreference = 'Stop' +`$ProgressPreference = 'SilentlyContinue' +Import-Module '$escapedMergeModulePath' -Force +Import-Module '$escapedResolveModulePath' -Force + +function ConvertTo-SnapshotStableValue { + param([object]`$Value) + + if (`$null -eq `$Value) { return `$null } + if (`$Value -is [string] -or `$Value -is [bool] -or `$Value -is [int] -or `$Value -is [long] -or `$Value -is [double] -or `$Value -is [decimal]) { return `$Value } + + if (`$Value -is [System.Collections.IDictionary]) { + `$result = [ordered]@{} + foreach (`$key in @(`$Value.Keys | Sort-Object)) { + `$result[[string]`$key] = ConvertTo-SnapshotStableValue -Value `$Value[`$key] + } + Write-Output -NoEnumerate `$result + return + } + + if (`$Value -is [pscustomobject]) { + `$result = [ordered]@{} + foreach (`$property in @(`$Value.PSObject.Properties | Sort-Object Name)) { + `$result[`$property.Name] = ConvertTo-SnapshotStableValue -Value `$property.Value + } + Write-Output -NoEnumerate `$result + return + } + + if (`$Value -is [System.Collections.IEnumerable] -and `$Value -isnot [string]) { + `$items = New-Object System.Collections.Generic.List[object] + foreach (`$item in `$Value) { + `$items.Add((ConvertTo-SnapshotStableValue -Value `$item)) + } + Write-Output -NoEnumerate `$items.ToArray() + return + } + + return `$Value +} + +function ConvertTo-SnapshotStableJson { + param([object]`$Value) + (ConvertTo-SnapshotStableValue -Value `$Value) | ConvertTo-Json -Depth 100 -Compress +} + +if ('$buildLocalBaselineText' -eq 'True') { + `$root = '$escapedBgwRoot' + `$sourceTemplates = @( + (Join-Path -Path `$root -ChildPath 'Environment\Test.psd1') + (Join-Path -Path `$root -ChildPath 'Domain\Contoso.psd1') + (Join-Path -Path `$root -ChildPath 'Service\SharePoint\Contoso.psd1') + (Join-Path -Path `$root -ChildPath 'Stage\Install.psd1') + ) + + `$allNodes = @( + @{ NodeName = 'CLD-SHP-01'; RunCentralAdministration = `$true } + @{ NodeName = 'CLD-SHP-02'; RunCentralAdministration = `$false } + @{ NodeName = 'CLD-SHP-03'; RunCentralAdministration = `$false } + ) + + `$configurationData = New-DSCConfigurationDataDeployment -Name 'Contoso-Test-SharePoint' -DeploymentId '8f6c2c1a' -SourceTemplatePath `$sourceTemplates -AllNodes `$allNodes +} +else { + `$configurationData = Import-PowerShellDataFile -LiteralPath '$escapedConfigurationDataPath' +} + +`$resolved = Resolve-DSCConfigurationData -ConfigurationData `$configurationData -SkipSecrets +`$snapshot = [ordered]@{ + ParametersJson = ConvertTo-SnapshotStableJson -Value `$configurationData.Parameters + VariablesJson = ConvertTo-SnapshotStableJson -Value `$configurationData.Variables + ResourcesJson = ConvertTo-SnapshotStableJson -Value `$configurationData.Resources + DatabasePrefix = `$resolved.Variables.DatabasePrefix + ServiceDbPrefix = `$resolved.Variables.ServiceDbPrefix + ConfigDbName = `$resolved.Variables.ConfigDbName + LcmConfigurationMode = `$resolved.Resources.NonNodeData.LocalConfigurationManager.ConfigurationMode + AllNodes = @(`$resolved.Resources.AllNodes | Sort-Object NodeName | ForEach-Object { + [ordered]@{ + NodeName = `$_.NodeName + RunCentralAdministration = `$_.RunCentralAdministration + } + }) +} + +`$snapshot | ConvertTo-Json -Depth 100 -Compress +"@ +} + +function New-TestBgwMergeLocalSnapshot { + Invoke-TestBgwMergeSnapshotScript -Script (New-TestBgwMergeSnapshotScript -BuildLocalBaseline) +} + +function New-TestBgwMergeSnapshotFromConfigurationData { + param([hashtable]$ConfigurationData) + + Import-Module $MergeModulePath -Force + + $tempPath = Join-Path -Path ([System.IO.Path]::GetTempPath()) -ChildPath ("BgwMergeApiSnapshot-{0}.psd1" -f ([guid]::NewGuid().ToString('N'))) + try { + Export-PowerShellDataFile -InputObject $ConfigurationData -Path $tempPath -Force + Invoke-TestBgwMergeSnapshotScript -Script (New-TestBgwMergeSnapshotScript -ConfigurationDataPath $tempPath) + } + finally { + if (Test-Path -LiteralPath $tempPath) { + Remove-Item -LiteralPath $tempPath -Force + } + } +} + +function New-TestBgwMergeApiConfigurationData { + param([object]$Composition) + + Import-Module $MergeModulePath -Force + + $mergedTemplateData = @{} + + foreach ($selection in @($Composition.templateSelections | Sort-Object sortOrder)) { + $templateData = ConvertFrom-TestBgwMergeTemplateJson -JsonData $selection.templateVersion.jsonData + $mergedTemplateData = Merge-DSCConfigurationData -Template $mergedTemplateData -Deployment $templateData + } + + $deploymentData = @{ + Resources = @{ + AllNodes = ConvertFrom-TestBgwMergeTargetAssignments -TargetAssignments @($Composition.targetAssignments) + } + } + + Merge-DSCConfigurationData -Template $mergedTemplateData -Deployment $deploymentData +} + +Describe 'BGW Test.Merge.ps1 API DemoData composition' { + BeforeAll { + $script:expectedTemplateAliases = @( + 'Environment-Test' + 'Domain-Contoso' + 'Service-SharePoint-Contoso' + 'Stage-Install' + ) + + $script:expectedTemplateRoles = @( + 'Environment' + 'Domain' + 'Service' + 'Stage' + ) + + $script:localSnapshot = New-TestBgwMergeLocalSnapshot + $script:apiComposition = Invoke-TestBgwMergeApiJson -Method GET -Path "deployment-batches/$DeploymentBatchId/composition" + $script:apiConfigurationData = New-TestBgwMergeApiConfigurationData -Composition $script:apiComposition + $script:apiSnapshot = New-TestBgwMergeSnapshotFromConfigurationData -ConfigurationData $script:apiConfigurationData + } + + It 'loads the seeded deployment composition from the API' { + $script:apiComposition.deploymentBatchId | Should Be $DeploymentBatchId + @($script:apiComposition.templateSelections).Count | Should Be 4 + @($script:apiComposition.targetAssignments).Count | Should Be 3 + } + + It 'keeps the template selection order from Test.Merge.ps1' { + $aliases = @($script:apiComposition.templateSelections | Sort-Object sortOrder | ForEach-Object { $_.alias }) + $roles = @($script:apiComposition.templateSelections | Sort-Object sortOrder | ForEach-Object { $_.templateRole }) + + ($aliases -join '|') | Should Be ($script:expectedTemplateAliases -join '|') + ($roles -join '|') | Should Be ($script:expectedTemplateRoles -join '|') + } + + It 'keeps the AllNodes data from Test.Merge.ps1' { + $nodes = @($script:apiSnapshot.AllNodes | Sort-Object NodeName) + + $nodes.Count | Should Be 3 + $nodes[0].NodeName | Should Be 'CLD-SHP-01' + $nodes[0].RunCentralAdministration | Should Be $true + $nodes[1].NodeName | Should Be 'CLD-SHP-02' + $nodes[1].RunCentralAdministration | Should Be $false + $nodes[2].NodeName | Should Be 'CLD-SHP-03' + $nodes[2].RunCentralAdministration | Should Be $false + } + + It 'resolves the same core values as the local Test.Merge.ps1 baseline' { + $script:apiSnapshot.DatabasePrefix | Should Be $script:localSnapshot.DatabasePrefix + $script:apiSnapshot.ServiceDbPrefix | Should Be $script:localSnapshot.ServiceDbPrefix + $script:apiSnapshot.ConfigDbName | Should Be $script:localSnapshot.ConfigDbName + $script:apiSnapshot.LcmConfigurationMode | Should Be $script:localSnapshot.LcmConfigurationMode + } + + It 'matches merged Parameters, Variables and Resources' { + $script:apiSnapshot.ParametersJson | Should Be $script:localSnapshot.ParametersJson + $script:apiSnapshot.VariablesJson | Should Be $script:localSnapshot.VariablesJson + $script:apiSnapshot.ResourcesJson | Should Be $script:localSnapshot.ResourcesJson + } +} + diff --git a/.tests/Compare-BgwMergeWithApi.ps1 b/.tests/Compare-BgwMergeWithApi.ps1 new file mode 100644 index 0000000..e20643d --- /dev/null +++ b/.tests/Compare-BgwMergeWithApi.ps1 @@ -0,0 +1,42 @@ +[CmdletBinding()] +param( + [string]$ApiBaseUrl = 'http://localhost:5286/api', + + [string]$BgwRoot = ('F:\Kunden Auftr' + [char]0x00E4 + 'ge\BGW'), + + [string]$DeploymentBatchId = '80000000-0000-0000-0000-000000000101', + + [string]$MergeModulePath = 'F:\Projekte\Coding\PowerShell\Merge-DSCConfigurationData\Merge-DSCConfigurationData.psd1', + + [string]$ResolveModulePath = 'F:\Projekte\Coding\PowerShell\Resolve-DSCConfigurationData\Resolve-DSCConfigurationData.psd1', + + [int]$ApiTimeoutSec = 30, + + [switch]$UseDefaultCredentials = $true +) + +$ErrorActionPreference = 'Stop' + +$testPath = Join-Path -Path $PSScriptRoot -ChildPath 'BgwMerge.Api.Tests.ps1' +if (-not (Test-Path -LiteralPath $testPath -PathType Leaf)) { + throw "Pester test file [$testPath] was not found." +} + +if (-not (Get-Command Invoke-Pester -ErrorAction SilentlyContinue)) { + throw 'Pester is required. Install-Module Pester or run this on a machine where Pester is available.' +} + +$parameters = @{ + ApiBaseUrl = $ApiBaseUrl + BgwRoot = $BgwRoot + DeploymentBatchId = $DeploymentBatchId + MergeModulePath = $MergeModulePath + ResolveModulePath = $ResolveModulePath + ApiTimeoutSec = $ApiTimeoutSec + UseDefaultCredentials = [bool]$UseDefaultCredentials +} + +$result = Invoke-Pester -Script @{ Path = $testPath; Parameters = $parameters } -PassThru +if ($result.FailedCount -gt 0) { + throw "Pester test run failed. Passed=[$($result.PassedCount)] Failed=[$($result.FailedCount)] Skipped=[$($result.SkippedCount)]." +} diff --git a/Context/DataContext.cs b/Context/DataContext.cs index f3034ff..3fec8f8 100644 --- a/Context/DataContext.cs +++ b/Context/DataContext.cs @@ -93,6 +93,21 @@ namespace Microsoft.SelfService.Portal.Core.API.Context modelBuilder.Entity() .ToTable("DeploymentJobs"); + modelBuilder.Entity() + .HasIndex(job => new { job.Status, job.ScheduledAt, job.LockedUntil, job.Priority, job.Created }); + modelBuilder.Entity() + .HasIndex(job => job.CorrelationId); + modelBuilder.Entity() + .HasIndex(job => job.WorkerName); + modelBuilder.Entity() + .Property(job => job.CorrelationId) + .HasDefaultValueSql("NEWID()"); + modelBuilder.Entity() + .Property(job => job.Priority) + .HasDefaultValue(100); + modelBuilder.Entity() + .Property(job => job.RowVersion) + .IsRowVersion(); modelBuilder.Entity() .ToTable("DeploymentJobTargets"); @@ -102,6 +117,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Context modelBuilder.Entity() .Property(target => target.DeploymentGroupId) .HasColumnName("DeploymentBatchId"); + modelBuilder.Entity() + .HasIndex(target => new { target.QueueJobId, target.Status }); + modelBuilder.Entity() + .ToTable(table => table.HasCheckConstraint("CK_DeploymentJobTargets_OutputMetadataJson_IsJson", "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1")); modelBuilder.Entity() .ToTable("DeploymentJobSteps"); @@ -111,6 +130,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Context modelBuilder.Entity() .Property(step => step.DependsOnQueueJobStepId) .HasColumnName("DependsOnDeploymentJobStepId"); + modelBuilder.Entity() + .HasIndex(step => new { step.QueueJobId, step.Status, step.SortOrder }); + modelBuilder.Entity() + .ToTable(table => table.HasCheckConstraint("CK_DeploymentJobSteps_OutputMetadataJson_IsJson", "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1")); modelBuilder.Entity() .HasKey(d => new { d.TargetId, d.DeploymentGroupId }); diff --git a/Context/DemoData.TemplateJson.cs b/Context/DemoData.TemplateJson.cs new file mode 100644 index 0000000..382c03f --- /dev/null +++ b/Context/DemoData.TemplateJson.cs @@ -0,0 +1,419 @@ +namespace Microsoft.SelfService.Portal.Core.API.Context +{ + internal static partial class DemoData + { + private const string BgwEnvironmentTestTemplateJson = """ + { + "schemaVersion": "1.0", + "templateType": "Environment", + "metadata": { + "TemplateType": "Environment", + "Name": "Test" + }, + "parameters": { + "Landscape": { + "DefaultValue": "Prod", + "Value": "Test", + "Type": "string", + "AllowedValues": [ + "Prod", + "QA", + "Test" + ] + } + }, + "variables": { + "AdminDbName": "[joinNotEmpty(\u0027_\u0027, variables(\u0027DatabasePrefix\u0027), \u0027Farm_AdminContent\u0027)]", + "ContentDbPrefix": "[joinNotEmpty(\u0027_\u0027, variables(\u0027DatabasePrefix\u0027), parameters(\u0027ContentDatabaseSegment\u0027))]", + "ServiceDbPrefix": "[joinNotEmpty(\u0027_\u0027, variables(\u0027DatabasePrefix\u0027), parameters(\u0027ServiceDatabaseSegment\u0027))]", + "DatabasePrefix": "[joinNotEmpty(\u0027_\u0027, parameters(\u0027DatabasePrefix\u0027), parameters(\u0027DomainLabel\u0027), if(equals(parameters(\u0027Landscape\u0027), \u0027Test\u0027), \u0027Test\u0027, \u0027\u0027))]", + "ConfigDbName": "[joinNotEmpty(\u0027_\u0027, variables(\u0027DatabasePrefix\u0027), \u0027Farm_Config\u0027)]" + }, + "resources": { + + } + } + """; + + private const string BgwDomainContosoTemplateJson = """ + { + "schemaVersion": "1.0", + "templateType": "Domain", + "metadata": { + "TemplateType": "Domain", + "Name": "Contoso" + }, + "parameters": { + "DomainFQDN": { + "DefaultValue": "", + "Pattern": "^[A-Za-z0-9.-]+$", + "Type": "string", + "Value": "contoso.local", + "Required": true + }, + "DomainLabel": { + "Type": "string", + "MaxLength": 32, + "Value": "Contoso", + "DefaultValue": "", + "Pattern": "^[A-Za-z][A-Za-z0-9_-]*$", + "MinLength": 2, + "Required": false + }, + "DomainNetBIOS": { + "Type": "string", + "MaxLength": 15, + "Value": "CONTOSO", + "DefaultValue": "", + "Pattern": "^[A-Za-z0-9_-]+$", + "MinLength": 1, + "Required": true + } + }, + "variables": { + + }, + "resources": { + "NonNodeData": { + "Services": { + "ActiveDirectory": { + "NetBIOSName": "[parameters(\u0027DomainNetBIOS\u0027)]", + "DomainName": "[parameters(\u0027DomainFQDN\u0027)]" + } + } + } + } + } + """; + + private const string BgwSharePointContosoTemplateJson = """ + { + "schemaVersion": "1.0", + "templateType": "Service", + "metadata": { + "TemplateType": "Service", + "Name": "SharePoint.Contoso" + }, + "parameters": { + "FarmCredential": { + "Sensitive": true, + "Value": { + "Provider": "SecretManagement", + "Vault": "Test", + "Name": "Windows/SharePoint/FarmAccount" + }, + "Type": "credential", + "Required": true + }, + "ContentDatabaseSegment": { + "DefaultValue": "Content", + "Type": "string", + "Metadata": { + "Description": { + "de-DE": "Namenssegment fuer SharePoint-Content-Datenbanken innerhalb des Datenbanknamens.", + "en-US": "Name segment used for SharePoint content databases within the database name." + } + } + }, + "ServiceApplicationPoolDefault": { + "DefaultValue": "SharePoint Service Applications", + "Type": "string", + "Metadata": { + "Description": { + "de-DE": "Anzeigename des Standard-Application-Pools fuer SharePoint-Serviceanwendungen.", + "en-US": "Display name of the default application pool for SharePoint service applications." + } + } + }, + "WebApplicationPoolDefault": { + "DefaultValue": "SharePoint Web Applications", + "Type": "string", + "Metadata": { + "Description": { + "de-DE": "Anzeigename des Standard-Application-Pools fuer SharePoint-Webanwendungen.", + "en-US": "Display name of the default application pool for SharePoint web applications." + } + } + }, + "DatabaseServerName": { + "DefaultValue": "SQL_Server", + "Type": "string", + "Value": "CL-SQL-01" + }, + "WebApplicationPoolDefaultAccount": { + "DefaultValue": "SVC_SHP_WAP", + "Type": "string", + "Metadata": { + "Description": { + "de-DE": "Kontoname fuer den Standard-Application-Pool der SharePoint-Webanwendungen.", + "en-US": "Account name used by the default application pool for SharePoint web applications." + } + } + }, + "ServiceDatabaseSegment": { + "DefaultValue": "Services", + "Type": "string", + "Metadata": { + "Description": { + "de-DE": "Namenssegment fuer SharePoint-Service-Datenbanken innerhalb des Datenbanknamens.", + "en-US": "Name segment used for SharePoint service databases within the database name." + } + } + }, + "FarmPassphrase": { + "Sensitive": true, + "Value": { + "Provider": "SecretManagement", + "Vault": "Test", + "Name": "Windows/SharePoint/FarmPassphrase" + }, + "Type": "credential", + "Required": true + }, + "DatabaseInstanceName": { + "DefaultValue": "SQL_Server", + "Type": "string", + "Value": "SQLServer" + }, + "DatabaseTcpPort": { + "DefaultValue": 1433, + "Type": "int", + "Value": 1433 + }, + "DefaultServiceApplicationPoolAccount": { + "Metadata": { + "Description": { + "de-DE": "Kontoname fuer den Standard-Application-Pool der SharePoint-Serviceanwendungen.", + "en-US": "Account name used by the default application pool for SharePoint service applications." + } + }, + "Sensitive": true, + "Value": { + "Provider": "SecretManagement", + "Vault": "Test", + "Name": "Windows/SharePoint/DefaultServiceAccount" + }, + "Type": "credential", + "Required": true + }, + "ProductKey": { + "DefaultValue": "0000-0000-0000-0000-0000", + "Type": "string", + "Metadata": { + "Description": { + "de-DE": "SharePoint-Produktlizenzschluessel.", + "en-US": "SharePoint product license key." + } + } + }, + "SetupCredential": { + "Sensitive": true, + "Value": { + "Provider": "SecretManagement", + "Vault": "Test", + "Name": "Windows/SharePoint/SetupAccount" + }, + "Type": "credential", + "Required": true + }, + "DatabasePrefix": { + "DefaultValue": "SharePoint", + "Type": "string", + "Value": "SharePoint" + }, + "SearchServiceApplicationPoolAccount": { + "Metadata": { + "Description": { + "de-DE": "Kontoname fuer den Search-Application-Pool der SharePoint-Serviceanwendungen.", + "en-US": "Account name used by the search application pool for SharePoint service applications." + } + }, + "Sensitive": true, + "Value": { + "Provider": "SecretManagement", + "Vault": "Test", + "Name": "Windows/SharePoint/SearchAccount" + }, + "Type": "credential", + "Required": true + }, + "CentralAdminPort": { + "DefaultValue": 443, + "Type": "int", + "Value": 4000 + }, + "ServiceApplicationPoolSearch": { + "DefaultValue": "SharePoint Search Service Applications", + "Type": "string", + "Metadata": { + "Description": { + "de-DE": "Anzeigename des Application-Pools fuer SharePoint Search-Serviceanwendungen.", + "en-US": "Display name of the application pool for SharePoint Search service applications." + } + } + } + }, + "variables": { + "AdminDbName": "[joinNotEmpty(\u0027_\u0027, variables(\u0027DatabasePrefix\u0027), \u0027Farm_AdminContent\u0027)]", + "ContentDbPrefix": "[joinNotEmpty(\u0027_\u0027, variables(\u0027DatabasePrefix\u0027), parameters(\u0027ContentDatabaseSegment\u0027))]", + "ServiceDbPrefix": "[joinNotEmpty(\u0027_\u0027, variables(\u0027DatabasePrefix\u0027), parameters(\u0027ServiceDatabaseSegment\u0027))]", + "DatabasePrefix": "[joinNotEmpty(\u0027_\u0027, parameters(\u0027DatabasePrefix\u0027), parameters(\u0027DomainLabel\u0027), if(equals(parameters(\u0027Landscape\u0027), \u0027Test\u0027), \u0027Test\u0027, \u0027\u0027))]", + "ConfigDbName": "[joinNotEmpty(\u0027_\u0027, variables(\u0027DatabasePrefix\u0027), \u0027Farm_Config\u0027)]" + }, + "resources": { + "AllNodes": [ + { + "PSDscAllowDomainUser": true, + "PSDSCAllowPlainTextPassword": true, + "NodeName": "*", + "RunCentralAdministration": false + } + ], + "NonNodeData": { + "Services": { + "SharePoint": { + "Farm": { + "ManagedAccounts": { + "DefaultServiceApplicationPoolAccount": "[parameters(\u0027DefaultServiceApplicationPoolAccount\u0027)]", + "FarmAccount": "[parameters(\u0027FarmCredential\u0027)]", + "SearchServiceApplicationPoolAccount": "[parameters(\u0027SearchServiceApplicationPoolAccount\u0027)]" + }, + "Passphrase": "[parameters(\u0027FarmPassphrase\u0027)]", + "ServiceApplications": { + "AppManagementService": { + "DatabaseName": "[concat(variables(\u0027ServiceDbPrefix\u0027),\u0027AppManagement\u0027)]", + "ApplicationPool": "[reference(\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\u0027, \u0027Name\u0027)]", + "Provision": true + }, + "StateService": { + "DatabaseName": "[concat(variables(\u0027ServiceDbPrefix\u0027),\u0027StateService\u0027)]", + "Provision": true + }, + "SubscriptionSettingsService": { + "DatabaseName": "[concat(variables(\u0027ServiceDbPrefix\u0027),\u0027SubscriptionSettings\u0027)]", + "ApplicationPool": "[reference(\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\u0027, \u0027Name\u0027)]", + "Provision": true + }, + "ManagedMetadataService": { + "Name": "Managed Metadata Service", + "DatabaseName": "[concat(variables(\u0027ServiceDbPrefix\u0027), \u0027ManagedMetadata\u0027)]", + "ApplicationPool": "[reference(\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\u0027, \u0027Name\u0027)]", + "Provision": true + }, + "SearchService": { + "Name": "Search Service Application", + "DatabaseName": "[concat(variables(\u0027ServiceDbPrefix\u0027),\u0027Search\u0027)]", + "ApplicationPool": "[reference(\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.SearchServiceApplicationPool\u0027, \u0027Name\u0027)]", + "Provision": true + }, + "UsageAndHealthService": { + "DatabaseName": "[concat(variables(\u0027ServiceDbPrefix\u0027),\u0027UsageAndHealth\u0027)]", + "Provision": true + }, + "SecureStoreService": { + "Name": "Secure Store Service", + "DatabaseName": "[concat(variables(\u0027ServiceDbPrefix\u0027),\u0027SecureStore\u0027)]", + "ApplicationPool": "[reference(\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\u0027, \u0027Name\u0027)]", + "Provision": true, + "AuditingEnabled": true + }, + "UserProfileService": { + "SyncDBName": "[concat(variables(\u0027ServiceDbPrefix\u0027), \u0027UserProfile_Sync\u0027)]", + "ApplicationPool": "[reference(\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\u0027, \u0027Name\u0027)]", + "Provision": true, + "Name": "User Profile Service", + "SocialDBName": "[concat(variables(\u0027ServiceDbPrefix\u0027), \u0027UserProfile_Social\u0027)]", + "ProfileDBName": "[concat(variables(\u0027ServiceDbPrefix\u0027), \u0027UserProfile_Profile\u0027)]" + } + }, + "CentralAdminAuth": "NTLM", + "ConfigDatabaseName": "[variables(\u0027ConfigDbName\u0027)]", + "Accounts": { + "SetupAccount": "[parameters(\u0027SetupCredential\u0027)]" + }, + "CentralAdminPort": "[parameters(\u0027CentralAdminPort\u0027)]", + "AdminContentDatabase": "[variables(\u0027AdminDbName\u0027)]", + "ServiceApplicationPools": { + "SearchServiceApplicationPool": { + "Account": "[reference(\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.SearchServiceApplicationPoolAccount\u0027, \u0027UserName\u0027)]", + "Name": "[parameters(\u0027ServiceApplicationPoolSearch\u0027)]" + }, + "DefaultServiceApplicationPool": { + "Account": "[reference(\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.DefaultServiceApplicationPoolAccount\u0027, \u0027UserName\u0027)]", + "Name": "[parameters(\u0027ServiceApplicationPoolDefault\u0027)]" + } + } + }, + "Database": { + "Targets": { + "Farm": { + "Server": "SQLServer", + "DependsOnAlias": "SQLServer" + }, + "Content": { + "Server": "SQLServer", + "DependsOnAlias": "SQLServer" + }, + "Service": { + "Server": "SQLServer", + "DependsOnAlias": "SQLServer" + } + }, + "SQLAlias": { + "SQLServer": { + "InstanceName": "[parameters(\u0027DatabaseInstanceName\u0027)]", + "ServerName": "[parameters(\u0027DatabaseServerName\u0027)]", + "Protocol": "TCP", + "TcpPort": "[parameters(\u0027DatabaseTcpPort\u0027)]" + } + } + }, + "General": { + "ProductKey": "[parameters(\u0027ProductKey\u0027)]" + }, + "Windows": { + "Registry": { + "DisableLoopbackCheck": { + "Path": "HKLM:\\SYSTEM\\CurrentControlSet\\Control\\Lsa", + "Name": "DisableLoopbackCheck", + "Value": 1, + "Type": "DWord" + } + } + } + } + } + } + } + } + """; + + private const string BgwStageInstallTemplateJson = """ + { + "schemaVersion": "1.0", + "templateType": "Stage", + "metadata": { + "TemplateType": "Stage", + "Name": "Install" + }, + "parameters": { + + }, + "variables": { + + }, + "resources": { + "NonNodeData": { + "LocalConfigurationManager": { + "RefreshFrequencyMins": "30", + "RefreshMode": "PUSH", + "ConfigurationModeFrequencyMins": "120", + "ConfigurationMode": "ApplyOnly" + } + } + } + } + """; + + } +} diff --git a/Context/DemoData.cs b/Context/DemoData.cs index fa810b2..848579d 100644 --- a/Context/DemoData.cs +++ b/Context/DemoData.cs @@ -3,7 +3,7 @@ using Microsoft.SelfService.Portal.Core.API.Models; namespace Microsoft.SelfService.Portal.Core.API.Context { - internal static class DemoData + internal static partial class DemoData { private static readonly DateTime Timestamp = new(2026, 7, 7, 0, 0, 0, DateTimeKind.Utc); private const string Owner = "DemoSeed"; @@ -22,16 +22,21 @@ namespace Microsoft.SelfService.Portal.Core.API.Context internal static readonly Guid VmSp02Id = Guid.Parse("30000000-0000-0000-0000-000000000005"); internal static readonly Guid TargetM365TenantId = Guid.Parse("30000000-0000-0000-0000-000000000006"); internal static readonly Guid TargetTeamsPolicyScopeId = Guid.Parse("30000000-0000-0000-0000-000000000007"); + internal static readonly Guid TargetBgwSp01Id = Guid.Parse("30000000-0000-0000-0000-000000000101"); + internal static readonly Guid TargetBgwSp02Id = Guid.Parse("30000000-0000-0000-0000-000000000102"); + internal static readonly Guid TargetBgwSp03Id = Guid.Parse("30000000-0000-0000-0000-000000000103"); internal static readonly Guid ServiceActiveDirectoryId = Guid.Parse("40000000-0000-0000-0000-000000000001"); internal static readonly Guid ServiceSqlServerId = Guid.Parse("40000000-0000-0000-0000-000000000002"); internal static readonly Guid ServiceSharePointId = Guid.Parse("40000000-0000-0000-0000-000000000003"); internal static readonly Guid ServiceTeamsId = Guid.Parse("40000000-0000-0000-0000-000000000004"); + internal static readonly Guid ServiceConfigurationDataId = Guid.Parse("40000000-0000-0000-0000-000000000101"); internal static readonly Guid CategoryActiveDirectoryId = Guid.Parse("50000000-0000-0000-0000-000000000001"); internal static readonly Guid CategorySqlServerId = Guid.Parse("50000000-0000-0000-0000-000000000002"); internal static readonly Guid CategorySharePointId = Guid.Parse("50000000-0000-0000-0000-000000000003"); internal static readonly Guid CategoryTeamsId = Guid.Parse("50000000-0000-0000-0000-000000000004"); + internal static readonly Guid CategoryBgwMergeTemplatesId = Guid.Parse("50000000-0000-0000-0000-000000000101"); internal static readonly Guid RuleStandardId = Guid.Parse("60000000-0000-0000-0000-000000000001"); internal static readonly Guid RuleStepValidateId = Guid.Parse("60000000-0000-0000-0000-000000000101"); @@ -42,20 +47,39 @@ namespace Microsoft.SelfService.Portal.Core.API.Context internal static readonly Guid TemplateSqlServerId = Guid.Parse("70000000-0000-0000-0000-000000000002"); internal static readonly Guid TemplateSharePointId = Guid.Parse("70000000-0000-0000-0000-000000000003"); internal static readonly Guid TemplateTeamsId = Guid.Parse("70000000-0000-0000-0000-000000000004"); + internal static readonly Guid TemplateBgwEnvironmentTestId = Guid.Parse("70000000-0000-0000-0000-000000000101"); + internal static readonly Guid TemplateBgwDomainContosoId = Guid.Parse("70000000-0000-0000-0000-000000000102"); + internal static readonly Guid TemplateBgwSharePointContosoId = Guid.Parse("70000000-0000-0000-0000-000000000103"); + internal static readonly Guid TemplateBgwStageInstallId = Guid.Parse("70000000-0000-0000-0000-000000000104"); internal static readonly Guid TemplateActiveDirectoryVersionId = Guid.Parse("71000000-0000-0000-0000-000000000001"); internal static readonly Guid TemplateSqlServerVersionId = Guid.Parse("71000000-0000-0000-0000-000000000002"); internal static readonly Guid TemplateSharePointVersionId = Guid.Parse("71000000-0000-0000-0000-000000000003"); internal static readonly Guid TemplateTeamsVersionId = Guid.Parse("71000000-0000-0000-0000-000000000004"); + internal static readonly Guid TemplateBgwEnvironmentTestVersionId = Guid.Parse("71000000-0000-0000-0000-000000000101"); + internal static readonly Guid TemplateBgwDomainContosoVersionId = Guid.Parse("71000000-0000-0000-0000-000000000102"); + internal static readonly Guid TemplateBgwSharePointContosoVersionId = Guid.Parse("71000000-0000-0000-0000-000000000103"); + internal static readonly Guid TemplateBgwStageInstallVersionId = Guid.Parse("71000000-0000-0000-0000-000000000104"); internal static readonly Guid DeploymentBatchSharePointId = Guid.Parse("80000000-0000-0000-0000-000000000001"); + internal static readonly Guid DeploymentBatchBgwMergeId = Guid.Parse("80000000-0000-0000-0000-000000000101"); internal static readonly Guid DeploymentSp01Id = Guid.Parse("81000000-0000-0000-0000-000000000001"); internal static readonly Guid DeploymentSp02Id = Guid.Parse("81000000-0000-0000-0000-000000000002"); + internal static readonly Guid DeploymentBgwSp01Id = Guid.Parse("81000000-0000-0000-0000-000000000101"); + internal static readonly Guid DeploymentBgwSp02Id = Guid.Parse("81000000-0000-0000-0000-000000000102"); + internal static readonly Guid DeploymentBgwSp03Id = Guid.Parse("81000000-0000-0000-0000-000000000103"); internal static readonly Guid DeploymentSharePointTemplateSelectionId = Guid.Parse("82000000-0000-0000-0000-000000000001"); + internal static readonly Guid DeploymentBgwEnvironmentSelectionId = Guid.Parse("82000000-0000-0000-0000-000000000101"); + internal static readonly Guid DeploymentBgwDomainSelectionId = Guid.Parse("82000000-0000-0000-0000-000000000102"); + internal static readonly Guid DeploymentBgwSharePointSelectionId = Guid.Parse("82000000-0000-0000-0000-000000000103"); + internal static readonly Guid DeploymentBgwStageSelectionId = Guid.Parse("82000000-0000-0000-0000-000000000104"); internal static readonly Guid DeploymentParameterDatabasePrefixId = Guid.Parse("83000000-0000-0000-0000-000000000001"); internal static readonly Guid DeploymentParameterFarmAccountId = Guid.Parse("83000000-0000-0000-0000-000000000002"); internal static readonly Guid DeploymentTargetSp01Id = Guid.Parse("84000000-0000-0000-0000-000000000001"); internal static readonly Guid DeploymentTargetSp02Id = Guid.Parse("84000000-0000-0000-0000-000000000002"); + internal static readonly Guid DeploymentTargetBgwSp01Id = Guid.Parse("84000000-0000-0000-0000-000000000101"); + internal static readonly Guid DeploymentTargetBgwSp02Id = Guid.Parse("84000000-0000-0000-0000-000000000102"); + internal static readonly Guid DeploymentTargetBgwSp03Id = Guid.Parse("84000000-0000-0000-0000-000000000103"); internal static void Seed(ModelBuilder modelBuilder) { @@ -105,7 +129,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Context Base(new TargetModel { Id = VmSp01Id, DomainID = DomainCentralId, Name = "CT-SHP-01", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\"}" }), Base(new TargetModel { Id = VmSp02Id, DomainID = DomainCentralId, Name = "CT-SHP-02", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\"}" }), Base(new TargetModel { Id = TargetM365TenantId, Name = "contoso.onmicrosoft.com", TargetType = "Tenant", ProviderType = "Microsoft365", ExternalId = "11111111-1111-1111-1111-111111111111", MetadataJson = "{\"environment\":\"Production\",\"workload\":\"M365\"}" }), - Base(new TargetModel { Id = TargetTeamsPolicyScopeId, Name = "Teams - Standard Users", TargetType = "PolicyScope", ProviderType = "Microsoft365", ExternalId = "Teams.StandardUsers", MetadataJson = "{\"workload\":\"Teams\",\"scope\":\"StandardUsers\"}" }) + Base(new TargetModel { Id = TargetTeamsPolicyScopeId, Name = "Teams - Standard Users", TargetType = "PolicyScope", ProviderType = "Microsoft365", ExternalId = "Teams.StandardUsers", MetadataJson = "{\"workload\":\"Teams\",\"scope\":\"StandardUsers\"}" }), + Base(new TargetModel { Id = TargetBgwSp01Id, DomainID = DomainCentralId, Name = "CLD-SHP-01", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}" }), + Base(new TargetModel { Id = TargetBgwSp02Id, DomainID = DomainCentralId, Name = "CLD-SHP-02", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}" }), + Base(new TargetModel { Id = TargetBgwSp03Id, DomainID = DomainCentralId, Name = "CLD-SHP-03", TargetType = "VirtualMachine", ProviderType = "OnPrem", MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}" }) ]; private static object[] Services() => @@ -113,7 +140,8 @@ namespace Microsoft.SelfService.Portal.Core.API.Context Base(new ServiceModel { Id = ServiceActiveDirectoryId, Name = "Active Directory", Description = "On-premises directory and identity service.", IconKey = "network", IsCloudService = false }), Base(new ServiceModel { Id = ServiceSqlServerId, Name = "SQL Server", Description = "Database platform for application workloads.", IconKey = "database", IsCloudService = false }), Base(new ServiceModel { Id = ServiceSharePointId, Name = "SharePoint Server", Description = "Collaboration platform for on-premises workloads.", IconKey = "sharepoint", IsCloudService = false }), - Base(new ServiceModel { Id = ServiceTeamsId, Name = "Microsoft Teams", Description = "Cloud collaboration workload in Microsoft 365.", IconKey = "messages-square", IsCloudService = true }) + Base(new ServiceModel { Id = ServiceTeamsId, Name = "Microsoft Teams", Description = "Cloud collaboration workload in Microsoft 365.", IconKey = "messages-square", IsCloudService = true }), + Base(new ServiceModel { Id = ServiceConfigurationDataId, Name = "DSC Configuration Data", Description = "Reusable configuration-data template building blocks for deployment composition.", IconKey = "braces", IsCloudService = false }) ]; private static object[] ServiceRoleDefinitions() => @@ -129,7 +157,8 @@ namespace Microsoft.SelfService.Portal.Core.API.Context Base(new TemplateCategoryModel { Id = CategoryActiveDirectoryId, ServiceId = ServiceActiveDirectoryId, Name = "Domain Services", Description = "Templates for domain controller and domain configuration.", Color = "#2563EB", IsActive = true }), Base(new TemplateCategoryModel { Id = CategorySqlServerId, ServiceId = ServiceSqlServerId, Name = "Database Platform", Description = "Templates for SQL Server workloads.", Color = "#16A34A", IsActive = true }), Base(new TemplateCategoryModel { Id = CategorySharePointId, ServiceId = ServiceSharePointId, Name = "Collaboration Farm", Description = "Templates for SharePoint Server farms.", Color = "#0F766E", IsActive = true }), - Base(new TemplateCategoryModel { Id = CategoryTeamsId, ServiceId = ServiceTeamsId, Name = "Teams Policies", Description = "Templates for Teams policy configuration.", Color = "#7C3AED", IsActive = true }) + Base(new TemplateCategoryModel { Id = CategoryTeamsId, ServiceId = ServiceTeamsId, Name = "Teams Policies", Description = "Templates for Teams policy configuration.", Color = "#7C3AED", IsActive = true }), + Base(new TemplateCategoryModel { Id = CategoryBgwMergeTemplatesId, ServiceId = ServiceConfigurationDataId, Name = "Test.Merge.ps1 Templates", Description = "Materialized template building blocks from the BGW Test.Merge.ps1 scenario.", Color = "#2563EB", IsActive = true }) ]; private static object[] DeploymentRules() => @@ -149,7 +178,11 @@ namespace Microsoft.SelfService.Portal.Core.API.Context Base(new TemplateModel { Id = TemplateActiveDirectoryId, TemplateCategoryId = CategoryActiveDirectoryId, DeploymentRuleId = RuleStandardId, Name = "Contoso Active Directory Domain", Version = "1.0.0", Description = "Creates a reusable Active Directory domain baseline.", JSONData = ActiveDirectoryTemplateJson }), Base(new TemplateModel { Id = TemplateSqlServerId, TemplateCategoryId = CategorySqlServerId, DeploymentRuleId = RuleStandardId, Name = "Contoso SQL Server", Version = "1.0.0", Description = "Creates a SQL Server baseline for application workloads.", JSONData = SqlServerTemplateJson }), Base(new TemplateModel { Id = TemplateSharePointId, TemplateCategoryId = CategorySharePointId, DeploymentRuleId = RuleStandardId, Name = "Contoso SharePoint Server", Version = "1.0.0", Description = "Creates a SharePoint Server farm baseline.", JSONData = SharePointTemplateJson }), - Base(new TemplateModel { Id = TemplateTeamsId, TemplateCategoryId = CategoryTeamsId, DeploymentRuleId = RuleStandardId, Name = "Contoso Teams Policies", Version = "1.0.0", Description = "Creates a Microsoft Teams policy baseline.", JSONData = TeamsTemplateJson }) + Base(new TemplateModel { Id = TemplateTeamsId, TemplateCategoryId = CategoryTeamsId, DeploymentRuleId = RuleStandardId, Name = "Contoso Teams Policies", Version = "1.0.0", Description = "Creates a Microsoft Teams policy baseline.", JSONData = TeamsTemplateJson }), + Base(new TemplateModel { Id = TemplateBgwEnvironmentTestId, TemplateCategoryId = CategoryBgwMergeTemplatesId, DeploymentRuleId = RuleStandardId, Name = "BGW Environment Test", Version = "1.0.0", Description = "Materialized Environment/Test.psd1 template from Test.Merge.ps1.", JSONData = BgwEnvironmentTestTemplateJson }), + Base(new TemplateModel { Id = TemplateBgwDomainContosoId, TemplateCategoryId = CategoryBgwMergeTemplatesId, DeploymentRuleId = RuleStandardId, Name = "BGW Domain Contoso", Version = "1.0.0", Description = "Materialized Domain/Contoso.psd1 template from Test.Merge.ps1.", JSONData = BgwDomainContosoTemplateJson }), + Base(new TemplateModel { Id = TemplateBgwSharePointContosoId, TemplateCategoryId = CategoryBgwMergeTemplatesId, DeploymentRuleId = RuleStandardId, Name = "BGW SharePoint Contoso", Version = "1.0.0", Description = "Materialized Service/SharePoint/Contoso.psd1 template from Test.Merge.ps1.", JSONData = BgwSharePointContosoTemplateJson }), + Base(new TemplateModel { Id = TemplateBgwStageInstallId, TemplateCategoryId = CategoryBgwMergeTemplatesId, DeploymentRuleId = RuleStandardId, Name = "BGW Stage Install", Version = "1.0.0", Description = "Materialized Stage/Install.psd1 template from Test.Merge.ps1.", JSONData = BgwStageInstallTemplateJson }) ]; private static object[] TemplateVersions() => @@ -157,23 +190,35 @@ namespace Microsoft.SelfService.Portal.Core.API.Context TemplateVersion(TemplateActiveDirectoryVersionId, TemplateActiveDirectoryId, ActiveDirectoryTemplateJson), TemplateVersion(TemplateSqlServerVersionId, TemplateSqlServerId, SqlServerTemplateJson), TemplateVersion(TemplateSharePointVersionId, TemplateSharePointId, SharePointTemplateJson), - TemplateVersion(TemplateTeamsVersionId, TemplateTeamsId, TeamsTemplateJson) + TemplateVersion(TemplateTeamsVersionId, TemplateTeamsId, TeamsTemplateJson), + TemplateVersion(TemplateBgwEnvironmentTestVersionId, TemplateBgwEnvironmentTestId, BgwEnvironmentTestTemplateJson), + TemplateVersion(TemplateBgwDomainContosoVersionId, TemplateBgwDomainContosoId, BgwDomainContosoTemplateJson), + TemplateVersion(TemplateBgwSharePointContosoVersionId, TemplateBgwSharePointContosoId, BgwSharePointContosoTemplateJson), + TemplateVersion(TemplateBgwStageInstallVersionId, TemplateBgwStageInstallId, BgwStageInstallTemplateJson) ]; private static object[] DeploymentBatches() => [ - Base(new DeploymentGroupModel { Id = DeploymentBatchSharePointId, TemplateId = TemplateSharePointId, DeploymentRuleId = RuleStandardId, Status = QueueJobStatus.Pending }) + Base(new DeploymentGroupModel { Id = DeploymentBatchSharePointId, TemplateId = TemplateSharePointId, DeploymentRuleId = RuleStandardId, Status = QueueJobStatus.Pending }), + Base(new DeploymentGroupModel { Id = DeploymentBatchBgwMergeId, TemplateId = TemplateBgwSharePointContosoId, DeploymentRuleId = RuleStandardId, Status = QueueJobStatus.Pending }) ]; private static object[] Deployments() => [ Base(new DeploymentModel { Id = DeploymentSp01Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp01Id, Status = QueueJobStatus.Pending, JSONData = "{\"role\":\"WebFrontEnd\"}" }), - Base(new DeploymentModel { Id = DeploymentSp02Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp02Id, Status = QueueJobStatus.Pending, JSONData = "{\"role\":\"Application\"}" }) + Base(new DeploymentModel { Id = DeploymentSp02Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp02Id, Status = QueueJobStatus.Pending, JSONData = "{\"role\":\"Application\"}" }), + Base(new DeploymentModel { Id = DeploymentBgwSp01Id, DeploymentGroupId = DeploymentBatchBgwMergeId, TargetId = TargetBgwSp01Id, Status = QueueJobStatus.Pending, JSONData = "{\"role\":\"Node\"}" }), + Base(new DeploymentModel { Id = DeploymentBgwSp02Id, DeploymentGroupId = DeploymentBatchBgwMergeId, TargetId = TargetBgwSp02Id, Status = QueueJobStatus.Pending, JSONData = "{\"role\":\"Node\"}" }), + Base(new DeploymentModel { Id = DeploymentBgwSp03Id, DeploymentGroupId = DeploymentBatchBgwMergeId, TargetId = TargetBgwSp03Id, Status = QueueJobStatus.Pending, JSONData = "{\"role\":\"Node\"}" }) ]; private static object[] DeploymentTemplateSelections() => [ - Base(new DeploymentTemplateSelectionModel { Id = DeploymentSharePointTemplateSelectionId, DeploymentGroupId = DeploymentBatchSharePointId, TemplateVersionId = TemplateSharePointVersionId, TemplateRole = "Service", SortOrder = 10, Alias = "SharePoint" }) + Base(new DeploymentTemplateSelectionModel { Id = DeploymentSharePointTemplateSelectionId, DeploymentGroupId = DeploymentBatchSharePointId, TemplateVersionId = TemplateSharePointVersionId, TemplateRole = "Service", SortOrder = 10, Alias = "SharePoint" }), + Base(new DeploymentTemplateSelectionModel { Id = DeploymentBgwEnvironmentSelectionId, DeploymentGroupId = DeploymentBatchBgwMergeId, TemplateVersionId = TemplateBgwEnvironmentTestVersionId, TemplateRole = "Environment", SortOrder = 10, Alias = "Environment-Test" }), + Base(new DeploymentTemplateSelectionModel { Id = DeploymentBgwDomainSelectionId, DeploymentGroupId = DeploymentBatchBgwMergeId, TemplateVersionId = TemplateBgwDomainContosoVersionId, TemplateRole = "Domain", SortOrder = 20, Alias = "Domain-Contoso" }), + Base(new DeploymentTemplateSelectionModel { Id = DeploymentBgwSharePointSelectionId, DeploymentGroupId = DeploymentBatchBgwMergeId, TemplateVersionId = TemplateBgwSharePointContosoVersionId, TemplateRole = "Service", SortOrder = 30, Alias = "Service-SharePoint-Contoso" }), + Base(new DeploymentTemplateSelectionModel { Id = DeploymentBgwStageSelectionId, DeploymentGroupId = DeploymentBatchBgwMergeId, TemplateVersionId = TemplateBgwStageInstallVersionId, TemplateRole = "Stage", SortOrder = 40, Alias = "Stage-Install" }) ]; private static object[] DeploymentParameterValues() => @@ -185,7 +230,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Context private static object[] DeploymentTargetAssignments() => [ Base(new DeploymentTargetAssignmentModel { Id = DeploymentTargetSp01Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp01Id, RoleKey = "WebFrontEnd", SortOrder = 10, NodeDataJson = "{\"nodeName\":\"CT-SHP-01\"}" }), - Base(new DeploymentTargetAssignmentModel { Id = DeploymentTargetSp02Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp02Id, RoleKey = "Application", SortOrder = 20, NodeDataJson = "{\"nodeName\":\"CT-SHP-02\"}" }) + Base(new DeploymentTargetAssignmentModel { Id = DeploymentTargetSp02Id, DeploymentGroupId = DeploymentBatchSharePointId, TargetId = VmSp02Id, RoleKey = "Application", SortOrder = 20, NodeDataJson = "{\"nodeName\":\"CT-SHP-02\"}" }), + Base(new DeploymentTargetAssignmentModel { Id = DeploymentTargetBgwSp01Id, DeploymentGroupId = DeploymentBatchBgwMergeId, TargetId = TargetBgwSp01Id, RoleKey = "Node", SortOrder = 10, NodeDataJson = "{\"nodeName\":\"CLD-SHP-01\",\"RunCentralAdministration\":true}" }), + Base(new DeploymentTargetAssignmentModel { Id = DeploymentTargetBgwSp02Id, DeploymentGroupId = DeploymentBatchBgwMergeId, TargetId = TargetBgwSp02Id, RoleKey = "Node", SortOrder = 20, NodeDataJson = "{\"nodeName\":\"CLD-SHP-02\",\"RunCentralAdministration\":false}" }), + Base(new DeploymentTargetAssignmentModel { Id = DeploymentTargetBgwSp03Id, DeploymentGroupId = DeploymentBatchBgwMergeId, TargetId = TargetBgwSp03Id, RoleKey = "Node", SortOrder = 30, NodeDataJson = "{\"nodeName\":\"CLD-SHP-03\",\"RunCentralAdministration\":false}" }) ]; private static TemplateVersionModel TemplateVersion(Guid id, Guid templateId, string jsonData) diff --git a/Controllers/DeploymentBatchController.cs b/Controllers/DeploymentBatchController.cs index ad356ff..fab22b8 100644 --- a/Controllers/DeploymentBatchController.cs +++ b/Controllers/DeploymentBatchController.cs @@ -34,16 +34,28 @@ namespace Microsoft.SelfService.Portal.Core.API.Controllers { var deploymentBatches = _deploymentBatchInterface .GetDeploymentBatches() - .Select(batch => new GetDeploymentBatchDto + .Select(batch => { - Id = batch.Id, - TemplateId = batch.TemplateId, - DeploymentRuleId = batch.DeploymentRuleId, - Status = batch.Status, - Created = batch.Created, - CreatedBy = batch.CreatedBy, - Modified = batch.Modified, - ModifiedBy = batch.ModifiedBy + var primarySelection = batch.TemplateSelections + .OrderBy(selection => selection.SortOrder) + .FirstOrDefault(); + + return new GetDeploymentBatchDto + { + Id = batch.Id, + TemplateId = batch.TemplateId, + DeploymentRuleId = batch.DeploymentRuleId, + Status = batch.Status, + Created = batch.Created, + CreatedBy = batch.CreatedBy, + Modified = batch.Modified, + ModifiedBy = batch.ModifiedBy, + PrimaryTemplateVersionId = primarySelection?.TemplateVersionId, + PrimaryTemplateName = primarySelection?.TemplateVersion?.Template?.Name, + PrimaryTemplateVersion = primarySelection?.TemplateVersion?.Version, + TemplateSelectionCount = batch.TemplateSelections.Count, + TargetAssignmentCount = batch.TargetAssignments.Count + }; }) .ToList(); @@ -80,6 +92,20 @@ namespace Microsoft.SelfService.Portal.Core.API.Controllers if (!ModelState.IsValid) return BadRequest(ModelState); + if (deploymentBatch.TemplateVersionId.HasValue + && (deploymentBatch.TemplateSelections == null || deploymentBatch.TemplateSelections.Count == 0)) + { + deploymentBatch.TemplateSelections = new List + { + new() + { + TemplateVersionId = deploymentBatch.TemplateVersionId.Value, + TemplateRole = "Service", + SortOrder = 10 + } + }; + } + var deploymentBatchMap = _mapper.Map(deploymentBatch); if (!_deploymentBatchInterface.AddDeploymentBatchById(deploymentBatchMap, deploymentBatch.TargetIds)) diff --git a/Controllers/DeploymentController.cs b/Controllers/DeploymentController.cs index 808d3c9..81bc116 100644 --- a/Controllers/DeploymentController.cs +++ b/Controllers/DeploymentController.cs @@ -100,12 +100,6 @@ namespace Microsoft.SelfService.Portal.Core.API.Controllers if (request == null) return BadRequest(ModelState); - if (request.TargetIds == null || request.TargetIds.Count == 0) - { - ModelState.AddModelError("", "At least one Target must be selected."); - return BadRequest(ModelState); - } - if (!ModelState.IsValid) return BadRequest(ModelState); @@ -149,6 +143,11 @@ namespace Microsoft.SelfService.Portal.Core.API.Controllers Started = job.Started, Finished = job.Finished, ErrorMessage = job.ErrorMessage, + CorrelationId = job.CorrelationId, + Priority = job.Priority, + ScheduledAt = job.ScheduledAt, + HeartbeatAt = job.HeartbeatAt, + WorkerName = job.WorkerName, TargetCount = job.Targets.Count, SucceededTargetCount = job.Targets.Count(target => target.Status == QueueJobStatus.Succeeded), FailedTargetCount = job.Targets.Count(target => target.Status == QueueJobStatus.Failed) @@ -185,6 +184,13 @@ namespace Microsoft.SelfService.Portal.Core.API.Controllers ErrorMessage = queueJob.ErrorMessage, MetadataJson = queueJob.MetadataJson, RuleSnapshotJson = queueJob.RuleSnapshotJson, + CorrelationId = queueJob.CorrelationId, + Priority = queueJob.Priority, + ScheduledAt = queueJob.ScheduledAt, + HeartbeatAt = queueJob.HeartbeatAt, + WorkerName = queueJob.WorkerName, + LockedBy = queueJob.LockedBy, + LockedUntil = queueJob.LockedUntil, Created = queueJob.Created, CreatedBy = queueJob.CreatedBy, Modified = queueJob.Modified, @@ -197,7 +203,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Controllers TemplateId = target.TemplateId, Status = target.Status, Attempts = target.Attempts, - ErrorMessage = target.ErrorMessage + ErrorMessage = target.ErrorMessage, + Started = target.Started, + Finished = target.Finished, + OutputMetadataJson = target.OutputMetadataJson }).ToList(), Steps = queueJob.Steps .OrderBy(step => step.SortOrder) @@ -212,7 +221,11 @@ namespace Microsoft.SelfService.Portal.Core.API.Controllers MetadataJson = step.MetadataJson, ApprovedAt = step.ApprovedAt, ApprovedBy = step.ApprovedBy, - ApprovalComment = step.ApprovalComment + ApprovalComment = step.ApprovalComment, + Started = step.Started, + Finished = step.Finished, + OutputMetadataJson = step.OutputMetadataJson, + ErrorMessage = step.ErrorMessage }).ToList() }; diff --git a/Docs/Architecture/Process.md b/Docs/Architecture/Process.md new file mode 100644 index 0000000..9aed3d2 --- /dev/null +++ b/Docs/Architecture/Process.md @@ -0,0 +1,597 @@ +# SelfService Portal Process + +## Purpose + +This document describes the current end-to-end process as understood for the SelfService Portal. +It is intentionally written as a business and platform flow, not as a low-level API reference. + +The goal is to make visible how catalog data, reusable templates, deployment composition, queue jobs, and worker execution fit together. + +## Big Picture + +The portal is intended to become a generic configuration composition platform. +It should support on-premises workloads such as Active Directory, SQL Server, SharePoint, and Exchange, and also cloud workloads such as Teams, Azure, Microsoft 365, and Azure resources. + +The important idea is: + +```text +Reusable catalog data + immutable template versions + deployment-specific choices + -> composed deployment document + -> queue job + -> worker renders and executes +``` + +The database should know generic concepts such as environments, domains, targets, services, templates, template versions, deployment groups, queue jobs, and artifacts. +Workload-specific details, for example SharePoint farm accounts or Teams policies, belong inside versioned template documents. + +## Roles Of The Applications + +### Microsoft.SelfService.Portal.Core.API + +The API owns the central data model and exposes it to the GUI and worker. + +Responsibilities: + +- Store catalog data such as environments, domains, services, targets, templates, and template versions. +- Store deployment composition data such as selected template versions, parameter overrides, and target assignments. +- Validate JSON documents before storing them. +- Create deployment queue jobs. +- Expose queue job status, steps, target progress, errors, and metadata. + +### Microsoft.SelfService.Portal.Web + +The web frontend is the user-facing surface. + +Responsibilities: + +- Let users browse catalog data. +- Let users create and edit deployment groups. +- Let users select template versions, targets, parameters, and later preview effective configuration data. +- Submit deployment requests into the API queue. +- Show queue job state and execution progress. + +The current GUI is intentionally rudimentary. The later target is a richer interactive deployment builder. + +### Microsoft.SelfService.Portal.Core.Worker + +The worker processes queued deployment jobs. + +Responsibilities: + +- Claim jobs safely from the queue. +- Load deployment composition from the API database. +- Render the deployment composition into an artifact. +- Support different renderers, currently DSC v2 PowerShell data files and DSC v3 JSON. +- Later execute or hand off the rendered artifacts. +- Persist target and step output metadata. + +## Catalog Process + +### 1. Environments Are Defined + +An environment is a logical deployment context, for example: + +```text +Prod A +Test A +QA B +Prod B +Test B +``` + +An environment describes where something belongs and what stage it represents. + +Examples of environment metadata: + +- Stage: Test, QA, Production +- Hosting type: OnPrem, Azure, M365, Hybrid +- Provider type +- Tenant or subscription reference + +### 2. Domains Are Defined Once And Linked + +A domain is reusable catalog and configuration data. +It can be linked to multiple environments. + +Example: + +```text +Central-Management Domain + -> Test A + -> QA A + -> Prod A +``` + +The intent is that a domain configuration is not duplicated for every environment. +Instead, a domain baseline can be maintained once, then linked or promoted into the environments that should consume it. + +Target process: + +```text +Change Central-Management domain baseline + -> validate in Test + -> promote or reuse for Prod +``` + +Not desired: + +```text +Maintain Central-Management Test separately +Maintain Central-Management Prod separately +Repeat every change manually +``` + +### 3. Services Describe Workload Families + +A service represents a workload type, not a single deployment. + +Examples: + +- Active Directory +- SQL Server +- SharePoint +- Exchange +- Teams +- Azure Network +- Microsoft 365 Policies + +Templates are categorized below services so users can find suitable building blocks. + +### 4. Targets Are Generic + +Targets are everything a deployment can act on. +They are not limited to virtual machines. + +Examples: + +- VirtualMachine +- Tenant +- Subscription +- ResourceGroup +- User +- Group +- Site +- PolicyScope + +For on-premises workloads, targets are often servers. +For cloud workloads, targets may be tenants, subscriptions, groups, sites, or policy scopes. + +## Template Process + +### 1. A Template Is A Catalog Entry + +A template is the stable entry shown in the portal. +It has metadata such as name, category, service, and description. + +The template itself should not be the mutable source of deployment content in the long term. +It is the catalog shell. + +### 2. TemplateVersions Are Immutable Building Blocks + +The actual configuration document lives in `TemplateVersion.JsonData`. + +Each template version contains a JSON document with this general shape: + +```json +{ + "schemaVersion": "1.0", + "templateType": "Service", + "parameters": {}, + "variables": {}, + "resources": {} +} +``` + +The template version is the thing that should be selected in a deployment. +This makes deployments reproducible, because they point to an immutable version instead of a mutable template document. + +### 3. Template Documents Stay Generic + +Template documents can describe many workloads. + +Examples: + +- Environment defaults +- Domain defaults +- Landscape values +- Service definitions +- Stage-specific settings +- Target or role specific blocks + +The document can contain parameters, variables, and resources. +The merge and resolve modules can later combine those pieces into effective configuration data. + +## Deployment Design Process + +### 1. User Creates A DeploymentGroup + +A deployment group represents a deployable unit or one part of a larger environment rollout. + +Example environment rollout: + +```text +Deployment Group: Contoso Test Environment + + Deployment AD + Targets: 2 domain controller servers + Templates: Active Directory baseline, environment defaults, stage defaults + + Deployment SQL + Targets: 1 SQL server + Templates: SQL baseline, environment defaults, stage defaults + + Deployment SharePoint + Targets: 6 SharePoint servers + Templates: SharePoint baseline, environment defaults, landscape, stage defaults +``` + +Current implementation still uses `DeploymentGroup`/`DeploymentBatch` naming in places. +Conceptually this is the deployment design container. + +### 2. User Selects Template Versions + +The deployment group gets one or more `DeploymentTemplateSelections`. + +Example: + +```text +SortOrder 10: Environment Default 1.0 +SortOrder 20: Environment Contoso Test 1.0 +SortOrder 30: Service SharePoint 1.0 +SortOrder 40: Stage Install 1.0 +``` + +The order matters because the selected template versions are composed in order. +Later selections can extend or override earlier selections, unless a parameter or resource block is sealed. + +Current state: + +- The API can store multiple template selections. +- The GUI can create an initial selection from a selected template version. +- The details page can add more selections manually. + +### 3. User Assigns Targets + +The deployment group gets `DeploymentTargetAssignments`. + +For server-based workloads, each target assignment usually points to a server. + +Example: + +```text +Target: CT-SHP-01 +RoleKey: WebFrontEnd +NodeDataJson: { "nodeName": "CT-SHP-01" } + +Target: CT-SHP-02 +RoleKey: Application +NodeDataJson: { "nodeName": "CT-SHP-02" } +``` + +For cloud workloads, the target may be a tenant, policy scope, group, or site instead of a server. + +Current state: + +- The API stores target assignments. +- The GUI create flow turns selected targets into target assignments. +- Queue requests can use target assignments if explicit target IDs are not sent again. + +### 4. User Adds Parameter Values + +The deployment group can store `DeploymentParameterValues`. + +Parameter values can be global or scoped to a specific template selection. + +Examples: + +```text +Global: + DatabasePrefix = Contoso_Test + +Scoped to SharePoint selection: + FarmAccount = secret reference +``` + +The intention is that the GUI later shows user-facing parameter forms based on selected template versions. +The user edits parameter values, and the portal can preview the effective resolved result. + +Current state: + +- API stores parameter values. +- Values are JSON validated. +- Secret references can be marked. +- Rich parameter editor and preview are still pending. + +## Deployment Request Process + +### 1. User Starts A Deployment + +When the user starts a deployment, the web frontend calls the API deployment request endpoint. + +The request currently contains: + +```text +DeploymentGroupId +TargetIds optional +JsonData optional deployment override +``` + +If `TargetIds` are omitted, the API can derive targets from the deployment group's target assignments. + +Target direction: + +```text +DeploymentGroup composition should be the source of truth. +The start request should eventually only reference the DeploymentGroup and optional runtime overrides. +``` + +### 2. API Validates The Request + +The API validates: + +- The deployment group exists. +- Target IDs exist or target assignments are present. +- Runtime JSON override is valid JSON. +- A deployment rule can be resolved from the deployment group or selected template metadata. + +### 3. API Creates Or Updates Legacy DeploymentExecutions + +Current compatibility behavior: + +- The API still creates or updates `DeploymentExecutions`. +- These records are useful for existing UI views and migration compatibility. + +Target direction: + +- `DeploymentExecutions` should become either a read-only compatibility view or be replaced by queue job target/artifact state. +- The deployment composition and queue job should become the primary execution model. + +### 4. API Creates A QueueJob + +The API creates a `QueueJob`. + +The queue job contains: + +- Job type +- Status +- Correlation ID +- Priority +- Schedule and lock metadata +- Payload JSON +- Rule snapshot JSON +- Queue job targets +- Queue job steps + +The payload includes the deployment group, selected template versions, target assignments, target IDs, runtime JSON, and metadata. + +## Queue Process + +### 1. Worker Claims A Job + +The worker looks for pending jobs. + +It claims a job atomically by setting: + +```text +Status = Running +Attempts += 1 +LockedBy +LockedUntil +HeartbeatAt +WorkerName +``` + +This prevents two workers from processing the same job at the same time. + +### 2. Worker Processes Steps + +Queue jobs can contain steps. + +Examples: + +- Approval +- Provision +- Validate +- Custom future step types + +Approval steps can pause the job until a user approves or rejects them through the API. + +### 3. Worker Processes Queue Targets + +For each queue target, the worker loads the deployment composition: + +```text +DeploymentGroup + TemplateSelections + ParameterValues + TargetAssignments + Target + Environment and Domain context +``` + +The worker then renders artifacts for that target. + +Current renderers: + +- PowerShell DSC v2 data file renderer +- DSC v3 JSON renderer + +### 4. Worker Writes Output Metadata + +The worker writes target and step metadata back to the queue records. + +Examples: + +- Artifact paths +- Renderer name +- Finished timestamps +- Errors + +## Composition And Rendering Process + +### 1. Load Selected Template Versions + +The worker loads all template selections in sort order. + +Example: + +```text +Environment Default +Environment Contoso Test +Landscape Test +Service SharePoint +Stage Install +``` + +### 2. Compose Documents + +The selected template JSON documents are merged into one effective deployment document. + +Conceptually: + +```text +Parameters +Variables +Resources +Targets / AllNodes +Metadata +``` + +Current worker state: + +- It can load the composition. +- It can render ordered PowerShell data files and JSON artifacts. + +Target direction: + +- DSC v2 renderer should call the existing `Merge-DSCConfigurationData` and `Resolve-DSCConfigurationData` modules. +- DSC v3 renderer can consume or emit JSON directly. + +### 3. Resolve Parameters, Variables, And Secrets + +The resolve module is responsible for resolving expressions and secrets. + +Examples: + +```text +[parameters('DatabasePrefix')] +[variables('ConfigDbName')] +[concat(parameters('DatabasePrefix'), '_Config')] +``` + +For previews, secrets should be skipped or replaced with dummy values. +For real deployments, secrets are resolved through the configured credential provider. + +## Preview Process + +This is not fully implemented yet, but the intended flow is: + +```text +User edits deployment composition + -> clicks Preview + -> API builds effective deployment composition + -> API or worker-style service merges selected template versions + -> Resolve runs with SkipSecrets + -> GUI shows effective parameters, variables, resources, and target data +``` + +The preview should help users see what will actually be deployed before a queue job is created. + +This belongs mostly to Step 8 and Step 8a. + +## Promotion Process + +This is not fully implemented yet. + +Target idea: + +```text +Change shared domain or service baseline + -> create new template version + -> test in Test environment + -> promote the same immutable version to QA or Prod deployment groups +``` + +Promotion should not mean copying large JSON blocks repeatedly. +It should mean reusing or advancing selected template versions in deployment groups. + +## Current Implemented State + +Implemented: + +- Generic targets exist. +- Template versions exist and are versioned with hashes. +- Deployment groups can store template selections. +- Deployment groups can store parameter values. +- Deployment groups can store target assignments. +- Queue jobs have claim/lock/heartbeat metadata. +- Queue job targets and steps can persist output metadata. +- Worker can load deployment composition. +- Worker can render DSC v2-style PowerShell data files and DSC v3-style JSON artifacts. +- Web can create a rudimentary deployment group using a selected template version and selected targets. + +Partially implemented: + +- Legacy `DeploymentGroup.TemplateId` and `DeploymentExecution.JSONData` are still present for compatibility. +- API still mixes repository and direct `DataContext` logic in some controllers. +- Queue payloads include composition data, but the API contract is not yet fully cleaned up. + +Pending: + +- Dedicated deployment composition service. +- Transactional deployment group creation. +- Rich validation results instead of generic `false` / `500`. +- Preview endpoint based on merge and resolve. +- Sealed parameter and resource block visibility in API/GUI. +- Promotion flow. +- Final cleanup of legacy template JSON and deployment execution fields. + +## Expected Future Clean Flow + +The desired future flow should look like this: + +```text +1. Admin maintains catalog: + Environments, Domains, Services, Targets + +2. Admin maintains templates: + Template -> TemplateVersion -> Published immutable version + +3. User creates deployment group: + Select environment/context + Select template versions + Assign targets + Set parameter values + +4. User previews: + Merge selected template versions + Resolve parameters and variables + Resolve secrets as dummy values + Show effective output + +5. User starts deployment: + API creates QueueJob + Worker claims QueueJob + Worker renders artifacts + Worker executes or hands off + API reports status and metadata + +6. User promotes: + Reuse tested template versions in the next environment + Avoid copying environment-specific JSON manually +``` + +## Main Understanding To Validate + +The core understanding is: + +```text +Templates describe reusable building blocks. +TemplateVersions make those building blocks immutable. +DeploymentGroups select and order those building blocks. +ParameterValues and TargetAssignments make the deployment concrete. +QueueJobs turn the deployment design into execution. +Workers render and execute without knowing SharePoint-specific database tables. +``` + +If this is correct, the next API work should focus on making this process stricter and more explicit, not on adding more legacy shortcuts. diff --git a/Dto/Deployment/Get/GetQueueJobDetailsDto.cs b/Dto/Deployment/Get/GetQueueJobDetailsDto.cs index ce766f8..cc5eceb 100644 --- a/Dto/Deployment/Get/GetQueueJobDetailsDto.cs +++ b/Dto/Deployment/Get/GetQueueJobDetailsDto.cs @@ -12,6 +12,13 @@ public string? ErrorMessage { get; set; } public string? MetadataJson { get; set; } public string? RuleSnapshotJson { get; set; } + public Guid CorrelationId { get; set; } + public int Priority { get; set; } + public DateTime? ScheduledAt { get; set; } + public DateTime? HeartbeatAt { get; set; } + public string? WorkerName { get; set; } + public string? LockedBy { get; set; } + public DateTime? LockedUntil { get; set; } public ICollection Targets { get; set; } = new List(); public ICollection Steps { get; set; } = new List(); } diff --git a/Dto/Deployment/Get/GetQueueJobDto.cs b/Dto/Deployment/Get/GetQueueJobDto.cs index 7018d0d..e0f58ea 100644 --- a/Dto/Deployment/Get/GetQueueJobDto.cs +++ b/Dto/Deployment/Get/GetQueueJobDto.cs @@ -9,6 +9,11 @@ public DateTime? Started { get; set; } public DateTime? Finished { get; set; } public string? ErrorMessage { get; set; } + public Guid CorrelationId { get; set; } + public int Priority { get; set; } + public DateTime? ScheduledAt { get; set; } + public DateTime? HeartbeatAt { get; set; } + public string? WorkerName { get; set; } public int TargetCount { get; set; } public int SucceededTargetCount { get; set; } public int FailedTargetCount { get; set; } diff --git a/Dto/Deployment/Get/GetQueueJobStepDto.cs b/Dto/Deployment/Get/GetQueueJobStepDto.cs index c591092..75a69ce 100644 --- a/Dto/Deployment/Get/GetQueueJobStepDto.cs +++ b/Dto/Deployment/Get/GetQueueJobStepDto.cs @@ -11,6 +11,10 @@ public DateTime? ApprovedAt { get; set; } public string? ApprovedBy { get; set; } public string? ApprovalComment { get; set; } + public DateTime? Started { get; set; } + public DateTime? Finished { get; set; } + public string? OutputMetadataJson { get; set; } + public string? ErrorMessage { get; set; } } } diff --git a/Dto/Deployment/Get/GetQueueJobTargetDto.cs b/Dto/Deployment/Get/GetQueueJobTargetDto.cs index bb987d5..0a0f9fb 100644 --- a/Dto/Deployment/Get/GetQueueJobTargetDto.cs +++ b/Dto/Deployment/Get/GetQueueJobTargetDto.cs @@ -8,6 +8,9 @@ public string Status { get; set; } = string.Empty; public int Attempts { get; set; } public string? ErrorMessage { get; set; } + public DateTime? Started { get; set; } + public DateTime? Finished { get; set; } + public string? OutputMetadataJson { get; set; } } } diff --git a/Dto/DeploymentBatch/Add/AddDeploymentBatchDto.cs b/Dto/DeploymentBatch/Add/AddDeploymentBatchDto.cs index b4aaee9..a4daddf 100644 --- a/Dto/DeploymentBatch/Add/AddDeploymentBatchDto.cs +++ b/Dto/DeploymentBatch/Add/AddDeploymentBatchDto.cs @@ -1,20 +1,29 @@ -using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations.Schema; +using Microsoft.SelfService.Portal.Core.API.Dto.DeploymentComposition.Add; namespace Microsoft.SelfService.Portal.Core.API.Dto.DeploymentBatch.Add { public class AddDeploymentBatchDto { [Column(Order = 1)] - public Guid TemplateId { get; set; } + public Guid? TemplateId { get; set; } [Column(Order = 2)] - public Guid? DeploymentRuleId { get; set; } + public Guid? TemplateVersionId { get; set; } [Column(Order = 3)] - public string Status { get; set; } = string.Empty; + public Guid? DeploymentRuleId { get; set; } [Column(Order = 4)] + public string Status { get; set; } = string.Empty; + + [Column(Order = 5)] public ICollection? TargetIds { get; set; } + + [Column(Order = 6)] + public ICollection? TemplateSelections { get; set; } + + [Column(Order = 7)] + public ICollection? TargetAssignments { get; set; } } } - diff --git a/Dto/DeploymentBatch/Get/GetDeploymentBatchDetailsDto.cs b/Dto/DeploymentBatch/Get/GetDeploymentBatchDetailsDto.cs index 03cc660..c6c7e03 100644 --- a/Dto/DeploymentBatch/Get/GetDeploymentBatchDetailsDto.cs +++ b/Dto/DeploymentBatch/Get/GetDeploymentBatchDetailsDto.cs @@ -1,4 +1,4 @@ -using Microsoft.SelfService.Portal.Core.API.Dto.Deployment.Get; +using Microsoft.SelfService.Portal.Core.API.Dto.Deployment.Get; using Microsoft.SelfService.Portal.Core.API.Dto.DeploymentComposition.Get; using Microsoft.SelfService.Portal.Core.API.Dto.Template.Get; @@ -6,11 +6,13 @@ namespace Microsoft.SelfService.Portal.Core.API.Dto.DeploymentBatch.Get { public class GetDeploymentBatchDetailsDto : BaseDto { + public Guid? TemplateId { get; set; } + public Guid? DeploymentRuleId { get; set; } public string Status { get; set; } = string.Empty; - public GetTemplateDetailsDto Template { get; set; } = null!; + public GetTemplateDetailsDto? Template { get; set; } public ICollection Deployments { get; set; } = new List(); public ICollection TemplateSelections { get; set; } = new List(); @@ -18,4 +20,3 @@ namespace Microsoft.SelfService.Portal.Core.API.Dto.DeploymentBatch.Get public ICollection TargetAssignments { get; set; } = new List(); } } - diff --git a/Dto/DeploymentBatch/Get/GetDeploymentBatchDto.cs b/Dto/DeploymentBatch/Get/GetDeploymentBatchDto.cs index 134ef56..495a629 100644 --- a/Dto/DeploymentBatch/Get/GetDeploymentBatchDto.cs +++ b/Dto/DeploymentBatch/Get/GetDeploymentBatchDto.cs @@ -1,12 +1,21 @@ -namespace Microsoft.SelfService.Portal.Core.API.Dto.DeploymentBatch.Get +namespace Microsoft.SelfService.Portal.Core.API.Dto.DeploymentBatch.Get { public class GetDeploymentBatchDto : BaseDetailsDto { - public Guid TemplateId { get; set; } + public Guid? TemplateId { get; set; } public Guid? DeploymentRuleId { get; set; } public string Status { get; set; } = string.Empty; + + public Guid? PrimaryTemplateVersionId { get; set; } + + public string? PrimaryTemplateName { get; set; } + + public string? PrimaryTemplateVersion { get; set; } + + public int TemplateSelectionCount { get; set; } + + public int TargetAssignmentCount { get; set; } } } - diff --git a/Migrations/20260708194227_AddQueueHardening.Designer.cs b/Migrations/20260708194227_AddQueueHardening.Designer.cs new file mode 100644 index 0000000..d61077e --- /dev/null +++ b/Migrations/20260708194227_AddQueueHardening.Designer.cs @@ -0,0 +1,2382 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Microsoft.SelfService.Portal.Core.API.Context; + +#nullable disable + +namespace Microsoft.SelfService.Portal.Core.API.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20260708194227_AddQueueHardening")] + partial class AddQueueHardening + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentRuleId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(3); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4) + .HasDefaultValueSql("'New'"); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("DeploymentRuleId"); + + b.HasIndex("TemplateId"); + + b.ToTable("DeploymentBatches", (string)null); + + b.HasData( + new + { + Id = new Guid("80000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending", + TemplateId = new Guid("70000000-0000-0000-0000-000000000003") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentModel", b => + { + b.Property("TargetId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(3); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeploymentBatchId") + .HasColumnOrder(2); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("JSONData") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.HasKey("TargetId", "DeploymentGroupId"); + + b.HasIndex("DeploymentGroupId"); + + b.ToTable("DeploymentExecutions", (string)null); + + b.HasData( + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000004"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000001"), + JSONData = "{\"role\":\"WebFrontEnd\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" + }, + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000005"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000002"), + JSONData = "{\"role\":\"Application\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentParameterValueModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("DeploymentTemplateSelectionId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.Property("IsOverride") + .HasColumnType("bit") + .HasColumnOrder(6); + + b.Property("IsSecretReference") + .HasColumnType("bit") + .HasColumnOrder(5); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(3); + + b.Property("ValueJson") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.HasKey("Id"); + + b.HasIndex("DeploymentTemplateSelectionId"); + + b.HasIndex("DeploymentGroupId", "Name") + .IsUnique() + .HasFilter("[DeploymentTemplateSelectionId] IS NULL"); + + b.HasIndex("DeploymentGroupId", "DeploymentTemplateSelectionId", "Name") + .IsUnique() + .HasFilter("[DeploymentTemplateSelectionId] IS NOT NULL"); + + b.ToTable("DeploymentParameterValues", t => + { + t.HasCheckConstraint("CK_DeploymentParameterValues_ValueJson_IsJson", "ISJSON([ValueJson]) = 1"); + }); + + b.HasData( + new + { + Id = new Guid("83000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + DeploymentTemplateSelectionId = new Guid("82000000-0000-0000-0000-000000000001"), + IsOverride = true, + IsSecretReference = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "DatabasePrefix", + ValueJson = "{\"value\":\"SharePoint_Contoso_Test\"}" + }, + new + { + Id = new Guid("83000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + DeploymentTemplateSelectionId = new Guid("82000000-0000-0000-0000-000000000001"), + IsOverride = true, + IsSecretReference = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "FarmAccount", + ValueJson = "{\"provider\":\"SecretManagement\",\"vault\":\"ContosoDemo\",\"name\":\"Windows/SharePoint/FarmAccount\"}" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Description") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnOrder(3); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.HasKey("Id"); + + b.ToTable("DeploymentRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Validate input, wait for approval, then provision targets.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Standard Provisioning" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleStepModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentRuleId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(6); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("RequiresApproval") + .HasColumnType("bit") + .HasColumnOrder(5); + + b.Property("SortOrder") + .HasColumnType("int") + .HasColumnOrder(2); + + b.Property("StepType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.HasKey("Id"); + + b.HasIndex("DeploymentRuleId"); + + b.ToTable("DeploymentRuleSteps"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"action\":\"validate\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Validate configuration", + RequiresApproval = false, + SortOrder = 10, + StepType = "Provision" + }, + new + { + Id = new Guid("60000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"approverGroup\":\"Platform Owners\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Approve deployment", + RequiresApproval = true, + SortOrder = 20, + StepType = "Approval" + }, + new + { + Id = new Guid("60000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"action\":\"deploy\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Provision workload", + RequiresApproval = false, + SortOrder = 30, + StepType = "Provision" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTargetAssignmentModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("NodeDataJson") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("RoleKey") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(3); + + b.Property("SortOrder") + .HasColumnType("int") + .HasColumnOrder(4); + + b.Property("TargetId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("TargetId"); + + b.HasIndex("DeploymentGroupId", "TargetId", "RoleKey") + .IsUnique(); + + b.ToTable("DeploymentTargetAssignments", t => + { + t.HasCheckConstraint("CK_DeploymentTargetAssignments_NodeDataJson_IsJson", "ISJSON([NodeDataJson]) = 1"); + }); + + b.HasData( + new + { + Id = new Guid("84000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CT-SHP-01\"}", + RoleKey = "WebFrontEnd", + SortOrder = 10, + TargetId = new Guid("30000000-0000-0000-0000-000000000004") + }, + new + { + Id = new Guid("84000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CT-SHP-02\"}", + RoleKey = "Application", + SortOrder = 20, + TargetId = new Guid("30000000-0000-0000-0000-000000000005") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTemplateSelectionModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Alias") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("SortOrder") + .HasColumnType("int") + .HasColumnOrder(4); + + b.Property("TemplateRole") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("TemplateVersionId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("TemplateVersionId"); + + b.HasIndex("DeploymentGroupId", "SortOrder") + .IsUnique(); + + b.ToTable("DeploymentTemplateSelections"); + + b.HasData( + new + { + Id = new Guid("82000000-0000-0000-0000-000000000001"), + Alias = "SharePoint", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 10, + TemplateRole = "Service", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000003") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DomainModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("FQDN") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("NetBIOS") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.HasKey("Id"); + + b.ToTable("Domains"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + FQDN = "corp.contoso.com", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Central Management", + NetBIOS = "CONTOSO" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + FQDN = "resource.contoso.com", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Resource Domain", + NetBIOS = "RESOURCE" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentDomainsModel", b => + { + b.Property("EnvironmentId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0); + + b.Property("DomainId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("Created") + .HasColumnType("datetime2") + .HasColumnOrder(52); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Modified") + .HasColumnType("datetime2") + .HasColumnOrder(50); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.HasKey("EnvironmentId", "DomainId"); + + b.HasIndex("DomainId"); + + b.ToTable("EnvironmentDomains"); + + b.HasData( + new + { + EnvironmentId = new Guid("10000000-0000-0000-0000-000000000001"), + DomainId = new Guid("20000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed" + }, + new + { + EnvironmentId = new Guid("10000000-0000-0000-0000-000000000002"), + DomainId = new Guid("20000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed" + }, + new + { + EnvironmentId = new Guid("10000000-0000-0000-0000-000000000002"), + DomainId = new Guid("20000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("EnvironmentType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("HostingType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(7); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("ProviderType") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("SubscriptionId") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(6); + + b.Property("TenantId") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.HasKey("Id"); + + b.ToTable("Environments"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + EnvironmentType = "Test", + HostingType = "OnPrem", + MetadataJson = "{\"location\":\"Datacenter A\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso Test" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + EnvironmentType = "Production", + HostingType = "OnPrem", + MetadataJson = "{\"location\":\"Datacenter A\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso Production" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + EnvironmentType = "Production", + HostingType = "M365Tenant", + MetadataJson = "{\"tenant\":\"contoso.onmicrosoft.com\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso M365", + ProviderType = "Microsoft365", + TenantId = "11111111-1111-1111-1111-111111111111" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionCategoryModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("ParentCategoryName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("showOrder") + .HasColumnType("int") + .HasColumnOrder(3); + + b.HasKey("Id"); + + b.ToTable("OptionCategories"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("OptionCategoryId") + .HasColumnType("uniqueidentifier"); + + b.Property("OptionType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("OptionValue") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.HasKey("Id"); + + b.HasIndex("OptionCategoryId"); + + b.ToTable("Options"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Attempts") + .HasColumnType("int") + .HasColumnOrder(4); + + b.Property("CorrelationId") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(13) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("ErrorMessage") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(10); + + b.Property("Finished") + .HasColumnType("datetime2") + .HasColumnOrder(7); + + b.Property("HeartbeatAt") + .HasColumnType("datetime2") + .HasColumnOrder(16); + + b.Property("LockedBy") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(9); + + b.Property("LockedUntil") + .HasColumnType("datetime2") + .HasColumnOrder(8); + + b.Property("MaxAttempts") + .HasColumnType("int") + .HasColumnOrder(5); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(11); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("PayloadJson") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(100) + .HasColumnOrder(14); + + b.Property("RowVersion") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + + b.Property("RuleSnapshotJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(12); + + b.Property("ScheduledAt") + .HasColumnType("datetime2") + .HasColumnOrder(15); + + b.Property("Started") + .HasColumnType("datetime2") + .HasColumnOrder(6); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(2); + + b.Property("Type") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("WorkerName") + .HasColumnType("nvarchar(450)") + .HasColumnOrder(17); + + b.HasKey("Id"); + + b.HasIndex("CorrelationId"); + + b.HasIndex("WorkerName"); + + b.HasIndex("Status", "ScheduledAt", "LockedUntil", "Priority", "Created"); + + b.ToTable("DeploymentJobs", (string)null); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobStepModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("ApprovalComment") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(10); + + b.Property("ApprovedAt") + .HasColumnType("datetime2") + .HasColumnOrder(8); + + b.Property("ApprovedBy") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(9); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DependsOnQueueJobStepId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DependsOnDeploymentJobStepId") + .HasColumnOrder(2); + + b.Property("ErrorMessage") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(14); + + b.Property("Finished") + .HasColumnType("datetime2") + .HasColumnOrder(12); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(7); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("OutputMetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(13); + + b.Property("QueueJobId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeploymentJobId") + .HasColumnOrder(1); + + b.Property("SortOrder") + .HasColumnType("int") + .HasColumnOrder(3); + + b.Property("Started") + .HasColumnType("datetime2") + .HasColumnOrder(11); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(6); + + b.Property("StepType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.HasKey("Id"); + + b.HasIndex("DependsOnQueueJobStepId"); + + b.HasIndex("QueueJobId", "Status", "SortOrder"); + + b.ToTable("DeploymentJobSteps", null, t => + { + t.HasCheckConstraint("CK_DeploymentJobSteps_OutputMetadataJson_IsJson", "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1"); + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobTargetModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Attempts") + .HasColumnType("int") + .HasColumnOrder(6); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeploymentBatchId") + .HasColumnOrder(3); + + b.Property("ErrorMessage") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(7); + + b.Property("Finished") + .HasColumnType("datetime2") + .HasColumnOrder(9); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("OutputMetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(10); + + b.Property("QueueJobId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeploymentJobId") + .HasColumnOrder(1); + + b.Property("Started") + .HasColumnType("datetime2") + .HasColumnOrder(8); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(5); + + b.Property("TargetId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(4); + + b.HasKey("Id"); + + b.HasIndex("QueueJobId", "Status"); + + b.ToTable("DeploymentJobTargets", null, t => + { + t.HasCheckConstraint("CK_DeploymentJobTargets_OutputMetadataJson_IsJson", "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1"); + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.ServiceModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("IconKey") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("IsCloudService") + .HasColumnType("bit") + .HasColumnOrder(3); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.HasKey("Id"); + + b.ToTable("Services"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "On-premises directory and identity service.", + IconKey = "network", + IsCloudService = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Active Directory" + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Database platform for application workloads.", + IconKey = "database", + IsCloudService = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "SQL Server" + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Collaboration platform for on-premises workloads.", + IconKey = "sharepoint", + IsCloudService = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "SharePoint Server" + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Cloud collaboration workload in Microsoft 365.", + IconKey = "messages-square", + IsCloudService = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Microsoft Teams" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.ServiceRoleDefinitionModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Description") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("Key") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("ServiceId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.HasKey("Id"); + + b.HasIndex("ServiceId"); + + b.ToTable("ServiceRoleDefinitions"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "SharePoint farm role.", + Key = "Farm", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Farm", + ServiceId = new Guid("40000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "SharePoint web front-end role.", + Key = "WebFrontEnd", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Web Front End", + ServiceId = new Guid("40000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "SharePoint service application role.", + Key = "Application", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Application", + ServiceId = new Guid("40000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "SQL Server database role.", + Key = "Database", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Database", + ServiceId = new Guid("40000000-0000-0000-0000-000000000002") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DomainID") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("ExternalId") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(6); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("ProviderType") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnOrder(4); + + b.Property("TargetType") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnOrder(3); + + b.HasKey("Id"); + + b.HasIndex("DomainID"); + + b.ToTable("Targets"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"DomainController\",\"environment\":\"Test\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-DC-01", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"DomainController\",\"environment\":\"Production\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-DC-02", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SqlServer\",\"environment\":\"Test\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-SQL-01", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-SHP-01", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000005"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-SHP-02", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000006"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + ExternalId = "11111111-1111-1111-1111-111111111111", + MetadataJson = "{\"environment\":\"Production\",\"workload\":\"M365\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "contoso.onmicrosoft.com", + ProviderType = "Microsoft365", + TargetType = "Tenant" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000007"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + ExternalId = "Teams.StandardUsers", + MetadataJson = "{\"workload\":\"Teams\",\"scope\":\"StandardUsers\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Teams - Standard Users", + ProviderType = "Microsoft365", + TargetType = "PolicyScope" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateCategoryModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Color") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Description") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnOrder(4); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("ServiceId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.HasKey("Id"); + + b.HasIndex("ServiceId"); + + b.ToTable("TemplateCategories"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + Color = "#2563EB", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Templates for domain controller and domain configuration.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Domain Services", + ServiceId = new Guid("40000000-0000-0000-0000-000000000001") + }, + new + { + Id = new Guid("50000000-0000-0000-0000-000000000002"), + Color = "#16A34A", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Templates for SQL Server workloads.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Database Platform", + ServiceId = new Guid("40000000-0000-0000-0000-000000000002") + }, + new + { + Id = new Guid("50000000-0000-0000-0000-000000000003"), + Color = "#0F766E", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Templates for SharePoint Server farms.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Collaboration Farm", + ServiceId = new Guid("40000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("50000000-0000-0000-0000-000000000004"), + Color = "#7C3AED", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Templates for Teams policy configuration.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Teams Policies", + ServiceId = new Guid("40000000-0000-0000-0000-000000000004") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentRuleId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(6); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("JSONData") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("TemplateCategoryId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(5); + + b.Property("Version") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("DeploymentRuleId"); + + b.HasIndex("TemplateCategoryId"); + + b.ToTable("Templates"); + + b.HasData( + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Creates a reusable Active Directory domain baseline.", + JSONData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"DomainName\": { \"type\": \"string\", \"defaultValue\": \"corp.contoso.com\" },\n \"NetBIOSName\": { \"type\": \"string\", \"defaultValue\": \"CONTOSO\" }\n },\n \"variables\": {\n \"DefaultSiteName\": \"[concat(parameters('DomainName'), '-DefaultSite')]\"\n },\n \"resources\": {\n \"AllNodes\": [\n { \"NodeName\": \"*\", \"PSDscAllowPlainTextPassword\": true }\n ],\n \"NonNodeData\": {\n \"Services\": {\n \"ActiveDirectory\": {\n \"DomainName\": \"[parameters('DomainName')]\",\n \"NetBIOSName\": \"[parameters('NetBIOSName')]\"\n }\n }\n }\n }\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso Active Directory Domain", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000001"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Creates a SQL Server baseline for application workloads.", + JSONData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"InstanceName\": { \"type\": \"string\", \"defaultValue\": \"MSSQLSERVER\" },\n \"DatabasePrefix\": { \"type\": \"string\", \"defaultValue\": \"Contoso\" }\n },\n \"variables\": {\n \"ConfigDatabase\": \"[concat(parameters('DatabasePrefix'), '_Config')]\"\n },\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"SqlServer\": {\n \"InstanceName\": \"[parameters('InstanceName')]\",\n \"ConfigDatabase\": \"[variables('ConfigDatabase')]\"\n }\n }\n }\n }\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso SQL Server", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000002"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Creates a SharePoint Server farm baseline.", + JSONData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"DatabasePrefix\": { \"type\": \"string\", \"defaultValue\": \"SharePoint_Contoso_Test\" },\n \"FarmAccount\": { \"type\": \"credential\", \"metadata\": { \"description\": \"Farm account resolved by the credential provider.\" } }\n },\n \"variables\": {\n \"ConfigDbName\": \"[concat(parameters('DatabasePrefix'), '_Farm_Config')]\",\n \"AdminContentDbName\": \"[concat(parameters('DatabasePrefix'), '_AdminContent')]\"\n },\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"SharePoint\": {\n \"Farm\": {\n \"ConfigDatabase\": \"[variables('ConfigDbName')]\",\n \"AdminContentDatabase\": \"[variables('AdminContentDbName')]\",\n \"ManagedAccounts\": {\n \"FarmAccount\": \"[parameters('FarmAccount')]\"\n }\n }\n }\n }\n }\n }\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso SharePoint Server", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000003"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Creates a Microsoft Teams policy baseline.", + JSONData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"CallingPolicyName\": { \"type\": \"string\", \"defaultValue\": \"Contoso-Standard-Calling\" },\n \"MeetingPolicyName\": { \"type\": \"string\", \"defaultValue\": \"Contoso-Standard-Meetings\" }\n },\n \"variables\": {},\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"Teams\": {\n \"CallingPolicy\": \"[parameters('CallingPolicyName')]\",\n \"MeetingPolicy\": \"[parameters('MeetingPolicyName')]\"\n }\n }\n }\n }\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso Teams Policies", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000004"), + Version = "1.0.0" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateOptionModel", b => + { + b.Property("OptionId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0); + + b.Property("Created") + .HasColumnType("datetime2") + .HasColumnOrder(52); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Modified") + .HasColumnType("datetime2") + .HasColumnOrder(50); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.HasKey("OptionId", "TemplateId"); + + b.HasIndex("TemplateId"); + + b.ToTable("TemplateOptions"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateVersionModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("IsPublished") + .HasColumnType("bit") + .HasColumnOrder(6); + + b.Property("JsonData") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("JsonHash") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnOrder(4); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("PublishedAt") + .HasColumnType("datetime2") + .HasColumnOrder(7); + + b.Property("PublishedBy") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(8); + + b.Property("SchemaVersion") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)") + .HasColumnOrder(5); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("Version") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("TemplateId") + .IsUnique() + .HasFilter("[IsPublished] = 1"); + + b.HasIndex("TemplateId", "Version") + .IsUnique(); + + b.ToTable("TemplateVersions", t => + { + t.HasCheckConstraint("CK_TemplateVersions_JsonData_IsJson", "ISJSON([JsonData]) = 1"); + }); + + b.HasData( + new + { + Id = new Guid("71000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"DomainName\": { \"type\": \"string\", \"defaultValue\": \"corp.contoso.com\" },\n \"NetBIOSName\": { \"type\": \"string\", \"defaultValue\": \"CONTOSO\" }\n },\n \"variables\": {\n \"DefaultSiteName\": \"[concat(parameters('DomainName'), '-DefaultSite')]\"\n },\n \"resources\": {\n \"AllNodes\": [\n { \"NodeName\": \"*\", \"PSDscAllowPlainTextPassword\": true }\n ],\n \"NonNodeData\": {\n \"Services\": {\n \"ActiveDirectory\": {\n \"DomainName\": \"[parameters('DomainName')]\",\n \"NetBIOSName\": \"[parameters('NetBIOSName')]\"\n }\n }\n }\n }\n}", + JsonHash = "C05CBEF91131C75DE53B9609D9C2709D680AFC9559EE8D998318A132490F79A7", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000001"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"InstanceName\": { \"type\": \"string\", \"defaultValue\": \"MSSQLSERVER\" },\n \"DatabasePrefix\": { \"type\": \"string\", \"defaultValue\": \"Contoso\" }\n },\n \"variables\": {\n \"ConfigDatabase\": \"[concat(parameters('DatabasePrefix'), '_Config')]\"\n },\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"SqlServer\": {\n \"InstanceName\": \"[parameters('InstanceName')]\",\n \"ConfigDatabase\": \"[variables('ConfigDatabase')]\"\n }\n }\n }\n }\n}", + JsonHash = "F376737E82CB6B729F7B9960CB9988897C16D90A1C454ED2F594B28EB86ECA11", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000002"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"DatabasePrefix\": { \"type\": \"string\", \"defaultValue\": \"SharePoint_Contoso_Test\" },\n \"FarmAccount\": { \"type\": \"credential\", \"metadata\": { \"description\": \"Farm account resolved by the credential provider.\" } }\n },\n \"variables\": {\n \"ConfigDbName\": \"[concat(parameters('DatabasePrefix'), '_Farm_Config')]\",\n \"AdminContentDbName\": \"[concat(parameters('DatabasePrefix'), '_AdminContent')]\"\n },\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"SharePoint\": {\n \"Farm\": {\n \"ConfigDatabase\": \"[variables('ConfigDbName')]\",\n \"AdminContentDatabase\": \"[variables('AdminContentDbName')]\",\n \"ManagedAccounts\": {\n \"FarmAccount\": \"[parameters('FarmAccount')]\"\n }\n }\n }\n }\n }\n }\n}", + JsonHash = "FD5F0FD3C13538FAC70646972DC364DFCEAAF85BBE91B0F50FDFF9FD3A3748B4", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000003"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"CallingPolicyName\": { \"type\": \"string\", \"defaultValue\": \"Contoso-Standard-Calling\" },\n \"MeetingPolicyName\": { \"type\": \"string\", \"defaultValue\": \"Contoso-Standard-Meetings\" }\n },\n \"variables\": {},\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"Teams\": {\n \"CallingPolicy\": \"[parameters('CallingPolicyName')]\",\n \"MeetingPolicy\": \"[parameters('MeetingPolicyName')]\"\n }\n }\n }\n }\n}", + JsonHash = "32A902FE1A871D4CE2C877EBC5542F7562856532F09BA7F53597B21270586241", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000004"), + Version = "1.0.0" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", "DeploymentRule") + .WithMany() + .HasForeignKey("DeploymentRuleId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", "Template") + .WithMany("DeploymentGroups") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeploymentRule"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", "DeploymentGroup") + .WithMany("Deployments") + .HasForeignKey("DeploymentGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", "Target") + .WithMany("Deployments") + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeploymentGroup"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentParameterValueModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", "DeploymentGroup") + .WithMany("ParameterValues") + .HasForeignKey("DeploymentGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTemplateSelectionModel", "DeploymentTemplateSelection") + .WithMany() + .HasForeignKey("DeploymentTemplateSelectionId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("DeploymentGroup"); + + b.Navigation("DeploymentTemplateSelection"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleStepModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", "DeploymentRule") + .WithMany("Steps") + .HasForeignKey("DeploymentRuleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeploymentRule"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTargetAssignmentModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", "DeploymentGroup") + .WithMany("TargetAssignments") + .HasForeignKey("DeploymentGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", "Target") + .WithMany() + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DeploymentGroup"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTemplateSelectionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", "DeploymentGroup") + .WithMany("TemplateSelections") + .HasForeignKey("DeploymentGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateVersionModel", "TemplateVersion") + .WithMany() + .HasForeignKey("TemplateVersionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DeploymentGroup"); + + b.Navigation("TemplateVersion"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentDomainsModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DomainModel", "Domain") + .WithMany("EnvironmentDomains") + .HasForeignKey("DomainId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentModel", "Environment") + .WithMany("EnvironmentDomains") + .HasForeignKey("EnvironmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Domain"); + + b.Navigation("Environment"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.OptionCategoryModel", "OptionCategory") + .WithMany("Options") + .HasForeignKey("OptionCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OptionCategory"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobStepModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.QueueJobStepModel", "DependsOnQueueJobStep") + .WithMany() + .HasForeignKey("DependsOnQueueJobStepId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.QueueJobModel", "QueueJob") + .WithMany("Steps") + .HasForeignKey("QueueJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DependsOnQueueJobStep"); + + b.Navigation("QueueJob"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobTargetModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.QueueJobModel", "QueueJob") + .WithMany("Targets") + .HasForeignKey("QueueJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QueueJob"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.ServiceRoleDefinitionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.ServiceModel", "Service") + .WithMany("RoleDefinitions") + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DomainModel", "Domain") + .WithMany("Targets") + .HasForeignKey("DomainID"); + + b.Navigation("Domain"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateCategoryModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.ServiceModel", "Service") + .WithMany("TemplateCategories") + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", "DeploymentRule") + .WithMany() + .HasForeignKey("DeploymentRuleId"); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateCategoryModel", "TemplateCategory") + .WithMany("Templates") + .HasForeignKey("TemplateCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeploymentRule"); + + b.Navigation("TemplateCategory"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateOptionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.OptionModel", "Option") + .WithMany("TemplateOptions") + .HasForeignKey("OptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", "Template") + .WithMany("TemplateOptions") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Option"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateVersionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", "Template") + .WithMany("TemplateVersions") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", b => + { + b.Navigation("Deployments"); + + b.Navigation("ParameterValues"); + + b.Navigation("TargetAssignments"); + + b.Navigation("TemplateSelections"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", b => + { + b.Navigation("Steps"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DomainModel", b => + { + b.Navigation("EnvironmentDomains"); + + b.Navigation("Targets"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentModel", b => + { + b.Navigation("EnvironmentDomains"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionCategoryModel", b => + { + b.Navigation("Options"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionModel", b => + { + b.Navigation("TemplateOptions"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobModel", b => + { + b.Navigation("Steps"); + + b.Navigation("Targets"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.ServiceModel", b => + { + b.Navigation("RoleDefinitions"); + + b.Navigation("TemplateCategories"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", b => + { + b.Navigation("Deployments"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateCategoryModel", b => + { + b.Navigation("Templates"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", b => + { + b.Navigation("DeploymentGroups"); + + b.Navigation("TemplateOptions"); + + b.Navigation("TemplateVersions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20260708194227_AddQueueHardening.cs b/Migrations/20260708194227_AddQueueHardening.cs new file mode 100644 index 0000000..bd7084b --- /dev/null +++ b/Migrations/20260708194227_AddQueueHardening.cs @@ -0,0 +1,294 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace Microsoft.SelfService.Portal.Core.API.Migrations +{ + /// + public partial class AddQueueHardening : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_DeploymentJobTargets_DeploymentJobId", + table: "DeploymentJobTargets"); + + migrationBuilder.DropIndex( + name: "IX_DeploymentJobSteps_DeploymentJobId", + table: "DeploymentJobSteps"); + + migrationBuilder.AlterColumn( + name: "Status", + table: "DeploymentJobTargets", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AddColumn( + name: "Finished", + table: "DeploymentJobTargets", + type: "datetime2", + nullable: true) + .Annotation("Relational:ColumnOrder", 9); + + migrationBuilder.AddColumn( + name: "OutputMetadataJson", + table: "DeploymentJobTargets", + type: "nvarchar(max)", + nullable: true) + .Annotation("Relational:ColumnOrder", 10); + + migrationBuilder.AddColumn( + name: "Started", + table: "DeploymentJobTargets", + type: "datetime2", + nullable: true) + .Annotation("Relational:ColumnOrder", 8); + + migrationBuilder.AlterColumn( + name: "Status", + table: "DeploymentJobSteps", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AddColumn( + name: "ErrorMessage", + table: "DeploymentJobSteps", + type: "nvarchar(max)", + nullable: true) + .Annotation("Relational:ColumnOrder", 14); + + migrationBuilder.AddColumn( + name: "Finished", + table: "DeploymentJobSteps", + type: "datetime2", + nullable: true) + .Annotation("Relational:ColumnOrder", 12); + + migrationBuilder.AddColumn( + name: "OutputMetadataJson", + table: "DeploymentJobSteps", + type: "nvarchar(max)", + nullable: true) + .Annotation("Relational:ColumnOrder", 13); + + migrationBuilder.AddColumn( + name: "Started", + table: "DeploymentJobSteps", + type: "datetime2", + nullable: true) + .Annotation("Relational:ColumnOrder", 11); + + migrationBuilder.AlterColumn( + name: "Status", + table: "DeploymentJobs", + type: "nvarchar(450)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(max)"); + + migrationBuilder.AddColumn( + name: "CorrelationId", + table: "DeploymentJobs", + type: "uniqueidentifier", + nullable: false, + defaultValueSql: "NEWID()") + .Annotation("Relational:ColumnOrder", 13); + + migrationBuilder.AddColumn( + name: "HeartbeatAt", + table: "DeploymentJobs", + type: "datetime2", + nullable: true) + .Annotation("Relational:ColumnOrder", 16); + + migrationBuilder.AddColumn( + name: "Priority", + table: "DeploymentJobs", + type: "int", + nullable: false, + defaultValue: 100) + .Annotation("Relational:ColumnOrder", 14); + + migrationBuilder.AddColumn( + name: "RowVersion", + table: "DeploymentJobs", + type: "rowversion", + rowVersion: true, + nullable: false, + defaultValue: new byte[0]); + + migrationBuilder.AddColumn( + name: "ScheduledAt", + table: "DeploymentJobs", + type: "datetime2", + nullable: true) + .Annotation("Relational:ColumnOrder", 15); + + migrationBuilder.AddColumn( + name: "WorkerName", + table: "DeploymentJobs", + type: "nvarchar(450)", + nullable: true) + .Annotation("Relational:ColumnOrder", 17); + + migrationBuilder.CreateIndex( + name: "IX_DeploymentJobTargets_DeploymentJobId_Status", + table: "DeploymentJobTargets", + columns: new[] { "DeploymentJobId", "Status" }); + + migrationBuilder.AddCheckConstraint( + name: "CK_DeploymentJobTargets_OutputMetadataJson_IsJson", + table: "DeploymentJobTargets", + sql: "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1"); + + migrationBuilder.CreateIndex( + name: "IX_DeploymentJobSteps_DeploymentJobId_Status_SortOrder", + table: "DeploymentJobSteps", + columns: new[] { "DeploymentJobId", "Status", "SortOrder" }); + + migrationBuilder.AddCheckConstraint( + name: "CK_DeploymentJobSteps_OutputMetadataJson_IsJson", + table: "DeploymentJobSteps", + sql: "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1"); + + migrationBuilder.CreateIndex( + name: "IX_DeploymentJobs_CorrelationId", + table: "DeploymentJobs", + column: "CorrelationId"); + + migrationBuilder.CreateIndex( + name: "IX_DeploymentJobs_Status_ScheduledAt_LockedUntil_Priority_Created", + table: "DeploymentJobs", + columns: new[] { "Status", "ScheduledAt", "LockedUntil", "Priority", "Created" }); + + migrationBuilder.CreateIndex( + name: "IX_DeploymentJobs_WorkerName", + table: "DeploymentJobs", + column: "WorkerName"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropIndex( + name: "IX_DeploymentJobTargets_DeploymentJobId_Status", + table: "DeploymentJobTargets"); + + migrationBuilder.DropCheckConstraint( + name: "CK_DeploymentJobTargets_OutputMetadataJson_IsJson", + table: "DeploymentJobTargets"); + + migrationBuilder.DropIndex( + name: "IX_DeploymentJobSteps_DeploymentJobId_Status_SortOrder", + table: "DeploymentJobSteps"); + + migrationBuilder.DropCheckConstraint( + name: "CK_DeploymentJobSteps_OutputMetadataJson_IsJson", + table: "DeploymentJobSteps"); + + migrationBuilder.DropIndex( + name: "IX_DeploymentJobs_CorrelationId", + table: "DeploymentJobs"); + + migrationBuilder.DropIndex( + name: "IX_DeploymentJobs_Status_ScheduledAt_LockedUntil_Priority_Created", + table: "DeploymentJobs"); + + migrationBuilder.DropIndex( + name: "IX_DeploymentJobs_WorkerName", + table: "DeploymentJobs"); + + migrationBuilder.DropColumn( + name: "Finished", + table: "DeploymentJobTargets"); + + migrationBuilder.DropColumn( + name: "OutputMetadataJson", + table: "DeploymentJobTargets"); + + migrationBuilder.DropColumn( + name: "Started", + table: "DeploymentJobTargets"); + + migrationBuilder.DropColumn( + name: "ErrorMessage", + table: "DeploymentJobSteps"); + + migrationBuilder.DropColumn( + name: "Finished", + table: "DeploymentJobSteps"); + + migrationBuilder.DropColumn( + name: "OutputMetadataJson", + table: "DeploymentJobSteps"); + + migrationBuilder.DropColumn( + name: "Started", + table: "DeploymentJobSteps"); + + migrationBuilder.DropColumn( + name: "CorrelationId", + table: "DeploymentJobs"); + + migrationBuilder.DropColumn( + name: "HeartbeatAt", + table: "DeploymentJobs"); + + migrationBuilder.DropColumn( + name: "Priority", + table: "DeploymentJobs"); + + migrationBuilder.DropColumn( + name: "RowVersion", + table: "DeploymentJobs"); + + migrationBuilder.DropColumn( + name: "ScheduledAt", + table: "DeploymentJobs"); + + migrationBuilder.DropColumn( + name: "WorkerName", + table: "DeploymentJobs"); + + migrationBuilder.AlterColumn( + name: "Status", + table: "DeploymentJobTargets", + type: "nvarchar(max)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); + + migrationBuilder.AlterColumn( + name: "Status", + table: "DeploymentJobSteps", + type: "nvarchar(max)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); + + migrationBuilder.AlterColumn( + name: "Status", + table: "DeploymentJobs", + type: "nvarchar(max)", + nullable: false, + oldClrType: typeof(string), + oldType: "nvarchar(450)"); + + migrationBuilder.CreateIndex( + name: "IX_DeploymentJobTargets_DeploymentJobId", + table: "DeploymentJobTargets", + column: "DeploymentJobId"); + + migrationBuilder.CreateIndex( + name: "IX_DeploymentJobSteps_DeploymentJobId", + table: "DeploymentJobSteps", + column: "DeploymentJobId"); + } + } +} diff --git a/Migrations/20260708202923_SeedBgwMergeTemplates.Designer.cs b/Migrations/20260708202923_SeedBgwMergeTemplates.Designer.cs new file mode 100644 index 0000000..e0324bc --- /dev/null +++ b/Migrations/20260708202923_SeedBgwMergeTemplates.Designer.cs @@ -0,0 +1,2704 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.EntityFrameworkCore.Metadata; +using Microsoft.EntityFrameworkCore.Migrations; +using Microsoft.EntityFrameworkCore.Storage.ValueConversion; +using Microsoft.SelfService.Portal.Core.API.Context; + +#nullable disable + +namespace Microsoft.SelfService.Portal.Core.API.Migrations +{ + [DbContext(typeof(DataContext))] + [Migration("20260708202923_SeedBgwMergeTemplates")] + partial class SeedBgwMergeTemplates + { + /// + protected override void BuildTargetModel(ModelBuilder modelBuilder) + { +#pragma warning disable 612, 618 + modelBuilder + .HasAnnotation("ProductVersion", "10.0.8") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentRuleId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(3); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Status") + .IsRequired() + .ValueGeneratedOnAdd() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4) + .HasDefaultValueSql("'New'"); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("DeploymentRuleId"); + + b.HasIndex("TemplateId"); + + b.ToTable("DeploymentBatches", (string)null); + + b.HasData( + new + { + Id = new Guid("80000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending", + TemplateId = new Guid("70000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("80000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending", + TemplateId = new Guid("70000000-0000-0000-0000-000000000103") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentModel", b => + { + b.Property("TargetId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(3); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeploymentBatchId") + .HasColumnOrder(2); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("JSONData") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.HasKey("TargetId", "DeploymentGroupId"); + + b.HasIndex("DeploymentGroupId"); + + b.ToTable("DeploymentExecutions", (string)null); + + b.HasData( + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000004"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000001"), + JSONData = "{\"role\":\"WebFrontEnd\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" + }, + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000005"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000002"), + JSONData = "{\"role\":\"Application\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" + }, + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000101"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000101"), + JSONData = "{\"role\":\"Node\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" + }, + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000102"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000102"), + JSONData = "{\"role\":\"Node\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" + }, + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000103"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000103"), + JSONData = "{\"role\":\"Node\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentParameterValueModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("DeploymentTemplateSelectionId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.Property("IsOverride") + .HasColumnType("bit") + .HasColumnOrder(6); + + b.Property("IsSecretReference") + .HasColumnType("bit") + .HasColumnOrder(5); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(3); + + b.Property("ValueJson") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.HasKey("Id"); + + b.HasIndex("DeploymentTemplateSelectionId"); + + b.HasIndex("DeploymentGroupId", "Name") + .IsUnique() + .HasFilter("[DeploymentTemplateSelectionId] IS NULL"); + + b.HasIndex("DeploymentGroupId", "DeploymentTemplateSelectionId", "Name") + .IsUnique() + .HasFilter("[DeploymentTemplateSelectionId] IS NOT NULL"); + + b.ToTable("DeploymentParameterValues", t => + { + t.HasCheckConstraint("CK_DeploymentParameterValues_ValueJson_IsJson", "ISJSON([ValueJson]) = 1"); + }); + + b.HasData( + new + { + Id = new Guid("83000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + DeploymentTemplateSelectionId = new Guid("82000000-0000-0000-0000-000000000001"), + IsOverride = true, + IsSecretReference = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "DatabasePrefix", + ValueJson = "{\"value\":\"SharePoint_Contoso_Test\"}" + }, + new + { + Id = new Guid("83000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + DeploymentTemplateSelectionId = new Guid("82000000-0000-0000-0000-000000000001"), + IsOverride = true, + IsSecretReference = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "FarmAccount", + ValueJson = "{\"provider\":\"SecretManagement\",\"vault\":\"ContosoDemo\",\"name\":\"Windows/SharePoint/FarmAccount\"}" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Description") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnOrder(3); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.HasKey("Id"); + + b.ToTable("DeploymentRules"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Validate input, wait for approval, then provision targets.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Standard Provisioning" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleStepModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentRuleId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(6); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("RequiresApproval") + .HasColumnType("bit") + .HasColumnOrder(5); + + b.Property("SortOrder") + .HasColumnType("int") + .HasColumnOrder(2); + + b.Property("StepType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.HasKey("Id"); + + b.HasIndex("DeploymentRuleId"); + + b.ToTable("DeploymentRuleSteps"); + + b.HasData( + new + { + Id = new Guid("60000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"action\":\"validate\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Validate configuration", + RequiresApproval = false, + SortOrder = 10, + StepType = "Provision" + }, + new + { + Id = new Guid("60000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"approverGroup\":\"Platform Owners\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Approve deployment", + RequiresApproval = true, + SortOrder = 20, + StepType = "Approval" + }, + new + { + Id = new Guid("60000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"action\":\"deploy\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Provision workload", + RequiresApproval = false, + SortOrder = 30, + StepType = "Provision" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTargetAssignmentModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("NodeDataJson") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("RoleKey") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(3); + + b.Property("SortOrder") + .HasColumnType("int") + .HasColumnOrder(4); + + b.Property("TargetId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("TargetId"); + + b.HasIndex("DeploymentGroupId", "TargetId", "RoleKey") + .IsUnique(); + + b.ToTable("DeploymentTargetAssignments", t => + { + t.HasCheckConstraint("CK_DeploymentTargetAssignments_NodeDataJson_IsJson", "ISJSON([NodeDataJson]) = 1"); + }); + + b.HasData( + new + { + Id = new Guid("84000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CT-SHP-01\"}", + RoleKey = "WebFrontEnd", + SortOrder = 10, + TargetId = new Guid("30000000-0000-0000-0000-000000000004") + }, + new + { + Id = new Guid("84000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CT-SHP-02\"}", + RoleKey = "Application", + SortOrder = 20, + TargetId = new Guid("30000000-0000-0000-0000-000000000005") + }, + new + { + Id = new Guid("84000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CLD-SHP-01\",\"RunCentralAdministration\":true}", + RoleKey = "Node", + SortOrder = 10, + TargetId = new Guid("30000000-0000-0000-0000-000000000101") + }, + new + { + Id = new Guid("84000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CLD-SHP-02\",\"RunCentralAdministration\":false}", + RoleKey = "Node", + SortOrder = 20, + TargetId = new Guid("30000000-0000-0000-0000-000000000102") + }, + new + { + Id = new Guid("84000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CLD-SHP-03\",\"RunCentralAdministration\":false}", + RoleKey = "Node", + SortOrder = 30, + TargetId = new Guid("30000000-0000-0000-0000-000000000103") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTemplateSelectionModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Alias") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("SortOrder") + .HasColumnType("int") + .HasColumnOrder(4); + + b.Property("TemplateRole") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("TemplateVersionId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("TemplateVersionId"); + + b.HasIndex("DeploymentGroupId", "SortOrder") + .IsUnique(); + + b.ToTable("DeploymentTemplateSelections"); + + b.HasData( + new + { + Id = new Guid("82000000-0000-0000-0000-000000000001"), + Alias = "SharePoint", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 10, + TemplateRole = "Service", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("82000000-0000-0000-0000-000000000101"), + Alias = "Environment-Test", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 10, + TemplateRole = "Environment", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000101") + }, + new + { + Id = new Guid("82000000-0000-0000-0000-000000000102"), + Alias = "Domain-Contoso", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 20, + TemplateRole = "Domain", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000102") + }, + new + { + Id = new Guid("82000000-0000-0000-0000-000000000103"), + Alias = "Service-SharePoint-Contoso", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 30, + TemplateRole = "Service", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000103") + }, + new + { + Id = new Guid("82000000-0000-0000-0000-000000000104"), + Alias = "Stage-Install", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 40, + TemplateRole = "Stage", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000104") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DomainModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("FQDN") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("NetBIOS") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.HasKey("Id"); + + b.ToTable("Domains"); + + b.HasData( + new + { + Id = new Guid("20000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + FQDN = "corp.contoso.com", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Central Management", + NetBIOS = "CONTOSO" + }, + new + { + Id = new Guid("20000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + FQDN = "resource.contoso.com", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Resource Domain", + NetBIOS = "RESOURCE" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentDomainsModel", b => + { + b.Property("EnvironmentId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0); + + b.Property("DomainId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("Created") + .HasColumnType("datetime2") + .HasColumnOrder(52); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Modified") + .HasColumnType("datetime2") + .HasColumnOrder(50); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.HasKey("EnvironmentId", "DomainId"); + + b.HasIndex("DomainId"); + + b.ToTable("EnvironmentDomains"); + + b.HasData( + new + { + EnvironmentId = new Guid("10000000-0000-0000-0000-000000000001"), + DomainId = new Guid("20000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed" + }, + new + { + EnvironmentId = new Guid("10000000-0000-0000-0000-000000000002"), + DomainId = new Guid("20000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed" + }, + new + { + EnvironmentId = new Guid("10000000-0000-0000-0000-000000000002"), + DomainId = new Guid("20000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("EnvironmentType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("HostingType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(7); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("ProviderType") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("SubscriptionId") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(6); + + b.Property("TenantId") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.HasKey("Id"); + + b.ToTable("Environments"); + + b.HasData( + new + { + Id = new Guid("10000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + EnvironmentType = "Test", + HostingType = "OnPrem", + MetadataJson = "{\"location\":\"Datacenter A\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso Test" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + EnvironmentType = "Production", + HostingType = "OnPrem", + MetadataJson = "{\"location\":\"Datacenter A\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso Production" + }, + new + { + Id = new Guid("10000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + EnvironmentType = "Production", + HostingType = "M365Tenant", + MetadataJson = "{\"tenant\":\"contoso.onmicrosoft.com\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso M365", + ProviderType = "Microsoft365", + TenantId = "11111111-1111-1111-1111-111111111111" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionCategoryModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("ParentCategoryName") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("showOrder") + .HasColumnType("int") + .HasColumnOrder(3); + + b.HasKey("Id"); + + b.ToTable("OptionCategories"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("OptionCategoryId") + .HasColumnType("uniqueidentifier"); + + b.Property("OptionType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("OptionValue") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.HasKey("Id"); + + b.HasIndex("OptionCategoryId"); + + b.ToTable("Options"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Attempts") + .HasColumnType("int") + .HasColumnOrder(4); + + b.Property("CorrelationId") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(13) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("ErrorMessage") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(10); + + b.Property("Finished") + .HasColumnType("datetime2") + .HasColumnOrder(7); + + b.Property("HeartbeatAt") + .HasColumnType("datetime2") + .HasColumnOrder(16); + + b.Property("LockedBy") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(9); + + b.Property("LockedUntil") + .HasColumnType("datetime2") + .HasColumnOrder(8); + + b.Property("MaxAttempts") + .HasColumnType("int") + .HasColumnOrder(5); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(11); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("PayloadJson") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(100) + .HasColumnOrder(14); + + b.Property("RowVersion") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + + b.Property("RuleSnapshotJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(12); + + b.Property("ScheduledAt") + .HasColumnType("datetime2") + .HasColumnOrder(15); + + b.Property("Started") + .HasColumnType("datetime2") + .HasColumnOrder(6); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(2); + + b.Property("Type") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("WorkerName") + .HasColumnType("nvarchar(450)") + .HasColumnOrder(17); + + b.HasKey("Id"); + + b.HasIndex("CorrelationId"); + + b.HasIndex("WorkerName"); + + b.HasIndex("Status", "ScheduledAt", "LockedUntil", "Priority", "Created"); + + b.ToTable("DeploymentJobs", (string)null); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobStepModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("ApprovalComment") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(10); + + b.Property("ApprovedAt") + .HasColumnType("datetime2") + .HasColumnOrder(8); + + b.Property("ApprovedBy") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(9); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DependsOnQueueJobStepId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DependsOnDeploymentJobStepId") + .HasColumnOrder(2); + + b.Property("ErrorMessage") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(14); + + b.Property("Finished") + .HasColumnType("datetime2") + .HasColumnOrder(12); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(7); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("OutputMetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(13); + + b.Property("QueueJobId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeploymentJobId") + .HasColumnOrder(1); + + b.Property("SortOrder") + .HasColumnType("int") + .HasColumnOrder(3); + + b.Property("Started") + .HasColumnType("datetime2") + .HasColumnOrder(11); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(6); + + b.Property("StepType") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.HasKey("Id"); + + b.HasIndex("DependsOnQueueJobStepId"); + + b.HasIndex("QueueJobId", "Status", "SortOrder"); + + b.ToTable("DeploymentJobSteps", null, t => + { + t.HasCheckConstraint("CK_DeploymentJobSteps_OutputMetadataJson_IsJson", "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1"); + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobTargetModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Attempts") + .HasColumnType("int") + .HasColumnOrder(6); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentGroupId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeploymentBatchId") + .HasColumnOrder(3); + + b.Property("ErrorMessage") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(7); + + b.Property("Finished") + .HasColumnType("datetime2") + .HasColumnOrder(9); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("OutputMetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(10); + + b.Property("QueueJobId") + .HasColumnType("uniqueidentifier") + .HasColumnName("DeploymentJobId") + .HasColumnOrder(1); + + b.Property("Started") + .HasColumnType("datetime2") + .HasColumnOrder(8); + + b.Property("Status") + .IsRequired() + .HasColumnType("nvarchar(450)") + .HasColumnOrder(5); + + b.Property("TargetId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(2); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(4); + + b.HasKey("Id"); + + b.HasIndex("QueueJobId", "Status"); + + b.ToTable("DeploymentJobTargets", null, t => + { + t.HasCheckConstraint("CK_DeploymentJobTargets_OutputMetadataJson_IsJson", "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1"); + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.ServiceModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("IconKey") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("IsCloudService") + .HasColumnType("bit") + .HasColumnOrder(3); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.HasKey("Id"); + + b.ToTable("Services"); + + b.HasData( + new + { + Id = new Guid("40000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "On-premises directory and identity service.", + IconKey = "network", + IsCloudService = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Active Directory" + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Database platform for application workloads.", + IconKey = "database", + IsCloudService = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "SQL Server" + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Collaboration platform for on-premises workloads.", + IconKey = "sharepoint", + IsCloudService = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "SharePoint Server" + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Cloud collaboration workload in Microsoft 365.", + IconKey = "messages-square", + IsCloudService = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Microsoft Teams" + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Reusable configuration-data template building blocks for deployment composition.", + IconKey = "braces", + IsCloudService = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "DSC Configuration Data" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.ServiceRoleDefinitionModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Description") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("Key") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("ServiceId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.HasKey("Id"); + + b.HasIndex("ServiceId"); + + b.ToTable("ServiceRoleDefinitions"); + + b.HasData( + new + { + Id = new Guid("41000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "SharePoint farm role.", + Key = "Farm", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Farm", + ServiceId = new Guid("40000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "SharePoint web front-end role.", + Key = "WebFrontEnd", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Web Front End", + ServiceId = new Guid("40000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "SharePoint service application role.", + Key = "Application", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Application", + ServiceId = new Guid("40000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("41000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "SQL Server database role.", + Key = "Database", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Database", + ServiceId = new Guid("40000000-0000-0000-0000-000000000002") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DomainID") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("ExternalId") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("MetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(6); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("ProviderType") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnOrder(4); + + b.Property("TargetType") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnOrder(3); + + b.HasKey("Id"); + + b.HasIndex("DomainID"); + + b.ToTable("Targets"); + + b.HasData( + new + { + Id = new Guid("30000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"DomainController\",\"environment\":\"Test\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-DC-01", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"DomainController\",\"environment\":\"Production\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-DC-02", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SqlServer\",\"environment\":\"Test\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-SQL-01", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-SHP-01", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000005"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CT-SHP-02", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000006"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + ExternalId = "11111111-1111-1111-1111-111111111111", + MetadataJson = "{\"environment\":\"Production\",\"workload\":\"M365\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "contoso.onmicrosoft.com", + ProviderType = "Microsoft365", + TargetType = "Tenant" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000007"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + ExternalId = "Teams.StandardUsers", + MetadataJson = "{\"workload\":\"Teams\",\"scope\":\"StandardUsers\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Teams - Standard Users", + ProviderType = "Microsoft365", + TargetType = "PolicyScope" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CLD-SHP-01", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CLD-SHP-02", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CLD-SHP-03", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateCategoryModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Color") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(5); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Description") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("IsActive") + .HasColumnType("bit") + .HasColumnOrder(4); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.Property("ServiceId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.HasKey("Id"); + + b.HasIndex("ServiceId"); + + b.ToTable("TemplateCategories"); + + b.HasData( + new + { + Id = new Guid("50000000-0000-0000-0000-000000000001"), + Color = "#2563EB", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Templates for domain controller and domain configuration.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Domain Services", + ServiceId = new Guid("40000000-0000-0000-0000-000000000001") + }, + new + { + Id = new Guid("50000000-0000-0000-0000-000000000002"), + Color = "#16A34A", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Templates for SQL Server workloads.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Database Platform", + ServiceId = new Guid("40000000-0000-0000-0000-000000000002") + }, + new + { + Id = new Guid("50000000-0000-0000-0000-000000000003"), + Color = "#0F766E", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Templates for SharePoint Server farms.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Collaboration Farm", + ServiceId = new Guid("40000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("50000000-0000-0000-0000-000000000004"), + Color = "#7C3AED", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Templates for Teams policy configuration.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Teams Policies", + ServiceId = new Guid("40000000-0000-0000-0000-000000000004") + }, + new + { + Id = new Guid("50000000-0000-0000-0000-000000000101"), + Color = "#2563EB", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Materialized template building blocks from the BGW Test.Merge.ps1 scenario.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Test.Merge.ps1 Templates", + ServiceId = new Guid("40000000-0000-0000-0000-000000000101") + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("DeploymentRuleId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(6); + + b.Property("Description") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("JSONData") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(4); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Name") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(1); + + b.Property("TemplateCategoryId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(5); + + b.Property("Version") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("DeploymentRuleId"); + + b.HasIndex("TemplateCategoryId"); + + b.ToTable("Templates"); + + b.HasData( + new + { + Id = new Guid("70000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Creates a reusable Active Directory domain baseline.", + JSONData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"DomainName\": { \"type\": \"string\", \"defaultValue\": \"corp.contoso.com\" },\n \"NetBIOSName\": { \"type\": \"string\", \"defaultValue\": \"CONTOSO\" }\n },\n \"variables\": {\n \"DefaultSiteName\": \"[concat(parameters('DomainName'), '-DefaultSite')]\"\n },\n \"resources\": {\n \"AllNodes\": [\n { \"NodeName\": \"*\", \"PSDscAllowPlainTextPassword\": true }\n ],\n \"NonNodeData\": {\n \"Services\": {\n \"ActiveDirectory\": {\n \"DomainName\": \"[parameters('DomainName')]\",\n \"NetBIOSName\": \"[parameters('NetBIOSName')]\"\n }\n }\n }\n }\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso Active Directory Domain", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000001"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Creates a SQL Server baseline for application workloads.", + JSONData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"InstanceName\": { \"type\": \"string\", \"defaultValue\": \"MSSQLSERVER\" },\n \"DatabasePrefix\": { \"type\": \"string\", \"defaultValue\": \"Contoso\" }\n },\n \"variables\": {\n \"ConfigDatabase\": \"[concat(parameters('DatabasePrefix'), '_Config')]\"\n },\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"SqlServer\": {\n \"InstanceName\": \"[parameters('InstanceName')]\",\n \"ConfigDatabase\": \"[variables('ConfigDatabase')]\"\n }\n }\n }\n }\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso SQL Server", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000002"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Creates a SharePoint Server farm baseline.", + JSONData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"DatabasePrefix\": { \"type\": \"string\", \"defaultValue\": \"SharePoint_Contoso_Test\" },\n \"FarmAccount\": { \"type\": \"credential\", \"metadata\": { \"description\": \"Farm account resolved by the credential provider.\" } }\n },\n \"variables\": {\n \"ConfigDbName\": \"[concat(parameters('DatabasePrefix'), '_Farm_Config')]\",\n \"AdminContentDbName\": \"[concat(parameters('DatabasePrefix'), '_AdminContent')]\"\n },\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"SharePoint\": {\n \"Farm\": {\n \"ConfigDatabase\": \"[variables('ConfigDbName')]\",\n \"AdminContentDatabase\": \"[variables('AdminContentDbName')]\",\n \"ManagedAccounts\": {\n \"FarmAccount\": \"[parameters('FarmAccount')]\"\n }\n }\n }\n }\n }\n }\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso SharePoint Server", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000003"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Creates a Microsoft Teams policy baseline.", + JSONData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"CallingPolicyName\": { \"type\": \"string\", \"defaultValue\": \"Contoso-Standard-Calling\" },\n \"MeetingPolicyName\": { \"type\": \"string\", \"defaultValue\": \"Contoso-Standard-Meetings\" }\n },\n \"variables\": {},\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"Teams\": {\n \"CallingPolicy\": \"[parameters('CallingPolicyName')]\",\n \"MeetingPolicy\": \"[parameters('MeetingPolicyName')]\"\n }\n }\n }\n }\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Contoso Teams Policies", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000004"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Materialized Environment/Test.psd1 template from Test.Merge.ps1.", + JSONData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Environment\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Environment\",\r\n \"Name\": \"Test\"\r\n },\r\n \"parameters\": {\r\n \"Landscape\": {\r\n \"DefaultValue\": \"Prod\",\r\n \"Value\": \"Test\",\r\n \"Type\": \"string\",\r\n \"AllowedValues\": [\r\n \"Prod\",\r\n \"QA\",\r\n \"Test\"\r\n ]\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n\r\n }\r\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "BGW Environment Test", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000101"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Materialized Domain/Contoso.psd1 template from Test.Merge.ps1.", + JSONData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Domain\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Domain\",\r\n \"Name\": \"Contoso\"\r\n },\r\n \"parameters\": {\r\n \"DomainFQDN\": {\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9.-]+$\",\r\n \"Type\": \"string\",\r\n \"Value\": \"contoso.local\",\r\n \"Required\": true\r\n },\r\n \"DomainLabel\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 32,\r\n \"Value\": \"Contoso\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z][A-Za-z0-9_-]*$\",\r\n \"MinLength\": 2,\r\n \"Required\": false\r\n },\r\n \"DomainNetBIOS\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 15,\r\n \"Value\": \"CONTOSO\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9_-]+$\",\r\n \"MinLength\": 1,\r\n \"Required\": true\r\n }\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"ActiveDirectory\": {\r\n \"NetBIOSName\": \"[parameters(\\u0027DomainNetBIOS\\u0027)]\",\r\n \"DomainName\": \"[parameters(\\u0027DomainFQDN\\u0027)]\"\r\n }\r\n }\r\n }\r\n }\r\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "BGW Domain Contoso", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000101"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Materialized Service/SharePoint/Contoso.psd1 template from Test.Merge.ps1.", + JSONData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Service\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Service\",\r\n \"Name\": \"SharePoint.Contoso\"\r\n },\r\n \"parameters\": {\r\n \"FarmCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ContentDatabaseSegment\": {\r\n \"DefaultValue\": \"Content\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Content-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint content databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"ServiceApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint service applications.\"\r\n }\r\n }\r\n },\r\n \"WebApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Web Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"DatabaseServerName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"CL-SQL-01\"\r\n },\r\n \"WebApplicationPoolDefaultAccount\": {\r\n \"DefaultValue\": \"SVC_SHP_WAP\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"ServiceDatabaseSegment\": {\r\n \"DefaultValue\": \"Services\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Service-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint service databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"FarmPassphrase\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmPassphrase\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabaseInstanceName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SQLServer\"\r\n },\r\n \"DatabaseTcpPort\": {\r\n \"DefaultValue\": 1433,\r\n \"Type\": \"int\",\r\n \"Value\": 1433\r\n },\r\n \"DefaultServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/DefaultServiceAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ProductKey\": {\r\n \"DefaultValue\": \"0000-0000-0000-0000-0000\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"SharePoint-Produktlizenzschluessel.\",\r\n \"en-US\": \"SharePoint product license key.\"\r\n }\r\n }\r\n },\r\n \"SetupCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SetupAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabasePrefix\": {\r\n \"DefaultValue\": \"SharePoint\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SharePoint\"\r\n },\r\n \"SearchServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Search-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the search application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SearchAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"CentralAdminPort\": {\r\n \"DefaultValue\": 443,\r\n \"Type\": \"int\",\r\n \"Value\": 4000\r\n },\r\n \"ServiceApplicationPoolSearch\": {\r\n \"DefaultValue\": \"SharePoint Search Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Application-Pools fuer SharePoint Search-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the application pool for SharePoint Search service applications.\"\r\n }\r\n }\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n \"AllNodes\": [\r\n {\r\n \"PSDscAllowDomainUser\": true,\r\n \"PSDSCAllowPlainTextPassword\": true,\r\n \"NodeName\": \"*\",\r\n \"RunCentralAdministration\": false\r\n }\r\n ],\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"SharePoint\": {\r\n \"Farm\": {\r\n \"ManagedAccounts\": {\r\n \"DefaultServiceApplicationPoolAccount\": \"[parameters(\\u0027DefaultServiceApplicationPoolAccount\\u0027)]\",\r\n \"FarmAccount\": \"[parameters(\\u0027FarmCredential\\u0027)]\",\r\n \"SearchServiceApplicationPoolAccount\": \"[parameters(\\u0027SearchServiceApplicationPoolAccount\\u0027)]\"\r\n },\r\n \"Passphrase\": \"[parameters(\\u0027FarmPassphrase\\u0027)]\",\r\n \"ServiceApplications\": {\r\n \"AppManagementService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027AppManagement\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"StateService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027StateService\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SubscriptionSettingsService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SubscriptionSettings\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"ManagedMetadataService\": {\r\n \"Name\": \"Managed Metadata Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027ManagedMetadata\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SearchService\": {\r\n \"Name\": \"Search Service Application\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027Search\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.SearchServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"UsageAndHealthService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027UsageAndHealth\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SecureStoreService\": {\r\n \"Name\": \"Secure Store Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SecureStore\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"AuditingEnabled\": true\r\n },\r\n \"UserProfileService\": {\r\n \"SyncDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Sync\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"Name\": \"User Profile Service\",\r\n \"SocialDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Social\\u0027)]\",\r\n \"ProfileDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Profile\\u0027)]\"\r\n }\r\n },\r\n \"CentralAdminAuth\": \"NTLM\",\r\n \"ConfigDatabaseName\": \"[variables(\\u0027ConfigDbName\\u0027)]\",\r\n \"Accounts\": {\r\n \"SetupAccount\": \"[parameters(\\u0027SetupCredential\\u0027)]\"\r\n },\r\n \"CentralAdminPort\": \"[parameters(\\u0027CentralAdminPort\\u0027)]\",\r\n \"AdminContentDatabase\": \"[variables(\\u0027AdminDbName\\u0027)]\",\r\n \"ServiceApplicationPools\": {\r\n \"SearchServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.SearchServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolSearch\\u0027)]\"\r\n },\r\n \"DefaultServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.DefaultServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolDefault\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"Database\": {\r\n \"Targets\": {\r\n \"Farm\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Content\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Service\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n }\r\n },\r\n \"SQLAlias\": {\r\n \"SQLServer\": {\r\n \"InstanceName\": \"[parameters(\\u0027DatabaseInstanceName\\u0027)]\",\r\n \"ServerName\": \"[parameters(\\u0027DatabaseServerName\\u0027)]\",\r\n \"Protocol\": \"TCP\",\r\n \"TcpPort\": \"[parameters(\\u0027DatabaseTcpPort\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"General\": {\r\n \"ProductKey\": \"[parameters(\\u0027ProductKey\\u0027)]\"\r\n },\r\n \"Windows\": {\r\n \"Registry\": {\r\n \"DisableLoopbackCheck\": {\r\n \"Path\": \"HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\",\r\n \"Name\": \"DisableLoopbackCheck\",\r\n \"Value\": 1,\r\n \"Type\": \"DWord\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "BGW SharePoint Contoso", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000101"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000104"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Materialized Stage/Install.psd1 template from Test.Merge.ps1.", + JSONData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Stage\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Stage\",\r\n \"Name\": \"Install\"\r\n },\r\n \"parameters\": {\r\n\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"LocalConfigurationManager\": {\r\n \"RefreshFrequencyMins\": \"30\",\r\n \"RefreshMode\": \"PUSH\",\r\n \"ConfigurationModeFrequencyMins\": \"120\",\r\n \"ConfigurationMode\": \"ApplyOnly\"\r\n }\r\n }\r\n }\r\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "BGW Stage Install", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000101"), + Version = "1.0.0" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateOptionModel", b => + { + b.Property("OptionId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0); + + b.Property("Created") + .HasColumnType("datetime2") + .HasColumnOrder(52); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("Modified") + .HasColumnType("datetime2") + .HasColumnOrder(50); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("Value") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(2); + + b.HasKey("OptionId", "TemplateId"); + + b.HasIndex("TemplateId"); + + b.ToTable("TemplateOptions"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateVersionModel", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(0) + .HasDefaultValueSql("NEWID()"); + + b.Property("Created") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(52) + .HasDefaultValueSql("GETDATE()"); + + b.Property("CreatedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(53); + + b.Property("IsPublished") + .HasColumnType("bit") + .HasColumnOrder(6); + + b.Property("JsonData") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(3); + + b.Property("JsonHash") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnOrder(4); + + b.Property("Modified") + .ValueGeneratedOnAdd() + .HasColumnType("datetime2") + .HasColumnOrder(50) + .HasDefaultValueSql("GETDATE()"); + + b.Property("ModifiedBy") + .IsRequired() + .HasColumnType("nvarchar(max)") + .HasColumnOrder(51); + + b.Property("PublishedAt") + .HasColumnType("datetime2") + .HasColumnOrder(7); + + b.Property("PublishedBy") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(8); + + b.Property("SchemaVersion") + .IsRequired() + .HasMaxLength(32) + .HasColumnType("nvarchar(32)") + .HasColumnOrder(5); + + b.Property("TemplateId") + .HasColumnType("uniqueidentifier") + .HasColumnOrder(1); + + b.Property("Version") + .IsRequired() + .HasMaxLength(64) + .HasColumnType("nvarchar(64)") + .HasColumnOrder(2); + + b.HasKey("Id"); + + b.HasIndex("TemplateId") + .IsUnique() + .HasFilter("[IsPublished] = 1"); + + b.HasIndex("TemplateId", "Version") + .IsUnique(); + + b.ToTable("TemplateVersions", t => + { + t.HasCheckConstraint("CK_TemplateVersions_JsonData_IsJson", "ISJSON([JsonData]) = 1"); + }); + + b.HasData( + new + { + Id = new Guid("71000000-0000-0000-0000-000000000001"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"DomainName\": { \"type\": \"string\", \"defaultValue\": \"corp.contoso.com\" },\n \"NetBIOSName\": { \"type\": \"string\", \"defaultValue\": \"CONTOSO\" }\n },\n \"variables\": {\n \"DefaultSiteName\": \"[concat(parameters('DomainName'), '-DefaultSite')]\"\n },\n \"resources\": {\n \"AllNodes\": [\n { \"NodeName\": \"*\", \"PSDscAllowPlainTextPassword\": true }\n ],\n \"NonNodeData\": {\n \"Services\": {\n \"ActiveDirectory\": {\n \"DomainName\": \"[parameters('DomainName')]\",\n \"NetBIOSName\": \"[parameters('NetBIOSName')]\"\n }\n }\n }\n }\n}", + JsonHash = "C05CBEF91131C75DE53B9609D9C2709D680AFC9559EE8D998318A132490F79A7", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000001"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000002"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"InstanceName\": { \"type\": \"string\", \"defaultValue\": \"MSSQLSERVER\" },\n \"DatabasePrefix\": { \"type\": \"string\", \"defaultValue\": \"Contoso\" }\n },\n \"variables\": {\n \"ConfigDatabase\": \"[concat(parameters('DatabasePrefix'), '_Config')]\"\n },\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"SqlServer\": {\n \"InstanceName\": \"[parameters('InstanceName')]\",\n \"ConfigDatabase\": \"[variables('ConfigDatabase')]\"\n }\n }\n }\n }\n}", + JsonHash = "F376737E82CB6B729F7B9960CB9988897C16D90A1C454ED2F594B28EB86ECA11", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000002"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000003"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"DatabasePrefix\": { \"type\": \"string\", \"defaultValue\": \"SharePoint_Contoso_Test\" },\n \"FarmAccount\": { \"type\": \"credential\", \"metadata\": { \"description\": \"Farm account resolved by the credential provider.\" } }\n },\n \"variables\": {\n \"ConfigDbName\": \"[concat(parameters('DatabasePrefix'), '_Farm_Config')]\",\n \"AdminContentDbName\": \"[concat(parameters('DatabasePrefix'), '_AdminContent')]\"\n },\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"SharePoint\": {\n \"Farm\": {\n \"ConfigDatabase\": \"[variables('ConfigDbName')]\",\n \"AdminContentDatabase\": \"[variables('AdminContentDbName')]\",\n \"ManagedAccounts\": {\n \"FarmAccount\": \"[parameters('FarmAccount')]\"\n }\n }\n }\n }\n }\n }\n}", + JsonHash = "FD5F0FD3C13538FAC70646972DC364DFCEAAF85BBE91B0F50FDFF9FD3A3748B4", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000003"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000004"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\n \"schemaVersion\": \"1.0\",\n \"templateType\": \"Service\",\n \"parameters\": {\n \"CallingPolicyName\": { \"type\": \"string\", \"defaultValue\": \"Contoso-Standard-Calling\" },\n \"MeetingPolicyName\": { \"type\": \"string\", \"defaultValue\": \"Contoso-Standard-Meetings\" }\n },\n \"variables\": {},\n \"resources\": {\n \"NonNodeData\": {\n \"Services\": {\n \"Teams\": {\n \"CallingPolicy\": \"[parameters('CallingPolicyName')]\",\n \"MeetingPolicy\": \"[parameters('MeetingPolicyName')]\"\n }\n }\n }\n }\n}", + JsonHash = "32A902FE1A871D4CE2C877EBC5542F7562856532F09BA7F53597B21270586241", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000004"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Environment\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Environment\",\r\n \"Name\": \"Test\"\r\n },\r\n \"parameters\": {\r\n \"Landscape\": {\r\n \"DefaultValue\": \"Prod\",\r\n \"Value\": \"Test\",\r\n \"Type\": \"string\",\r\n \"AllowedValues\": [\r\n \"Prod\",\r\n \"QA\",\r\n \"Test\"\r\n ]\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n\r\n }\r\n}", + JsonHash = "58553C7A4E902B5E39D30272754FEF9EF805A7F36363D8316A9B37540C6D4646", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000101"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Domain\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Domain\",\r\n \"Name\": \"Contoso\"\r\n },\r\n \"parameters\": {\r\n \"DomainFQDN\": {\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9.-]+$\",\r\n \"Type\": \"string\",\r\n \"Value\": \"contoso.local\",\r\n \"Required\": true\r\n },\r\n \"DomainLabel\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 32,\r\n \"Value\": \"Contoso\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z][A-Za-z0-9_-]*$\",\r\n \"MinLength\": 2,\r\n \"Required\": false\r\n },\r\n \"DomainNetBIOS\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 15,\r\n \"Value\": \"CONTOSO\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9_-]+$\",\r\n \"MinLength\": 1,\r\n \"Required\": true\r\n }\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"ActiveDirectory\": {\r\n \"NetBIOSName\": \"[parameters(\\u0027DomainNetBIOS\\u0027)]\",\r\n \"DomainName\": \"[parameters(\\u0027DomainFQDN\\u0027)]\"\r\n }\r\n }\r\n }\r\n }\r\n}", + JsonHash = "B265C4D542826423BAAF50BF939F026CC67FF631FEC19F708067516BCE4C7667", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000102"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Service\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Service\",\r\n \"Name\": \"SharePoint.Contoso\"\r\n },\r\n \"parameters\": {\r\n \"FarmCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ContentDatabaseSegment\": {\r\n \"DefaultValue\": \"Content\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Content-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint content databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"ServiceApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint service applications.\"\r\n }\r\n }\r\n },\r\n \"WebApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Web Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"DatabaseServerName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"CL-SQL-01\"\r\n },\r\n \"WebApplicationPoolDefaultAccount\": {\r\n \"DefaultValue\": \"SVC_SHP_WAP\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"ServiceDatabaseSegment\": {\r\n \"DefaultValue\": \"Services\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Service-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint service databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"FarmPassphrase\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmPassphrase\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabaseInstanceName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SQLServer\"\r\n },\r\n \"DatabaseTcpPort\": {\r\n \"DefaultValue\": 1433,\r\n \"Type\": \"int\",\r\n \"Value\": 1433\r\n },\r\n \"DefaultServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/DefaultServiceAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ProductKey\": {\r\n \"DefaultValue\": \"0000-0000-0000-0000-0000\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"SharePoint-Produktlizenzschluessel.\",\r\n \"en-US\": \"SharePoint product license key.\"\r\n }\r\n }\r\n },\r\n \"SetupCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SetupAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabasePrefix\": {\r\n \"DefaultValue\": \"SharePoint\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SharePoint\"\r\n },\r\n \"SearchServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Search-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the search application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SearchAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"CentralAdminPort\": {\r\n \"DefaultValue\": 443,\r\n \"Type\": \"int\",\r\n \"Value\": 4000\r\n },\r\n \"ServiceApplicationPoolSearch\": {\r\n \"DefaultValue\": \"SharePoint Search Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Application-Pools fuer SharePoint Search-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the application pool for SharePoint Search service applications.\"\r\n }\r\n }\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n \"AllNodes\": [\r\n {\r\n \"PSDscAllowDomainUser\": true,\r\n \"PSDSCAllowPlainTextPassword\": true,\r\n \"NodeName\": \"*\",\r\n \"RunCentralAdministration\": false\r\n }\r\n ],\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"SharePoint\": {\r\n \"Farm\": {\r\n \"ManagedAccounts\": {\r\n \"DefaultServiceApplicationPoolAccount\": \"[parameters(\\u0027DefaultServiceApplicationPoolAccount\\u0027)]\",\r\n \"FarmAccount\": \"[parameters(\\u0027FarmCredential\\u0027)]\",\r\n \"SearchServiceApplicationPoolAccount\": \"[parameters(\\u0027SearchServiceApplicationPoolAccount\\u0027)]\"\r\n },\r\n \"Passphrase\": \"[parameters(\\u0027FarmPassphrase\\u0027)]\",\r\n \"ServiceApplications\": {\r\n \"AppManagementService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027AppManagement\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"StateService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027StateService\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SubscriptionSettingsService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SubscriptionSettings\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"ManagedMetadataService\": {\r\n \"Name\": \"Managed Metadata Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027ManagedMetadata\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SearchService\": {\r\n \"Name\": \"Search Service Application\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027Search\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.SearchServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"UsageAndHealthService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027UsageAndHealth\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SecureStoreService\": {\r\n \"Name\": \"Secure Store Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SecureStore\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"AuditingEnabled\": true\r\n },\r\n \"UserProfileService\": {\r\n \"SyncDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Sync\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"Name\": \"User Profile Service\",\r\n \"SocialDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Social\\u0027)]\",\r\n \"ProfileDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Profile\\u0027)]\"\r\n }\r\n },\r\n \"CentralAdminAuth\": \"NTLM\",\r\n \"ConfigDatabaseName\": \"[variables(\\u0027ConfigDbName\\u0027)]\",\r\n \"Accounts\": {\r\n \"SetupAccount\": \"[parameters(\\u0027SetupCredential\\u0027)]\"\r\n },\r\n \"CentralAdminPort\": \"[parameters(\\u0027CentralAdminPort\\u0027)]\",\r\n \"AdminContentDatabase\": \"[variables(\\u0027AdminDbName\\u0027)]\",\r\n \"ServiceApplicationPools\": {\r\n \"SearchServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.SearchServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolSearch\\u0027)]\"\r\n },\r\n \"DefaultServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.DefaultServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolDefault\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"Database\": {\r\n \"Targets\": {\r\n \"Farm\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Content\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Service\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n }\r\n },\r\n \"SQLAlias\": {\r\n \"SQLServer\": {\r\n \"InstanceName\": \"[parameters(\\u0027DatabaseInstanceName\\u0027)]\",\r\n \"ServerName\": \"[parameters(\\u0027DatabaseServerName\\u0027)]\",\r\n \"Protocol\": \"TCP\",\r\n \"TcpPort\": \"[parameters(\\u0027DatabaseTcpPort\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"General\": {\r\n \"ProductKey\": \"[parameters(\\u0027ProductKey\\u0027)]\"\r\n },\r\n \"Windows\": {\r\n \"Registry\": {\r\n \"DisableLoopbackCheck\": {\r\n \"Path\": \"HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\",\r\n \"Name\": \"DisableLoopbackCheck\",\r\n \"Value\": 1,\r\n \"Type\": \"DWord\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}", + JsonHash = "E3B0E2A8E0C85CCD92AEA521ECD243E61E34C61D7078D6715E6317F5669A1D69", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000103"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000104"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Stage\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Stage\",\r\n \"Name\": \"Install\"\r\n },\r\n \"parameters\": {\r\n\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"LocalConfigurationManager\": {\r\n \"RefreshFrequencyMins\": \"30\",\r\n \"RefreshMode\": \"PUSH\",\r\n \"ConfigurationModeFrequencyMins\": \"120\",\r\n \"ConfigurationMode\": \"ApplyOnly\"\r\n }\r\n }\r\n }\r\n}", + JsonHash = "ACA23E44C9F625F080D2653646555A9DE5546D8DE7BB2166324E775BCF47F3C1", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000104"), + Version = "1.0.0" + }); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", "DeploymentRule") + .WithMany() + .HasForeignKey("DeploymentRuleId") + .OnDelete(DeleteBehavior.SetNull); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", "Template") + .WithMany("DeploymentGroups") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeploymentRule"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", "DeploymentGroup") + .WithMany("Deployments") + .HasForeignKey("DeploymentGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", "Target") + .WithMany("Deployments") + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeploymentGroup"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentParameterValueModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", "DeploymentGroup") + .WithMany("ParameterValues") + .HasForeignKey("DeploymentGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTemplateSelectionModel", "DeploymentTemplateSelection") + .WithMany() + .HasForeignKey("DeploymentTemplateSelectionId") + .OnDelete(DeleteBehavior.NoAction); + + b.Navigation("DeploymentGroup"); + + b.Navigation("DeploymentTemplateSelection"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleStepModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", "DeploymentRule") + .WithMany("Steps") + .HasForeignKey("DeploymentRuleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeploymentRule"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTargetAssignmentModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", "DeploymentGroup") + .WithMany("TargetAssignments") + .HasForeignKey("DeploymentGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", "Target") + .WithMany() + .HasForeignKey("TargetId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DeploymentGroup"); + + b.Navigation("Target"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentTemplateSelectionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", "DeploymentGroup") + .WithMany("TemplateSelections") + .HasForeignKey("DeploymentGroupId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateVersionModel", "TemplateVersion") + .WithMany() + .HasForeignKey("TemplateVersionId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("DeploymentGroup"); + + b.Navigation("TemplateVersion"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentDomainsModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DomainModel", "Domain") + .WithMany("EnvironmentDomains") + .HasForeignKey("DomainId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentModel", "Environment") + .WithMany("EnvironmentDomains") + .HasForeignKey("EnvironmentId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Domain"); + + b.Navigation("Environment"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.OptionCategoryModel", "OptionCategory") + .WithMany("Options") + .HasForeignKey("OptionCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("OptionCategory"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobStepModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.QueueJobStepModel", "DependsOnQueueJobStep") + .WithMany() + .HasForeignKey("DependsOnQueueJobStepId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.QueueJobModel", "QueueJob") + .WithMany("Steps") + .HasForeignKey("QueueJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DependsOnQueueJobStep"); + + b.Navigation("QueueJob"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobTargetModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.QueueJobModel", "QueueJob") + .WithMany("Targets") + .HasForeignKey("QueueJobId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("QueueJob"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.ServiceRoleDefinitionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.ServiceModel", "Service") + .WithMany("RoleDefinitions") + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DomainModel", "Domain") + .WithMany("Targets") + .HasForeignKey("DomainID"); + + b.Navigation("Domain"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateCategoryModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.ServiceModel", "Service") + .WithMany("TemplateCategories") + .HasForeignKey("ServiceId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Service"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", "DeploymentRule") + .WithMany() + .HasForeignKey("DeploymentRuleId"); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateCategoryModel", "TemplateCategory") + .WithMany("Templates") + .HasForeignKey("TemplateCategoryId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("DeploymentRule"); + + b.Navigation("TemplateCategory"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateOptionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.OptionModel", "Option") + .WithMany("TemplateOptions") + .HasForeignKey("OptionId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", "Template") + .WithMany("TemplateOptions") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Option"); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateVersionModel", b => + { + b.HasOne("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", "Template") + .WithMany("TemplateVersions") + .HasForeignKey("TemplateId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.Navigation("Template"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentGroupModel", b => + { + b.Navigation("Deployments"); + + b.Navigation("ParameterValues"); + + b.Navigation("TargetAssignments"); + + b.Navigation("TemplateSelections"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DeploymentRuleModel", b => + { + b.Navigation("Steps"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.DomainModel", b => + { + b.Navigation("EnvironmentDomains"); + + b.Navigation("Targets"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.EnvironmentModel", b => + { + b.Navigation("EnvironmentDomains"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionCategoryModel", b => + { + b.Navigation("Options"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.OptionModel", b => + { + b.Navigation("TemplateOptions"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobModel", b => + { + b.Navigation("Steps"); + + b.Navigation("Targets"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.ServiceModel", b => + { + b.Navigation("RoleDefinitions"); + + b.Navigation("TemplateCategories"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TargetModel", b => + { + b.Navigation("Deployments"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateCategoryModel", b => + { + b.Navigation("Templates"); + }); + + modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.TemplateModel", b => + { + b.Navigation("DeploymentGroups"); + + b.Navigation("TemplateOptions"); + + b.Navigation("TemplateVersions"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20260708202923_SeedBgwMergeTemplates.cs b/Migrations/20260708202923_SeedBgwMergeTemplates.cs new file mode 100644 index 0000000..5a6ddc7 --- /dev/null +++ b/Migrations/20260708202923_SeedBgwMergeTemplates.cs @@ -0,0 +1,219 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +#pragma warning disable CA1814 // Prefer jagged arrays over multidimensional + +namespace Microsoft.SelfService.Portal.Core.API.Migrations +{ + /// + public partial class SeedBgwMergeTemplates : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.InsertData( + table: "Services", + columns: new[] { "Id", "Created", "CreatedBy", "Description", "IconKey", "IsCloudService", "Modified", "ModifiedBy", "Name" }, + values: new object[] { new Guid("40000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "Reusable configuration-data template building blocks for deployment composition.", "braces", false, new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "DSC Configuration Data" }); + + migrationBuilder.InsertData( + table: "Targets", + columns: new[] { "Id", "Created", "CreatedBy", "DomainID", "ExternalId", "MetadataJson", "Modified", "ModifiedBy", "Name", "ProviderType", "TargetType" }, + values: new object[,] + { + { new Guid("30000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("20000000-0000-0000-0000-000000000001"), null, "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "CLD-SHP-01", "OnPrem", "VirtualMachine" }, + { new Guid("30000000-0000-0000-0000-000000000102"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("20000000-0000-0000-0000-000000000001"), null, "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "CLD-SHP-02", "OnPrem", "VirtualMachine" }, + { new Guid("30000000-0000-0000-0000-000000000103"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("20000000-0000-0000-0000-000000000001"), null, "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "CLD-SHP-03", "OnPrem", "VirtualMachine" } + }); + + migrationBuilder.InsertData( + table: "TemplateCategories", + columns: new[] { "Id", "Color", "Created", "CreatedBy", "Description", "IsActive", "Modified", "ModifiedBy", "Name", "ServiceId" }, + values: new object[] { new Guid("50000000-0000-0000-0000-000000000101"), "#2563EB", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "Materialized template building blocks from the BGW Test.Merge.ps1 scenario.", true, new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "Test.Merge.ps1 Templates", new Guid("40000000-0000-0000-0000-000000000101") }); + + migrationBuilder.InsertData( + table: "Templates", + columns: new[] { "Id", "Created", "CreatedBy", "DeploymentRuleId", "Description", "JSONData", "Modified", "ModifiedBy", "Name", "TemplateCategoryId", "Version" }, + values: new object[,] + { + { new Guid("70000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("60000000-0000-0000-0000-000000000001"), "Materialized Environment/Test.psd1 template from Test.Merge.ps1.", "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Environment\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Environment\",\r\n \"Name\": \"Test\"\r\n },\r\n \"parameters\": {\r\n \"Landscape\": {\r\n \"DefaultValue\": \"Prod\",\r\n \"Value\": \"Test\",\r\n \"Type\": \"string\",\r\n \"AllowedValues\": [\r\n \"Prod\",\r\n \"QA\",\r\n \"Test\"\r\n ]\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n\r\n }\r\n}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "BGW Environment Test", new Guid("50000000-0000-0000-0000-000000000101"), "1.0.0" }, + { new Guid("70000000-0000-0000-0000-000000000102"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("60000000-0000-0000-0000-000000000001"), "Materialized Domain/Contoso.psd1 template from Test.Merge.ps1.", "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Domain\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Domain\",\r\n \"Name\": \"Contoso\"\r\n },\r\n \"parameters\": {\r\n \"DomainFQDN\": {\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9.-]+$\",\r\n \"Type\": \"string\",\r\n \"Value\": \"contoso.local\",\r\n \"Required\": true\r\n },\r\n \"DomainLabel\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 32,\r\n \"Value\": \"Contoso\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z][A-Za-z0-9_-]*$\",\r\n \"MinLength\": 2,\r\n \"Required\": false\r\n },\r\n \"DomainNetBIOS\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 15,\r\n \"Value\": \"CONTOSO\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9_-]+$\",\r\n \"MinLength\": 1,\r\n \"Required\": true\r\n }\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"ActiveDirectory\": {\r\n \"NetBIOSName\": \"[parameters(\\u0027DomainNetBIOS\\u0027)]\",\r\n \"DomainName\": \"[parameters(\\u0027DomainFQDN\\u0027)]\"\r\n }\r\n }\r\n }\r\n }\r\n}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "BGW Domain Contoso", new Guid("50000000-0000-0000-0000-000000000101"), "1.0.0" }, + { new Guid("70000000-0000-0000-0000-000000000103"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("60000000-0000-0000-0000-000000000001"), "Materialized Service/SharePoint/Contoso.psd1 template from Test.Merge.ps1.", "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Service\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Service\",\r\n \"Name\": \"SharePoint.Contoso\"\r\n },\r\n \"parameters\": {\r\n \"FarmCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ContentDatabaseSegment\": {\r\n \"DefaultValue\": \"Content\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Content-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint content databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"ServiceApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint service applications.\"\r\n }\r\n }\r\n },\r\n \"WebApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Web Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"DatabaseServerName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"CL-SQL-01\"\r\n },\r\n \"WebApplicationPoolDefaultAccount\": {\r\n \"DefaultValue\": \"SVC_SHP_WAP\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"ServiceDatabaseSegment\": {\r\n \"DefaultValue\": \"Services\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Service-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint service databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"FarmPassphrase\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmPassphrase\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabaseInstanceName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SQLServer\"\r\n },\r\n \"DatabaseTcpPort\": {\r\n \"DefaultValue\": 1433,\r\n \"Type\": \"int\",\r\n \"Value\": 1433\r\n },\r\n \"DefaultServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/DefaultServiceAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ProductKey\": {\r\n \"DefaultValue\": \"0000-0000-0000-0000-0000\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"SharePoint-Produktlizenzschluessel.\",\r\n \"en-US\": \"SharePoint product license key.\"\r\n }\r\n }\r\n },\r\n \"SetupCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SetupAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabasePrefix\": {\r\n \"DefaultValue\": \"SharePoint\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SharePoint\"\r\n },\r\n \"SearchServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Search-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the search application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SearchAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"CentralAdminPort\": {\r\n \"DefaultValue\": 443,\r\n \"Type\": \"int\",\r\n \"Value\": 4000\r\n },\r\n \"ServiceApplicationPoolSearch\": {\r\n \"DefaultValue\": \"SharePoint Search Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Application-Pools fuer SharePoint Search-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the application pool for SharePoint Search service applications.\"\r\n }\r\n }\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n \"AllNodes\": [\r\n {\r\n \"PSDscAllowDomainUser\": true,\r\n \"PSDSCAllowPlainTextPassword\": true,\r\n \"NodeName\": \"*\",\r\n \"RunCentralAdministration\": false\r\n }\r\n ],\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"SharePoint\": {\r\n \"Farm\": {\r\n \"ManagedAccounts\": {\r\n \"DefaultServiceApplicationPoolAccount\": \"[parameters(\\u0027DefaultServiceApplicationPoolAccount\\u0027)]\",\r\n \"FarmAccount\": \"[parameters(\\u0027FarmCredential\\u0027)]\",\r\n \"SearchServiceApplicationPoolAccount\": \"[parameters(\\u0027SearchServiceApplicationPoolAccount\\u0027)]\"\r\n },\r\n \"Passphrase\": \"[parameters(\\u0027FarmPassphrase\\u0027)]\",\r\n \"ServiceApplications\": {\r\n \"AppManagementService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027AppManagement\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"StateService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027StateService\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SubscriptionSettingsService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SubscriptionSettings\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"ManagedMetadataService\": {\r\n \"Name\": \"Managed Metadata Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027ManagedMetadata\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SearchService\": {\r\n \"Name\": \"Search Service Application\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027Search\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.SearchServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"UsageAndHealthService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027UsageAndHealth\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SecureStoreService\": {\r\n \"Name\": \"Secure Store Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SecureStore\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"AuditingEnabled\": true\r\n },\r\n \"UserProfileService\": {\r\n \"SyncDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Sync\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"Name\": \"User Profile Service\",\r\n \"SocialDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Social\\u0027)]\",\r\n \"ProfileDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Profile\\u0027)]\"\r\n }\r\n },\r\n \"CentralAdminAuth\": \"NTLM\",\r\n \"ConfigDatabaseName\": \"[variables(\\u0027ConfigDbName\\u0027)]\",\r\n \"Accounts\": {\r\n \"SetupAccount\": \"[parameters(\\u0027SetupCredential\\u0027)]\"\r\n },\r\n \"CentralAdminPort\": \"[parameters(\\u0027CentralAdminPort\\u0027)]\",\r\n \"AdminContentDatabase\": \"[variables(\\u0027AdminDbName\\u0027)]\",\r\n \"ServiceApplicationPools\": {\r\n \"SearchServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.SearchServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolSearch\\u0027)]\"\r\n },\r\n \"DefaultServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.DefaultServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolDefault\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"Database\": {\r\n \"Targets\": {\r\n \"Farm\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Content\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Service\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n }\r\n },\r\n \"SQLAlias\": {\r\n \"SQLServer\": {\r\n \"InstanceName\": \"[parameters(\\u0027DatabaseInstanceName\\u0027)]\",\r\n \"ServerName\": \"[parameters(\\u0027DatabaseServerName\\u0027)]\",\r\n \"Protocol\": \"TCP\",\r\n \"TcpPort\": \"[parameters(\\u0027DatabaseTcpPort\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"General\": {\r\n \"ProductKey\": \"[parameters(\\u0027ProductKey\\u0027)]\"\r\n },\r\n \"Windows\": {\r\n \"Registry\": {\r\n \"DisableLoopbackCheck\": {\r\n \"Path\": \"HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\",\r\n \"Name\": \"DisableLoopbackCheck\",\r\n \"Value\": 1,\r\n \"Type\": \"DWord\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "BGW SharePoint Contoso", new Guid("50000000-0000-0000-0000-000000000101"), "1.0.0" }, + { new Guid("70000000-0000-0000-0000-000000000104"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("60000000-0000-0000-0000-000000000001"), "Materialized Stage/Install.psd1 template from Test.Merge.ps1.", "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Stage\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Stage\",\r\n \"Name\": \"Install\"\r\n },\r\n \"parameters\": {\r\n\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"LocalConfigurationManager\": {\r\n \"RefreshFrequencyMins\": \"30\",\r\n \"RefreshMode\": \"PUSH\",\r\n \"ConfigurationModeFrequencyMins\": \"120\",\r\n \"ConfigurationMode\": \"ApplyOnly\"\r\n }\r\n }\r\n }\r\n}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "BGW Stage Install", new Guid("50000000-0000-0000-0000-000000000101"), "1.0.0" } + }); + + migrationBuilder.InsertData( + table: "DeploymentBatches", + columns: new[] { "Id", "Created", "CreatedBy", "DeploymentRuleId", "Modified", "ModifiedBy", "Status", "TemplateId" }, + values: new object[] { new Guid("80000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("60000000-0000-0000-0000-000000000001"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "Pending", new Guid("70000000-0000-0000-0000-000000000103") }); + + migrationBuilder.InsertData( + table: "TemplateVersions", + columns: new[] { "Id", "Created", "CreatedBy", "IsPublished", "JsonData", "JsonHash", "Modified", "ModifiedBy", "PublishedAt", "PublishedBy", "SchemaVersion", "TemplateId", "Version" }, + values: new object[,] + { + { new Guid("71000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", true, "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Environment\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Environment\",\r\n \"Name\": \"Test\"\r\n },\r\n \"parameters\": {\r\n \"Landscape\": {\r\n \"DefaultValue\": \"Prod\",\r\n \"Value\": \"Test\",\r\n \"Type\": \"string\",\r\n \"AllowedValues\": [\r\n \"Prod\",\r\n \"QA\",\r\n \"Test\"\r\n ]\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n\r\n }\r\n}", "58553C7A4E902B5E39D30272754FEF9EF805A7F36363D8316A9B37540C6D4646", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "1.0", new Guid("70000000-0000-0000-0000-000000000101"), "1.0.0" }, + { new Guid("71000000-0000-0000-0000-000000000102"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", true, "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Domain\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Domain\",\r\n \"Name\": \"Contoso\"\r\n },\r\n \"parameters\": {\r\n \"DomainFQDN\": {\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9.-]+$\",\r\n \"Type\": \"string\",\r\n \"Value\": \"contoso.local\",\r\n \"Required\": true\r\n },\r\n \"DomainLabel\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 32,\r\n \"Value\": \"Contoso\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z][A-Za-z0-9_-]*$\",\r\n \"MinLength\": 2,\r\n \"Required\": false\r\n },\r\n \"DomainNetBIOS\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 15,\r\n \"Value\": \"CONTOSO\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9_-]+$\",\r\n \"MinLength\": 1,\r\n \"Required\": true\r\n }\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"ActiveDirectory\": {\r\n \"NetBIOSName\": \"[parameters(\\u0027DomainNetBIOS\\u0027)]\",\r\n \"DomainName\": \"[parameters(\\u0027DomainFQDN\\u0027)]\"\r\n }\r\n }\r\n }\r\n }\r\n}", "B265C4D542826423BAAF50BF939F026CC67FF631FEC19F708067516BCE4C7667", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "1.0", new Guid("70000000-0000-0000-0000-000000000102"), "1.0.0" }, + { new Guid("71000000-0000-0000-0000-000000000103"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", true, "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Service\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Service\",\r\n \"Name\": \"SharePoint.Contoso\"\r\n },\r\n \"parameters\": {\r\n \"FarmCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ContentDatabaseSegment\": {\r\n \"DefaultValue\": \"Content\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Content-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint content databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"ServiceApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint service applications.\"\r\n }\r\n }\r\n },\r\n \"WebApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Web Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"DatabaseServerName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"CL-SQL-01\"\r\n },\r\n \"WebApplicationPoolDefaultAccount\": {\r\n \"DefaultValue\": \"SVC_SHP_WAP\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"ServiceDatabaseSegment\": {\r\n \"DefaultValue\": \"Services\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Service-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint service databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"FarmPassphrase\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmPassphrase\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabaseInstanceName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SQLServer\"\r\n },\r\n \"DatabaseTcpPort\": {\r\n \"DefaultValue\": 1433,\r\n \"Type\": \"int\",\r\n \"Value\": 1433\r\n },\r\n \"DefaultServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/DefaultServiceAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ProductKey\": {\r\n \"DefaultValue\": \"0000-0000-0000-0000-0000\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"SharePoint-Produktlizenzschluessel.\",\r\n \"en-US\": \"SharePoint product license key.\"\r\n }\r\n }\r\n },\r\n \"SetupCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SetupAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabasePrefix\": {\r\n \"DefaultValue\": \"SharePoint\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SharePoint\"\r\n },\r\n \"SearchServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Search-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the search application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SearchAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"CentralAdminPort\": {\r\n \"DefaultValue\": 443,\r\n \"Type\": \"int\",\r\n \"Value\": 4000\r\n },\r\n \"ServiceApplicationPoolSearch\": {\r\n \"DefaultValue\": \"SharePoint Search Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Application-Pools fuer SharePoint Search-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the application pool for SharePoint Search service applications.\"\r\n }\r\n }\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n \"AllNodes\": [\r\n {\r\n \"PSDscAllowDomainUser\": true,\r\n \"PSDSCAllowPlainTextPassword\": true,\r\n \"NodeName\": \"*\",\r\n \"RunCentralAdministration\": false\r\n }\r\n ],\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"SharePoint\": {\r\n \"Farm\": {\r\n \"ManagedAccounts\": {\r\n \"DefaultServiceApplicationPoolAccount\": \"[parameters(\\u0027DefaultServiceApplicationPoolAccount\\u0027)]\",\r\n \"FarmAccount\": \"[parameters(\\u0027FarmCredential\\u0027)]\",\r\n \"SearchServiceApplicationPoolAccount\": \"[parameters(\\u0027SearchServiceApplicationPoolAccount\\u0027)]\"\r\n },\r\n \"Passphrase\": \"[parameters(\\u0027FarmPassphrase\\u0027)]\",\r\n \"ServiceApplications\": {\r\n \"AppManagementService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027AppManagement\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"StateService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027StateService\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SubscriptionSettingsService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SubscriptionSettings\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"ManagedMetadataService\": {\r\n \"Name\": \"Managed Metadata Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027ManagedMetadata\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SearchService\": {\r\n \"Name\": \"Search Service Application\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027Search\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.SearchServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"UsageAndHealthService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027UsageAndHealth\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SecureStoreService\": {\r\n \"Name\": \"Secure Store Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SecureStore\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"AuditingEnabled\": true\r\n },\r\n \"UserProfileService\": {\r\n \"SyncDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Sync\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"Name\": \"User Profile Service\",\r\n \"SocialDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Social\\u0027)]\",\r\n \"ProfileDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Profile\\u0027)]\"\r\n }\r\n },\r\n \"CentralAdminAuth\": \"NTLM\",\r\n \"ConfigDatabaseName\": \"[variables(\\u0027ConfigDbName\\u0027)]\",\r\n \"Accounts\": {\r\n \"SetupAccount\": \"[parameters(\\u0027SetupCredential\\u0027)]\"\r\n },\r\n \"CentralAdminPort\": \"[parameters(\\u0027CentralAdminPort\\u0027)]\",\r\n \"AdminContentDatabase\": \"[variables(\\u0027AdminDbName\\u0027)]\",\r\n \"ServiceApplicationPools\": {\r\n \"SearchServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.SearchServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolSearch\\u0027)]\"\r\n },\r\n \"DefaultServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.DefaultServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolDefault\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"Database\": {\r\n \"Targets\": {\r\n \"Farm\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Content\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Service\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n }\r\n },\r\n \"SQLAlias\": {\r\n \"SQLServer\": {\r\n \"InstanceName\": \"[parameters(\\u0027DatabaseInstanceName\\u0027)]\",\r\n \"ServerName\": \"[parameters(\\u0027DatabaseServerName\\u0027)]\",\r\n \"Protocol\": \"TCP\",\r\n \"TcpPort\": \"[parameters(\\u0027DatabaseTcpPort\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"General\": {\r\n \"ProductKey\": \"[parameters(\\u0027ProductKey\\u0027)]\"\r\n },\r\n \"Windows\": {\r\n \"Registry\": {\r\n \"DisableLoopbackCheck\": {\r\n \"Path\": \"HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\",\r\n \"Name\": \"DisableLoopbackCheck\",\r\n \"Value\": 1,\r\n \"Type\": \"DWord\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}", "E3B0E2A8E0C85CCD92AEA521ECD243E61E34C61D7078D6715E6317F5669A1D69", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "1.0", new Guid("70000000-0000-0000-0000-000000000103"), "1.0.0" }, + { new Guid("71000000-0000-0000-0000-000000000104"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", true, "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Stage\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Stage\",\r\n \"Name\": \"Install\"\r\n },\r\n \"parameters\": {\r\n\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"LocalConfigurationManager\": {\r\n \"RefreshFrequencyMins\": \"30\",\r\n \"RefreshMode\": \"PUSH\",\r\n \"ConfigurationModeFrequencyMins\": \"120\",\r\n \"ConfigurationMode\": \"ApplyOnly\"\r\n }\r\n }\r\n }\r\n}", "ACA23E44C9F625F080D2653646555A9DE5546D8DE7BB2166324E775BCF47F3C1", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "1.0", new Guid("70000000-0000-0000-0000-000000000104"), "1.0.0" } + }); + + migrationBuilder.InsertData( + table: "DeploymentExecutions", + columns: new[] { "DeploymentBatchId", "TargetId", "Created", "CreatedBy", "Id", "JSONData", "Modified", "ModifiedBy", "Status" }, + values: new object[,] + { + { new Guid("80000000-0000-0000-0000-000000000101"), new Guid("30000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("81000000-0000-0000-0000-000000000101"), "{\"role\":\"Node\"}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "Pending" }, + { new Guid("80000000-0000-0000-0000-000000000101"), new Guid("30000000-0000-0000-0000-000000000102"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("81000000-0000-0000-0000-000000000102"), "{\"role\":\"Node\"}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "Pending" }, + { new Guid("80000000-0000-0000-0000-000000000101"), new Guid("30000000-0000-0000-0000-000000000103"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("81000000-0000-0000-0000-000000000103"), "{\"role\":\"Node\"}", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "Pending" } + }); + + migrationBuilder.InsertData( + table: "DeploymentTargetAssignments", + columns: new[] { "Id", "Created", "CreatedBy", "DeploymentGroupId", "Modified", "ModifiedBy", "NodeDataJson", "RoleKey", "SortOrder", "TargetId" }, + values: new object[,] + { + { new Guid("84000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("80000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "{\"nodeName\":\"CLD-SHP-01\",\"RunCentralAdministration\":true}", "Node", 10, new Guid("30000000-0000-0000-0000-000000000101") }, + { new Guid("84000000-0000-0000-0000-000000000102"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("80000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "{\"nodeName\":\"CLD-SHP-02\",\"RunCentralAdministration\":false}", "Node", 20, new Guid("30000000-0000-0000-0000-000000000102") }, + { new Guid("84000000-0000-0000-0000-000000000103"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("80000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", "{\"nodeName\":\"CLD-SHP-03\",\"RunCentralAdministration\":false}", "Node", 30, new Guid("30000000-0000-0000-0000-000000000103") } + }); + + migrationBuilder.InsertData( + table: "DeploymentTemplateSelections", + columns: new[] { "Id", "Alias", "Created", "CreatedBy", "DeploymentGroupId", "Modified", "ModifiedBy", "SortOrder", "TemplateRole", "TemplateVersionId" }, + values: new object[,] + { + { new Guid("82000000-0000-0000-0000-000000000101"), "Environment-Test", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("80000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", 10, "Environment", new Guid("71000000-0000-0000-0000-000000000101") }, + { new Guid("82000000-0000-0000-0000-000000000102"), "Domain-Contoso", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("80000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", 20, "Domain", new Guid("71000000-0000-0000-0000-000000000102") }, + { new Guid("82000000-0000-0000-0000-000000000103"), "Service-SharePoint-Contoso", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("80000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", 30, "Service", new Guid("71000000-0000-0000-0000-000000000103") }, + { new Guid("82000000-0000-0000-0000-000000000104"), "Stage-Install", new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", new Guid("80000000-0000-0000-0000-000000000101"), new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), "DemoSeed", 40, "Stage", new Guid("71000000-0000-0000-0000-000000000104") } + }); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DeleteData( + table: "DeploymentExecutions", + keyColumns: new[] { "DeploymentBatchId", "TargetId" }, + keyValues: new object[] { new Guid("80000000-0000-0000-0000-000000000101"), new Guid("30000000-0000-0000-0000-000000000101") }); + + migrationBuilder.DeleteData( + table: "DeploymentExecutions", + keyColumns: new[] { "DeploymentBatchId", "TargetId" }, + keyValues: new object[] { new Guid("80000000-0000-0000-0000-000000000101"), new Guid("30000000-0000-0000-0000-000000000102") }); + + migrationBuilder.DeleteData( + table: "DeploymentExecutions", + keyColumns: new[] { "DeploymentBatchId", "TargetId" }, + keyValues: new object[] { new Guid("80000000-0000-0000-0000-000000000101"), new Guid("30000000-0000-0000-0000-000000000103") }); + + migrationBuilder.DeleteData( + table: "DeploymentTargetAssignments", + keyColumn: "Id", + keyValue: new Guid("84000000-0000-0000-0000-000000000101")); + + migrationBuilder.DeleteData( + table: "DeploymentTargetAssignments", + keyColumn: "Id", + keyValue: new Guid("84000000-0000-0000-0000-000000000102")); + + migrationBuilder.DeleteData( + table: "DeploymentTargetAssignments", + keyColumn: "Id", + keyValue: new Guid("84000000-0000-0000-0000-000000000103")); + + migrationBuilder.DeleteData( + table: "DeploymentTemplateSelections", + keyColumn: "Id", + keyValue: new Guid("82000000-0000-0000-0000-000000000101")); + + migrationBuilder.DeleteData( + table: "DeploymentTemplateSelections", + keyColumn: "Id", + keyValue: new Guid("82000000-0000-0000-0000-000000000102")); + + migrationBuilder.DeleteData( + table: "DeploymentTemplateSelections", + keyColumn: "Id", + keyValue: new Guid("82000000-0000-0000-0000-000000000103")); + + migrationBuilder.DeleteData( + table: "DeploymentTemplateSelections", + keyColumn: "Id", + keyValue: new Guid("82000000-0000-0000-0000-000000000104")); + + migrationBuilder.DeleteData( + table: "DeploymentBatches", + keyColumn: "Id", + keyValue: new Guid("80000000-0000-0000-0000-000000000101")); + + migrationBuilder.DeleteData( + table: "Targets", + keyColumn: "Id", + keyValue: new Guid("30000000-0000-0000-0000-000000000101")); + + migrationBuilder.DeleteData( + table: "Targets", + keyColumn: "Id", + keyValue: new Guid("30000000-0000-0000-0000-000000000102")); + + migrationBuilder.DeleteData( + table: "Targets", + keyColumn: "Id", + keyValue: new Guid("30000000-0000-0000-0000-000000000103")); + + migrationBuilder.DeleteData( + table: "TemplateVersions", + keyColumn: "Id", + keyValue: new Guid("71000000-0000-0000-0000-000000000101")); + + migrationBuilder.DeleteData( + table: "TemplateVersions", + keyColumn: "Id", + keyValue: new Guid("71000000-0000-0000-0000-000000000102")); + + migrationBuilder.DeleteData( + table: "TemplateVersions", + keyColumn: "Id", + keyValue: new Guid("71000000-0000-0000-0000-000000000103")); + + migrationBuilder.DeleteData( + table: "TemplateVersions", + keyColumn: "Id", + keyValue: new Guid("71000000-0000-0000-0000-000000000104")); + + migrationBuilder.DeleteData( + table: "Templates", + keyColumn: "Id", + keyValue: new Guid("70000000-0000-0000-0000-000000000101")); + + migrationBuilder.DeleteData( + table: "Templates", + keyColumn: "Id", + keyValue: new Guid("70000000-0000-0000-0000-000000000102")); + + migrationBuilder.DeleteData( + table: "Templates", + keyColumn: "Id", + keyValue: new Guid("70000000-0000-0000-0000-000000000103")); + + migrationBuilder.DeleteData( + table: "Templates", + keyColumn: "Id", + keyValue: new Guid("70000000-0000-0000-0000-000000000104")); + + migrationBuilder.DeleteData( + table: "TemplateCategories", + keyColumn: "Id", + keyValue: new Guid("50000000-0000-0000-0000-000000000101")); + + migrationBuilder.DeleteData( + table: "Services", + keyColumn: "Id", + keyValue: new Guid("40000000-0000-0000-0000-000000000101")); + } + } +} diff --git a/Migrations/DataContextModelSnapshot.cs b/Migrations/DataContextModelSnapshot.cs index 5aa041f..beb6808 100644 --- a/Migrations/DataContextModelSnapshot.cs +++ b/Migrations/DataContextModelSnapshot.cs @@ -86,6 +86,17 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations ModifiedBy = "DemoSeed", Status = "Pending", TemplateId = new Guid("70000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("80000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending", + TemplateId = new Guid("70000000-0000-0000-0000-000000000103") }); }); @@ -168,6 +179,42 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), ModifiedBy = "DemoSeed", Status = "Pending" + }, + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000101"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000101"), + JSONData = "{\"role\":\"Node\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" + }, + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000102"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000102"), + JSONData = "{\"role\":\"Node\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" + }, + new + { + TargetId = new Guid("30000000-0000-0000-0000-000000000103"), + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Id = new Guid("81000000-0000-0000-0000-000000000103"), + JSONData = "{\"role\":\"Node\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Status = "Pending" }); }); @@ -533,6 +580,45 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations RoleKey = "Application", SortOrder = 20, TargetId = new Guid("30000000-0000-0000-0000-000000000005") + }, + new + { + Id = new Guid("84000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CLD-SHP-01\",\"RunCentralAdministration\":true}", + RoleKey = "Node", + SortOrder = 10, + TargetId = new Guid("30000000-0000-0000-0000-000000000101") + }, + new + { + Id = new Guid("84000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CLD-SHP-02\",\"RunCentralAdministration\":false}", + RoleKey = "Node", + SortOrder = 20, + TargetId = new Guid("30000000-0000-0000-0000-000000000102") + }, + new + { + Id = new Guid("84000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + NodeDataJson = "{\"nodeName\":\"CLD-SHP-03\",\"RunCentralAdministration\":false}", + RoleKey = "Node", + SortOrder = 30, + TargetId = new Guid("30000000-0000-0000-0000-000000000103") }); }); @@ -609,6 +695,58 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations SortOrder = 10, TemplateRole = "Service", TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000003") + }, + new + { + Id = new Guid("82000000-0000-0000-0000-000000000101"), + Alias = "Environment-Test", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 10, + TemplateRole = "Environment", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000101") + }, + new + { + Id = new Guid("82000000-0000-0000-0000-000000000102"), + Alias = "Domain-Contoso", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 20, + TemplateRole = "Domain", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000102") + }, + new + { + Id = new Guid("82000000-0000-0000-0000-000000000103"), + Alias = "Service-SharePoint-Contoso", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 30, + TemplateRole = "Service", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000103") + }, + new + { + Id = new Guid("82000000-0000-0000-0000-000000000104"), + Alias = "Stage-Install", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentGroupId = new Guid("80000000-0000-0000-0000-000000000101"), + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + SortOrder = 40, + TemplateRole = "Stage", + TemplateVersionId = new Guid("71000000-0000-0000-0000-000000000104") }); }); @@ -972,6 +1110,12 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations .HasColumnType("int") .HasColumnOrder(4); + b.Property("CorrelationId") + .ValueGeneratedOnAdd() + .HasColumnType("uniqueidentifier") + .HasColumnOrder(13) + .HasDefaultValueSql("NEWID()"); + b.Property("Created") .ValueGeneratedOnAdd() .HasColumnType("datetime2") @@ -991,6 +1135,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations .HasColumnType("datetime2") .HasColumnOrder(7); + b.Property("HeartbeatAt") + .HasColumnType("datetime2") + .HasColumnOrder(16); + b.Property("LockedBy") .HasColumnType("nvarchar(max)") .HasColumnOrder(9); @@ -1023,17 +1171,33 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations .HasColumnType("nvarchar(max)") .HasColumnOrder(3); + b.Property("Priority") + .ValueGeneratedOnAdd() + .HasColumnType("int") + .HasDefaultValue(100) + .HasColumnOrder(14); + + b.Property("RowVersion") + .IsConcurrencyToken() + .IsRequired() + .ValueGeneratedOnAddOrUpdate() + .HasColumnType("rowversion"); + b.Property("RuleSnapshotJson") .HasColumnType("nvarchar(max)") .HasColumnOrder(12); + b.Property("ScheduledAt") + .HasColumnType("datetime2") + .HasColumnOrder(15); + b.Property("Started") .HasColumnType("datetime2") .HasColumnOrder(6); b.Property("Status") .IsRequired() - .HasColumnType("nvarchar(max)") + .HasColumnType("nvarchar(450)") .HasColumnOrder(2); b.Property("Type") @@ -1041,8 +1205,18 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations .HasColumnType("nvarchar(max)") .HasColumnOrder(1); + b.Property("WorkerName") + .HasColumnType("nvarchar(450)") + .HasColumnOrder(17); + b.HasKey("Id"); + b.HasIndex("CorrelationId"); + + b.HasIndex("WorkerName"); + + b.HasIndex("Status", "ScheduledAt", "LockedUntil", "Priority", "Created"); + b.ToTable("DeploymentJobs", (string)null); }); @@ -1082,6 +1256,14 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations .HasColumnName("DependsOnDeploymentJobStepId") .HasColumnOrder(2); + b.Property("ErrorMessage") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(14); + + b.Property("Finished") + .HasColumnType("datetime2") + .HasColumnOrder(12); + b.Property("MetadataJson") .HasColumnType("nvarchar(max)") .HasColumnOrder(7); @@ -1102,6 +1284,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations .HasColumnType("nvarchar(max)") .HasColumnOrder(4); + b.Property("OutputMetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(13); + b.Property("QueueJobId") .HasColumnType("uniqueidentifier") .HasColumnName("DeploymentJobId") @@ -1111,9 +1297,13 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations .HasColumnType("int") .HasColumnOrder(3); + b.Property("Started") + .HasColumnType("datetime2") + .HasColumnOrder(11); + b.Property("Status") .IsRequired() - .HasColumnType("nvarchar(max)") + .HasColumnType("nvarchar(450)") .HasColumnOrder(6); b.Property("StepType") @@ -1125,9 +1315,12 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations b.HasIndex("DependsOnQueueJobStepId"); - b.HasIndex("QueueJobId"); + b.HasIndex("QueueJobId", "Status", "SortOrder"); - b.ToTable("DeploymentJobSteps", (string)null); + b.ToTable("DeploymentJobSteps", null, t => + { + t.HasCheckConstraint("CK_DeploymentJobSteps_OutputMetadataJson_IsJson", "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1"); + }); }); modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.QueueJobTargetModel", b => @@ -1162,6 +1355,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations .HasColumnType("nvarchar(max)") .HasColumnOrder(7); + b.Property("Finished") + .HasColumnType("datetime2") + .HasColumnOrder(9); + b.Property("Modified") .ValueGeneratedOnAdd() .HasColumnType("datetime2") @@ -1173,14 +1370,22 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations .HasColumnType("nvarchar(max)") .HasColumnOrder(51); + b.Property("OutputMetadataJson") + .HasColumnType("nvarchar(max)") + .HasColumnOrder(10); + b.Property("QueueJobId") .HasColumnType("uniqueidentifier") .HasColumnName("DeploymentJobId") .HasColumnOrder(1); + b.Property("Started") + .HasColumnType("datetime2") + .HasColumnOrder(8); + b.Property("Status") .IsRequired() - .HasColumnType("nvarchar(max)") + .HasColumnType("nvarchar(450)") .HasColumnOrder(5); b.Property("TargetId") @@ -1193,9 +1398,12 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations b.HasKey("Id"); - b.HasIndex("QueueJobId"); + b.HasIndex("QueueJobId", "Status"); - b.ToTable("DeploymentJobTargets", (string)null); + b.ToTable("DeploymentJobTargets", null, t => + { + t.HasCheckConstraint("CK_DeploymentJobTargets_OutputMetadataJson_IsJson", "[OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1"); + }); }); modelBuilder.Entity("Microsoft.SelfService.Portal.Core.API.Models.ServiceModel", b => @@ -1298,6 +1506,18 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), ModifiedBy = "DemoSeed", Name = "Microsoft Teams" + }, + new + { + Id = new Guid("40000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Reusable configuration-data template building blocks for deployment composition.", + IconKey = "braces", + IsCloudService = false, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "DSC Configuration Data" }); }); @@ -1562,6 +1782,45 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations Name = "Teams - Standard Users", ProviderType = "Microsoft365", TargetType = "PolicyScope" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CLD-SHP-01", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CLD-SHP-02", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" + }, + new + { + Id = new Guid("30000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DomainID = new Guid("20000000-0000-0000-0000-000000000001"), + MetadataJson = "{\"role\":\"SharePoint\",\"environment\":\"Test\",\"source\":\"Test.Merge.ps1\"}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "CLD-SHP-03", + ProviderType = "OnPrem", + TargetType = "VirtualMachine" }); }); @@ -1674,6 +1933,19 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations ModifiedBy = "DemoSeed", Name = "Teams Policies", ServiceId = new Guid("40000000-0000-0000-0000-000000000004") + }, + new + { + Id = new Guid("50000000-0000-0000-0000-000000000101"), + Color = "#2563EB", + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + Description = "Materialized template building blocks from the BGW Test.Merge.ps1 scenario.", + IsActive = true, + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "Test.Merge.ps1 Templates", + ServiceId = new Guid("40000000-0000-0000-0000-000000000101") }); }); @@ -1799,6 +2071,62 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations Name = "Contoso Teams Policies", TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000004"), Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Materialized Environment/Test.psd1 template from Test.Merge.ps1.", + JSONData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Environment\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Environment\",\r\n \"Name\": \"Test\"\r\n },\r\n \"parameters\": {\r\n \"Landscape\": {\r\n \"DefaultValue\": \"Prod\",\r\n \"Value\": \"Test\",\r\n \"Type\": \"string\",\r\n \"AllowedValues\": [\r\n \"Prod\",\r\n \"QA\",\r\n \"Test\"\r\n ]\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n\r\n }\r\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "BGW Environment Test", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000101"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Materialized Domain/Contoso.psd1 template from Test.Merge.ps1.", + JSONData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Domain\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Domain\",\r\n \"Name\": \"Contoso\"\r\n },\r\n \"parameters\": {\r\n \"DomainFQDN\": {\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9.-]+$\",\r\n \"Type\": \"string\",\r\n \"Value\": \"contoso.local\",\r\n \"Required\": true\r\n },\r\n \"DomainLabel\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 32,\r\n \"Value\": \"Contoso\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z][A-Za-z0-9_-]*$\",\r\n \"MinLength\": 2,\r\n \"Required\": false\r\n },\r\n \"DomainNetBIOS\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 15,\r\n \"Value\": \"CONTOSO\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9_-]+$\",\r\n \"MinLength\": 1,\r\n \"Required\": true\r\n }\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"ActiveDirectory\": {\r\n \"NetBIOSName\": \"[parameters(\\u0027DomainNetBIOS\\u0027)]\",\r\n \"DomainName\": \"[parameters(\\u0027DomainFQDN\\u0027)]\"\r\n }\r\n }\r\n }\r\n }\r\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "BGW Domain Contoso", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000101"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Materialized Service/SharePoint/Contoso.psd1 template from Test.Merge.ps1.", + JSONData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Service\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Service\",\r\n \"Name\": \"SharePoint.Contoso\"\r\n },\r\n \"parameters\": {\r\n \"FarmCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ContentDatabaseSegment\": {\r\n \"DefaultValue\": \"Content\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Content-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint content databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"ServiceApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint service applications.\"\r\n }\r\n }\r\n },\r\n \"WebApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Web Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"DatabaseServerName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"CL-SQL-01\"\r\n },\r\n \"WebApplicationPoolDefaultAccount\": {\r\n \"DefaultValue\": \"SVC_SHP_WAP\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"ServiceDatabaseSegment\": {\r\n \"DefaultValue\": \"Services\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Service-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint service databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"FarmPassphrase\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmPassphrase\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabaseInstanceName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SQLServer\"\r\n },\r\n \"DatabaseTcpPort\": {\r\n \"DefaultValue\": 1433,\r\n \"Type\": \"int\",\r\n \"Value\": 1433\r\n },\r\n \"DefaultServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/DefaultServiceAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ProductKey\": {\r\n \"DefaultValue\": \"0000-0000-0000-0000-0000\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"SharePoint-Produktlizenzschluessel.\",\r\n \"en-US\": \"SharePoint product license key.\"\r\n }\r\n }\r\n },\r\n \"SetupCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SetupAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabasePrefix\": {\r\n \"DefaultValue\": \"SharePoint\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SharePoint\"\r\n },\r\n \"SearchServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Search-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the search application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SearchAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"CentralAdminPort\": {\r\n \"DefaultValue\": 443,\r\n \"Type\": \"int\",\r\n \"Value\": 4000\r\n },\r\n \"ServiceApplicationPoolSearch\": {\r\n \"DefaultValue\": \"SharePoint Search Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Application-Pools fuer SharePoint Search-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the application pool for SharePoint Search service applications.\"\r\n }\r\n }\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n \"AllNodes\": [\r\n {\r\n \"PSDscAllowDomainUser\": true,\r\n \"PSDSCAllowPlainTextPassword\": true,\r\n \"NodeName\": \"*\",\r\n \"RunCentralAdministration\": false\r\n }\r\n ],\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"SharePoint\": {\r\n \"Farm\": {\r\n \"ManagedAccounts\": {\r\n \"DefaultServiceApplicationPoolAccount\": \"[parameters(\\u0027DefaultServiceApplicationPoolAccount\\u0027)]\",\r\n \"FarmAccount\": \"[parameters(\\u0027FarmCredential\\u0027)]\",\r\n \"SearchServiceApplicationPoolAccount\": \"[parameters(\\u0027SearchServiceApplicationPoolAccount\\u0027)]\"\r\n },\r\n \"Passphrase\": \"[parameters(\\u0027FarmPassphrase\\u0027)]\",\r\n \"ServiceApplications\": {\r\n \"AppManagementService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027AppManagement\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"StateService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027StateService\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SubscriptionSettingsService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SubscriptionSettings\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"ManagedMetadataService\": {\r\n \"Name\": \"Managed Metadata Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027ManagedMetadata\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SearchService\": {\r\n \"Name\": \"Search Service Application\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027Search\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.SearchServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"UsageAndHealthService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027UsageAndHealth\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SecureStoreService\": {\r\n \"Name\": \"Secure Store Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SecureStore\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"AuditingEnabled\": true\r\n },\r\n \"UserProfileService\": {\r\n \"SyncDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Sync\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"Name\": \"User Profile Service\",\r\n \"SocialDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Social\\u0027)]\",\r\n \"ProfileDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Profile\\u0027)]\"\r\n }\r\n },\r\n \"CentralAdminAuth\": \"NTLM\",\r\n \"ConfigDatabaseName\": \"[variables(\\u0027ConfigDbName\\u0027)]\",\r\n \"Accounts\": {\r\n \"SetupAccount\": \"[parameters(\\u0027SetupCredential\\u0027)]\"\r\n },\r\n \"CentralAdminPort\": \"[parameters(\\u0027CentralAdminPort\\u0027)]\",\r\n \"AdminContentDatabase\": \"[variables(\\u0027AdminDbName\\u0027)]\",\r\n \"ServiceApplicationPools\": {\r\n \"SearchServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.SearchServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolSearch\\u0027)]\"\r\n },\r\n \"DefaultServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.DefaultServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolDefault\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"Database\": {\r\n \"Targets\": {\r\n \"Farm\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Content\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Service\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n }\r\n },\r\n \"SQLAlias\": {\r\n \"SQLServer\": {\r\n \"InstanceName\": \"[parameters(\\u0027DatabaseInstanceName\\u0027)]\",\r\n \"ServerName\": \"[parameters(\\u0027DatabaseServerName\\u0027)]\",\r\n \"Protocol\": \"TCP\",\r\n \"TcpPort\": \"[parameters(\\u0027DatabaseTcpPort\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"General\": {\r\n \"ProductKey\": \"[parameters(\\u0027ProductKey\\u0027)]\"\r\n },\r\n \"Windows\": {\r\n \"Registry\": {\r\n \"DisableLoopbackCheck\": {\r\n \"Path\": \"HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\",\r\n \"Name\": \"DisableLoopbackCheck\",\r\n \"Value\": 1,\r\n \"Type\": \"DWord\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "BGW SharePoint Contoso", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000101"), + Version = "1.0.0" + }, + new + { + Id = new Guid("70000000-0000-0000-0000-000000000104"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + DeploymentRuleId = new Guid("60000000-0000-0000-0000-000000000001"), + Description = "Materialized Stage/Install.psd1 template from Test.Merge.ps1.", + JSONData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Stage\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Stage\",\r\n \"Name\": \"Install\"\r\n },\r\n \"parameters\": {\r\n\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"LocalConfigurationManager\": {\r\n \"RefreshFrequencyMins\": \"30\",\r\n \"RefreshMode\": \"PUSH\",\r\n \"ConfigurationModeFrequencyMins\": \"120\",\r\n \"ConfigurationMode\": \"ApplyOnly\"\r\n }\r\n }\r\n }\r\n}", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + Name = "BGW Stage Install", + TemplateCategoryId = new Guid("50000000-0000-0000-0000-000000000101"), + Version = "1.0.0" }); }); @@ -1989,6 +2317,70 @@ namespace Microsoft.SelfService.Portal.Core.API.Migrations SchemaVersion = "1.0", TemplateId = new Guid("70000000-0000-0000-0000-000000000004"), Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000101"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Environment\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Environment\",\r\n \"Name\": \"Test\"\r\n },\r\n \"parameters\": {\r\n \"Landscape\": {\r\n \"DefaultValue\": \"Prod\",\r\n \"Value\": \"Test\",\r\n \"Type\": \"string\",\r\n \"AllowedValues\": [\r\n \"Prod\",\r\n \"QA\",\r\n \"Test\"\r\n ]\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n\r\n }\r\n}", + JsonHash = "58553C7A4E902B5E39D30272754FEF9EF805A7F36363D8316A9B37540C6D4646", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000101"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000102"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Domain\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Domain\",\r\n \"Name\": \"Contoso\"\r\n },\r\n \"parameters\": {\r\n \"DomainFQDN\": {\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9.-]+$\",\r\n \"Type\": \"string\",\r\n \"Value\": \"contoso.local\",\r\n \"Required\": true\r\n },\r\n \"DomainLabel\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 32,\r\n \"Value\": \"Contoso\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z][A-Za-z0-9_-]*$\",\r\n \"MinLength\": 2,\r\n \"Required\": false\r\n },\r\n \"DomainNetBIOS\": {\r\n \"Type\": \"string\",\r\n \"MaxLength\": 15,\r\n \"Value\": \"CONTOSO\",\r\n \"DefaultValue\": \"\",\r\n \"Pattern\": \"^[A-Za-z0-9_-]+$\",\r\n \"MinLength\": 1,\r\n \"Required\": true\r\n }\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"ActiveDirectory\": {\r\n \"NetBIOSName\": \"[parameters(\\u0027DomainNetBIOS\\u0027)]\",\r\n \"DomainName\": \"[parameters(\\u0027DomainFQDN\\u0027)]\"\r\n }\r\n }\r\n }\r\n }\r\n}", + JsonHash = "B265C4D542826423BAAF50BF939F026CC67FF631FEC19F708067516BCE4C7667", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000102"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000103"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Service\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Service\",\r\n \"Name\": \"SharePoint.Contoso\"\r\n },\r\n \"parameters\": {\r\n \"FarmCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ContentDatabaseSegment\": {\r\n \"DefaultValue\": \"Content\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Content-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint content databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"ServiceApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint service applications.\"\r\n }\r\n }\r\n },\r\n \"WebApplicationPoolDefault\": {\r\n \"DefaultValue\": \"SharePoint Web Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Standard-Application-Pools fuer SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Display name of the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"DatabaseServerName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"CL-SQL-01\"\r\n },\r\n \"WebApplicationPoolDefaultAccount\": {\r\n \"DefaultValue\": \"SVC_SHP_WAP\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Webanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint web applications.\"\r\n }\r\n }\r\n },\r\n \"ServiceDatabaseSegment\": {\r\n \"DefaultValue\": \"Services\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Namenssegment fuer SharePoint-Service-Datenbanken innerhalb des Datenbanknamens.\",\r\n \"en-US\": \"Name segment used for SharePoint service databases within the database name.\"\r\n }\r\n }\r\n },\r\n \"FarmPassphrase\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/FarmPassphrase\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabaseInstanceName\": {\r\n \"DefaultValue\": \"SQL_Server\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SQLServer\"\r\n },\r\n \"DatabaseTcpPort\": {\r\n \"DefaultValue\": 1433,\r\n \"Type\": \"int\",\r\n \"Value\": 1433\r\n },\r\n \"DefaultServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Standard-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the default application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/DefaultServiceAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"ProductKey\": {\r\n \"DefaultValue\": \"0000-0000-0000-0000-0000\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"SharePoint-Produktlizenzschluessel.\",\r\n \"en-US\": \"SharePoint product license key.\"\r\n }\r\n }\r\n },\r\n \"SetupCredential\": {\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SetupAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"DatabasePrefix\": {\r\n \"DefaultValue\": \"SharePoint\",\r\n \"Type\": \"string\",\r\n \"Value\": \"SharePoint\"\r\n },\r\n \"SearchServiceApplicationPoolAccount\": {\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Kontoname fuer den Search-Application-Pool der SharePoint-Serviceanwendungen.\",\r\n \"en-US\": \"Account name used by the search application pool for SharePoint service applications.\"\r\n }\r\n },\r\n \"Sensitive\": true,\r\n \"Value\": {\r\n \"Provider\": \"SecretManagement\",\r\n \"Vault\": \"Test\",\r\n \"Name\": \"Windows/SharePoint/SearchAccount\"\r\n },\r\n \"Type\": \"credential\",\r\n \"Required\": true\r\n },\r\n \"CentralAdminPort\": {\r\n \"DefaultValue\": 443,\r\n \"Type\": \"int\",\r\n \"Value\": 4000\r\n },\r\n \"ServiceApplicationPoolSearch\": {\r\n \"DefaultValue\": \"SharePoint Search Service Applications\",\r\n \"Type\": \"string\",\r\n \"Metadata\": {\r\n \"Description\": {\r\n \"de-DE\": \"Anzeigename des Application-Pools fuer SharePoint Search-Serviceanwendungen.\",\r\n \"en-US\": \"Display name of the application pool for SharePoint Search service applications.\"\r\n }\r\n }\r\n }\r\n },\r\n \"variables\": {\r\n \"AdminDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_AdminContent\\u0027)]\",\r\n \"ContentDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ContentDatabaseSegment\\u0027))]\",\r\n \"ServiceDbPrefix\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), parameters(\\u0027ServiceDatabaseSegment\\u0027))]\",\r\n \"DatabasePrefix\": \"[joinNotEmpty(\\u0027_\\u0027, parameters(\\u0027DatabasePrefix\\u0027), parameters(\\u0027DomainLabel\\u0027), if(equals(parameters(\\u0027Landscape\\u0027), \\u0027Test\\u0027), \\u0027Test\\u0027, \\u0027\\u0027))]\",\r\n \"ConfigDbName\": \"[joinNotEmpty(\\u0027_\\u0027, variables(\\u0027DatabasePrefix\\u0027), \\u0027Farm_Config\\u0027)]\"\r\n },\r\n \"resources\": {\r\n \"AllNodes\": [\r\n {\r\n \"PSDscAllowDomainUser\": true,\r\n \"PSDSCAllowPlainTextPassword\": true,\r\n \"NodeName\": \"*\",\r\n \"RunCentralAdministration\": false\r\n }\r\n ],\r\n \"NonNodeData\": {\r\n \"Services\": {\r\n \"SharePoint\": {\r\n \"Farm\": {\r\n \"ManagedAccounts\": {\r\n \"DefaultServiceApplicationPoolAccount\": \"[parameters(\\u0027DefaultServiceApplicationPoolAccount\\u0027)]\",\r\n \"FarmAccount\": \"[parameters(\\u0027FarmCredential\\u0027)]\",\r\n \"SearchServiceApplicationPoolAccount\": \"[parameters(\\u0027SearchServiceApplicationPoolAccount\\u0027)]\"\r\n },\r\n \"Passphrase\": \"[parameters(\\u0027FarmPassphrase\\u0027)]\",\r\n \"ServiceApplications\": {\r\n \"AppManagementService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027AppManagement\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"StateService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027StateService\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SubscriptionSettingsService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SubscriptionSettings\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"ManagedMetadataService\": {\r\n \"Name\": \"Managed Metadata Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027ManagedMetadata\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SearchService\": {\r\n \"Name\": \"Search Service Application\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027Search\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.SearchServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"UsageAndHealthService\": {\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027UsageAndHealth\\u0027)]\",\r\n \"Provision\": true\r\n },\r\n \"SecureStoreService\": {\r\n \"Name\": \"Secure Store Service\",\r\n \"DatabaseName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027),\\u0027SecureStore\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"AuditingEnabled\": true\r\n },\r\n \"UserProfileService\": {\r\n \"SyncDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Sync\\u0027)]\",\r\n \"ApplicationPool\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ServiceApplicationPools.DefaultServiceApplicationPool\\u0027, \\u0027Name\\u0027)]\",\r\n \"Provision\": true,\r\n \"Name\": \"User Profile Service\",\r\n \"SocialDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Social\\u0027)]\",\r\n \"ProfileDBName\": \"[concat(variables(\\u0027ServiceDbPrefix\\u0027), \\u0027UserProfile_Profile\\u0027)]\"\r\n }\r\n },\r\n \"CentralAdminAuth\": \"NTLM\",\r\n \"ConfigDatabaseName\": \"[variables(\\u0027ConfigDbName\\u0027)]\",\r\n \"Accounts\": {\r\n \"SetupAccount\": \"[parameters(\\u0027SetupCredential\\u0027)]\"\r\n },\r\n \"CentralAdminPort\": \"[parameters(\\u0027CentralAdminPort\\u0027)]\",\r\n \"AdminContentDatabase\": \"[variables(\\u0027AdminDbName\\u0027)]\",\r\n \"ServiceApplicationPools\": {\r\n \"SearchServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.SearchServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolSearch\\u0027)]\"\r\n },\r\n \"DefaultServiceApplicationPool\": {\r\n \"Account\": \"[reference(\\u0027Resources.NonNodeData.Services.SharePoint.Farm.ManagedAccounts.DefaultServiceApplicationPoolAccount\\u0027, \\u0027UserName\\u0027)]\",\r\n \"Name\": \"[parameters(\\u0027ServiceApplicationPoolDefault\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"Database\": {\r\n \"Targets\": {\r\n \"Farm\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Content\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n },\r\n \"Service\": {\r\n \"Server\": \"SQLServer\",\r\n \"DependsOnAlias\": \"SQLServer\"\r\n }\r\n },\r\n \"SQLAlias\": {\r\n \"SQLServer\": {\r\n \"InstanceName\": \"[parameters(\\u0027DatabaseInstanceName\\u0027)]\",\r\n \"ServerName\": \"[parameters(\\u0027DatabaseServerName\\u0027)]\",\r\n \"Protocol\": \"TCP\",\r\n \"TcpPort\": \"[parameters(\\u0027DatabaseTcpPort\\u0027)]\"\r\n }\r\n }\r\n },\r\n \"General\": {\r\n \"ProductKey\": \"[parameters(\\u0027ProductKey\\u0027)]\"\r\n },\r\n \"Windows\": {\r\n \"Registry\": {\r\n \"DisableLoopbackCheck\": {\r\n \"Path\": \"HKLM:\\\\SYSTEM\\\\CurrentControlSet\\\\Control\\\\Lsa\",\r\n \"Name\": \"DisableLoopbackCheck\",\r\n \"Value\": 1,\r\n \"Type\": \"DWord\"\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n }\r\n}", + JsonHash = "E3B0E2A8E0C85CCD92AEA521ECD243E61E34C61D7078D6715E6317F5669A1D69", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000103"), + Version = "1.0.0" + }, + new + { + Id = new Guid("71000000-0000-0000-0000-000000000104"), + Created = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + CreatedBy = "DemoSeed", + IsPublished = true, + JsonData = "{\r\n \"schemaVersion\": \"1.0\",\r\n \"templateType\": \"Stage\",\r\n \"metadata\": {\r\n \"TemplateType\": \"Stage\",\r\n \"Name\": \"Install\"\r\n },\r\n \"parameters\": {\r\n\r\n },\r\n \"variables\": {\r\n\r\n },\r\n \"resources\": {\r\n \"NonNodeData\": {\r\n \"LocalConfigurationManager\": {\r\n \"RefreshFrequencyMins\": \"30\",\r\n \"RefreshMode\": \"PUSH\",\r\n \"ConfigurationModeFrequencyMins\": \"120\",\r\n \"ConfigurationMode\": \"ApplyOnly\"\r\n }\r\n }\r\n }\r\n}", + JsonHash = "ACA23E44C9F625F080D2653646555A9DE5546D8DE7BB2166324E775BCF47F3C1", + Modified = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + ModifiedBy = "DemoSeed", + PublishedAt = new DateTime(2026, 7, 7, 0, 0, 0, 0, DateTimeKind.Utc), + PublishedBy = "DemoSeed", + SchemaVersion = "1.0", + TemplateId = new Guid("70000000-0000-0000-0000-000000000104"), + Version = "1.0.0" }); }); diff --git a/Models/DeploymentJobModel.cs b/Models/DeploymentJobModel.cs index 76adaa2..d471210 100644 --- a/Models/DeploymentJobModel.cs +++ b/Models/DeploymentJobModel.cs @@ -1,5 +1,7 @@ using System.ComponentModel.DataAnnotations.Schema; +using System.ComponentModel.DataAnnotations; + namespace Microsoft.SelfService.Portal.Core.API.Models { public class QueueJobModel : BaseModel @@ -40,6 +42,24 @@ namespace Microsoft.SelfService.Portal.Core.API.Models [Column(Order = 12)] public string? RuleSnapshotJson { get; set; } + [Column(Order = 13)] + public Guid CorrelationId { get; set; } = Guid.NewGuid(); + + [Column(Order = 14)] + public int Priority { get; set; } = 100; + + [Column(Order = 15)] + public DateTime? ScheduledAt { get; set; } + + [Column(Order = 16)] + public DateTime? HeartbeatAt { get; set; } + + [Column(Order = 17)] + public string? WorkerName { get; set; } + + [Timestamp] + public byte[] RowVersion { get; set; } = []; + public ICollection Targets { get; set; } = new List(); public ICollection Steps { get; set; } = new List(); } diff --git a/Models/DeploymentJobStepModel.cs b/Models/DeploymentJobStepModel.cs index 7a698c0..c2ae893 100644 --- a/Models/DeploymentJobStepModel.cs +++ b/Models/DeploymentJobStepModel.cs @@ -34,6 +34,18 @@ namespace Microsoft.SelfService.Portal.Core.API.Models [Column(Order = 10)] public string? ApprovalComment { get; set; } + [Column(Order = 11)] + public DateTime? Started { get; set; } + + [Column(Order = 12)] + public DateTime? Finished { get; set; } + + [Column(Order = 13)] + public string? OutputMetadataJson { get; set; } + + [Column(Order = 14)] + public string? ErrorMessage { get; set; } + public QueueJobModel QueueJob { get; set; } public QueueJobStepModel? DependsOnQueueJobStep { get; set; } } diff --git a/Models/DeploymentJobTargetModel.cs b/Models/DeploymentJobTargetModel.cs index 6ab0443..960af09 100644 --- a/Models/DeploymentJobTargetModel.cs +++ b/Models/DeploymentJobTargetModel.cs @@ -25,6 +25,15 @@ namespace Microsoft.SelfService.Portal.Core.API.Models [Column(Order = 7)] public string? ErrorMessage { get; set; } + [Column(Order = 8)] + public DateTime? Started { get; set; } + + [Column(Order = 9)] + public DateTime? Finished { get; set; } + + [Column(Order = 10)] + public string? OutputMetadataJson { get; set; } + public QueueJobModel QueueJob { get; set; } } } diff --git a/Repository/DeploymentBatchRepository.cs b/Repository/DeploymentBatchRepository.cs index ee76791..42bffae 100644 --- a/Repository/DeploymentBatchRepository.cs +++ b/Repository/DeploymentBatchRepository.cs @@ -2,6 +2,7 @@ using Microsoft.SelfService.Portal.Core.API.Context; using Microsoft.SelfService.Portal.Core.API.Interfaces; using Microsoft.SelfService.Portal.Core.API.Models; +using System.Text.Json; namespace Microsoft.SelfService.Portal.Core.API.Repository { @@ -16,7 +17,12 @@ namespace Microsoft.SelfService.Portal.Core.API.Repository public ICollection GetDeploymentBatches() { - return _context.DeploymentGroups.ToList(); + return _context.DeploymentGroups + .Include(batch => batch.TemplateSelections) + .ThenInclude(selection => selection.TemplateVersion) + .ThenInclude(version => version.Template) + .Include(batch => batch.TargetAssignments) + .ToList(); } public DeploymentGroupModel? GetDeploymentBatchById(Guid id) @@ -42,16 +48,33 @@ namespace Microsoft.SelfService.Portal.Core.API.Repository deploymentBatch.Id = Guid.NewGuid(); } - var template = _context.Templates - .Include(existing => existing.TemplateCategory) - .ThenInclude(existing => existing.Service) - .FirstOrDefault(existing => existing.Id == deploymentBatch.TemplateId); + var requestedTemplateVersionId = deploymentBatch.TemplateSelections + .OrderBy(selection => selection.SortOrder) + .Select(selection => (Guid?)selection.TemplateVersionId) + .FirstOrDefault(); + + var templateVersion = requestedTemplateVersionId.HasValue + ? _context.TemplateVersions + .Include(version => version.Template) + .ThenInclude(template => template.TemplateCategory) + .ThenInclude(category => category.Service) + .FirstOrDefault(version => version.Id == requestedTemplateVersionId.Value) + : null; + + var template = templateVersion?.Template + ?? _context.Templates + .Include(existing => existing.TemplateCategory) + .ThenInclude(existing => existing.Service) + .Include(existing => existing.TemplateVersions) + .FirstOrDefault(existing => existing.Id == deploymentBatch.TemplateId); if (template == null) { return false; } + deploymentBatch.TemplateId = template.Id; + if (deploymentBatch.DeploymentRuleId.HasValue) { var ruleExists = _context.DeploymentRules.Any(existing => existing.Id == deploymentBatch.DeploymentRuleId.Value); @@ -63,6 +86,7 @@ namespace Microsoft.SelfService.Portal.Core.API.Repository var isCloudService = template.TemplateCategory.Service.IsCloudService; var selectedTargetIds = (targetIds ?? Array.Empty()) + .Concat(deploymentBatch.TargetAssignments.Select(assignment => assignment.TargetId)) .Distinct() .ToList(); @@ -86,6 +110,53 @@ namespace Microsoft.SelfService.Portal.Core.API.Repository _context.Add(deploymentBatch); + if (deploymentBatch.TemplateSelections.Count == 0) + { + templateVersion ??= template.TemplateVersions? + .OrderByDescending(version => version.IsPublished) + .ThenByDescending(version => version.PublishedAt) + .ThenByDescending(version => version.Created) + .FirstOrDefault(); + + if (templateVersion == null) + { + return false; + } + + deploymentBatch.TemplateSelections.Add(new DeploymentTemplateSelectionModel + { + Id = Guid.NewGuid(), + DeploymentGroupId = deploymentBatch.Id, + TemplateVersionId = templateVersion.Id, + TemplateRole = "Service", + SortOrder = 10, + Alias = template.Name + }); + } + + if (deploymentBatch.TargetAssignments.Count == 0) + { + var sortOrder = 10; + foreach (var targetId in selectedTargetIds) + { + var targetName = _context.Targets + .Where(target => target.Id == targetId) + .Select(target => target.Name) + .FirstOrDefault(); + + deploymentBatch.TargetAssignments.Add(new DeploymentTargetAssignmentModel + { + Id = Guid.NewGuid(), + DeploymentGroupId = deploymentBatch.Id, + TargetId = targetId, + RoleKey = "Node", + SortOrder = sortOrder, + NodeDataJson = JsonSerializer.Serialize(new { nodeName = targetName ?? targetId.ToString() }) + }); + sortOrder += 10; + } + } + if (!SaveChanges()) { return false; @@ -112,10 +183,34 @@ namespace Microsoft.SelfService.Portal.Core.API.Repository public bool DeleteDeploymentBatchById(DeploymentGroupModel deploymentBatch) { + var templateSelections = _context.DeploymentTemplateSelections + .Where(existing => existing.DeploymentGroupId == deploymentBatch.Id) + .ToList(); + var parameterValues = _context.DeploymentParameterValues + .Where(existing => existing.DeploymentGroupId == deploymentBatch.Id) + .ToList(); + var targetAssignments = _context.DeploymentTargetAssignments + .Where(existing => existing.DeploymentGroupId == deploymentBatch.Id) + .ToList(); var deployments = _context.Deployments .Where(existing => existing.DeploymentGroupId == deploymentBatch.Id) .ToList(); + if (parameterValues.Count > 0) + { + _context.DeploymentParameterValues.RemoveRange(parameterValues); + } + + if (targetAssignments.Count > 0) + { + _context.DeploymentTargetAssignments.RemoveRange(targetAssignments); + } + + if (templateSelections.Count > 0) + { + _context.DeploymentTemplateSelections.RemoveRange(templateSelections); + } + if (deployments.Count > 0) { _context.Deployments.RemoveRange(deployments); diff --git a/Services/QueueJobService.cs b/Services/QueueJobService.cs index 0fc3a4e..fe57009 100644 --- a/Services/QueueJobService.cs +++ b/Services/QueueJobService.cs @@ -37,6 +37,7 @@ namespace Microsoft.SelfService.Portal.Core.API.Services { Type = QueueJobType.TemplateJsonChanged, Status = QueueJobStatus.Pending, + CorrelationId = Guid.NewGuid(), PayloadJson = JsonSerializer.Serialize(payload), Targets = deployments.Select(deployment => new QueueJobTargetModel { @@ -66,6 +67,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Services .Include(group => group.Template) .ThenInclude(template => template.DeploymentRule) .ThenInclude(rule => rule.Steps) + .Include(group => group.TemplateSelections) + .ThenInclude(selection => selection.TemplateVersion) + .ThenInclude(version => version.Template) + .Include(group => group.TargetAssignments) .Include(group => group.DeploymentRule) .ThenInclude(rule => rule!.Steps) .FirstOrDefault(group => group.Id == deploymentGroupId); @@ -75,11 +80,23 @@ namespace Microsoft.SelfService.Portal.Core.API.Services throw new InvalidOperationException("DeploymentGroup does not exist."); } - var templateId = deploymentGroup.TemplateId; + var primaryTemplateSelection = deploymentGroup.TemplateSelections + .OrderBy(selection => selection.SortOrder) + .FirstOrDefault(); + var templateId = primaryTemplateSelection?.TemplateVersion.TemplateId ?? deploymentGroup.TemplateId; var resolvedTargetIds = targetIds .Distinct() .ToList(); + if (resolvedTargetIds.Count == 0) + { + resolvedTargetIds = deploymentGroup.TargetAssignments + .OrderBy(assignment => assignment.SortOrder) + .Select(assignment => assignment.TargetId) + .Distinct() + .ToList(); + } + if (resolvedTargetIds.Count == 0) { throw new InvalidOperationException("No target Targets provided."); @@ -133,6 +150,31 @@ namespace Microsoft.SelfService.Portal.Core.API.Services DeploymentGroupId = deploymentGroupId, TemplateId = templateId, DeploymentRuleId = resolvedRule?.Id, + TemplateSelections = deploymentGroup.TemplateSelections + .OrderBy(selection => selection.SortOrder) + .Select(selection => new + { + selection.Id, + selection.TemplateVersionId, + TemplateId = selection.TemplateVersion.TemplateId, + TemplateName = selection.TemplateVersion.Template.Name, + selection.TemplateVersion.Version, + selection.TemplateVersion.JsonHash, + selection.TemplateRole, + selection.SortOrder, + selection.Alias + }), + TargetAssignments = deploymentGroup.TargetAssignments + .OrderBy(assignment => assignment.SortOrder) + .Where(assignment => resolvedTargetIds.Contains(assignment.TargetId)) + .Select(assignment => new + { + assignment.Id, + assignment.TargetId, + assignment.RoleKey, + assignment.SortOrder, + assignment.NodeDataJson + }), TargetIds = resolvedTargetIds, JsonData = jsonData, TargetCount = resolvedTargetIds.Count, @@ -143,6 +185,7 @@ namespace Microsoft.SelfService.Portal.Core.API.Services { Type = QueueJobType.DeploymentRequested, Status = QueueJobStatus.Pending, + CorrelationId = Guid.NewGuid(), PayloadJson = JsonSerializer.Serialize(payload), RuleSnapshotJson = resolvedRule != null ? SerializeRuleSnapshot(resolvedRule) @@ -179,6 +222,8 @@ namespace Microsoft.SelfService.Portal.Core.API.Services queueJob.Finished = null; queueJob.LockedUntil = null; queueJob.LockedBy = null; + queueJob.HeartbeatAt = null; + queueJob.WorkerName = null; queueJob.Steps ??= new List(); foreach (var target in queueJob.Targets) @@ -187,6 +232,9 @@ namespace Microsoft.SelfService.Portal.Core.API.Services { target.Status = QueueJobStatus.Pending; target.ErrorMessage = null; + target.Started = null; + target.Finished = null; + target.OutputMetadataJson = null; } } foreach (var step in queueJob.Steps) @@ -200,6 +248,10 @@ namespace Microsoft.SelfService.Portal.Core.API.Services step.ApprovedAt = null; step.ApprovedBy = null; step.ApprovalComment = null; + step.Started = null; + step.Finished = null; + step.ErrorMessage = null; + step.OutputMetadataJson = null; } } @@ -224,6 +276,8 @@ namespace Microsoft.SelfService.Portal.Core.API.Services step.QueueJob.Status = QueueJobStatus.Pending; step.QueueJob.LockedUntil = null; step.QueueJob.LockedBy = null; + step.QueueJob.HeartbeatAt = null; + step.QueueJob.WorkerName = null; step.QueueJob.ErrorMessage = null; return _context.SaveChanges() > 0; @@ -248,6 +302,8 @@ namespace Microsoft.SelfService.Portal.Core.API.Services step.QueueJob.Finished = DateTime.UtcNow; step.QueueJob.LockedUntil = null; step.QueueJob.LockedBy = null; + step.QueueJob.HeartbeatAt = null; + step.QueueJob.WorkerName = null; step.QueueJob.ErrorMessage = comment ?? "Deployment step rejected."; return _context.SaveChanges() > 0; diff --git a/ToDo.md b/ToDo.md index 686a4c1..f169d3f 100644 --- a/ToDo.md +++ b/ToDo.md @@ -79,31 +79,34 @@ Status: Completed ### 6. Worker Pipeline Refactor -Status: Pending +Status: Completed -- Load deployment composition from API/database. -- Convert JSON documents to ordered PowerShell hashtables for the existing Merge/Resolve modules. -- Add a renderer abstraction: - - `PowerShellDscV2Renderer` - - `DscV3JsonRenderer` - - future cloud/action renderers -- Store generated artifacts and logs. +- Load deployment composition from API/database. Completed in Worker `DeploymentCompositionLoader`. +- Convert JSON documents to ordered PowerShell hashtables for the existing Merge/Resolve modules. Completed as `PowerShellDscV2Renderer`, which writes `ConfigurationData.psd1` with `[ordered]@{...}` output for the composed deployment document. +- Add a renderer abstraction. Completed through `IDeploymentRenderer`. + - `PowerShellDscV2Renderer`. Completed. + - `DscV3JsonRenderer`. Completed. + - future cloud/action renderers. Extension point added. +- Store generated artifacts and logs. Completed as filesystem artifacts under configurable `WorkerPipeline:ArtifactRoot`; structured logs are written through `ILogger`. +- Replace the old dry-run provisioning provider path with `DeploymentPipeline`. Completed. +- Note: actual invocation of `Merge-DSCConfigurationData` / `Resolve-DSCConfigurationData` can now be added inside the DSC v2 renderer when the worker moves from render-only to execute mode. ### 7. Queue Hardening -Status: Pending +Status: Completed -- Add worker claim/lock semantics based on `LockedBy`, `LockedUntil`, and a concurrency token. -- Add `CorrelationId`, `Priority`, `ScheduledAt`, `HeartbeatAt`, and `WorkerName`. -- Add useful indexes for pending/running jobs. -- Persist step and target output metadata. +- Add worker claim/lock semantics based on `LockedBy`, `LockedUntil`, and a concurrency token. Completed with atomic `ExecuteUpdateAsync` claim logic in the worker and SQL `rowversion` on deployment jobs. +- Add `CorrelationId`, `Priority`, `ScheduledAt`, `HeartbeatAt`, and `WorkerName`. Completed in model, DTOs, API mapping, and Web TypeScript contracts. +- Add useful indexes for pending/running jobs. Completed for queue claim lookup, worker lookup, correlation id, target status, and step status/sort order. +- Persist step and target output metadata. Completed with JSON metadata columns and SQL `ISJSON` constraints. +- Migration `20260708194227_AddQueueHardening` and SQL script `buildcheck/AddQueueHardening.sql` generated. ### 8. Web/API Migration -Status: Pending +Status: In Progress -- Update API endpoints to expose template versions and deployment composition. -- Update Web to create DeploymentGroups with multiple Deployments. +- Update API endpoints to expose template versions and deployment composition. Completed for deployment batch list/details, version-aware create, and queue payloads. +- Update Web to create DeploymentGroups with multiple Deployments. Completed for the rudimentary create flow: users select a template version, targets become target assignments, and legacy executions stay available for compatibility. - Add GUI support for sealed parameters and sealed template blocks. - Add preview mode based on `Resolve-DSCConfigurationData -SkipSecrets`. - Add promotion flow from Test to QA/Prod. @@ -139,4 +142,4 @@ Status: In Progress ## Next Step -Start work package 6 by refactoring the worker pipeline to load deployment composition from the API/database and render artifacts through a DSC v2/v3-capable abstraction. +Continue work package 8 with sealed parameter/block visibility, a backend preview endpoint, and the later promotion flow. Keep rich interactive preview UX in Step 8a. diff --git a/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.dll b/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.dll index d0571c7..8f99dd9 100644 Binary files a/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.dll and b/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.dll differ diff --git a/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.exe b/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.exe index 6292682..2e7df02 100644 Binary files a/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.exe and b/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.exe differ diff --git a/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.pdb b/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.pdb index 883d2b2..207f65e 100644 Binary files a/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.pdb and b/bin/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.pdb differ diff --git a/buildcheck/AddQueueHardening.sql b/buildcheck/AddQueueHardening.sql new file mode 100644 index 0000000..f3cca4f --- /dev/null +++ b/buildcheck/AddQueueHardening.sql @@ -0,0 +1,75 @@ +BEGIN TRANSACTION; +DROP INDEX [IX_DeploymentJobTargets_DeploymentJobId] ON [DeploymentJobTargets]; + +DROP INDEX [IX_DeploymentJobSteps_DeploymentJobId] ON [DeploymentJobSteps]; + +DECLARE @var nvarchar(max); +SELECT @var = QUOTENAME([d].[name]) +FROM [sys].[default_constraints] [d] +INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id] +WHERE ([d].[parent_object_id] = OBJECT_ID(N'[DeploymentJobTargets]') AND [c].[name] = N'Status'); +IF @var IS NOT NULL EXEC(N'ALTER TABLE [DeploymentJobTargets] DROP CONSTRAINT ' + @var + ';'); +ALTER TABLE [DeploymentJobTargets] ALTER COLUMN [Status] nvarchar(450) NOT NULL; + +ALTER TABLE [DeploymentJobTargets] ADD [Finished] datetime2 NULL; + +ALTER TABLE [DeploymentJobTargets] ADD [OutputMetadataJson] nvarchar(max) NULL; + +ALTER TABLE [DeploymentJobTargets] ADD [Started] datetime2 NULL; + +DECLARE @var1 nvarchar(max); +SELECT @var1 = QUOTENAME([d].[name]) +FROM [sys].[default_constraints] [d] +INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id] +WHERE ([d].[parent_object_id] = OBJECT_ID(N'[DeploymentJobSteps]') AND [c].[name] = N'Status'); +IF @var1 IS NOT NULL EXEC(N'ALTER TABLE [DeploymentJobSteps] DROP CONSTRAINT ' + @var1 + ';'); +ALTER TABLE [DeploymentJobSteps] ALTER COLUMN [Status] nvarchar(450) NOT NULL; + +ALTER TABLE [DeploymentJobSteps] ADD [ErrorMessage] nvarchar(max) NULL; + +ALTER TABLE [DeploymentJobSteps] ADD [Finished] datetime2 NULL; + +ALTER TABLE [DeploymentJobSteps] ADD [OutputMetadataJson] nvarchar(max) NULL; + +ALTER TABLE [DeploymentJobSteps] ADD [Started] datetime2 NULL; + +DECLARE @var2 nvarchar(max); +SELECT @var2 = QUOTENAME([d].[name]) +FROM [sys].[default_constraints] [d] +INNER JOIN [sys].[columns] [c] ON [d].[parent_column_id] = [c].[column_id] AND [d].[parent_object_id] = [c].[object_id] +WHERE ([d].[parent_object_id] = OBJECT_ID(N'[DeploymentJobs]') AND [c].[name] = N'Status'); +IF @var2 IS NOT NULL EXEC(N'ALTER TABLE [DeploymentJobs] DROP CONSTRAINT ' + @var2 + ';'); +ALTER TABLE [DeploymentJobs] ALTER COLUMN [Status] nvarchar(450) NOT NULL; + +ALTER TABLE [DeploymentJobs] ADD [CorrelationId] uniqueidentifier NOT NULL DEFAULT (NEWID()); + +ALTER TABLE [DeploymentJobs] ADD [HeartbeatAt] datetime2 NULL; + +ALTER TABLE [DeploymentJobs] ADD [Priority] int NOT NULL DEFAULT 100; + +ALTER TABLE [DeploymentJobs] ADD [RowVersion] rowversion NOT NULL; + +ALTER TABLE [DeploymentJobs] ADD [ScheduledAt] datetime2 NULL; + +ALTER TABLE [DeploymentJobs] ADD [WorkerName] nvarchar(450) NULL; + +CREATE INDEX [IX_DeploymentJobTargets_DeploymentJobId_Status] ON [DeploymentJobTargets] ([DeploymentJobId], [Status]); + +ALTER TABLE [DeploymentJobTargets] ADD CONSTRAINT [CK_DeploymentJobTargets_OutputMetadataJson_IsJson] CHECK ([OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1); + +CREATE INDEX [IX_DeploymentJobSteps_DeploymentJobId_Status_SortOrder] ON [DeploymentJobSteps] ([DeploymentJobId], [Status], [SortOrder]); + +ALTER TABLE [DeploymentJobSteps] ADD CONSTRAINT [CK_DeploymentJobSteps_OutputMetadataJson_IsJson] CHECK ([OutputMetadataJson] IS NULL OR ISJSON([OutputMetadataJson]) = 1); + +CREATE INDEX [IX_DeploymentJobs_CorrelationId] ON [DeploymentJobs] ([CorrelationId]); + +CREATE INDEX [IX_DeploymentJobs_Status_ScheduledAt_LockedUntil_Priority_Created] ON [DeploymentJobs] ([Status], [ScheduledAt], [LockedUntil], [Priority], [Created]); + +CREATE INDEX [IX_DeploymentJobs_WorkerName] ON [DeploymentJobs] ([WorkerName]); + +INSERT INTO [__EFMigrationsHistory] ([MigrationId], [ProductVersion]) +VALUES (N'20260708194227_AddQueueHardening', N'10.0.8'); + +COMMIT; +GO + diff --git a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.AssemblyInfo.cs b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.AssemblyInfo.cs index 947d873..3428e7d 100644 --- a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.AssemblyInfo.cs +++ b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.AssemblyInfo.cs @@ -14,7 +14,7 @@ using System.Reflection; [assembly: System.Reflection.AssemblyCompanyAttribute("Microsoft.SelfService.Portal.Core.API")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] -[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+bbe521b38d2b1025802798d026ddc12b40aeb367")] +[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+97238c28c911aa2649a9ef1c5e9f48522e0822cf")] [assembly: System.Reflection.AssemblyProductAttribute("Microsoft.SelfService.Portal.Core.API")] [assembly: System.Reflection.AssemblyTitleAttribute("Microsoft.SelfService.Portal.Core.API")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] diff --git a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.AssemblyInfoInputs.cache b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.AssemblyInfoInputs.cache index b2d6e26..30eb115 100644 --- a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.AssemblyInfoInputs.cache +++ b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.AssemblyInfoInputs.cache @@ -1 +1 @@ -9739c25723019e3534359faa29df80d589d4d7f81f05bc81477e616494ff1a53 +0a79ca958402e374cec625e71698edf95ebbc8aeff8ad654ecc44a7f7862c01d diff --git a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.assets.cache b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.assets.cache index 441fd82..2fbe693 100644 Binary files a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.assets.cache and b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.assets.cache differ diff --git a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.csproj.CoreCompileInputs.cache b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.csproj.CoreCompileInputs.cache index 8e58789..44ab331 100644 --- a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.csproj.CoreCompileInputs.cache +++ b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.csproj.CoreCompileInputs.cache @@ -1 +1 @@ -e6d93761138aa5e56e9aa342a1381ffc12105e136fe8753079012d465b342813 +70cb083ca1d78990e360c9946e7473dbe67844782d9253e595e598ef6042af13 diff --git a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.csproj.FileListAbsolute.txt b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.csproj.FileListAbsolute.txt index 3d9d8ef..acee90c 100644 --- a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.csproj.FileListAbsolute.txt +++ b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.csproj.FileListAbsolute.txt @@ -173,3 +173,178 @@ F:\Projekte\Coding\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\ F:\Projekte\Coding\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.pdb F:\Projekte\Coding\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.genruntimeconfig.cache F:\Projekte\Coding\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\ref\Microsoft.SelfService.Portal.Core.API.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\appsettings.Development.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\appsettings.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\buildcheck\appsettings.Development.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\buildcheck\appsettings.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\buildcheck\Microsoft.SelfService.Portal.Core.API.deps.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\buildcheck\Microsoft.SelfService.Portal.Core.API.runtimeconfig.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\buildcheck\Microsoft.SelfService.Portal.Core.API.staticwebassets.endpoints.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.staticwebassets.endpoints.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.exe +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.deps.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.runtimeconfig.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.pdb +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\AutoMapper.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Azure.Core.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Azure.Identity.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Humanizer.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.AspNetCore.Authentication.Negotiate.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.AspNetCore.JsonPatch.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.AspNetCore.Mvc.NewtonsoftJson.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.AspNetCore.OpenApi.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.Bcl.AsyncInterfaces.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.Bcl.Cryptography.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.Build.Framework.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.CodeAnalysis.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.CodeAnalysis.CSharp.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.CodeAnalysis.CSharp.Workspaces.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.CodeAnalysis.Workspaces.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.CodeAnalysis.ExternalAccess.RazorCompiler.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.CodeAnalysis.Workspaces.MSBuild.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.Data.SqlClient.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.EntityFrameworkCore.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.EntityFrameworkCore.Abstractions.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.EntityFrameworkCore.Design.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.EntityFrameworkCore.Relational.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.EntityFrameworkCore.SqlServer.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.Extensions.DependencyModel.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.Identity.Client.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.Identity.Client.Extensions.Msal.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.IdentityModel.Abstractions.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.IdentityModel.JsonWebTokens.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.IdentityModel.Logging.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.IdentityModel.Protocols.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.IdentityModel.Protocols.OpenIdConnect.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.IdentityModel.Tokens.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.OpenApi.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.SqlServer.Server.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Microsoft.VisualStudio.SolutionPersistence.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Mono.TextTemplating.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Newtonsoft.Json.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Newtonsoft.Json.Bson.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Swashbuckle.AspNetCore.Swagger.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Swashbuckle.AspNetCore.SwaggerGen.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\Swashbuckle.AspNetCore.SwaggerUI.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.ClientModel.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.CodeDom.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.Composition.AttributedModel.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.Composition.Convention.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.Composition.Hosting.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.Composition.Runtime.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.Composition.TypedParts.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.Configuration.ConfigurationManager.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.DirectoryServices.Protocols.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.IdentityModel.Tokens.Jwt.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.Memory.Data.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\System.Security.Cryptography.ProtectedData.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\cs\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\de\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\es\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\fr\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\it\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ja\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ko\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pl\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pt-BR\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ru\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\tr\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hans\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hant\Microsoft.CodeAnalysis.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\cs\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\de\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\es\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\fr\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\it\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ja\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ko\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pl\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pt-BR\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ru\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\tr\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hans\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hant\Microsoft.CodeAnalysis.CSharp.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\cs\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\de\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\es\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\fr\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\it\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ja\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ko\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pl\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pt-BR\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ru\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\tr\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hans\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hant\Microsoft.CodeAnalysis.CSharp.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\cs\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\de\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\es\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\fr\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\it\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ja\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ko\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pl\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pt-BR\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ru\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\tr\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hans\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hant\Microsoft.CodeAnalysis.Workspaces.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\cs\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\de\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\es\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\fr\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\it\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ja\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ko\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pl\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pt-BR\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ru\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\tr\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hans\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hant\Microsoft.CodeAnalysis.Workspaces.MSBuild.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\cs\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\de\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\es\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\fr\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\it\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ja\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ko\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pl\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\pt-BR\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\ru\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\tr\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hans\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\zh-Hant\Microsoft.Data.SqlClient.resources.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\runtimes\unix\lib\net9.0\Microsoft.Data.SqlClient.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\runtimes\win\lib\net9.0\Microsoft.Data.SqlClient.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\runtimes\win-arm64\native\Microsoft.Data.SqlClient.SNI.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\runtimes\win-x64\native\Microsoft.Data.SqlClient.SNI.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\runtimes\win-x86\native\Microsoft.Data.SqlClient.SNI.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\runtimes\linux\lib\net10.0\System.DirectoryServices.Protocols.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\runtimes\osx\lib\net10.0\System.DirectoryServices.Protocols.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\bin\Debug\net10.0\runtimes\win\lib\net10.0\System.DirectoryServices.Protocols.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.csproj.AssemblyReference.cache +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\rpswa.dswa.cache.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.GeneratedMSBuildEditorConfig.editorconfig +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.AssemblyInfoInputs.cache +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.AssemblyInfo.cs +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.csproj.CoreCompileInputs.cache +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.MvcApplicationPartsAssemblyInfo.cs +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.MvcApplicationPartsAssemblyInfo.cache +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\rjimswa.dswa.cache.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\rjsmrazor.dswa.cache.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\rjsmcshtml.dswa.cache.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\scopedcss\bundle\Microsoft.SelfService.Portal.Core.API.styles.css +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\staticwebassets.build.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\staticwebassets.build.json.cache +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\staticwebassets.development.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\staticwebassets.build.endpoints.json +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\swae.build.ex.cache +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsof.CC767D45.Up2Date +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\refint\Microsoft.SelfService.Portal.Core.API.dll +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.pdb +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\Microsoft.SelfService.Portal.Core.API.genruntimeconfig.cache +C:\Users\CodexSandboxOffline\.codex\.sandbox\cwd\d792b6c97b5c3243\.Net\Microsoft.SelfService.Portal.Core.API\obj\Debug\net10.0\ref\Microsoft.SelfService.Portal.Core.API.dll diff --git a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.dll b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.dll index d0571c7..8f99dd9 100644 Binary files a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.dll and b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.dll differ diff --git a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.pdb b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.pdb index 883d2b2..207f65e 100644 Binary files a/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.pdb and b/obj/Debug/net10.0/Microsoft.SelfService.Portal.Core.API.pdb differ diff --git a/obj/Debug/net10.0/apphost.exe b/obj/Debug/net10.0/apphost.exe index 6292682..2e7df02 100644 Binary files a/obj/Debug/net10.0/apphost.exe and b/obj/Debug/net10.0/apphost.exe differ diff --git a/obj/Debug/net10.0/ref/Microsoft.SelfService.Portal.Core.API.dll b/obj/Debug/net10.0/ref/Microsoft.SelfService.Portal.Core.API.dll index ea5918a..653218a 100644 Binary files a/obj/Debug/net10.0/ref/Microsoft.SelfService.Portal.Core.API.dll and b/obj/Debug/net10.0/ref/Microsoft.SelfService.Portal.Core.API.dll differ diff --git a/obj/Debug/net10.0/refint/Microsoft.SelfService.Portal.Core.API.dll b/obj/Debug/net10.0/refint/Microsoft.SelfService.Portal.Core.API.dll index ea5918a..653218a 100644 Binary files a/obj/Debug/net10.0/refint/Microsoft.SelfService.Portal.Core.API.dll and b/obj/Debug/net10.0/refint/Microsoft.SelfService.Portal.Core.API.dll differ diff --git a/obj/Debug/net10.0/rjsmcshtml.dswa.cache.json b/obj/Debug/net10.0/rjsmcshtml.dswa.cache.json index a3f2940..cb661d4 100644 --- a/obj/Debug/net10.0/rjsmcshtml.dswa.cache.json +++ b/obj/Debug/net10.0/rjsmcshtml.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"ILSx+4dCyQzML0PLL1+iAfuwi4o6nolNPq04aGa56YY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["vdtHh/zOSUzIXLsY12md/hRdo1uZ8G/3wAHBzgfEumw=","Dk3jsy\u002BHNDsFnpDAXEvqr0DE5QzMsv07/7VUXD3w9W8=","Wg33Et8yFcu2zn6Pa6EbqJ4Wd9Ylvtny/w98VI1JWIU=","KbuoQ4jDMnsw4hJVn9i6DmW2Nz5CxEDJvwwKd4TxCJk=","Z4r6\u002BGVAPN4NDXk4KvDa6997WlSoz\u002B6H0kpZ3q0V31A=","/m60RmZz2fhgc1KOpLbKpGCSUB4kqYElc3KzVbKE2lg=","m7w7W8zTzxeeZFyPitiWIFjpblzXTPJDz6o\u002BHZK7CVU=","nK\u002B04lADm1tnmhfAsICjcWCSfwvpuC/IHJsbZc3bIp4=","nUClS7oFrZLvLNwhbsqJACYqlO3yHfIMloPT65jBSog=","MwSsw1CNRND/o1//2ixHM/m9Piww\u002B7/CH7QSR759iWc=","phsbo\u002BKjgk3WcMMAvJVBJyGlWoH1MNwBGaLeIlvRGrk=","ZqdGPeUo2iPpvof5MH6FkcnChkz6C9GSzHezqBS9/10=","LGn\u002BTs2AlBPTvjNwZ7k8Aq0m3gI5AGZbn6HD/H0bR1c=","vEKhpAYE\u002BzMd3RKVoVccKQiaF5iCkNnB5t2ISTovDhk=","bsqFDF2DGBah6dbUGbY6mc5S32so0O3frTrEXrDBidk=","Bx0REq5xuplRN8RWJtDcBJ8qwVa\u002B3RprzPVh1gn2QKo=","e9YJzJs3bC5IxyaJieTq8\u002Buchd3vMMHgZR4QyapyaF4=","X8da3N3GLR2OXFzpxibmFCdKvwM0f5k2SwK3qPrrCmU=","s\u002BnzHzh6UKBOESaLQiq5UrkABYvP55C0PeG4596YAeo=","Zn4P4tCDx2xQ\u002BW4Punev1c0e14KnGEFZoaM3coU9Oyw=","2J5nW1mHMcQQ7BCXERoyT9EUT74CLIeUFBxqiEvQ0\u002B0=","lsayflr7ePSw3nn5pzsWXcSDcHCt3v\u002B8d2EXn0n3hoU=","TT9IUobP/5FnZYKfRiuNjT40XhIuJvEt38c32/FOATI=","ubM3BdmdyRAjd6pk\u002BHclJ/7Amy7akudm5A10gL1gjWw=","o3g2jNh9WOAqOF1O1J/QXxNFEs7vzSCPc7vl2W2Eg5Y=","sVmkbfD6xp4OTJU/LaUA6P/uxG65mCYXMW6xIV6MN48=","4IauJF4oeE1Noflm6hfom3iWIU96zXcG3Y4jwbQd7LI=","atk208TT1Wna3CCZSQ2EhkO2tU\u002BLB1SuqxSQs8MgUt4=","91fYA5enOmHQuf1tX9oXb2HCELocONh0MRud0V7SRpg=","rrVLzPx2cjWgcilaF2eqL44JkL6c26quM\u002B9vMiXjJgU=","AwjwFpokBzy/E/hxSPMuLUFONk4Jwn/qQXlyLDZpalw=","yzeU43IYP/wkf/R\u002BAxPtD3ObkRV\u002Bi3wCqwRcdug1nqE=","eHhaDYbCiAVjvLZ7jX6KaLVrZuB652l6WU\u002Bj097Q/KM=","pRJnsSJXRlM6YTPVxgIyzL\u002BGHSkbS31//OKkSyw\u002Ba3k=","Pd2QcrYRM6PoaZy00Ut9oSombDHplR6NcBFdU3v9x3M=","q8ajtc/4veJd5VcIVoEj1P8KpQFjKbezXZJHKsJsJ58=","H7w7IVHV1blGB66YKjJjYOqr8L4hQUAlmWdXTvMCkE0=","p7ZzL0tA6X7hgdesmkPzC\u002BMpsKyxzAYPehKHPZpUUTk=","zUW9Z3rxL6ZnerUdf0NBDKa94RJXN7z2NV6CjiD8muU=","L1v/GbPaWkITIzaEKWp3UCr607opQVx2qA6naw/L6N8=","msmngHYRHJkuXsjRP0XljcPE93hmxtRNGr5ZwTsctd4=","DELXdaQdlPtNXr\u002BrabQjiVJAeqo9LjU2xmrtahy8mKo=","rWIVl8epbka81lIcO3AKQy4w33ceOwQT2QeMk\u002B6ij98=","Hqi4yNphcLPLrj58hjCfXdWzu8dxabXZjQPFo\u002B\u002BP4JI=","ApYnA/j38MrMv4T\u002B2ADNAPT0JraxMDh8RP6i2qIPFBA=","SAL\u002BYrSupSDTm0Zz5fv7XdQz7d2NQ6jz\u002BvuJRl1wIXs=","YVvfWQtzbjO0LKeoqqyRhgkzZsbTp4DEFvRb3OoavdM=","iN1Ih97am65koTUFe0\u002BczXZBA9qF/bsq07lNVxPIJJ0=","q1OrWBqLfMRp7HP0hZCNWgfRaKA6Qw4\u002BkygV75N/G0U=","BPDzHamGTP15tIilvwiguLMJiERSBeQXUlUPf5TNJdg=","Y6VjYVU1BuBF2nL3Wo0h0KofFd\u002B/PROMNutY/HeHfG0=","HAGnG0vAUkQoVpj3KmmyWaeqGvX5raZzkTg4lgJl1EA=","SUz\u002B39TzMnrIGs4iRsMUSjY/reCZIvWEQ4L2KgOgV8U=","Ru0JjtUetcVWj/sLUi96WG8SR9BZ3o1b39SWpgI\u002BrgU=","h1qZW31sNXwbQSLK\u002Be091il6T52u1IeAaVdEFgWurU8=","YA03W6C9vGyQAnQsb5sTsrbZ57H7qdMmk4hOi6HNMlI=","nslXCM6T1fD/m3MdfqareFDcf9yuWj8yXmFfhTZIUso=","KQw13/e3x9B8wwrECqg1FJVMHuGkg4X0zzRZ1Ft//wk=","oZZ9gw8Xu0ImrWYLWisekRrt8pj70CzUEsXir3ToPUg=","vEgQrDpbnaEEqlRr9cVHvermY6Ufys56CNcGKFHqA/E=","HRo96sJdprS/DQuCohFj2Dg688/MNGGg4XselS1HlXs=","gW66luebHgv7ZGJKWOpcyg7VqZykwx\u002BNPg2fJAcN6PA=","j/lDqeyFuI4\u002BIIfYhTQTY5eXoatVII0JZ2XzFSf5eqg=","8plOue6cCDL7IYKvCOa/70ES3mKgmgwu8D/ptvCQ\u002Bp8=","mXLvrNI3BLdeGoOfgYetjU5dE6p/KFYR/I/OIdX\u002Bqd4=","ry4\u002BRYKOZclrBMw3LcqkJ6CY90OM0v1AXlw49vmkAmM=","gFwyh4HVsVXcOzYLuxSGSZVIMDd\u002BsDZc2v2LClngkcc=","ddNOamm5\u002BkCo8XARDYqMgwaRMR3rQJBH2L7RYewh3\u002B8=","vOA8raIIqshcvMSq0DQp4u\u002BrQARfVFUuoDBnY3S0AlQ=","5\u002BJCDEp2ZY7VYwhjuaiCz3EJ0PdqjDBNdnIOJqolgGs=","ppDPoYW5PkIatn38a8kFIAmq5V25R/jMgaPvLifwR4k=","XEqP4NjPk9NMApOEnFNcAiH0QEb8cE1nrlOC9uKsICk=","V8f4xVCIpB1\u002Bn7KlKv9JBE/I4O0kyj\u002BDyl17UjCww7o=","qFUjEXtXGV7LlbFqGJcMpw8DUGVbp4PSKpYwAt8t1Og=","wSqcBylLry7z72LKJlElMvLFlukX1HhbMaYXq0uODtc=","08qVljQjjo7A8HMuCI6klHx4rrZXLy4jaicEsq8KBu0=","pgivgEFvzRRcVAe\u002B7Yo6T/T\u002BLwjJPygNX1D20CTi1gU=","FP/lZPAriWn\u002Bl/31TtvzdAeiVl7d4nmNeycrrEuDeh4=","P\u002B3eTkBqrjO0umcCYpJJAmgYask4fkM9b8uCPU8tqvM=","ysE7XwKMb9OiWXdjq6MFzQZQ4bvAdj6R4LQISa9JO2c=","\u002BZ5OwDIqmznZPoMmxIkST7RqdQvCI91M2qNGQvN2fuM=","uojdN41adPpaYPwL1yTvftYF\u002BedskvUhsDru7sZsZnE=","m4d76Fdxk5seFCbzdLoTq9yORCMly7FJDnydkQDcPDo=","JpOMe7CWIFFojKrebfKGUCWVUoPoDUC4dkV8vYr\u002BzW0=","jPTiCvAZ/oi0GTmCyu8Br4O2AZ2GMkCDF6lyc5frBJA=","FQ0gyXEk/xdJ\u002B/1anr7ru\u002BP5Bg0WKIi0BZL4uVaBFuQ=","an6GQb7UdbYyEBqlE8J2XCu44C3\u002B7JBSvwizV8l0Xnw=","Bnn9gVT9BFj/en5frkJtTGjatFRNBqZdM85teDbUpp0=","mWcReXh\u002BYPUaDLQSZw7XM\u002BY9Pl1xGVFbbJc0mOWF2yA=","p2uT6mCzPrreCub3aRtRS83zXGtC47cAlswZ/fu4fSM=","hjPncBEzLcq\u002BWwL5r\u002B3buoSjr9CSlpMUaRHZQrh1A6U=","SS44288xoupJ92CceY5EYJTmnRGWJ4mtS/y40lQ1QTc=","dB91N/2kOPdxGh3PIlTgJMTtGNSOvNXtFjFQxn8CHiM=","Ip551/U2XR5bZznmjPDii0SCmaZ67u5rT0oDIYCY5ls=","gz47MkvqbZWcBshLKJeuvyoCslvtnoIucpRiHSFEPyk=","Y483Ph7YAAsbUMAOs15d6MowtryAUV3VC4OLKnEVNkE=","BGoo0OiISiJcp\u002BI8Yp5EEUqtC7N81D\u002BfSSwhPC\u002BJ9eY=","N/0XqSsgY55UQHWxqE/I9G/8SxjO\u002BASHdq2KkEVgqLY=","KkQYAPrIxSqhg68zAXCkBZMVhbwsZ\u002BuD0TT4/luUV8M=","veKHkWTx4AH6DaLc7p0gEYvNhgRn23vfUwXOkbV/pf4=","hW8fxvmRC0qpBORpoge2/xEHDo6aLP49\u002BRr8D0Qk3XY=","cwwZhswCN7GbS0MGN47WoKwXiYAFUxygIFL/LizK1Q4=","SjWBohOw85bhkuZUG3XzckEjFPLur2\u002BKfJu3oNF4ZXM=","jipY0QNqoS5cixuUHAuKCmkYxXd\u002B/78PxgYZ9fRKBoE=","T4NMN4f00LjL/5m8u\u002BbCum2w5poqUbG0uj\u002BRO3yc07g=","Y2yO7FFoGIfVYwiUcj0J6j0swZ4qDr\u002BZtDz/Q7WzO7w=","rOhByTY1VZvcXCH2sUGtVss0XIEKfTXurCcVhZI\u002BiUU=","lxihuOX1rC0Ql5h4wUTkfQRh8NpjXgZOTRjBysv66h4=","VAW5s9v7eXp8T8/6284wCvrvCd2NdJDrUydZ5GpoB7g=","qmoVxo3esH9E0GquZyxZP\u002B9Spb9m2m1V53m05p5uPpg=","F7sA7swBgNhttpyXMWvIHSrRFqD0HjlcHq30PiYy1q4=","1V8cNUwsg1BiMf6GpO2VNLiZxwxOcIhRtq/saTloTqk=","jngCSqdr/xgbb4VbX5HmJyHyrfF0GrSnrpIjb7Ckd00=","d5hPvNpdZ20OoM0Cwl0MJhFRB5I/nPLNz82TWig6f/k=","iXqQj8kc8tEMWZmhfOJyJut0KQYyj5d0uAnmKghuHrw=","dlTcgFLe8qXysiFvIpDEZuCHuRqxpPgddzVkLnwQicI=","fS2iYNE9SA4uHphzAtEsUUFXepDFypQ0Ril3t2Hoh7g=","AT/blW2cJbt\u002BfiWcPQMQpJcqNFXQa0bGfP\u002BHUM1kL54=","ok7QFVhd70t4isjrHEelH\u002B1BY37AmWP7qA7EAwG/PPk=","A/twxiiHrtlWaEJFuPBJKZDfXZ5wpRDT/pO3EL5LNy8=","KVtRjT33BPrAyj4Fw2fLOcuj1aJCr4dL1ZWnjDdFSlM=","Lom\u002BVziOiO42zMxUpawwZRQbcN/xSMGDWLfDNVTfpSw=","sgG04T0HMM9i\u002BMRB8valL5bR4EmYWP9HgV/bfqepo9s=","vtfx1MaXWB\u002Bv1HAAX2WzcWLv9QyvWrZJW1A2055/dk8=","kefD5EeyxCZZAcl6folD\u002B7u2rT2kkISue4CSoF6J9C4=","rYkJKsc0T2JOCQLnt8GPUYhzzfqwkRYDEAyPjkL46U8=","w/XozXUd5qMPqtMuCaBeh1k2typVlerzjJ9kb9CKybs=","uy4J0ZhwP7dH\u002Bkp68VBu/40eBGY1p7ad4CgbQ9Kvhhw=","kFRhnNu1\u002BVBeZhi\u002BF8Y4W0d1FHh8kBlTcug3Ga9\u002BoW0=","MLAMzXpxhgeI5JdySDYk9YntsypjBIa1m\u002BI/2MmMSMU=","dx/MdyE5BjPEsQU2Z75bgQQCK7PrmhwdeBJ4jfkegKs=","h\u002BAad/KYhehtlzQ96ZdFTw97viCUiaA7g1MVb\u002BNFsCE=","AwTSfROG7ZZUCPpFhIRCsFHK\u002BkwMjCFunY3243b07i0=","flOxnn1OQqD5l28M2rKBqT8rUneszl18190EqM1mVkg=","zwU3NguVcHCLFI4yiWySAvIcAiBxpjRYHMpMILogxAM=","H9aq4S97Gok0pMpudZjkv7wVKHU/sS6TyWHCnkjJOL4=","Dc2QSV4OTIajvIG6pe2qYZyVJ1WQcPHrPtN9TcDgQmo=","uO0sQpKDo5uH09SM7VjYLUUat0BWOsxli2jsuGZghD8=","D585tyD233J9UwRzFkysWiZxetSuSyji1M\u002B6X\u002Bn0mzc=","T3eYdQDumwCK/5WCqaDU4D/Ez\u002BPrtf\u002BjuR1HykqL4Ho=","2NYAwrCF\u002BjeLZHpnDY8IQ7N1QEwz\u002BR1De5dONGP4br0=","5s8rj0rWToL6bPbCtxIRjik2YDEZmgk8gis8HgSyGR4=","rBf6sCW0rs2bzf75K884XM8fYA9orFDutH5H2XVHk2E=","UxhyMsp038jyjrGK1kB7l5WIQg\u002B3SzU0KSZqF1HCsYI=","ROUjpkACO1uAEhKqo5MlX7/DvfX3fzcn7zMBE9iosG8=","MosrLDJLpdQDPSbGd8AkXahdf0t9S0HE7HYpjXI6NdI=","y9yiw6st3Lke\u002BJLypvU7vaBcMGmfkjMdfaa3tQD\u002BnEk=","2w6nOBTN9GYt5py71xBdKchbrkf5YHk9phehe21wtag=","Vq852Ou648JNjTWzdEWMkX4u/CbYNxyP0Vl/kiXxsS0=","AfrBCqpUzJhv2AEB9nAy9r0\u002BnL9K7lB/a8Aud1Gv5sc=","7EkZdAkTmxzGjykK9c\u002BpEib9PgGeDo1s/jVxK65M1P8=","2bFEVHPiWcCWya9reNO\u002BAqncAW3WERS6JmnxU3BOZYo=","CGX\u002B1NvbvxNidkOH8fkujNvTV6egIwWvwy6ZDGStCj8=","H/E7DPwTV93r9rdZNCAHQjnNSTt9yJr5fZzu6lQhWAA=","9ptxttHrSWr8PrMBiCQF1TBSXzsBJCLSlf13kBKKSdg=","ldBX\u002B6Xl3NqSX/SRvpRuaKQi3SzjOWSajitoKvfsrNQ=","rxOidqyfVnu8y9OvBYwDM8gVZ3\u002BIEsKkbJzECHplLsk=","QMLTZhagzDwrj1b/P5MTYqmUJU\u002Bq6cc7kaQWBB1KBYk=","YrxhWdrWFiLi3I/JU7BS0uBBdx6k7icRsEGHy8FsqJY=","Un9Nk3yrPgQHFRoXy5jLTJ7R7mYAyX2GeSrtCIqXC5E=","flFnk3fYwEdbwRmYL\u002B06cYqoQFaRNzZ\u002B9NORBgPlFHw=","bDQSIh/\u002BHKU/QTxM1ElrhOG6x8shfui/6WM3uWqaE6E=","MfaPbAIS9u6sTP2Adk\u002BW\u002BFd80F9BfuxNr35q1UPN2cQ=","rhOnnZ3n30PtdoMQFgkLTVqGnw7hMZyp/CitqWiX4S4=","J5mPx5xTFH1wy7CX2FCv39V2\u002BiNX7Hq9rNV9GkpT45Q="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"ILSx+4dCyQzML0PLL1+iAfuwi4o6nolNPq04aGa56YY=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["vdtHh/zOSUzIXLsY12md/hRdo1uZ8G/3wAHBzgfEumw=","Dk3jsy\u002BHNDsFnpDAXEvqr0DE5QzMsv07/7VUXD3w9W8=","Wg33Et8yFcu2zn6Pa6EbqJ4Wd9Ylvtny/w98VI1JWIU=","KbuoQ4jDMnsw4hJVn9i6DmW2Nz5CxEDJvwwKd4TxCJk=","Z4r6\u002BGVAPN4NDXk4KvDa6997WlSoz\u002B6H0kpZ3q0V31A=","/m60RmZz2fhgc1KOpLbKpGCSUB4kqYElc3KzVbKE2lg=","m7w7W8zTzxeeZFyPitiWIFjpblzXTPJDz6o\u002BHZK7CVU=","Ie9kuFo83tlUBDINdDK764XgS1i7i9dtORDj/DVsZD4=","nK\u002B04lADm1tnmhfAsICjcWCSfwvpuC/IHJsbZc3bIp4=","nUClS7oFrZLvLNwhbsqJACYqlO3yHfIMloPT65jBSog=","EgWxQBdTA0fzRSPmRpirqMbuoWo0\u002BguYR5f0okTsBJQ=","MwSsw1CNRND/o1//2ixHM/m9Piww\u002B7/CH7QSR759iWc=","phsbo\u002BKjgk3WcMMAvJVBJyGlWoH1MNwBGaLeIlvRGrk=","ZqdGPeUo2iPpvof5MH6FkcnChkz6C9GSzHezqBS9/10=","LGn\u002BTs2AlBPTvjNwZ7k8Aq0m3gI5AGZbn6HD/H0bR1c=","vEKhpAYE\u002BzMd3RKVoVccKQiaF5iCkNnB5t2ISTovDhk=","bsqFDF2DGBah6dbUGbY6mc5S32so0O3frTrEXrDBidk=","Bx0REq5xuplRN8RWJtDcBJ8qwVa\u002B3RprzPVh1gn2QKo=","e9YJzJs3bC5IxyaJieTq8\u002Buchd3vMMHgZR4QyapyaF4=","X8da3N3GLR2OXFzpxibmFCdKvwM0f5k2SwK3qPrrCmU=","s\u002BnzHzh6UKBOESaLQiq5UrkABYvP55C0PeG4596YAeo=","Zn4P4tCDx2xQ\u002BW4Punev1c0e14KnGEFZoaM3coU9Oyw=","2J5nW1mHMcQQ7BCXERoyT9EUT74CLIeUFBxqiEvQ0\u002B0=","lsayflr7ePSw3nn5pzsWXcSDcHCt3v\u002B8d2EXn0n3hoU=","TT9IUobP/5FnZYKfRiuNjT40XhIuJvEt38c32/FOATI=","ubM3BdmdyRAjd6pk\u002BHclJ/7Amy7akudm5A10gL1gjWw=","o3g2jNh9WOAqOF1O1J/QXxNFEs7vzSCPc7vl2W2Eg5Y=","sVmkbfD6xp4OTJU/LaUA6P/uxG65mCYXMW6xIV6MN48=","4IauJF4oeE1Noflm6hfom3iWIU96zXcG3Y4jwbQd7LI=","atk208TT1Wna3CCZSQ2EhkO2tU\u002BLB1SuqxSQs8MgUt4=","91fYA5enOmHQuf1tX9oXb2HCELocONh0MRud0V7SRpg=","rrVLzPx2cjWgcilaF2eqL44JkL6c26quM\u002B9vMiXjJgU=","AwjwFpokBzy/E/hxSPMuLUFONk4Jwn/qQXlyLDZpalw=","yzeU43IYP/wkf/R\u002BAxPtD3ObkRV\u002Bi3wCqwRcdug1nqE=","eHhaDYbCiAVjvLZ7jX6KaLVrZuB652l6WU\u002Bj097Q/KM=","pRJnsSJXRlM6YTPVxgIyzL\u002BGHSkbS31//OKkSyw\u002Ba3k=","Pd2QcrYRM6PoaZy00Ut9oSombDHplR6NcBFdU3v9x3M=","q8ajtc/4veJd5VcIVoEj1P8KpQFjKbezXZJHKsJsJ58=","H7w7IVHV1blGB66YKjJjYOqr8L4hQUAlmWdXTvMCkE0=","p7ZzL0tA6X7hgdesmkPzC\u002BMpsKyxzAYPehKHPZpUUTk=","zUW9Z3rxL6ZnerUdf0NBDKa94RJXN7z2NV6CjiD8muU=","L1v/GbPaWkITIzaEKWp3UCr607opQVx2qA6naw/L6N8=","msmngHYRHJkuXsjRP0XljcPE93hmxtRNGr5ZwTsctd4=","DELXdaQdlPtNXr\u002BrabQjiVJAeqo9LjU2xmrtahy8mKo=","rWIVl8epbka81lIcO3AKQy4w33ceOwQT2QeMk\u002B6ij98=","Hqi4yNphcLPLrj58hjCfXdWzu8dxabXZjQPFo\u002B\u002BP4JI=","ApYnA/j38MrMv4T\u002B2ADNAPT0JraxMDh8RP6i2qIPFBA=","SAL\u002BYrSupSDTm0Zz5fv7XdQz7d2NQ6jz\u002BvuJRl1wIXs=","YVvfWQtzbjO0LKeoqqyRhgkzZsbTp4DEFvRb3OoavdM=","iN1Ih97am65koTUFe0\u002BczXZBA9qF/bsq07lNVxPIJJ0=","q1OrWBqLfMRp7HP0hZCNWgfRaKA6Qw4\u002BkygV75N/G0U=","BPDzHamGTP15tIilvwiguLMJiERSBeQXUlUPf5TNJdg=","Y6VjYVU1BuBF2nL3Wo0h0KofFd\u002B/PROMNutY/HeHfG0=","HAGnG0vAUkQoVpj3KmmyWaeqGvX5raZzkTg4lgJl1EA=","SUz\u002B39TzMnrIGs4iRsMUSjY/reCZIvWEQ4L2KgOgV8U=","Ru0JjtUetcVWj/sLUi96WG8SR9BZ3o1b39SWpgI\u002BrgU=","h1qZW31sNXwbQSLK\u002Be091il6T52u1IeAaVdEFgWurU8=","YA03W6C9vGyQAnQsb5sTsrbZ57H7qdMmk4hOi6HNMlI=","nslXCM6T1fD/m3MdfqareFDcf9yuWj8yXmFfhTZIUso=","KQw13/e3x9B8wwrECqg1FJVMHuGkg4X0zzRZ1Ft//wk=","oZZ9gw8Xu0ImrWYLWisekRrt8pj70CzUEsXir3ToPUg=","vEgQrDpbnaEEqlRr9cVHvermY6Ufys56CNcGKFHqA/E=","HRo96sJdprS/DQuCohFj2Dg688/MNGGg4XselS1HlXs=","gW66luebHgv7ZGJKWOpcyg7VqZykwx\u002BNPg2fJAcN6PA=","j/lDqeyFuI4\u002BIIfYhTQTY5eXoatVII0JZ2XzFSf5eqg=","8plOue6cCDL7IYKvCOa/70ES3mKgmgwu8D/ptvCQ\u002Bp8=","mXLvrNI3BLdeGoOfgYetjU5dE6p/KFYR/I/OIdX\u002Bqd4=","ry4\u002BRYKOZclrBMw3LcqkJ6CY90OM0v1AXlw49vmkAmM=","gFwyh4HVsVXcOzYLuxSGSZVIMDd\u002BsDZc2v2LClngkcc=","ddNOamm5\u002BkCo8XARDYqMgwaRMR3rQJBH2L7RYewh3\u002B8=","vOA8raIIqshcvMSq0DQp4u\u002BrQARfVFUuoDBnY3S0AlQ=","5\u002BJCDEp2ZY7VYwhjuaiCz3EJ0PdqjDBNdnIOJqolgGs=","ppDPoYW5PkIatn38a8kFIAmq5V25R/jMgaPvLifwR4k=","XEqP4NjPk9NMApOEnFNcAiH0QEb8cE1nrlOC9uKsICk=","V8f4xVCIpB1\u002Bn7KlKv9JBE/I4O0kyj\u002BDyl17UjCww7o=","qFUjEXtXGV7LlbFqGJcMpw8DUGVbp4PSKpYwAt8t1Og=","wSqcBylLry7z72LKJlElMvLFlukX1HhbMaYXq0uODtc=","08qVljQjjo7A8HMuCI6klHx4rrZXLy4jaicEsq8KBu0=","pgivgEFvzRRcVAe\u002B7Yo6T/T\u002BLwjJPygNX1D20CTi1gU=","FP/lZPAriWn\u002Bl/31TtvzdAeiVl7d4nmNeycrrEuDeh4=","P\u002B3eTkBqrjO0umcCYpJJAmgYask4fkM9b8uCPU8tqvM=","ysE7XwKMb9OiWXdjq6MFzQZQ4bvAdj6R4LQISa9JO2c=","\u002BZ5OwDIqmznZPoMmxIkST7RqdQvCI91M2qNGQvN2fuM=","uojdN41adPpaYPwL1yTvftYF\u002BedskvUhsDru7sZsZnE=","m4d76Fdxk5seFCbzdLoTq9yORCMly7FJDnydkQDcPDo=","JpOMe7CWIFFojKrebfKGUCWVUoPoDUC4dkV8vYr\u002BzW0=","jPTiCvAZ/oi0GTmCyu8Br4O2AZ2GMkCDF6lyc5frBJA=","FQ0gyXEk/xdJ\u002B/1anr7ru\u002BP5Bg0WKIi0BZL4uVaBFuQ=","an6GQb7UdbYyEBqlE8J2XCu44C3\u002B7JBSvwizV8l0Xnw=","Bnn9gVT9BFj/en5frkJtTGjatFRNBqZdM85teDbUpp0=","mWcReXh\u002BYPUaDLQSZw7XM\u002BY9Pl1xGVFbbJc0mOWF2yA=","p2uT6mCzPrreCub3aRtRS83zXGtC47cAlswZ/fu4fSM=","hjPncBEzLcq\u002BWwL5r\u002B3buoSjr9CSlpMUaRHZQrh1A6U=","SS44288xoupJ92CceY5EYJTmnRGWJ4mtS/y40lQ1QTc=","dB91N/2kOPdxGh3PIlTgJMTtGNSOvNXtFjFQxn8CHiM=","Ip551/U2XR5bZznmjPDii0SCmaZ67u5rT0oDIYCY5ls=","gz47MkvqbZWcBshLKJeuvyoCslvtnoIucpRiHSFEPyk=","Y483Ph7YAAsbUMAOs15d6MowtryAUV3VC4OLKnEVNkE=","BGoo0OiISiJcp\u002BI8Yp5EEUqtC7N81D\u002BfSSwhPC\u002BJ9eY=","N/0XqSsgY55UQHWxqE/I9G/8SxjO\u002BASHdq2KkEVgqLY=","KkQYAPrIxSqhg68zAXCkBZMVhbwsZ\u002BuD0TT4/luUV8M=","veKHkWTx4AH6DaLc7p0gEYvNhgRn23vfUwXOkbV/pf4=","hW8fxvmRC0qpBORpoge2/xEHDo6aLP49\u002BRr8D0Qk3XY=","cwwZhswCN7GbS0MGN47WoKwXiYAFUxygIFL/LizK1Q4=","SjWBohOw85bhkuZUG3XzckEjFPLur2\u002BKfJu3oNF4ZXM=","jipY0QNqoS5cixuUHAuKCmkYxXd\u002B/78PxgYZ9fRKBoE=","T4NMN4f00LjL/5m8u\u002BbCum2w5poqUbG0uj\u002BRO3yc07g=","Y2yO7FFoGIfVYwiUcj0J6j0swZ4qDr\u002BZtDz/Q7WzO7w=","rOhByTY1VZvcXCH2sUGtVss0XIEKfTXurCcVhZI\u002BiUU=","lxihuOX1rC0Ql5h4wUTkfQRh8NpjXgZOTRjBysv66h4=","VAW5s9v7eXp8T8/6284wCvrvCd2NdJDrUydZ5GpoB7g=","qmoVxo3esH9E0GquZyxZP\u002B9Spb9m2m1V53m05p5uPpg=","F7sA7swBgNhttpyXMWvIHSrRFqD0HjlcHq30PiYy1q4=","1V8cNUwsg1BiMf6GpO2VNLiZxwxOcIhRtq/saTloTqk=","jngCSqdr/xgbb4VbX5HmJyHyrfF0GrSnrpIjb7Ckd00=","d5hPvNpdZ20OoM0Cwl0MJhFRB5I/nPLNz82TWig6f/k=","iXqQj8kc8tEMWZmhfOJyJut0KQYyj5d0uAnmKghuHrw=","dlTcgFLe8qXysiFvIpDEZuCHuRqxpPgddzVkLnwQicI=","fS2iYNE9SA4uHphzAtEsUUFXepDFypQ0Ril3t2Hoh7g=","AT/blW2cJbt\u002BfiWcPQMQpJcqNFXQa0bGfP\u002BHUM1kL54=","ok7QFVhd70t4isjrHEelH\u002B1BY37AmWP7qA7EAwG/PPk=","A/twxiiHrtlWaEJFuPBJKZDfXZ5wpRDT/pO3EL5LNy8=","KVtRjT33BPrAyj4Fw2fLOcuj1aJCr4dL1ZWnjDdFSlM=","Lom\u002BVziOiO42zMxUpawwZRQbcN/xSMGDWLfDNVTfpSw=","sgG04T0HMM9i\u002BMRB8valL5bR4EmYWP9HgV/bfqepo9s=","vtfx1MaXWB\u002Bv1HAAX2WzcWLv9QyvWrZJW1A2055/dk8=","kefD5EeyxCZZAcl6folD\u002B7u2rT2kkISue4CSoF6J9C4=","rYkJKsc0T2JOCQLnt8GPUYhzzfqwkRYDEAyPjkL46U8=","w/XozXUd5qMPqtMuCaBeh1k2typVlerzjJ9kb9CKybs=","uy4J0ZhwP7dH\u002Bkp68VBu/40eBGY1p7ad4CgbQ9Kvhhw=","kFRhnNu1\u002BVBeZhi\u002BF8Y4W0d1FHh8kBlTcug3Ga9\u002BoW0=","MLAMzXpxhgeI5JdySDYk9YntsypjBIa1m\u002BI/2MmMSMU=","dx/MdyE5BjPEsQU2Z75bgQQCK7PrmhwdeBJ4jfkegKs=","h\u002BAad/KYhehtlzQ96ZdFTw97viCUiaA7g1MVb\u002BNFsCE=","AwTSfROG7ZZUCPpFhIRCsFHK\u002BkwMjCFunY3243b07i0=","flOxnn1OQqD5l28M2rKBqT8rUneszl18190EqM1mVkg=","zwU3NguVcHCLFI4yiWySAvIcAiBxpjRYHMpMILogxAM=","H9aq4S97Gok0pMpudZjkv7wVKHU/sS6TyWHCnkjJOL4=","Dc2QSV4OTIajvIG6pe2qYZyVJ1WQcPHrPtN9TcDgQmo=","uO0sQpKDo5uH09SM7VjYLUUat0BWOsxli2jsuGZghD8=","D585tyD233J9UwRzFkysWiZxetSuSyji1M\u002B6X\u002Bn0mzc=","T3eYdQDumwCK/5WCqaDU4D/Ez\u002BPrtf\u002BjuR1HykqL4Ho=","2NYAwrCF\u002BjeLZHpnDY8IQ7N1QEwz\u002BR1De5dONGP4br0=","5s8rj0rWToL6bPbCtxIRjik2YDEZmgk8gis8HgSyGR4=","rBf6sCW0rs2bzf75K884XM8fYA9orFDutH5H2XVHk2E=","UxhyMsp038jyjrGK1kB7l5WIQg\u002B3SzU0KSZqF1HCsYI=","ROUjpkACO1uAEhKqo5MlX7/DvfX3fzcn7zMBE9iosG8=","MosrLDJLpdQDPSbGd8AkXahdf0t9S0HE7HYpjXI6NdI=","y9yiw6st3Lke\u002BJLypvU7vaBcMGmfkjMdfaa3tQD\u002BnEk=","2w6nOBTN9GYt5py71xBdKchbrkf5YHk9phehe21wtag=","Vq852Ou648JNjTWzdEWMkX4u/CbYNxyP0Vl/kiXxsS0=","AfrBCqpUzJhv2AEB9nAy9r0\u002BnL9K7lB/a8Aud1Gv5sc=","7EkZdAkTmxzGjykK9c\u002BpEib9PgGeDo1s/jVxK65M1P8=","2bFEVHPiWcCWya9reNO\u002BAqncAW3WERS6JmnxU3BOZYo=","CGX\u002B1NvbvxNidkOH8fkujNvTV6egIwWvwy6ZDGStCj8=","H/E7DPwTV93r9rdZNCAHQjnNSTt9yJr5fZzu6lQhWAA=","9ptxttHrSWr8PrMBiCQF1TBSXzsBJCLSlf13kBKKSdg=","ldBX\u002B6Xl3NqSX/SRvpRuaKQi3SzjOWSajitoKvfsrNQ=","0\u002BZCxUEb6T\u002Bqpmdn04jbsqUO3hGjGyg5xV01hil/Vw0=","rxOidqyfVnu8y9OvBYwDM8gVZ3\u002BIEsKkbJzECHplLsk=","QMLTZhagzDwrj1b/P5MTYqmUJU\u002Bq6cc7kaQWBB1KBYk=","ArTeer7381mAujYhdWMEqLiURdBhO9OaK4zfC7IcwJk=","Un9Nk3yrPgQHFRoXy5jLTJ7R7mYAyX2GeSrtCIqXC5E=","flFnk3fYwEdbwRmYL\u002B06cYqoQFaRNzZ\u002B9NORBgPlFHw=","bDQSIh/\u002BHKU/QTxM1ElrhOG6x8shfui/6WM3uWqaE6E=","MfaPbAIS9u6sTP2Adk\u002BW\u002BFd80F9BfuxNr35q1UPN2cQ=","rhOnnZ3n30PtdoMQFgkLTVqGnw7hMZyp/CitqWiX4S4=","XfBm9o70GbcIH\u002BJSiav82vAh2CR1Ta5\u002BvWAHzAhtyBk="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/obj/Debug/net10.0/rjsmrazor.dswa.cache.json b/obj/Debug/net10.0/rjsmrazor.dswa.cache.json index 63e1a34..6445ac9 100644 --- a/obj/Debug/net10.0/rjsmrazor.dswa.cache.json +++ b/obj/Debug/net10.0/rjsmrazor.dswa.cache.json @@ -1 +1 @@ -{"GlobalPropertiesHash":"oEWZHnagBW83RxQSHOHII+WmGDIpscet4eQQc08gJ10=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["vdtHh/zOSUzIXLsY12md/hRdo1uZ8G/3wAHBzgfEumw=","Dk3jsy\u002BHNDsFnpDAXEvqr0DE5QzMsv07/7VUXD3w9W8=","Wg33Et8yFcu2zn6Pa6EbqJ4Wd9Ylvtny/w98VI1JWIU=","KbuoQ4jDMnsw4hJVn9i6DmW2Nz5CxEDJvwwKd4TxCJk=","Z4r6\u002BGVAPN4NDXk4KvDa6997WlSoz\u002B6H0kpZ3q0V31A=","/m60RmZz2fhgc1KOpLbKpGCSUB4kqYElc3KzVbKE2lg=","m7w7W8zTzxeeZFyPitiWIFjpblzXTPJDz6o\u002BHZK7CVU=","nK\u002B04lADm1tnmhfAsICjcWCSfwvpuC/IHJsbZc3bIp4=","nUClS7oFrZLvLNwhbsqJACYqlO3yHfIMloPT65jBSog=","MwSsw1CNRND/o1//2ixHM/m9Piww\u002B7/CH7QSR759iWc=","phsbo\u002BKjgk3WcMMAvJVBJyGlWoH1MNwBGaLeIlvRGrk=","ZqdGPeUo2iPpvof5MH6FkcnChkz6C9GSzHezqBS9/10=","LGn\u002BTs2AlBPTvjNwZ7k8Aq0m3gI5AGZbn6HD/H0bR1c=","vEKhpAYE\u002BzMd3RKVoVccKQiaF5iCkNnB5t2ISTovDhk=","bsqFDF2DGBah6dbUGbY6mc5S32so0O3frTrEXrDBidk=","Bx0REq5xuplRN8RWJtDcBJ8qwVa\u002B3RprzPVh1gn2QKo=","e9YJzJs3bC5IxyaJieTq8\u002Buchd3vMMHgZR4QyapyaF4=","X8da3N3GLR2OXFzpxibmFCdKvwM0f5k2SwK3qPrrCmU=","s\u002BnzHzh6UKBOESaLQiq5UrkABYvP55C0PeG4596YAeo=","Zn4P4tCDx2xQ\u002BW4Punev1c0e14KnGEFZoaM3coU9Oyw=","2J5nW1mHMcQQ7BCXERoyT9EUT74CLIeUFBxqiEvQ0\u002B0=","lsayflr7ePSw3nn5pzsWXcSDcHCt3v\u002B8d2EXn0n3hoU=","TT9IUobP/5FnZYKfRiuNjT40XhIuJvEt38c32/FOATI=","ubM3BdmdyRAjd6pk\u002BHclJ/7Amy7akudm5A10gL1gjWw=","o3g2jNh9WOAqOF1O1J/QXxNFEs7vzSCPc7vl2W2Eg5Y=","sVmkbfD6xp4OTJU/LaUA6P/uxG65mCYXMW6xIV6MN48=","4IauJF4oeE1Noflm6hfom3iWIU96zXcG3Y4jwbQd7LI=","atk208TT1Wna3CCZSQ2EhkO2tU\u002BLB1SuqxSQs8MgUt4=","91fYA5enOmHQuf1tX9oXb2HCELocONh0MRud0V7SRpg=","rrVLzPx2cjWgcilaF2eqL44JkL6c26quM\u002B9vMiXjJgU=","AwjwFpokBzy/E/hxSPMuLUFONk4Jwn/qQXlyLDZpalw=","yzeU43IYP/wkf/R\u002BAxPtD3ObkRV\u002Bi3wCqwRcdug1nqE=","eHhaDYbCiAVjvLZ7jX6KaLVrZuB652l6WU\u002Bj097Q/KM=","pRJnsSJXRlM6YTPVxgIyzL\u002BGHSkbS31//OKkSyw\u002Ba3k=","Pd2QcrYRM6PoaZy00Ut9oSombDHplR6NcBFdU3v9x3M=","q8ajtc/4veJd5VcIVoEj1P8KpQFjKbezXZJHKsJsJ58=","H7w7IVHV1blGB66YKjJjYOqr8L4hQUAlmWdXTvMCkE0=","p7ZzL0tA6X7hgdesmkPzC\u002BMpsKyxzAYPehKHPZpUUTk=","zUW9Z3rxL6ZnerUdf0NBDKa94RJXN7z2NV6CjiD8muU=","L1v/GbPaWkITIzaEKWp3UCr607opQVx2qA6naw/L6N8=","msmngHYRHJkuXsjRP0XljcPE93hmxtRNGr5ZwTsctd4=","DELXdaQdlPtNXr\u002BrabQjiVJAeqo9LjU2xmrtahy8mKo=","rWIVl8epbka81lIcO3AKQy4w33ceOwQT2QeMk\u002B6ij98=","Hqi4yNphcLPLrj58hjCfXdWzu8dxabXZjQPFo\u002B\u002BP4JI=","ApYnA/j38MrMv4T\u002B2ADNAPT0JraxMDh8RP6i2qIPFBA=","SAL\u002BYrSupSDTm0Zz5fv7XdQz7d2NQ6jz\u002BvuJRl1wIXs=","YVvfWQtzbjO0LKeoqqyRhgkzZsbTp4DEFvRb3OoavdM=","iN1Ih97am65koTUFe0\u002BczXZBA9qF/bsq07lNVxPIJJ0=","q1OrWBqLfMRp7HP0hZCNWgfRaKA6Qw4\u002BkygV75N/G0U=","BPDzHamGTP15tIilvwiguLMJiERSBeQXUlUPf5TNJdg=","Y6VjYVU1BuBF2nL3Wo0h0KofFd\u002B/PROMNutY/HeHfG0=","HAGnG0vAUkQoVpj3KmmyWaeqGvX5raZzkTg4lgJl1EA=","SUz\u002B39TzMnrIGs4iRsMUSjY/reCZIvWEQ4L2KgOgV8U=","Ru0JjtUetcVWj/sLUi96WG8SR9BZ3o1b39SWpgI\u002BrgU=","h1qZW31sNXwbQSLK\u002Be091il6T52u1IeAaVdEFgWurU8=","YA03W6C9vGyQAnQsb5sTsrbZ57H7qdMmk4hOi6HNMlI=","nslXCM6T1fD/m3MdfqareFDcf9yuWj8yXmFfhTZIUso=","KQw13/e3x9B8wwrECqg1FJVMHuGkg4X0zzRZ1Ft//wk=","oZZ9gw8Xu0ImrWYLWisekRrt8pj70CzUEsXir3ToPUg=","vEgQrDpbnaEEqlRr9cVHvermY6Ufys56CNcGKFHqA/E=","HRo96sJdprS/DQuCohFj2Dg688/MNGGg4XselS1HlXs=","gW66luebHgv7ZGJKWOpcyg7VqZykwx\u002BNPg2fJAcN6PA=","j/lDqeyFuI4\u002BIIfYhTQTY5eXoatVII0JZ2XzFSf5eqg=","8plOue6cCDL7IYKvCOa/70ES3mKgmgwu8D/ptvCQ\u002Bp8=","mXLvrNI3BLdeGoOfgYetjU5dE6p/KFYR/I/OIdX\u002Bqd4=","ry4\u002BRYKOZclrBMw3LcqkJ6CY90OM0v1AXlw49vmkAmM=","gFwyh4HVsVXcOzYLuxSGSZVIMDd\u002BsDZc2v2LClngkcc=","ddNOamm5\u002BkCo8XARDYqMgwaRMR3rQJBH2L7RYewh3\u002B8=","vOA8raIIqshcvMSq0DQp4u\u002BrQARfVFUuoDBnY3S0AlQ=","5\u002BJCDEp2ZY7VYwhjuaiCz3EJ0PdqjDBNdnIOJqolgGs=","ppDPoYW5PkIatn38a8kFIAmq5V25R/jMgaPvLifwR4k=","XEqP4NjPk9NMApOEnFNcAiH0QEb8cE1nrlOC9uKsICk=","V8f4xVCIpB1\u002Bn7KlKv9JBE/I4O0kyj\u002BDyl17UjCww7o=","qFUjEXtXGV7LlbFqGJcMpw8DUGVbp4PSKpYwAt8t1Og=","wSqcBylLry7z72LKJlElMvLFlukX1HhbMaYXq0uODtc=","08qVljQjjo7A8HMuCI6klHx4rrZXLy4jaicEsq8KBu0=","pgivgEFvzRRcVAe\u002B7Yo6T/T\u002BLwjJPygNX1D20CTi1gU=","FP/lZPAriWn\u002Bl/31TtvzdAeiVl7d4nmNeycrrEuDeh4=","P\u002B3eTkBqrjO0umcCYpJJAmgYask4fkM9b8uCPU8tqvM=","ysE7XwKMb9OiWXdjq6MFzQZQ4bvAdj6R4LQISa9JO2c=","\u002BZ5OwDIqmznZPoMmxIkST7RqdQvCI91M2qNGQvN2fuM=","uojdN41adPpaYPwL1yTvftYF\u002BedskvUhsDru7sZsZnE=","m4d76Fdxk5seFCbzdLoTq9yORCMly7FJDnydkQDcPDo=","JpOMe7CWIFFojKrebfKGUCWVUoPoDUC4dkV8vYr\u002BzW0=","jPTiCvAZ/oi0GTmCyu8Br4O2AZ2GMkCDF6lyc5frBJA=","FQ0gyXEk/xdJ\u002B/1anr7ru\u002BP5Bg0WKIi0BZL4uVaBFuQ=","an6GQb7UdbYyEBqlE8J2XCu44C3\u002B7JBSvwizV8l0Xnw=","Bnn9gVT9BFj/en5frkJtTGjatFRNBqZdM85teDbUpp0=","mWcReXh\u002BYPUaDLQSZw7XM\u002BY9Pl1xGVFbbJc0mOWF2yA=","p2uT6mCzPrreCub3aRtRS83zXGtC47cAlswZ/fu4fSM=","hjPncBEzLcq\u002BWwL5r\u002B3buoSjr9CSlpMUaRHZQrh1A6U=","SS44288xoupJ92CceY5EYJTmnRGWJ4mtS/y40lQ1QTc=","dB91N/2kOPdxGh3PIlTgJMTtGNSOvNXtFjFQxn8CHiM=","Ip551/U2XR5bZznmjPDii0SCmaZ67u5rT0oDIYCY5ls=","gz47MkvqbZWcBshLKJeuvyoCslvtnoIucpRiHSFEPyk=","Y483Ph7YAAsbUMAOs15d6MowtryAUV3VC4OLKnEVNkE=","BGoo0OiISiJcp\u002BI8Yp5EEUqtC7N81D\u002BfSSwhPC\u002BJ9eY=","N/0XqSsgY55UQHWxqE/I9G/8SxjO\u002BASHdq2KkEVgqLY=","KkQYAPrIxSqhg68zAXCkBZMVhbwsZ\u002BuD0TT4/luUV8M=","veKHkWTx4AH6DaLc7p0gEYvNhgRn23vfUwXOkbV/pf4=","hW8fxvmRC0qpBORpoge2/xEHDo6aLP49\u002BRr8D0Qk3XY=","cwwZhswCN7GbS0MGN47WoKwXiYAFUxygIFL/LizK1Q4=","SjWBohOw85bhkuZUG3XzckEjFPLur2\u002BKfJu3oNF4ZXM=","jipY0QNqoS5cixuUHAuKCmkYxXd\u002B/78PxgYZ9fRKBoE=","T4NMN4f00LjL/5m8u\u002BbCum2w5poqUbG0uj\u002BRO3yc07g=","Y2yO7FFoGIfVYwiUcj0J6j0swZ4qDr\u002BZtDz/Q7WzO7w=","rOhByTY1VZvcXCH2sUGtVss0XIEKfTXurCcVhZI\u002BiUU=","lxihuOX1rC0Ql5h4wUTkfQRh8NpjXgZOTRjBysv66h4=","VAW5s9v7eXp8T8/6284wCvrvCd2NdJDrUydZ5GpoB7g=","qmoVxo3esH9E0GquZyxZP\u002B9Spb9m2m1V53m05p5uPpg=","F7sA7swBgNhttpyXMWvIHSrRFqD0HjlcHq30PiYy1q4=","1V8cNUwsg1BiMf6GpO2VNLiZxwxOcIhRtq/saTloTqk=","jngCSqdr/xgbb4VbX5HmJyHyrfF0GrSnrpIjb7Ckd00=","d5hPvNpdZ20OoM0Cwl0MJhFRB5I/nPLNz82TWig6f/k=","iXqQj8kc8tEMWZmhfOJyJut0KQYyj5d0uAnmKghuHrw=","dlTcgFLe8qXysiFvIpDEZuCHuRqxpPgddzVkLnwQicI=","fS2iYNE9SA4uHphzAtEsUUFXepDFypQ0Ril3t2Hoh7g=","AT/blW2cJbt\u002BfiWcPQMQpJcqNFXQa0bGfP\u002BHUM1kL54=","ok7QFVhd70t4isjrHEelH\u002B1BY37AmWP7qA7EAwG/PPk=","A/twxiiHrtlWaEJFuPBJKZDfXZ5wpRDT/pO3EL5LNy8=","KVtRjT33BPrAyj4Fw2fLOcuj1aJCr4dL1ZWnjDdFSlM=","Lom\u002BVziOiO42zMxUpawwZRQbcN/xSMGDWLfDNVTfpSw=","sgG04T0HMM9i\u002BMRB8valL5bR4EmYWP9HgV/bfqepo9s=","vtfx1MaXWB\u002Bv1HAAX2WzcWLv9QyvWrZJW1A2055/dk8=","kefD5EeyxCZZAcl6folD\u002B7u2rT2kkISue4CSoF6J9C4=","rYkJKsc0T2JOCQLnt8GPUYhzzfqwkRYDEAyPjkL46U8=","w/XozXUd5qMPqtMuCaBeh1k2typVlerzjJ9kb9CKybs=","uy4J0ZhwP7dH\u002Bkp68VBu/40eBGY1p7ad4CgbQ9Kvhhw=","kFRhnNu1\u002BVBeZhi\u002BF8Y4W0d1FHh8kBlTcug3Ga9\u002BoW0=","MLAMzXpxhgeI5JdySDYk9YntsypjBIa1m\u002BI/2MmMSMU=","dx/MdyE5BjPEsQU2Z75bgQQCK7PrmhwdeBJ4jfkegKs=","h\u002BAad/KYhehtlzQ96ZdFTw97viCUiaA7g1MVb\u002BNFsCE=","AwTSfROG7ZZUCPpFhIRCsFHK\u002BkwMjCFunY3243b07i0=","flOxnn1OQqD5l28M2rKBqT8rUneszl18190EqM1mVkg=","zwU3NguVcHCLFI4yiWySAvIcAiBxpjRYHMpMILogxAM=","H9aq4S97Gok0pMpudZjkv7wVKHU/sS6TyWHCnkjJOL4=","Dc2QSV4OTIajvIG6pe2qYZyVJ1WQcPHrPtN9TcDgQmo=","uO0sQpKDo5uH09SM7VjYLUUat0BWOsxli2jsuGZghD8=","D585tyD233J9UwRzFkysWiZxetSuSyji1M\u002B6X\u002Bn0mzc=","T3eYdQDumwCK/5WCqaDU4D/Ez\u002BPrtf\u002BjuR1HykqL4Ho=","2NYAwrCF\u002BjeLZHpnDY8IQ7N1QEwz\u002BR1De5dONGP4br0=","5s8rj0rWToL6bPbCtxIRjik2YDEZmgk8gis8HgSyGR4=","rBf6sCW0rs2bzf75K884XM8fYA9orFDutH5H2XVHk2E=","UxhyMsp038jyjrGK1kB7l5WIQg\u002B3SzU0KSZqF1HCsYI=","ROUjpkACO1uAEhKqo5MlX7/DvfX3fzcn7zMBE9iosG8=","MosrLDJLpdQDPSbGd8AkXahdf0t9S0HE7HYpjXI6NdI=","y9yiw6st3Lke\u002BJLypvU7vaBcMGmfkjMdfaa3tQD\u002BnEk=","2w6nOBTN9GYt5py71xBdKchbrkf5YHk9phehe21wtag=","Vq852Ou648JNjTWzdEWMkX4u/CbYNxyP0Vl/kiXxsS0=","AfrBCqpUzJhv2AEB9nAy9r0\u002BnL9K7lB/a8Aud1Gv5sc=","7EkZdAkTmxzGjykK9c\u002BpEib9PgGeDo1s/jVxK65M1P8=","2bFEVHPiWcCWya9reNO\u002BAqncAW3WERS6JmnxU3BOZYo=","CGX\u002B1NvbvxNidkOH8fkujNvTV6egIwWvwy6ZDGStCj8=","H/E7DPwTV93r9rdZNCAHQjnNSTt9yJr5fZzu6lQhWAA=","9ptxttHrSWr8PrMBiCQF1TBSXzsBJCLSlf13kBKKSdg=","ldBX\u002B6Xl3NqSX/SRvpRuaKQi3SzjOWSajitoKvfsrNQ=","rxOidqyfVnu8y9OvBYwDM8gVZ3\u002BIEsKkbJzECHplLsk=","QMLTZhagzDwrj1b/P5MTYqmUJU\u002Bq6cc7kaQWBB1KBYk=","YrxhWdrWFiLi3I/JU7BS0uBBdx6k7icRsEGHy8FsqJY=","Un9Nk3yrPgQHFRoXy5jLTJ7R7mYAyX2GeSrtCIqXC5E=","flFnk3fYwEdbwRmYL\u002B06cYqoQFaRNzZ\u002B9NORBgPlFHw=","bDQSIh/\u002BHKU/QTxM1ElrhOG6x8shfui/6WM3uWqaE6E=","MfaPbAIS9u6sTP2Adk\u002BW\u002BFd80F9BfuxNr35q1UPN2cQ=","rhOnnZ3n30PtdoMQFgkLTVqGnw7hMZyp/CitqWiX4S4=","J5mPx5xTFH1wy7CX2FCv39V2\u002BiNX7Hq9rNV9GkpT45Q="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file +{"GlobalPropertiesHash":"oEWZHnagBW83RxQSHOHII+WmGDIpscet4eQQc08gJ10=","FingerprintPatternsHash":"gq3WsqcKBUGTSNle7RKKyXRIwh7M8ccEqOqYvIzoM04=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["vdtHh/zOSUzIXLsY12md/hRdo1uZ8G/3wAHBzgfEumw=","Dk3jsy\u002BHNDsFnpDAXEvqr0DE5QzMsv07/7VUXD3w9W8=","Wg33Et8yFcu2zn6Pa6EbqJ4Wd9Ylvtny/w98VI1JWIU=","KbuoQ4jDMnsw4hJVn9i6DmW2Nz5CxEDJvwwKd4TxCJk=","Z4r6\u002BGVAPN4NDXk4KvDa6997WlSoz\u002B6H0kpZ3q0V31A=","/m60RmZz2fhgc1KOpLbKpGCSUB4kqYElc3KzVbKE2lg=","m7w7W8zTzxeeZFyPitiWIFjpblzXTPJDz6o\u002BHZK7CVU=","Ie9kuFo83tlUBDINdDK764XgS1i7i9dtORDj/DVsZD4=","nK\u002B04lADm1tnmhfAsICjcWCSfwvpuC/IHJsbZc3bIp4=","nUClS7oFrZLvLNwhbsqJACYqlO3yHfIMloPT65jBSog=","EgWxQBdTA0fzRSPmRpirqMbuoWo0\u002BguYR5f0okTsBJQ=","MwSsw1CNRND/o1//2ixHM/m9Piww\u002B7/CH7QSR759iWc=","phsbo\u002BKjgk3WcMMAvJVBJyGlWoH1MNwBGaLeIlvRGrk=","ZqdGPeUo2iPpvof5MH6FkcnChkz6C9GSzHezqBS9/10=","LGn\u002BTs2AlBPTvjNwZ7k8Aq0m3gI5AGZbn6HD/H0bR1c=","vEKhpAYE\u002BzMd3RKVoVccKQiaF5iCkNnB5t2ISTovDhk=","bsqFDF2DGBah6dbUGbY6mc5S32so0O3frTrEXrDBidk=","Bx0REq5xuplRN8RWJtDcBJ8qwVa\u002B3RprzPVh1gn2QKo=","e9YJzJs3bC5IxyaJieTq8\u002Buchd3vMMHgZR4QyapyaF4=","X8da3N3GLR2OXFzpxibmFCdKvwM0f5k2SwK3qPrrCmU=","s\u002BnzHzh6UKBOESaLQiq5UrkABYvP55C0PeG4596YAeo=","Zn4P4tCDx2xQ\u002BW4Punev1c0e14KnGEFZoaM3coU9Oyw=","2J5nW1mHMcQQ7BCXERoyT9EUT74CLIeUFBxqiEvQ0\u002B0=","lsayflr7ePSw3nn5pzsWXcSDcHCt3v\u002B8d2EXn0n3hoU=","TT9IUobP/5FnZYKfRiuNjT40XhIuJvEt38c32/FOATI=","ubM3BdmdyRAjd6pk\u002BHclJ/7Amy7akudm5A10gL1gjWw=","o3g2jNh9WOAqOF1O1J/QXxNFEs7vzSCPc7vl2W2Eg5Y=","sVmkbfD6xp4OTJU/LaUA6P/uxG65mCYXMW6xIV6MN48=","4IauJF4oeE1Noflm6hfom3iWIU96zXcG3Y4jwbQd7LI=","atk208TT1Wna3CCZSQ2EhkO2tU\u002BLB1SuqxSQs8MgUt4=","91fYA5enOmHQuf1tX9oXb2HCELocONh0MRud0V7SRpg=","rrVLzPx2cjWgcilaF2eqL44JkL6c26quM\u002B9vMiXjJgU=","AwjwFpokBzy/E/hxSPMuLUFONk4Jwn/qQXlyLDZpalw=","yzeU43IYP/wkf/R\u002BAxPtD3ObkRV\u002Bi3wCqwRcdug1nqE=","eHhaDYbCiAVjvLZ7jX6KaLVrZuB652l6WU\u002Bj097Q/KM=","pRJnsSJXRlM6YTPVxgIyzL\u002BGHSkbS31//OKkSyw\u002Ba3k=","Pd2QcrYRM6PoaZy00Ut9oSombDHplR6NcBFdU3v9x3M=","q8ajtc/4veJd5VcIVoEj1P8KpQFjKbezXZJHKsJsJ58=","H7w7IVHV1blGB66YKjJjYOqr8L4hQUAlmWdXTvMCkE0=","p7ZzL0tA6X7hgdesmkPzC\u002BMpsKyxzAYPehKHPZpUUTk=","zUW9Z3rxL6ZnerUdf0NBDKa94RJXN7z2NV6CjiD8muU=","L1v/GbPaWkITIzaEKWp3UCr607opQVx2qA6naw/L6N8=","msmngHYRHJkuXsjRP0XljcPE93hmxtRNGr5ZwTsctd4=","DELXdaQdlPtNXr\u002BrabQjiVJAeqo9LjU2xmrtahy8mKo=","rWIVl8epbka81lIcO3AKQy4w33ceOwQT2QeMk\u002B6ij98=","Hqi4yNphcLPLrj58hjCfXdWzu8dxabXZjQPFo\u002B\u002BP4JI=","ApYnA/j38MrMv4T\u002B2ADNAPT0JraxMDh8RP6i2qIPFBA=","SAL\u002BYrSupSDTm0Zz5fv7XdQz7d2NQ6jz\u002BvuJRl1wIXs=","YVvfWQtzbjO0LKeoqqyRhgkzZsbTp4DEFvRb3OoavdM=","iN1Ih97am65koTUFe0\u002BczXZBA9qF/bsq07lNVxPIJJ0=","q1OrWBqLfMRp7HP0hZCNWgfRaKA6Qw4\u002BkygV75N/G0U=","BPDzHamGTP15tIilvwiguLMJiERSBeQXUlUPf5TNJdg=","Y6VjYVU1BuBF2nL3Wo0h0KofFd\u002B/PROMNutY/HeHfG0=","HAGnG0vAUkQoVpj3KmmyWaeqGvX5raZzkTg4lgJl1EA=","SUz\u002B39TzMnrIGs4iRsMUSjY/reCZIvWEQ4L2KgOgV8U=","Ru0JjtUetcVWj/sLUi96WG8SR9BZ3o1b39SWpgI\u002BrgU=","h1qZW31sNXwbQSLK\u002Be091il6T52u1IeAaVdEFgWurU8=","YA03W6C9vGyQAnQsb5sTsrbZ57H7qdMmk4hOi6HNMlI=","nslXCM6T1fD/m3MdfqareFDcf9yuWj8yXmFfhTZIUso=","KQw13/e3x9B8wwrECqg1FJVMHuGkg4X0zzRZ1Ft//wk=","oZZ9gw8Xu0ImrWYLWisekRrt8pj70CzUEsXir3ToPUg=","vEgQrDpbnaEEqlRr9cVHvermY6Ufys56CNcGKFHqA/E=","HRo96sJdprS/DQuCohFj2Dg688/MNGGg4XselS1HlXs=","gW66luebHgv7ZGJKWOpcyg7VqZykwx\u002BNPg2fJAcN6PA=","j/lDqeyFuI4\u002BIIfYhTQTY5eXoatVII0JZ2XzFSf5eqg=","8plOue6cCDL7IYKvCOa/70ES3mKgmgwu8D/ptvCQ\u002Bp8=","mXLvrNI3BLdeGoOfgYetjU5dE6p/KFYR/I/OIdX\u002Bqd4=","ry4\u002BRYKOZclrBMw3LcqkJ6CY90OM0v1AXlw49vmkAmM=","gFwyh4HVsVXcOzYLuxSGSZVIMDd\u002BsDZc2v2LClngkcc=","ddNOamm5\u002BkCo8XARDYqMgwaRMR3rQJBH2L7RYewh3\u002B8=","vOA8raIIqshcvMSq0DQp4u\u002BrQARfVFUuoDBnY3S0AlQ=","5\u002BJCDEp2ZY7VYwhjuaiCz3EJ0PdqjDBNdnIOJqolgGs=","ppDPoYW5PkIatn38a8kFIAmq5V25R/jMgaPvLifwR4k=","XEqP4NjPk9NMApOEnFNcAiH0QEb8cE1nrlOC9uKsICk=","V8f4xVCIpB1\u002Bn7KlKv9JBE/I4O0kyj\u002BDyl17UjCww7o=","qFUjEXtXGV7LlbFqGJcMpw8DUGVbp4PSKpYwAt8t1Og=","wSqcBylLry7z72LKJlElMvLFlukX1HhbMaYXq0uODtc=","08qVljQjjo7A8HMuCI6klHx4rrZXLy4jaicEsq8KBu0=","pgivgEFvzRRcVAe\u002B7Yo6T/T\u002BLwjJPygNX1D20CTi1gU=","FP/lZPAriWn\u002Bl/31TtvzdAeiVl7d4nmNeycrrEuDeh4=","P\u002B3eTkBqrjO0umcCYpJJAmgYask4fkM9b8uCPU8tqvM=","ysE7XwKMb9OiWXdjq6MFzQZQ4bvAdj6R4LQISa9JO2c=","\u002BZ5OwDIqmznZPoMmxIkST7RqdQvCI91M2qNGQvN2fuM=","uojdN41adPpaYPwL1yTvftYF\u002BedskvUhsDru7sZsZnE=","m4d76Fdxk5seFCbzdLoTq9yORCMly7FJDnydkQDcPDo=","JpOMe7CWIFFojKrebfKGUCWVUoPoDUC4dkV8vYr\u002BzW0=","jPTiCvAZ/oi0GTmCyu8Br4O2AZ2GMkCDF6lyc5frBJA=","FQ0gyXEk/xdJ\u002B/1anr7ru\u002BP5Bg0WKIi0BZL4uVaBFuQ=","an6GQb7UdbYyEBqlE8J2XCu44C3\u002B7JBSvwizV8l0Xnw=","Bnn9gVT9BFj/en5frkJtTGjatFRNBqZdM85teDbUpp0=","mWcReXh\u002BYPUaDLQSZw7XM\u002BY9Pl1xGVFbbJc0mOWF2yA=","p2uT6mCzPrreCub3aRtRS83zXGtC47cAlswZ/fu4fSM=","hjPncBEzLcq\u002BWwL5r\u002B3buoSjr9CSlpMUaRHZQrh1A6U=","SS44288xoupJ92CceY5EYJTmnRGWJ4mtS/y40lQ1QTc=","dB91N/2kOPdxGh3PIlTgJMTtGNSOvNXtFjFQxn8CHiM=","Ip551/U2XR5bZznmjPDii0SCmaZ67u5rT0oDIYCY5ls=","gz47MkvqbZWcBshLKJeuvyoCslvtnoIucpRiHSFEPyk=","Y483Ph7YAAsbUMAOs15d6MowtryAUV3VC4OLKnEVNkE=","BGoo0OiISiJcp\u002BI8Yp5EEUqtC7N81D\u002BfSSwhPC\u002BJ9eY=","N/0XqSsgY55UQHWxqE/I9G/8SxjO\u002BASHdq2KkEVgqLY=","KkQYAPrIxSqhg68zAXCkBZMVhbwsZ\u002BuD0TT4/luUV8M=","veKHkWTx4AH6DaLc7p0gEYvNhgRn23vfUwXOkbV/pf4=","hW8fxvmRC0qpBORpoge2/xEHDo6aLP49\u002BRr8D0Qk3XY=","cwwZhswCN7GbS0MGN47WoKwXiYAFUxygIFL/LizK1Q4=","SjWBohOw85bhkuZUG3XzckEjFPLur2\u002BKfJu3oNF4ZXM=","jipY0QNqoS5cixuUHAuKCmkYxXd\u002B/78PxgYZ9fRKBoE=","T4NMN4f00LjL/5m8u\u002BbCum2w5poqUbG0uj\u002BRO3yc07g=","Y2yO7FFoGIfVYwiUcj0J6j0swZ4qDr\u002BZtDz/Q7WzO7w=","rOhByTY1VZvcXCH2sUGtVss0XIEKfTXurCcVhZI\u002BiUU=","lxihuOX1rC0Ql5h4wUTkfQRh8NpjXgZOTRjBysv66h4=","VAW5s9v7eXp8T8/6284wCvrvCd2NdJDrUydZ5GpoB7g=","qmoVxo3esH9E0GquZyxZP\u002B9Spb9m2m1V53m05p5uPpg=","F7sA7swBgNhttpyXMWvIHSrRFqD0HjlcHq30PiYy1q4=","1V8cNUwsg1BiMf6GpO2VNLiZxwxOcIhRtq/saTloTqk=","jngCSqdr/xgbb4VbX5HmJyHyrfF0GrSnrpIjb7Ckd00=","d5hPvNpdZ20OoM0Cwl0MJhFRB5I/nPLNz82TWig6f/k=","iXqQj8kc8tEMWZmhfOJyJut0KQYyj5d0uAnmKghuHrw=","dlTcgFLe8qXysiFvIpDEZuCHuRqxpPgddzVkLnwQicI=","fS2iYNE9SA4uHphzAtEsUUFXepDFypQ0Ril3t2Hoh7g=","AT/blW2cJbt\u002BfiWcPQMQpJcqNFXQa0bGfP\u002BHUM1kL54=","ok7QFVhd70t4isjrHEelH\u002B1BY37AmWP7qA7EAwG/PPk=","A/twxiiHrtlWaEJFuPBJKZDfXZ5wpRDT/pO3EL5LNy8=","KVtRjT33BPrAyj4Fw2fLOcuj1aJCr4dL1ZWnjDdFSlM=","Lom\u002BVziOiO42zMxUpawwZRQbcN/xSMGDWLfDNVTfpSw=","sgG04T0HMM9i\u002BMRB8valL5bR4EmYWP9HgV/bfqepo9s=","vtfx1MaXWB\u002Bv1HAAX2WzcWLv9QyvWrZJW1A2055/dk8=","kefD5EeyxCZZAcl6folD\u002B7u2rT2kkISue4CSoF6J9C4=","rYkJKsc0T2JOCQLnt8GPUYhzzfqwkRYDEAyPjkL46U8=","w/XozXUd5qMPqtMuCaBeh1k2typVlerzjJ9kb9CKybs=","uy4J0ZhwP7dH\u002Bkp68VBu/40eBGY1p7ad4CgbQ9Kvhhw=","kFRhnNu1\u002BVBeZhi\u002BF8Y4W0d1FHh8kBlTcug3Ga9\u002BoW0=","MLAMzXpxhgeI5JdySDYk9YntsypjBIa1m\u002BI/2MmMSMU=","dx/MdyE5BjPEsQU2Z75bgQQCK7PrmhwdeBJ4jfkegKs=","h\u002BAad/KYhehtlzQ96ZdFTw97viCUiaA7g1MVb\u002BNFsCE=","AwTSfROG7ZZUCPpFhIRCsFHK\u002BkwMjCFunY3243b07i0=","flOxnn1OQqD5l28M2rKBqT8rUneszl18190EqM1mVkg=","zwU3NguVcHCLFI4yiWySAvIcAiBxpjRYHMpMILogxAM=","H9aq4S97Gok0pMpudZjkv7wVKHU/sS6TyWHCnkjJOL4=","Dc2QSV4OTIajvIG6pe2qYZyVJ1WQcPHrPtN9TcDgQmo=","uO0sQpKDo5uH09SM7VjYLUUat0BWOsxli2jsuGZghD8=","D585tyD233J9UwRzFkysWiZxetSuSyji1M\u002B6X\u002Bn0mzc=","T3eYdQDumwCK/5WCqaDU4D/Ez\u002BPrtf\u002BjuR1HykqL4Ho=","2NYAwrCF\u002BjeLZHpnDY8IQ7N1QEwz\u002BR1De5dONGP4br0=","5s8rj0rWToL6bPbCtxIRjik2YDEZmgk8gis8HgSyGR4=","rBf6sCW0rs2bzf75K884XM8fYA9orFDutH5H2XVHk2E=","UxhyMsp038jyjrGK1kB7l5WIQg\u002B3SzU0KSZqF1HCsYI=","ROUjpkACO1uAEhKqo5MlX7/DvfX3fzcn7zMBE9iosG8=","MosrLDJLpdQDPSbGd8AkXahdf0t9S0HE7HYpjXI6NdI=","y9yiw6st3Lke\u002BJLypvU7vaBcMGmfkjMdfaa3tQD\u002BnEk=","2w6nOBTN9GYt5py71xBdKchbrkf5YHk9phehe21wtag=","Vq852Ou648JNjTWzdEWMkX4u/CbYNxyP0Vl/kiXxsS0=","AfrBCqpUzJhv2AEB9nAy9r0\u002BnL9K7lB/a8Aud1Gv5sc=","7EkZdAkTmxzGjykK9c\u002BpEib9PgGeDo1s/jVxK65M1P8=","2bFEVHPiWcCWya9reNO\u002BAqncAW3WERS6JmnxU3BOZYo=","CGX\u002B1NvbvxNidkOH8fkujNvTV6egIwWvwy6ZDGStCj8=","H/E7DPwTV93r9rdZNCAHQjnNSTt9yJr5fZzu6lQhWAA=","9ptxttHrSWr8PrMBiCQF1TBSXzsBJCLSlf13kBKKSdg=","ldBX\u002B6Xl3NqSX/SRvpRuaKQi3SzjOWSajitoKvfsrNQ=","0\u002BZCxUEb6T\u002Bqpmdn04jbsqUO3hGjGyg5xV01hil/Vw0=","rxOidqyfVnu8y9OvBYwDM8gVZ3\u002BIEsKkbJzECHplLsk=","QMLTZhagzDwrj1b/P5MTYqmUJU\u002Bq6cc7kaQWBB1KBYk=","ArTeer7381mAujYhdWMEqLiURdBhO9OaK4zfC7IcwJk=","Un9Nk3yrPgQHFRoXy5jLTJ7R7mYAyX2GeSrtCIqXC5E=","flFnk3fYwEdbwRmYL\u002B06cYqoQFaRNzZ\u002B9NORBgPlFHw=","bDQSIh/\u002BHKU/QTxM1ElrhOG6x8shfui/6WM3uWqaE6E=","MfaPbAIS9u6sTP2Adk\u002BW\u002BFd80F9BfuxNr35q1UPN2cQ=","rhOnnZ3n30PtdoMQFgkLTVqGnw7hMZyp/CitqWiX4S4=","XfBm9o70GbcIH\u002BJSiav82vAh2CR1Ta5\u002BvWAHzAhtyBk="],"CachedAssets":{},"CachedCopyCandidates":{}} \ No newline at end of file diff --git a/obj/project.assets.json b/obj/project.assets.json index 97c133f..11d076b 100644 --- a/obj/project.assets.json +++ b/obj/project.assets.json @@ -4369,7 +4369,7 @@ "code": "NU1903", "level": "Warning", "warningLevel": 1, - "message": "Package 'Microsoft.OpenApi' 2.4.1 has a known high severity vulnerability, https://github.com/advisories/GHSA-v5pm-xwqc-g5wc", + "message": "Das Paket \"Microsoft.OpenApi\" 2.4.1 weist eine bekannte hoch Schweregrad-Sicherheitsanfälligkeit auf, https://github.com/advisories/GHSA-v5pm-xwqc-g5wc.", "libraryId": "Microsoft.OpenApi", "targetGraphs": [ "net10.0" diff --git a/obj/project.nuget.cache b/obj/project.nuget.cache index f774252..43ca910 100644 --- a/obj/project.nuget.cache +++ b/obj/project.nuget.cache @@ -69,7 +69,7 @@ { "code": "NU1903", "level": "Warning", - "message": "Package 'Microsoft.OpenApi' 2.4.1 has a known high severity vulnerability, https://github.com/advisories/GHSA-v5pm-xwqc-g5wc", + "message": "Das Paket \"Microsoft.OpenApi\" 2.4.1 weist eine bekannte hoch Schweregrad-Sicherheitsanfälligkeit auf, https://github.com/advisories/GHSA-v5pm-xwqc-g5wc.", "projectPath": "F:\\Projekte\\Coding\\.Net\\Microsoft.SelfService.Portal.Core.API\\Microsoft.SelfService.Portal.Core.API.csproj", "warningLevel": 1, "filePath": "F:\\Projekte\\Coding\\.Net\\Microsoft.SelfService.Portal.Core.API\\Microsoft.SelfService.Portal.Core.API.csproj",