La bitacora del run 26 tenia la respuesta: la sonda decia que install.ps1 NO
EXISTE y el paso siguiente, "Ejecutar instalador", salia en verde. Comprobado con
PowerShell real por que:
& 'C:\no-existe.ps1' -Service; exit $LASTEXITCODE -> exit 0
$LASTEXITCODE no se fija nunca (no corrio ningun comando nativo), asi que
`exit $null` da 0. El panel leia 0 y asentaba el paso como exitoso. NADA se
instalaba, y por eso seguia viva la 1.1.0: el agente viejo nunca se detuvo porque
el instalador nunca se ejecuto. Esa evidencia falsa mando el diagnostico a otra
parte durante varios runs.
- El script emite un CENTINELA `CRAS-FIN|<codigo>` y el panel lo EXIGE. Sin el, el
instalador no termino, de lo que de el codigo de salida. Un fallo no es una
respuesta — la misma leccion que la sonda, ahora en la invocacion.
Validado con PowerShell real: instalador normal -> CRAS-FIN|0; instalador que
sale 75 -> CRAS-FIN|75 (la traduccion a "restauracion en curso" sigue viva);
instalador inexistente -> CRAS-ERROR| y codigo 90 en vez de un 0 silencioso.
- "El instalador no esta" pasa a ser un hecho aparte de "no pude leerlo", y aborta
con 502. Antes se colapsaba en `desconocido`, el run continuaba sabiendolo ya,
gastaba el intento entero y acababa culpando al agente de no escribir su sello.
- Se asienta el CONTENIDO del staging tras extraer. Sin eso no se distinguia "el
instalador no esta", "esta en otra ruta" y "esta pero no se puede leer", que son
tres arreglos distintos.
Y dos cambios en el endurecimiento del token, cada uno defendible por si solo:
- Se restringe SOLO panel.env, no la carpeta. La restriccion de la carpeta era un
extra —su motivo declarado, que el archivo heredara una ACL permisiva al
crearse, ya lo cubre la ACE del propio archivo— y a cambio dejaba la carpeta con
ACE NO heredables, de modo que lo creado dentro despues podia quedar sin
permisos utilizables. Ahi se extrae el artefacto: era candidato serio a explicar
por que el instalador "no existia".
- Por SID y no por nombre de grupo. En un Windows en espanol
`BUILTIN\Administrators` no resuelve y el icacls falla entero; comprobado.
S-1-5-32-544 y S-1-5-18 valen en cualquier idioma.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reviewed-on: #30
Co-authored-by: hreyes <hreyes@aduanasoft.com.mx>
Co-committed-by: hreyes <hreyes@aduanasoft.com.mx>
Los 88s de antes (45 x 2s) se quedaban cortos con un caso real: en los agentes
hasta 1.1.4 el sello se escribia DETRAS del re-despliegue de las deps embebidas,
que al cambiar de version se re-copian enteras, y eso va despues de desempacar un
onefile de ~254 MB con el antivirus escaneando. Se reportaba como fallida una
actualizacion que iba bien.
Desde 1.1.5 el agente escribe el sello lo primero y este margen sobra, pero tiene
que cubrir los artefactos YA publicados, que no se pueden arreglar hacia atras.
Agotar el margen es un FALLO en una actualizacion, asi que quedarse corto
convierte un despliegue bueno en un error — el mas caro de los dos.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reviewed-on: #29
Co-authored-by: hreyes <hreyes@aduanasoft.com.mx>
Co-committed-by: hreyes <hreyes@aduanasoft.com.mx>
El run de Windows terminaba en verde sobre un servidor que seguia con la version
anterior. La verificacion no podia detectarlo:
- El sello config\.version ausente se toleraba SIEMPRE. Los agentes anteriores a
1.1.1 no lo escribian, asi que al actualizar uno de esos `deployed` llegaba
vacio y no se comprobaba ninguna version — justo la combinacion que importa.
Ahora, en una ACTUALIZACION, un sello ausente es un fallo: el binario nuevo lo
escribe en ensure_runtime_layout(), asi que su ausencia significa que lo que
corre no es el que se instalo. La tolerancia se queda solo en instalacion nueva.
- `Get-Process -Name` responde "hay un proceso con ese nombre", no "corre el
binario que instale". Se compara la RUTA del ejecutable; si no es legible no se
concluye que sea ajeno, porque un proceso de SYSTEM no la expone sin elevacion.
- Se interroga la tarea programada a fondo: su accion dice DONDE arranca el
agente de verdad y se asienta en la bitacora (el dato que habria explicado esto
en diez segundos), y cuando el agente no reporta su ruta —nada anterior a 1.1.1
lo hace— se usa la de la tarea en vez del default.
Y dos correcciones de lo anterior:
- needsElevation exigia admin en cuanto la tarea EXISTIA, bloqueando de entrada
toda actualizacion sobre un servidor ya instalado. Ahora depende de que la
tarea corra como SYSTEM, que es lo que de verdad obliga a elevar; y el token
filtrado por UAC deja de rechazarse por adelantado: se intenta y se reporta lo
que responda el servidor.
- -UpdateInPlace se pasaba siempre, pero solo existe desde 1.1.3 y install.ps1
usa [CmdletBinding()], asi que con un artefacto anterior fallaba con
NamedParameterNotFound sin ejecutar una linea. Se le pregunta a PowerShell por
el param() del propio artefacto en vez de mantener una tabla de versiones.
Verificar comparte las dos sondas nuevas para que no pueda contradecir al
instalador, y gana un chequeo de "el arranque apunta a la instalacion".
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Reviewed-on: #24
Co-authored-by: hreyes <hreyes@aduanasoft.com.mx>
Co-committed-by: hreyes <hreyes@aduanasoft.com.mx>