# Nexora Cron Realm Isolation V1

## Problema corregido

La web separa los datos de Legado y Seasonal, pero dos comportamientos podían dejar un reino sin información después de limpiar caché:

1. Los escritores `UpdateCache()` / `updateCacheFile()` abandonaban si el archivo `.cache` había sido eliminado físicamente.
2. En modo Platform compartido, `cron_last_run` es una sola marca y no representa de forma inequívoca la ejecución de cada reino.

El resultado podía ser SQL conectado + cron aparentemente reciente + ranking vacío.

## Nueva arquitectura

Cada reino conserva ahora su estado operativo de cron en:

```text
includes/cache/realms/legacy/cron_state.json
includes/cache/realms/seasonal/cron_state.json
```

La tabla `WEBENGINE_CRON` continúa existiendo para configuración, habilitación, frecuencia y compatibilidad. La decisión de si un job está vencido se toma usando la marca aislada del reino.

## Recuperación de caché

Las escrituras de caché ahora:

- crean el directorio del reino si falta;
- crean el archivo si fue borrado;
- escriben a un temporal y publican mediante rename;
- registran en `php_errors.log` cuando no hay permisos;
- no requieren SQL nuevo.

## AdminCP

### Tools → Cache Manager

Incluye un bloque `Salud de caché · <Reino>` con:

- archivos esperados;
- archivos faltantes;
- archivos no escribibles;
- último cambio;
- botón `Reconstruir caché de <Reino>`.

La reconstrucción ejecuta únicamente productores de caché del reino: rankings, Castle Siege, Server Info, países, online characters y Event Rankings.

### Tools → Cron Job Manager

La columna de última ejecución muestra la marca del reino seleccionado en el selector operativo del AdminCP.

### Website Configuration → Legado + Seasonal

Cada reino muestra adicionalmente:

- estado de caché;
- último cron del reino.

## Operación recomendada después de instalar

1. Selecciona `Seasonal` en el selector superior del AdminCP.
2. Abre `Tools → Cache Manager`.
3. Confirma que `Faltantes = 0` y `No escribibles = 0`.
4. Pulsa `Reconstruir caché de Seasonal`.
5. Abre `Tools → Cron Job Manager` y confirma timestamps para Seasonal.
6. Comprueba `/rankings/level/?realm=seasonal` o fija Seasonal en el selector público.
7. Cambia a Legado y confirma que sus marcas son independientes.

## Permisos

No uses `777` como solución general. El usuario PHP debe poder escribir en:

```text
includes/cache/
includes/cache/realms/
includes/cache/realms/legacy/
includes/cache/realms/seasonal/
```

`writable.paths.json` incluye ahora estas rutas explícitamente.
