Skip to content

3.0.0 — Jellyfin 12.1, consola SQL y verificacion automatizada - #3

Merged
BORNIOS merged 16 commits into
mainfrom
release/V3
Sep 16, 2026
Merged

BORNIOS merged 16 commits into
mainfrom
release/V3

Conversation

@BORNIOS

@BORNIOS BORNIOS commented Sep 16, 2026 •

Copy link
Copy Markdown
Owner

3.0.0 — Jellyfin 12.1, consola SQL y verificación automatizada

Resumen

Trae a main la versión 3.0.0 del plugin: adaptación completa al contrato de proveedores de Jellyfin 12.1, correcciones críticas de arranque y restauración, consola SQL de solo lectura, opciones avanzadas que ahora sí se aplican y una suite de pruebas xUnit que corre en CI.

main queda alineado con la versión publicada (contenía 2.0.0.0). La rama release/2.0.1 se mantiene para dar soporte a Jellyfin 10.11.x y su release ya está publicado.

Cambios principales

Compatibilidad con Jellyfin 12.1

  • MigrationAssemblyResolver: localiza el proveedor SQLite que distribuye el servidor en lugar de asumir que está en la carpeta del plugin.
  • SqliteCompatibilityBootstrap: preparación por base de datos, con los agregados min/max sobre uuid que el home de 12.1 necesita.
  • MigrationEngine, MigrationTableCopier, MigrationSchemaPreparer y MigrationCodeMigrations reescritos: orden de dependencias, copiado por lotes, truncado previo a la primera fila y reporte de tabla fallida como importación fallida.
  • PurgeDatabase implementado: en la línea 2.x lanzaba NotImplementedException, lo que rompía la restauración del respaldo completo del sistema.

Panel del plugin

  • Cinco pestañas en orden: Configuración, Migración, Mantenimiento, Health y Consola SQL.
  • Opciones avanzadas funcionales: SaveConfig valida (max >= min, rechaza con 400) y persiste pool y timeout; el proveedor respeta lo que trae la cadena de conexión y solo rellena lo que falta; SaveConfig/Activate reescriben config/database.xml, que es de donde Jellyfin lee la cadena activa; el estado actual muestra Pool · Timeout · Prepared statements.
  • Consola SQL de solo lectura: 10 plantillas de diagnóstico con filtro por base de datos, historial en la sesión del navegador, rechazo de mutaciones y de sentencias múltiples.
  • Diccionarios ES/EN simétricos, verificados por una prueba automática.

Verificación

  • Suite xUnit en Tests/ con 74 pruebas, 0 fallos, incluidas pruebas de integración contra PostgreSQL 17.
  • Tools/Generar-ResumenEjecutivo.ps1 regenera docs/VERIFICACION-RESUMEN.md a partir del TRX real.
  • CI: verification.yml (servicio postgres:17, resumen publicado en el job) y build.yaml ejecutando la suite en cada push. El auditor de esquema ahora filtra rutas con separadores normalizados, así que se comporta igual en Windows y en los runners Linux.

Exportación a SQLite

  • Columnas de clave primaria copiadas verbatim y diagnóstico de constraint (origen del release 2.0.1).
  • Copia solo de columnas presentes en ambos motores, limpieza de filas huérfanas y library.db mínimo válido que las rutinas heredadas de 12.1 exigen.

Publicación

  • release.yml publica la entrada del catálogo también en main, de modo que un release hecho desde su rama no queda invisible.
  • El changelog llega por variable de entorno, así que los saltos de línea se guardan como \n reales y el catálogo los muestra como párrafos.

Seguridad y análisis estático

El chequeo CodeQL aparece en rojo con 36 hallazgos, y conviene ser explícito: no son nuevos. Los 36 existen en main desde 2.0.0.0, con las mismas reglas y archivos; el análisis de PR atribuye 12 de ellos a este PR porque reescribe los archivos donde viven.

Regla Severidad Cantidad Contexto
cs/sql-injection alta 10 SQL dinámico con identificadores de catálogo validados con RequireSqlIdentifier y escapados con QuoteIdentifier, con supresión justificada en el código
cs/path-injection alta 5 Rutas de backup, exportación y restauración que llegan desde el panel
cs/resource-injection crítica 5 Descriptores de proceso/archivo construidos con la cadena de conexión y rutas de configuración
cs/command-line-injection crítica 2 pg_dump/psql con ejecutable resuelto contra AllowedPgExecutables y argumentos escapados con QuoteArg
cs/log-forging media 14 Valores de usuario escritos en el log del plugin sin neutralizar saltos de línea

Todos los endpoints implicados exigen RequiresElevation (administrador). El triaje queda registrado en #4 para cerrarse en una versión posterior: neutralizar saltos de línea en el log, validar rutas contra raíces permitidas y evaluar ProcessStartInfo.ArgumentList.

El workflow propio del repositorio (🔬 Run CodeQL → job Analyze) termina en verde y sube los resultados sin errores de análisis.

Documentación incluida

Documento Contenido
docs/migracion-10.11-a-12.md · EN Manual de migración 10.11.x → 12.x con diagrama, contingencias y rollback
docs/novedades-3.0.0.md · EN Qué cambia en 3.0.0 frente a 2.0.1
docs/JELLYFIN-12.1.md Notas técnicas de la adaptación y cómo ejecutar la suite
docs/VERIFICACION-RESUMEN.md Resumen ejecutivo generado desde la suite real
README.md · EN Reorganizados por pestañas, con la consola SQL documentada y capturas nuevas

Pruebas realizadas

  • dotnet build -c Release: 0 errores, 0 avisos.
  • Suite completa contra PostgreSQL real: 74/74.
  • Verificación funcional en Jellyfin 12.1.0 sobre Windows: arranque correcto, [HealthCheck] Severidad: Ok, [ENGINE] Modo activo: PostgreSQL, exportación e importación ejecutadas.
  • Release 2.0.1 publicado y validado: MD5 del ZIP descargado contra el checksum del manifiesto y ZIP con los tres DLL.

Notas de publicación

Tras el merge se publicará 3.0.0 (targetAbi 12.1.0.0). El catálogo de main conserva las entradas 2.0.1.0 (10.11.x), 2.0.0.0 y 1.0.0.0.

Jorge Chávez Bornios added 16 commits September 16, 2026 02:07
Reemplaza el runner casero CompatibilityChecks por un proyecto xUnit estandar (57 pruebas en 7 areas) que cualquiera puede ejecutar con dotnet test: contrato con Jellyfin 12.1, database.xml, auditoria del SQL crudo contra el modelo EF, reescrituras de SQL, logger y pruebas de integracion con PostgreSQL desechable (omitidas si no hay conexion).

Anade tools/Generar-ResumenEjecutivo.ps1, que traduce el TRX a docs/VERIFICACION-RESUMEN.md, y el workflow verification.yml que lo publica en CI con un servicio postgres:17.
Endpoint POST Plugins/PostgresProvider/Query (solo administradores) con validacion en servidor: una sentencia por peticion, whitelist SELECT/WITH/TABLE/VALUES/EXPLAIN/SHOW, palabras de escritura bloqueadas, maximo de filas y timeout corto, con auditoria en el log del plugin. La pestana SQL del panel trae plantillas de diagnostico, historial, EXPLAIN e i18n ES/EN.
… servidor

Resuelve la carga del ensamblado de migraciones en el ALC por defecto, bufferiza los lectores sincronos que Jellyfin deja abiertos, eleva el timeout de comandos, limita la reescritura de MigrateRatingLevels, crea los agregados min/max(uuid) por base de datos e implementa PurgeDatabase (usada al restaurar un backup completo). El logging pasa a registrar traza completa y detalle de PostgreSQL con niveles coherentes, y solo en Postgres-*.log.
… configuracion

Sincroniza los READMEs y el manifiesto con la version 3.0.0.0, e incluye el resumen ejecutivo de verificacion generado por la propia suite (docs/VERIFICACION-RESUMEN.md) y el global.json del SDK.
tests/TestResults y los archivos .trx son artefactos generados por dotnet test.
… integridad

La pestana activa, el foco y las tablas usan ahora el acento del panel y un unico estilo de tabla con cabecera fija. Se anaden 4 pruebas que revisan el HTML del panel como parte de la suite: ids usados por el script, una pestana por seccion, los dos diccionarios con las mismas claves (y todas las usadas traducidas) y que el recurso embebido sea el que el plugin anuncia. Esas pruebas destaparon 8 claves sin traducir que se muestran ahora en espanol.
…n ruido de otras bases

Las plantillas que leen pg_stat_statements filtran ahora por la base actual y excluyen las sentencias de administracion, para que la consola no arrastre el ruido de trabajos ajenos (por ejemplo las bases desechables que crea la propia suite de pruebas). El historial se guarda en sessionStorage y se puede vaciar con un boton. Dos pruebas nuevas comprueban que toda plantilla del panel es una sentencia de solo lectura aceptada por la consola y que ninguna muestra estadisticas de otras bases.
tests/CompatibilityChecks quedo huerfano al migrar las comprobaciones a Jellyfin.Database.Providers.Postgres.Tests y no aparece en la solucion; se elimina para no mantener dos runners en el repositorio.
… a Jellyfin 12

Opciones avanzadas (pool y timeout):
- SaveConfig valida (max >= min) y persiste MinPoolSize, MaxPoolSize y MaxAutoPrepare.
- El proveedor respeta la cadena de conexion y solo completa huecos con la configuracion
  guardada, que era la razon por la que editar el pool no tenia efecto.
- Current status refleja pool, timeout y sentencias preparadas.
- 5 pruebas nuevas en AdvancedOptionTests.

Rutas y limpieza:
- tests -> Tests y tools -> Tools, con workflows, solucion e informes alineados.
- build.yaml ejecuta la suite xUnit en lugar del runner retirado.
- .gitignore y verificacion apuntan a Tests/TestResults.

Publicacion:
- release.yml replica la entrada del catalogo en main para que el release sea visible.

Documentacion (ES principal + EN):
- Manual de migracion 10.11.x -> 12.x con diagrama, contingencias y rollback.
- Novedades de 3.0.0 frente a 2.0.1.
- Plan de publicacion de 2.0.1 y 3.0.0 (orden obligatorio y verificacion posterior).

Suite de verificacion: 68 pruebas, 0 fallos.
Jellyfin lee la cadena de conexion activa de config/database.xml, no de la
configuracion del plugin. Hasta ahora, cambiar el pool en el panel actualizaba
la configuracion y el estado, pero el runtime seguia abriendo conexiones con la
cadena antigua guardada en database.xml.

- SaveConfig reescribe database.xml (con la cadena ya ajustada) cuando PostgreSQL
  esta activo, y lo deja registrado en el log del plugin.
- Activate escribe la cadena ajustada en lugar de la cadena cruda del request.

Suite de verificacion: 68 pruebas, 0 fallos.
- README (ES/EN) reorganizado siguiendo el orden real de pestanas: Configuracion,
  Migracion, Mantenimiento, Health y Consola SQL, cada una con su descripcion y sus
  funciones. Se documenta la pestana Consola SQL con Screenshots/Tab-Console.png.
- Manual 10.11 -> 12: el paso 3 aclara que Jellyfin recrea database.xml declarando
  Jellyfin-SQLite al arrancar (lo que no debe aparecer es PLUGIN_PROVIDER).
- Paso 5 con las dos vias de instalacion del plugin: catalogo y ZIP manual.
- Pasos 6 y 7: reutilizar la base PostgreSQL de 10.11.x es valido; se explica el uso
  de Truncar tablas antes de insertar y la limpieza de residuos de pruebas.
- README ES: se anaden las secciones Compatibilidad e Instalacion que solo tenia la
  version inglesa, y se actualiza la compatibilidad a Jellyfin 12.1 / .NET 10.
- El plan de publicacion se retira del repositorio por ser documentacion interna.
- README (ES/EN): nueva caracteristica en la lista principal, con la aclaracion de
  que es de solo lectura y que rechaza sentencias que modifiquen datos.
- manifest.json: la consola SQL se menciona en la descripcion (catalogo en ingles)
  y en el resumen en espanol que ve Jellyfin.
…l catalogo

- release.yml: el changelog llega por env en los tres pasos que lo usan (manifiesto de
  la rama, manifiesto de main y notas del release). Interpolado en el script, los saltos
  de linea se guardaban como \\n literales y Jellyfin los mostraba asi.
- manifest.json: se anade la entrada 2.0.1.0 (targetAbi 10.11.0.0, checksum verificado)
  para conservarla cuando main se alinee con esta rama.
El auditor ignoraba bin, obj y Migrations con separadores de Windows, asi que en los
runners Linux analizaba los archivos de migracion y fallaba con tablas auxiliares que
no pertenecen al modelo EF (PostgresItemValueDuplicates y similares).

- El filtro normaliza la ruta y usa separadores '/'.
- Nueva prueba IgnoredSourcePathsMatchOnEveryPlatform con rutas de Windows y Linux.

Suite de verificacion: 74 pruebas, 0 fallos.

using var sqlite = new SqliteConnection($"Data Source={sqlitePath};Mode=ReadOnly;Cache=Shared");
using var pg = new NpgsqlConnection(postgresConnectionString);
using var sqlite = new SqliteConnection($"Data Source={options.SqlitePath};Mode=ReadOnly;Cache=Shared");
// and this keeps CA2007 (ConfigureAwait on every awaited operation) satisfied.
using var connection = new NpgsqlConnection(builder.ConnectionString);
await connection.OpenAsync(cancellationToken).ConfigureAwait(false);
using var command = new NpgsqlCommand(statement, connection);
_logger.LogInformation("Existing SQLite file renamed to {Bkp}", bkpPath);
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Existing SQLite file renamed to {Bkp}", bkpPath);
_logger.LogInformation("Existing SQLite file deleted for overwrite: {Path}", sqlitePath);
if (_logger.IsEnabled(LogLevel.Information))
{
_logger.LogInformation("Existing SQLite file deleted for overwrite: {Path}", sqlitePath);
logger.LogInformation("SQLite schema created via Jellyfin SQLite provider at {Path}", sqlitePath);
if (logger.IsEnabled(LogLevel.Information))
{
logger.LogInformation("SQLite schema created via Jellyfin SQLite provider at {Path}", sqlitePath);
{
_logger.LogInformation(
"Fixed sequence {Target}: setval({Max:N0}) for {Table}.{Column}",
target,

if (_logger?.IsEnabled(LogLevel.Information) == true)
{
_logger.LogInformation("Starting PostgreSQL backup with pg_dump to {Path}", sqlFilePath);
PostgresLog.Warn($"[Backup] COMPLETADO: {sqlFilePath} ({sqlSize})");
if (_logger?.IsEnabled(LogLevel.Information) == true)
{
_logger.LogInformation("PostgreSQL backup completed at {Path} ({Size})", sqlFilePath, sqlSize);
PostgresLog.Warn($"[Backup] COMPLETADO (ZIP): {zipPath} ({zipSize})");
if (_logger?.IsEnabled(LogLevel.Information) == true)
{
_logger.LogInformation("PostgreSQL backup completed at {Path} ({Size})", zipPath, zipSize);
_logger.LogInformation("{Message}", message);
if (_logger?.IsEnabled(LogLevel.Information) == true)
{
_logger.LogInformation("{Message}", message);
@BORNIOS
BORNIOS merged commit 1869b16 into main Sep 16, 2026
5 of 6 checks passed
@BORNIOS BORNIOS linked an issue Sep 17, 2026 that may be closed by this pull request
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for Jellyfin V12

2 participants