# Runbook de instalación FourZ en Windows

Esta guía instala y verifica la plataforma FourZ. Cubre dos modalidades:

1. **Servidor único**: Gitea, Jenkins, Control Center, sitio Web, sitio WCF y Windows Services en una misma máquina.
2. **Nodos autónomos separados**: un nodo para WCF/Windows Services y otro para Web. Por decisión actual, **cada nodo tiene su propio Gitea, Jenkins y FourZ Control Center**; no hay un portal central todavía.

La guía no elimina repositorios de Azure DevOps, publicaciones existentes ni respaldos. No ejecute una acción con `-Apply` sin haber ejecutado primero el mismo comando en modo de planeación.

## 0. Ruta rápida: servidor limpio desde cero

Use este orden cuando la máquina no contiene instalaciones FourZ previas. Todos los comandos se ejecutan en PowerShell como Administrador.

1. Copie `FourZ.Deployment` completo (sin `bin` ni `obj`) a `C:\FourZ.Deployment`, incluyendo `Tools`, `Resources`, `Config`, `Jenkins` y `ServerBootstrap`.
2. Instale los prerrequisitos de IIS/Redis, Build Agent y Java; reinicie Windows.
3. Instale y configure Gitea y Jenkins. El rol `Platform` instala Java, pero Gitea y Jenkins requieren completar sus asistentes iniciales.
4. Cree el sitio IIS y publique Control Center.
5. Registre las variables de máquina y permisos mínimos del App Pool; valide el portal con `Test-ControlCenterReadiness.ps1`.
6. Cree el job `FourZ-Deployment`, registre la credencial `gitea-fourz` e importe los repositorios requeridos a Gitea.
7. Desde Control Center haga la primera liberación de Website y Services en `Production`, con **Inicializar IIS antes de liberar**. Esta es la acción que crea los sitios IIS y las carpetas `C:\inetpub\wwwroot\Production\...`.
8. Instale o actualice los Windows Services seleccionados y, por último, configure el webhook para la rama productiva.

No use `-UpdateExistingSitePaths` en un servidor limpio: no hay una ruta IIS previa que migrar.

## 1. Convenciones

| Recurso | Valor inicial |
| --- | --- |
| Directorio de automatización | `C:\FourZ.Deployment` |
| Código KidZania | `C:\Repos\KidZania_` |
| Gitea actual | `http://10.1.2.62:3000/` |
| Jenkins actual | `http://10.1.2.62:8080/` |
| Control Center | `http://10.1.2.62/` |
| Puerto Web FourZ | `20003` |
| Puerto HTTP WCF | `30003` |
| Windows Services | `C:\FourZ.Services\<Servicio>` |

Los valores de `Config\website.json`, `Config\services.json` y `Config\windows-services.json` son la fuente de verdad para rutas, App Pools y ejecutables. Revise esos archivos antes de publicar.

> Los secretos no se guardan en JSON ni en el repositorio. Use variables de entorno de máquina, el almacén de credenciales de Jenkins o el almacén de secretos aprobado.

## 2. Prerrequisitos y material de instalación

Ejecute todos los comandos de instalación desde **PowerShell como Administrador**.

1. Copie o clone `FourZ.Deployment` en `C:\FourZ.Deployment`.
2. Confirme los instaladores locales:

```powershell
Set-Location C:\FourZ.Deployment
Get-ChildItem .\Tools
```

La carpeta debe incluir, como mínimo: `Git.exe`, `nuget.exe`, `7z.exe`, `DotNetFramework48.exe`, `DotNet8HostingBundle.exe`, `VisualStudioBuildTools.exe`, `JDKJava.msi`, `Gitea.exe`, `jenkins.msi` y `Redis.msi`.

3. Antes de cualquier instalación, consulte el estado:

```powershell
.\ServerBootstrap\Scripts\Test-ServerReadiness.ps1 -Role BuildAgent
.\ServerBootstrap\Scripts\Test-ServerReadiness.ps1 -Role Platform
.\ServerBootstrap\Scripts\Test-ServerReadiness.ps1 -Role IisServer
```

## 3. Escenario A: instalación completa en una sola máquina

### 3.1 Instalar Build Agent

Este rol instala/verifica Git, NuGet, MSBuild y Web Build Tools. Es necesario para compilar desde Jenkins.

```powershell
.\ServerBootstrap\Scripts\Install-ServerPrerequisites.ps1 -Role BuildAgent -Apply
.\ServerBootstrap\Scripts\Test-ServerReadiness.ps1 -Role BuildAgent
```

El resultado debe mostrar `Healthy` para .NET Framework, PowerShell, Git, NuGet y MSBuild/Web Build Tools.

### 3.2 Instalar Java para Jenkins

El rol `Platform` usa `Tools\JDKJava.msi`. El instalador actual es Eclipse Temurin JDK 21 y el bootstrap configura `JAVA_HOME` y `PATH`.

```powershell
.\ServerBootstrap\Scripts\Install-ServerPrerequisites.ps1 -Role Platform -Apply
java -version
$env:JAVA_HOME
```

Verifique después:

```powershell
.\ServerBootstrap\Scripts\Test-ServerReadiness.ps1 -Role Platform
```

Java, Gitea y Jenkins deben aparecer como `Healthy`. Si el instalador solicita reinicio o devuelve `3010`, reinicie Windows antes de continuar.

### 3.2.1 Instalar y verificar Redis

Redis es un prerrequisito local de los nodos que alojan FourZ Web o WCF. El bootstrap toma `Tools\Redis.msi`, instala el servicio `Redis` cuando falta y lo inicia. Redis queda limitado a `127.0.0.1:6379`; no abra ese puerto hacia la red sin una necesidad y controles explícitos.

```powershell
Set-Location C:\FourZ.Deployment
.\ServerBootstrap\Scripts\Install-ServerPrerequisites.ps1 -Role IisServer -Apply
.\ServerBootstrap\Scripts\Test-ServerReadiness.ps1 -Role IisServer
Get-Service Redis
netstat -ano | findstr :6379
```

El resultado esperado es `Redis = Running` y `127.0.0.1:6379 = LISTENING`. En Control Center aparece en **Windows Server**, junto a SQL Server.

### 3.3 Instalar y configurar Gitea

Gitea se ejecuta en `http://10.1.2.62:3000/`. Confirme el servicio antes de configurarlo:

```powershell
Get-Service gitea
```

En la interfaz inicial de Gitea:

1. Defina la URL base, el directorio de datos y la base de datos. Para un MVP de una sola máquina puede usar SQLite; para producción prefiera una base administrada y respaldada.
2. Cree el administrador inicial.
3. Cree la organización `fourz`.
4. Cree el usuario técnico `jenkins` y un token para acceso a los repositorios de `fourz`.
5. Guarde respaldo de `app.ini`, del directorio de datos y de la base de datos.

No sobrescriba `app.ini` mediante `Configure-Gitea.ps1` si ya terminó el asistente inicial o si no conoce las credenciales de base de datos.

### 3.4 Instalar y configurar Jenkins

Jenkins se ejecuta en `http://10.1.2.62:8080/`.

```powershell
Get-Service Jenkins
```

En el primer acceso:

1. Obtenga la contraseña inicial en `C:\ProgramData\Jenkins\secrets\initialAdminPassword`.
2. Cree el administrador de Jenkins.
3. Instale: **Pipeline**, **Git**, **Gitea**, **Credentials Binding** y **Workspace Cleanup**.
4. Configure la URL pública de Jenkins.
5. Agregue una credencial de usuario/token para Gitea, con ID `gitea-fourz`.
6. Cree o etiquete el nodo de compilación con `fourz-windows-build-agent`.

No guarde el token de Gitea directamente en `jenkins.yaml`; use el almacén de credenciales de Jenkins.

### 3.5 Importar repositorios de Azure DevOps a Gitea

Control Center incorpora el módulo **Repositorios**, que enumera los repositorios de Azure DevOps `kidnetazure/FourZ` y solicita su migración hacia Gitea.

1. Cree un PAT de Azure DevOps con permiso `Code: Read`.
2. Cree un token de Gitea con permiso para crear/escribir repositorios en `fourz`.
3. Defina en el servidor, sin confirmar los valores en archivos:

```text
FOURZ_AZURE_DEVOPS_PAT
FOURZ_GITEA_TOKEN
```

4. En la configuración publicada de Control Center defina `GiteaBaseUrl`, `GiteaOwner` y habilite temporalmente `AllowRepositoryImportActions`.
5. Abra **Repositorios**, revise la lista, seleccione repositorios e importe.
6. Verifique ramas, tags, commits y acceso en Gitea antes de modificar los remotos de los equipos.

La migración mantiene Azure DevOps como origen de respaldo; no elimina Azure Repos, Boards, políticas, pull requests ni pipelines.

### 3.6 Instalar IIS y el sitio de Control Center

Control Center es .NET 8. Instale el rol IIS:

```powershell
.\ServerBootstrap\Scripts\Install-ServerPrerequisites.ps1 -Role IisServer -Apply
.\ServerBootstrap\Scripts\Test-ServerReadiness.ps1 -Role IisServer
dotnet --list-runtimes
```

Confirme que aparece `Microsoft.AspNetCore.App 8.x`. El Hosting Bundle debe contener el runtime compatible con .NET 8; el nombre del archivo en `Tools` no es suficiente como validación.

Planee y cree **solo** el sitio de Control Center. Esto no crea aún Web ni WCF:

```powershell
.\EnvironmentInstaller\Scripts\Install-Environment.ps1 -ControlCenterOnly
.\EnvironmentInstaller\Scripts\Install-Environment.ps1 -Apply -InstallIis -ControlCenterOnly
```

Esto crea el sitio `FourZ.ControlCenter`, el App Pool del mismo nombre y `C:\inetpub\wwwroot\controlcenter`.

Publique desde una máquina que tenga SDK .NET 8:

```powershell
dotnet publish .\src\FourZ.ControlCenter.Web\FourZ.ControlCenter.Web.csproj `
  -c Release `
  -o .\Publish\ControlCenter
```

El directorio de publicación debe quedar exactamente en `C:\inetpub\wwwroot\controlcenter`; no basta con que los archivos existan en `bin`, `obj` o `Publish\ControlCenter`.

```powershell
dotnet publish .\src\FourZ.ControlCenter.Web\FourZ.ControlCenter.Web.csproj `
  -c Release `
  -o C:\inetpub\wwwroot\controlcenter

Test-Path C:\inetpub\wwwroot\controlcenter\web.config
Get-ChildItem C:\inetpub\wwwroot\controlcenter
```

El primer comando de validación debe devolver `True`. La carpeta debe contener `web.config`, `FourZ.ControlCenter.Web.dll`, `appsettings.json` y `Config\topology.production.json`.

Control Center se expone temporalmente por IP, sin host header. Valide el binding y reinicie solamente su App Pool:

```powershell
Import-Module WebAdministration
Get-WebBinding -Name FourZ.ControlCenter
Restart-WebAppPool FourZ.ControlCenter
Invoke-WebRequest -Uri http://10.1.2.62/ -UseBasicParsing
```

Abra `http://10.1.2.62/`.

### 3.7 Clonar KidZania y revisar configuraciones

Los JSON actuales esperan el código en `C:\Repos\KidZania_`:

```powershell
New-Item -ItemType Directory -Force C:\Repos
Set-Location C:\Repos
git clone <URL-DE-GITEA-DE-KIDZANIA> KidZania_
```

Revise antes de construir:

```powershell
Test-Path C:\Repos\KidZania_\KZoftware.WebSite\KZoftware.WebSite.csproj
Test-Path C:\Repos\KidZania_\KZoftware.Services.Host\KZoftware.Services.Host.csproj
Get-Content C:\FourZ.Deployment\Config\website.json
Get-Content C:\FourZ.Deployment\Config\services.json
Get-Content C:\FourZ.Deployment\Config\windows-services.json
```

### 3.8 Instalar Website y WCF

Compruebe que los ZIP y snapshots IIS existan en `Resources`. Primero ejecute el plan:

```powershell
Set-Location C:\FourZ.Deployment
.\EnvironmentInstaller\Scripts\Install-Environment.ps1 -Target All
```

En un servidor limpio, ejecute:

```powershell
.\EnvironmentInstaller\Scripts\Install-Environment.ps1 -Apply -InstallIis -Target All
```

El comando crea/ajusta el sitio Web, el sitio WCF, sus App Pools, directorios de servicios Windows y el sitio Control Center. Extrae los ZIP de `Resources` en las rutas configuradas. Si una ruta ya contiene archivos, el proceso se detiene; use `-ReplaceExistingContent` solo después de verificar respaldo y destino.

### 3.9 Instalar Windows Services

El instalador de ambiente crea los directorios, pero cada servicio se registra y actualiza mediante los scripts de servicio.

Ejemplo para Facility Message:

```powershell
.\Scripts\Publish-WindowsService.ps1 -ServiceId facility-message
.\Scripts\Deploy-WindowsService.ps1 -ServiceId facility-message
Get-Service KZoftwareFacilityMessageService
```

Servicios incluidos actualmente: `bank-task`, `expiration`, `facility-message`, `general-metrics`, `pazzport-expiration`, `queue-turn`, `restaurant-booking`, `takeaway-eot` y `work-order-notification`.

Repita el proceso para cada `Id` autorizado. Use el apartado **Windows Services** de Control Center para revisar estado. No cambie el `ServiceName` sin cambiar también el código fuente y `Config\windows-services.json`.

### 3.10 Primer pipeline Jenkins

1. Cree un Pipeline en Jenkins para el repositorio `FourZ.Deployment` ya importado a Gitea.
2. Use `Jenkins\Jenkinsfile`; el archivo `FourZ.Deployment.Jenkinsfile.template` sólo se conserva por compatibilidad.
3. Primero ejecute solo `TARGET=website` o `TARGET=services` con `DEPLOY=false`.
4. Verifique artefactos en `Publish` y `Packages`.
5. Habilite `DEPLOY=true` únicamente tras validar la publicación y el backup.

El pipeline ejecuta build, publish, backup, deploy y smoke test mediante los scripts existentes. No sustituye la lógica de `FourZ.Deployment`.

## 4. Escenario B: nodos autónomos separados

### 4.1 Diseño solicitado

| Nodo | Componentes locales |
| --- | --- |
| Nodo Services | Gitea, Jenkins, Java, Control Center, IIS/WCF y Windows Services |
| Nodo Web | Gitea, Jenkins, Java, Control Center e IIS/Web FourZ |

Cada nodo tendrá puertos y DNS propios. Ejemplo:

| Servicio | Nodo Services | Nodo Web |
| --- | --- | --- |
| Gitea | `http://gitea-services.fourz.local:3000` | `http://gitea-web.fourz.local:3000` |
| Jenkins | `http://jenkins-services.fourz.local:8080` | `http://jenkins-web.fourz.local:8080` |
| Control Center | `http://controlcenter-services.fourz.local` | `http://controlcenter-web.fourz.local` |

Esta modalidad duplica repositorios, usuarios, tokens, configuraciones y pipelines de Gitea/Jenkins. Mantenga una convención de nombres y defina cuál instancia es la fuente operativa de cada repositorio; no use dos Gitea como origen de escritura del mismo repositorio.

### 4.2 Pasos comunes en **cada** nodo

1. Copie `FourZ.Deployment` y `Tools` al nodo.
2. Ejecute `-Role BuildAgent -Apply` si Jenkins compilará localmente.
3. Ejecute `-Role Platform -Apply` para Java y configure Gitea/Jenkins locales.
4. Ejecute `-Role IisServer -Apply` para alojar Control Center y el sitio local.
5. Publique Control Center con `-ControlCenterOnly` y cree el DNS específico del nodo.
6. Importe/cloné solo los repositorios que ese nodo debe compilar o desplegar.

### 4.3 Nodo Services: WCF y Windows Services

En este nodo no instale el sitio Web. Planee primero:

```powershell
.\EnvironmentInstaller\Scripts\Install-Environment.ps1 -Target Services
```

Luego instale WCF, Control Center local y los directorios de servicios:

```powershell
.\EnvironmentInstaller\Scripts\Install-Environment.ps1 -Apply -InstallIis -Target Services
```

Publique y despliegue `services`, y después los Windows Services requeridos:

```powershell
.\Scripts\Build.ps1 -ConfigurationPath .\Config\services.json
.\Scripts\Publish.ps1 -ConfigurationPath .\Config\services.json
.\Scripts\Backup.ps1 -ConfigurationPath .\Config\services.json
.\Scripts\Deploy.ps1 -ConfigurationPath .\Config\services.json
```

Revise el endpoint WCF configurado en `HealthCheckUrl` y los logs IIS/Windows Services antes de dar por concluida la liberación.

### 4.4 Nodo Web: Website

En este nodo no instale el sitio WCF. Planee primero:

```powershell
.\EnvironmentInstaller\Scripts\Install-Environment.ps1 -Target Website
```

Luego instale Website y Control Center local:

```powershell
.\EnvironmentInstaller\Scripts\Install-Environment.ps1 -Apply -InstallIis -Target Website
```

Publique y despliegue Website:

```powershell
.\Scripts\Build.ps1 -ConfigurationPath .\Config\website.json
.\Scripts\Publish.ps1 -ConfigurationPath .\Config\website.json
.\Scripts\Backup.ps1 -ConfigurationPath .\Config\website.json
.\Scripts\Deploy.ps1 -ConfigurationPath .\Config\website.json
```

En `Config\website.json`, configure `HealthCheckUrl` con el host/puerto realmente publicado por el nodo Web.

## 5. Checklist de aceptación

- [ ] Gitea y Jenkins están `Running` en cada nodo requerido.
- [ ] `java -version` y `JAVA_HOME` son correctos en el nodo Jenkins.
- [ ] `Test-ServerReadiness` está saludable para los roles instalados.
- [ ] Control Center responde por DNS sin puerto explícito.
- [ ] Los sitios IIS y App Pools requeridos están iniciados.
- [ ] El sitio Web responde su health check.
- [ ] El endpoint WCF responde en el nodo Services.
- [ ] Cada Windows Service configurado está instalado y `Running`.
- [ ] Existe un backup previo a la primera liberación.
- [ ] Jenkins ejecutó un build/publish exitoso antes de habilitar `DEPLOY`.

## 6. Diagnóstico de publicación de Control Center

Siga esta secuencia antes de modificar el proyecto o reinstalar IIS. Cada resultado identifica una causa distinta.

| Síntoma | Causa probable | Corrección |
| --- | --- | --- |
| `404 Not Found` con página IIS clásica | La petición llegó a otro sitio IIS. | Verifique el binding de `FourZ.ControlCenter`; para esta fase debe ser `10.1.2.62:80:`. |
| `403.14 Forbidden` | IIS llegó a `C:\inetpub\wwwroot\controlcenter`, pero no hay publicación ASP.NET Core. | Ejecute `dotnet publish` directamente hacia esa carpeta y compruebe `web.config`. |
| `500.31 Failed to load ASP.NET Core runtime` | Falta `Microsoft.AspNetCore.App 8.x` o se instaló otro Hosting Bundle. | Instale el **ASP.NET Core Hosting Bundle 8.0.x** y reinicie IIS/Windows. |

Comandos de diagnóstico:

```powershell
Import-Module WebAdministration
Get-Website | Select-Object Name, State, PhysicalPath, Bindings
Get-WebBinding -Name FourZ.ControlCenter
Get-ChildItem C:\inetpub\wwwroot\controlcenter
Test-Path C:\inetpub\wwwroot\controlcenter\web.config
dotnet --list-runtimes
Get-WinEvent -LogName Application -MaxEvents 30 |
  Where-Object { $_.ProviderName -match 'IIS|AspNetCore' } |
  Select-Object TimeCreated, ProviderName, Id, LevelDisplayName, Message
```

El proyecto es `net8.0`, por lo que debe aparecer una línea como esta antes de abrir el portal:

```text
Microsoft.AspNetCore.App 8.0.x [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
```

El instalador verifica ahora esa versión exacta. Si `Tools\DotNet8HostingBundle.exe` no es versión `8.x`, el bootstrap se detiene de forma explícita en vez de instalar un bundle incompatible. El instalador local actual reporta versión `10.0.10`; debe sustituirse por un instalador aprobado de Hosting Bundle **8.0.x**, conservando el mismo nombre de archivo.

Después de instalar el bundle correcto, reinicie Windows y ejecute:

```powershell
Set-Location C:\FourZ.Deployment
.\ServerBootstrap\Scripts\Test-ServerReadiness.ps1 -Role IisServer
Restart-WebAppPool FourZ.ControlCenter
Invoke-WebRequest -Uri http://10.1.2.62/ -UseBasicParsing
```

## 7. Recuperación y soporte

Para revertir Website o WCF, use el script correspondiente solo después de confirmar que existe un backup válido:

```powershell
.\Scripts\Rollback.ps1 -ConfigurationPath .\Config\website.json
.\Scripts\Rollback.ps1 -ConfigurationPath .\Config\services.json
```

Control Center muestra el estado local y puede exponer la operación de recuperación únicamente cuando `AllowRecoveryActions` esté habilitado. Manténgala deshabilitada hasta contar con autenticación, auditoría y un procedimiento de aprobación.

Consulte logs en `C:\FourZ.Deployment\Logs`, `C:\FourZ.Deployment\Backups`, los logs IIS, Event Viewer y el historial de Jenkins.
# Jenkins: crear el job FourZ-Deployment

Después de instalar Jenkins, instalar los plugins **Pipeline** y **Git**, y crear la
credencial de tipo *Username with password* con id `gitea-fourz`, ejecutar como
administrador desde la raíz de FourZ.Deployment:

```powershell
[Environment]::SetEnvironmentVariable('FOURZ_JENKINS_USER', 'usuario-jenkins', 'Machine')
[Environment]::SetEnvironmentVariable('FOURZ_JENKINS_API_TOKEN', 'token-api-jenkins', 'Machine')
.\ServerBootstrap\Scripts\New-JenkinsDeploymentJob.ps1 -JenkinsUrl 'http://localhost:8080'
```

El token se lee únicamente de variables de máquina y no se escribe en el proyecto.
Si el job ya existe y se actualizó el proyecto, ejecutar de nuevo con
`-UpdateExisting`.

El job **FourZ-Deployment** permite seleccionar `Development`, `UAT` o
`Production`; `Website` o `Services`; organización, repositorio y rama de Gitea.
Primero realiza checkout, build y publish. La casilla `DEPLOY` está desactivada por
defecto: al activarla solicita una aprobación y ejecuta backup, deploy, smoke test
y el rollback existente si algo falla.

## 8. Operacion desde FourZ Control Center

La pantalla **Deployments** es la entrada operativa para una liberacion. No copia archivos directamente desde el navegador: valida el origen en Gitea y solicita el trabajo `FourZ-Deployment` en Jenkins. Jenkins conserva la responsabilidad administrativa y ejecuta los scripts existentes.

### 8.1 Configuracion requerida

En **Settings** habilite `AllowDeploymentActions` y configure:

| Campo | Valor inicial |
| --- | --- |
| URL Gitea | `http://localhost:3000` |
| URL Jenkins | `http://localhost:8080` |
| Job Jenkins | `FourZ-Deployment` |
| Organizaciones / owners | Una organizacion Gitea por linea, por ejemplo `kidnetazure` |

Las variables de maquina que usa el App Pool son:

```text
FOURZ_GITEA_TOKEN
FOURZ_JENKINS_USER
FOURZ_JENKINS_API_TOKEN
```

Despues de crearlas o modificarlas, recicle el App Pool `FourZ.ControlCenter` para que IIS reciba el entorno nuevo.

### 8.2 Primera instalacion de Web o WCF

En **Deployments**, seleccione ambiente, componente, organizacion, repositorio y rama. Marque **Inicializar IIS antes de liberar** solamente si el sitio todavia no existe. Jenkins ejecutara `Install-Environment.ps1 -Apply -InstallIis` para el destino correspondiente, extraera el ZIP base de `Resources` y despues continuara con build, publish, backup y deploy.

### 6.4 Liberar un Windows Service desde Jenkins

Actualice el job `FourZ-Deployment` con el `Jenkins\Jenkinsfile` vigente. En **Build with Parameters** seleccione:

- `COMPONENT`: `WindowsService`.
- `WINDOWS_SERVICE_ID`: uno de los identificadores definidos en `Config\windows-services.json`, por ejemplo `bank-task` o `queue-turn`.
- `DEPLOY`: activo para instalar o actualizar y arrancar el servicio; desactívelo para sólo generar el paquete ZIP.

El pipeline resuelve el proyecto desde el repositorio clonado, restaura paquetes, compila en Release, genera `Packages\WindowsServices\<id>.zip` y ejecuta `Deploy-WindowsService.ps1`. El modo `Auto` no despliega Windows Services por un push: cada servicio requiere selección explícita para evitar actualizaciones involuntarias.

En liberaciones posteriores deje esa opcion desmarcada: el flujo realiza backup, deploy, smoke test y rollback si falla.

### 8.3 Guardar Settings y habilitar deploy

En **Settings**, el interruptor **Despliegues mediante Jenkins** habilita la pantalla Deployments. El color azul solamente indica el valor seleccionado en el formulario: debe pulsarse **Guardar configuración** y reciclar el App Pool para aplicarlo.

La pantalla guarda únicamente URLs, nombres de job, organizaciones y banderas de operación. Los tokens permanecen en variables de máquina. Para permitir ese guardado, ejecute una sola vez como Administrador:

```powershell
Import-Module WebAdministration
$appPool = 'FourZ.ControlCenter'
$file = 'C:\inetpub\wwwroot\controlcenter\appsettings.json'
icacls $file /grant "IIS AppPool\${appPool}:(M)"
Restart-WebAppPool -Name $appPool
```

El permiso `Modify` se concede exclusivamente al archivo `appsettings.json`, no a toda la carpeta publicada.

### 8.4 Respaldar dependencias NuGet externas

El proyecto legado requiere `Microsoft.ApplicationInsights.Wcf` versión `0.28.0-build06820`; esa versión preliminar no está en nuget.org. Antes de hacer la primera liberación, mientras MyGet esté disponible, descargue una copia local reutilizable:

```powershell
Set-Location C:\FourZ.Deployment
.\ServerBootstrap\Scripts\Save-ApplicationInsightsArtifact.ps1
```

El resultado queda en `Artifacts\NuGet\packages` y `Artifacts\NuGet\manifest.json`. `Config\NuGet.Config` consulta primero dicho artefacto local y después nuget.org. Respaldar la carpeta `Artifacts\NuGet` con FourZ.Deployment. Esto es obligatorio para el build, independientemente de marcar o no **Inicializar IIS antes de liberar**.

### 8.5 Windows Services desde el portal

La pantalla **Windows Services** muestra los nueve servicios configurados, su estado, y si el ZIP publicado esta disponible. Sus acciones son:

- **Instalar / actualizar**: ejecuta `Scripts\Deploy-WindowsService.ps1 -ServiceId <id>`; requiere que el paquete exista en `Packages\WindowsServices`.
- **Iniciar**, **Detener** y **Reiniciar**: usan el `ServiceName` de `Config\windows-services.json`.

Para que estas acciones funcionen, la identidad del App Pool `FourZ.ControlCenter` debe tener permisos para controlar servicios Windows. En esta fase sin autenticacion, habilite `AllowWindowsServiceActions` solo en una red administrativa y utilice una identidad de servicio restringida con esos permisos; no exponga el portal a Internet.

### 8.6 Actualizar el pipeline y resolver fallas comunes

El job debe usar el contenido de `Jenkins\Jenkinsfile`. Después de actualizar FourZ.Deployment, copie ese archivo completo y reemplácelo en **Jenkins → FourZ-Deployment → Configure → Pipeline script**.

- El checkout usa el workspace corto `C:\J\FZ` para evitar `Filename too long` en el repositorio legado.
- El pipeline deshabilita la interacción de Git Credential Manager. La credencial `gitea-fourz` sigue siendo obligatoria para repositorios privados.
- `INITIALIZE_IIS` sólo se marca para la primera instalación: crea el sitio, App Pool, bindings y extrae el ZIP de `Resources` antes de compilar.
- `DEPLOY` debe marcarse para que el pipeline haga backup, deploy, smoke test y rollback. Jenkins pedirá una aprobación manual antes de reemplazar contenido.
- Si el build no encuentra un paquete, confirme primero que `Artifacts\NuGet\packages` contiene los `.nupkg` y que `Config\NuGet.Config` fue copiado al servidor.

### 8.7 Webhook Gitea para liberacion desatendida

El job `FourZ-Deployment` ya no solicita aprobacion manual. Con `COMPONENT=Auto` detecta `KZoftware.WebSite` y `KZoftware.Services.Host`; libera Web, WCF o ambos, pero solo si existe la ruta de despliegue configurada para cada componente. Si ninguno existe, termina sin reemplazar archivos.

El hook llama a un relay local de Control Center. El relay valida la firma HMAC de Gitea y solicita el job a Jenkins usando las credenciales de maquina, incluyendo el crumb CSRF. Asi Jenkins no se abre a solicitudes anonimas y Gitea no recibe el token de Jenkins.

Antes de crear el hook, defina un secreto aleatorio de maquina y reinicie el App Pool de Control Center:

```powershell
[Environment]::SetEnvironmentVariable('FOURZ_GITEA_WEBHOOK_SECRET', ([Guid]::NewGuid().ToString('N')), 'Machine')
Import-Module WebAdministration
Restart-WebAppPool FourZ.ControlCenter
```

Luego cree o actualice el hook para la rama productiva:

```powershell
Set-Location C:\FourZ.Deployment
.\ServerBootstrap\Scripts\Set-GiteaJenkinsWebhook.ps1 `
  -ControlCenterWebhookUrl 'http://10.1.2.62/api/webhooks/gitea/release' `
  -Organization kidnetazure `
  -Repository KidZania_ `
  -BranchFilter ProductionOnPremise
```

Actualice el job con el contenido actual de `Jenkins\Jenkinsfile` y ejecútelo manualmente una vez para guardar sus parámetros. Después haga un push de prueba a `ProductionOnPremise`. Gitea permite filtros de rama, por lo que no se desplegarán pushes de ramas de desarrollo.

### 8.9 Backups y rollback verificable

El pipeline ya no ejecuta un backup separado antes de `Deploy.ps1`. El propio deploy crea un único backup consistente: contenido del sitio, backup IIS y manifiesto `Backup.json` bajo `Backups\Production\Website` o `Backups\Production\Services`. Si falla la copia o el health check, restaura automáticamente el contenido y la configuración IIS de ese mismo identificador.

Para una recuperación manual, use el backup más reciente o indique explícitamente uno:

```powershell
Set-Location C:\FourZ.Deployment
.\Scripts\Rollback.ps1 -ConfigurationPath .\Config\website.json
.\Scripts\Rollback.ps1 -ConfigurationPath .\Config\services.json -BackupId 20260727_153000
```

El rollback usa una copia espejo para retirar archivos que no existían en el backup. Antes de ejecutarlo, revise el identificador y confirme que el sitio corresponde al componente seleccionado.

### 8.10 Perfiles por ambiente

`Config\deployment-environments.json` separa las rutas de publicación, paquetes, backups, App Pools y health checks. Production está habilitado y apunta al servidor actual. Development y UAT están deshabilitados a propósito hasta registrar rutas propias; Jenkins se detiene antes del build si se selecciona un ambiente sin habilitar.

### 8.10.1 Convención de rutas por ambiente

Las aplicaciones Web y WCF conservan sus nombres de sitio y App Pool, pero su contenido queda separado por ambiente:

```text
C:\inetpub\wwwroot\Production\web_www.fourz.net
C:\inetpub\wwwroot\Production\svc_www.fourz.net
```

La misma convención se aplicará a Development y UAT cuando se habiliten: `C:\inetpub\wwwroot\Development\...` y `C:\inetpub\wwwroot\UAT\...`. Sus rutas no se completan aún porque faltan sus bindings, App Pools y URLs definitivas.

Para mover una instalación IIS existente a la carpeta Production, haga una liberación inicial controlada desde Jenkins con **Inicializar IIS antes de liberar**. El pipeline crea la carpeta, actualiza la ruta física IIS, extrae el ZIP base y después publica la rama elegida. Para ejecutarlo manualmente:

```powershell
Set-Location C:\FourZ.Deployment
.\EnvironmentInstaller\Scripts\Install-Environment.ps1 `
  -Apply -InstallIis -Target All -UpdateExistingSitePaths
```

El cambio de ruta es intencional: sin `-UpdateExistingSitePaths`, el instalador se detiene ante una ruta IIS distinta. Antes de aplicarlo, confirme que el nuevo destino no contiene archivos no respaldados.

### 8.10.2 Verificación autenticada de SQL Server

La cadena se mantiene fuera del repositorio mediante la variable de máquina `FOURZ_SQL_CONNECTION_STRING`. Debe contener servidor, base, usuario y contraseña; no la coloque en `appsettings.json`, Jenkinsfile, capturas o documentos.

Ejemplo de forma (sustituya los valores entre corchetes directamente en el servidor):

```powershell
[Environment]::SetEnvironmentVariable(
  'FOURZ_SQL_CONNECTION_STRING',
  'Server=[servidor];Database=FourZ-PROD-Test;User ID=[usuario];Password=[contraseña];Encrypt=True;TrustServerCertificate=True;',
  'Machine'
)
```

Después, valide sin exponer la cadena:

```powershell
Set-Location C:\FourZ.Deployment
.\ServerBootstrap\Scripts\Test-SqlConnectivity.ps1 -ExpectedDatabase 'FourZ-PROD-Test'
```

El resultado muestra sólo estado, servidor y base conectada. Un resultado `Warning` indica que las credenciales funcionan pero apuntan a una base distinta; `Missing` indica que falta la variable o que la conexión no pudo abrirse.

Control Center usa la misma variable para el estado **SQL Server** del Dashboard. Después de definirla, reinicie el App Pool `FourZ.ControlCenter`; el portal mostrará una conexión autenticada exitosa, una advertencia por base distinta o una advertencia de conectividad sin revelar la cadena.

### Ramas configurables por ambiente para liberación automática

En **Settings** se configuran tres ramas independientes: **Development**, **UAT** y **Production**. Los valores iniciales son `dev`, `UAT` y `ProductionOnPremise`; cada uno puede cambiarse y debe ser distinto. Cuando llega un push, Control Center identifica el ambiente por la rama y solicita Jenkins con `ENVIRONMENT=Development`, `ENVIRONMENT=UAT` o `ENVIRONMENT=Production`.

Para registrar los tres filtros de Gitea en una sola ejecución, indique las tres ramas configuradas:

```powershell
.\ServerBootstrap\Scripts\Set-GiteaJenkinsWebhook.ps1 `
  -ControlCenterWebhookUrl 'http://10.1.2.62/api/webhooks/gitea/release' `
  -Organization kidnetazure `
  -Repository KidZania_ `
  -BranchFilter 'dev', 'UAT', 'ProductionOnPremise'
```

El script crea o actualiza un webhook por cada filtro de rama. Si más adelante cambia una rama desde Settings, vuelva a ejecutar el comando con el conjunto completo actualizado.

### 8.11 Diagnóstico integral de Control Center

Antes de la primera prueba, o después de una actualización, ejecute el diagnóstico local:

```powershell
Set-Location C:\FourZ.Deployment
.\ServerBootstrap\Scripts\Test-ControlCenterReadiness.ps1
```

El script no modifica configuración. Valida la publicación del portal, JSON de `appsettings.json`, runtime ASP.NET Core 8, sitio y App Pool IIS, puertos locales de Gitea/Jenkins/Redis, permisos **Modify** del App Pool para la cola y bitácora, y la presencia de las variables de máquina requeridas sin mostrar sus valores.

Para consumirlo desde una herramienta futura use `-AsJson`.

### 8.12 Alcance pendiente y controles de seguridad

La versión actual opera recursos locales y está preparada para Web, WCF, Windows Services, IIS, repositorios y Jenkins. Antes de exponerla fuera de una red administrativa aún faltan autenticación, autorización por roles, auditoría de acciones administrativas y HTTPS con certificado válido.

SQL permanece como módulo de visibilidad/preparación; las migraciones y operaciones destructivas deben integrarse después con la herramienta de migración aprobada. Para centralizar varios Control Center se requerirá una fase posterior de comunicación segura entre nodos; por ahora cada máquina mantiene su propia instancia, Gitea y Jenkins.
