Osumi Framework
es en eu v9.10.0 GitHub

Guía de migración: 9.8.5 → 9.9.0

La versión 9.9.0 sustituye el runtime de Filters por un sistema de Middlewares por fases e introduce el primer motor de migraciones versionadas de aplicaciones de Osumi Framework.

Es una versión con cambios incompatibles para aplicaciones que utilicen Filters.

El framework incluye una migración automática que transforma los usos compatibles de Filters al nuevo sistema de Middlewares conservando la lógica de negocio original de los Filters.


Resumen

Añadido

Modificado

Eliminado del runtime 9.9

Las clases Filter antiguas pueden permanecer temporalmente en proyectos migrados porque la migración automática genera adaptadores Middleware de compatibilidad sobre ellas.


1. Requisitos antes de actualizar

Osumi Framework 9.9 requiere:

Antes de actualizar un proyecto existente, añade esto al composer.json raíz si aún no existe:

{
	"config": {
		"allow-plugins": {
			"osumionline/plugin-updater": true
		}
	}
}

Composer también puede preguntar de forma interactiva si se confía en el plugin cuando se instala por primera vez.


2. Procedimiento de actualización recomendado

Antes de actualizar:

  1. Haz commit o stash de los cambios de la aplicación.
  2. Comprueba que el proyecto está en un estado funcional conocido.
  3. Haz copia de los datos persistentes si se trata de producción.
  4. Actualiza el framework mediante Composer.

Ejemplo:

composer update osumionline/framework --with-dependencies

Cuando Composer haya regenerado el autoloader, osumionline/plugin-updater comprueba la versión instalada del framework y ejecuta todas las migraciones pendientes.

Para la actualización 9.8.5 → 9.9.0 se ejecuta el paso de migración 9.9.0.


3. Migración automática mediante Composer

La integración sigue este flujo:

Composer update
↓
osumionline/plugin-updater
↓
post-autoload-dump
↓
Runner::runPending()
↓
preflight de la migración 9.9.0
↓
cambios transaccionales del proyecto
↓
actualización de state.json

El estado de migración es la fuente autoritativa. Esto permite ejecutar correctamente las migraciones aunque:

Durante una migración lanzada por Composer, la comprobación de Git ignora únicamente:

composer.json
composer.lock

Los cambios en el código de la aplicación u otros archivos del proyecto siguen provocando que la migración se detenga, salvo que se habilite explícitamente la ejecución forzada.


4. Previsualizar migraciones lanzadas por Composer

El updater admite variables de entorno.

Dry-run

OFW_DRY_RUN=1 composer update osumionline/framework --with-dependencies

Esto ejecuta en dry-run la migración del framework.

Importante: Composer sigue realizando su operación de paquetes. OFW_DRY_RUN solo evita que la migración de Osumi Framework persista cambios de migración en el proyecto.

Salida detallada

OFW_VERBOSE=1 composer update osumionline/framework --with-dependencies

Forzar comprobaciones de seguridad

OFW_FORCE=1 composer update osumionline/framework --with-dependencies

Úsalo con precaución. Omite las comprobaciones de seguridad de migración que admiten ejecución forzada.

Valores booleanos aceptados:

1
true
yes
y
on

y:

0
false
no
n
off

5. CLI manual de migraciones

El paquete del framework expone:

php vendor/bin/ofw-migrate --help

Ejecución normal de migraciones pendientes:

php vendor/bin/ofw-migrate

Comando recomendado para inspección:

php vendor/bin/ofw-migrate --dry-run --verbose

Opciones disponibles:

--from=VERSION
--to=VERSION
--dry-run
--force
--verbose
--no-interaction
--help

--from

Sustituye la versión de origen obtenida del estado de migración.

Ejemplo:

php vendor/bin/ofw-migrate --from=9.8.5 --to=9.9.0

Úsalo solo cuando necesites intencionadamente un rango explícito.

--to

Sobrescribe la versión objetivo. Si no se indica, se detecta automáticamente la versión instalada.

--dry-run

Muestra las operaciones previstas sin modificar archivos del proyecto.

--force

Omite las comprobaciones de seguridad que admiten ejecución forzada, incluida la comprobación de árbol Git limpio.

--verbose

Muestra detalles de las migraciones y operaciones de archivos.

--no-interaction

Deshabilita el comportamiento interactivo.


6. Protección del árbol Git

En una migración manual normal, un proyecto gestionado por Git debe tener el árbol de trabajo limpio.

Si existen cambios inesperados, la migración se detiene en lugar de modificar el proyecto.

Los proyectos sin .git también son válidos; siguen protegidos mediante las copias transaccionales de migración.

El modo dry-run no requiere un árbol Git limpio porque no persiste cambios del proyecto.

En la migración automática de Composer solo se excluyen de esta comprobación composer.json y composer.lock.

Es preferible hacer commit o stash antes que utilizar --force.


7. Qué hace la migración 9.9.0

La migración realiza un preflight completo antes de escribir archivos de aplicación.

Busca Filters antiguos bajo:

src/Filter/

Los Filters compatibles deben seguir las convenciones normales de namespace PSR-4 y nombres de archivo de Osumi Framework.

Los archivos Filter originales no se eliminan ni se reescriben.

Para cada Filter compatible se genera un Middleware de compatibilidad en:

src/Middleware/

Ejemplo:

src/Filter/LoginFilter.php
↓ se conserva

src/Middleware/LoginMiddleware.php
↓ adaptador de compatibilidad generado

Los adaptadores generados ejecutan el Filter original únicamente durante:

OMiddleware::PHASE_BEFORE

8. Conversión del resultado de un Filter antiguo

El adaptador transforma el resultado del Filter al contrato de Middleware 9.9.

Filter correcto

Resultado antiguo:

[
	'status' => 'ok',
	'id' => 42
]

se convierte en contexto:

[
	'context' => [
		'status' => 'ok',
		'id' => 42
	]
]

Puede leerse mediante:

$login = $req->getMiddleware(
	'Login'
);

o:

$id = $req->getMiddlewareValue(
	'Login',
	'id'
);

Filter fallido

Un Filter cuyo resultado no sea correcto se convierte en stop con HTTP 403.

Redirección antigua

Si el Filter devuelve una URL válida en return, el adaptador produce:

De esta forma se conserva el comportamiento legacy durante la migración.


9. Transformaciones automáticas de código

La migración transforma el código compatible fuera de src/Filter/ y src/Middleware/.

ORequest

Antes:

$login = $req->getFilter(
	'Login'
);

Después:

$login = $req->getMiddleware(
	'Login'
);

DTOs

Antes:

#[ODTOField(
	filter: 'Login',
	filterProperty: 'id'
)]
public ?int $idUser = null;

Después:

#[ODTOField(
	middleware: 'Login',
	middlewareProperty: 'id'
)]
public ?int $idUser = null;

Rutas

Antes:

ORoute::get(
	'/profile',
	ProfileComponent::class,
	[
		LoginFilter::class
	]
);

Después:

ORoute::get(
	'/profile',
	ProfileComponent::class,
	[
		'before' => [
			\Osumi\OsumiFramework\App\Middleware\LoginMiddleware::class
		]
	]
);

Los arrays literales de Filters en llamadas ORoute compatibles se convierten en listas de Middlewares before.


10. Configuración global de Middlewares

Si no existe:

src/Middleware/Middlewares.php

la migración crea:

<?php

declare(strict_types=1);

namespace Osumi\OsumiFramework\App\Middleware;

use Osumi\OsumiFramework\Core\OMiddleware;

OMiddleware::setGlobal([
	OMiddleware::PHASE_BEFORE => [],
	OMiddleware::PHASE_AFTER_RENDER => [],
	OMiddleware::PHASE_AFTER_RESPONSE => []
]);

Si ya existe, se conserva exactamente.


11. Casos que no se migran automáticamente

La migración se detiene deliberadamente cuando no puede transformar el código con seguridad.

Expresiones dinámicas de Filters en rutas

No compatible:

$filters = [
	LoginFilter::class
];

ORoute::get(
	'/profile',
	ProfileComponent::class,
	$filters
);

Para la migración automática, las expresiones de Filters de ruta deben ser arrays literales de clases.

Métodos legacy de ORequest

Requieren cambios manuales:

$req->getFilters()
$req->setFilter(...)
$req->setFilters(...)

La migración se detiene si encuentra estas llamadas.

Referencias de Filter no resolubles

Una ruta que haga referencia a un Filter que no pueda asociarse a una definición migrable se rechaza.

Conflictos con Middlewares existentes

Si el destino del Middleware generado ya existe con contenido diferente, la migración se detiene en lugar de sobrescribirlo.

Estructuras de archivos inseguras

Se rechazan recorridos mediante enlaces simbólicos y rutas inseguras.

La migración es deliberadamente conservadora: el código ambiguo debe migrarse manualmente en lugar de intentar adivinar su intención.


12. Seguridad transaccional y rollback

Los cambios se escriben mediante un sistema transaccional.

Las copias se almacenan bajo:

ofw/tmp/migrations/

Cada transacción tiene su propio directorio con timestamp/identificador aleatorio y un manifest de archivos modificados.

El estado de migración se escribe dentro de la misma transacción que los cambios de aplicación.

Si una operación falla:

  1. se restauran los archivos modificados;
  2. se eliminan los archivos creados por la migración fallida;
  3. el estado se revierte junto con el proyecto;
  4. la migración finaliza con error.

Las copias de una transacción completada correctamente se conservan para inspección.


13. Estado de migración

El estado se guarda en:

ofw/tmp/state.json

Después de completar 9.9.0:

{
	"last_migrated": "9.9.0"
}

Si no existe estado, el runner considera 0.0.0 como versión inicial de migración y selecciona todos los pasos pendientes aplicables hasta la versión instalada.

Esto permite migrar proyectos creados antes de que existiera el motor de migraciones.

Una ejecución normal posterior no vuelve a aplicar 9.9.0.


14. Idempotencia

El sistema está diseñado para ser idempotente.

Por ejemplo:

No utilices --from para volver a seleccionar deliberadamente una migración ya completada salvo que conozcas las consecuencias.


15. Verificación posterior

Después de migrar:

  1. Revisa los archivos generados en src/Middleware/.
  2. Revisa las rutas transformadas.
  3. Revisa los DTOs que usan middleware / middlewareProperty.
  4. Busca usos legacy del runtime.
  5. Ejecuta la batería completa de tests.
  6. Realiza pruebas funcionales de autenticación/autorización.
  7. Haz commit del proyecto migrado.

Búsquedas útiles:

getFilter(
getFilters(
setFilter(
setFilters(
filterProperty

Es normal que las clases legacy de src/Filter/ sigan existiendo mientras se usen los adaptadores de compatibilidad.


16. Convertir adaptadores generados en Middlewares nativos

Los adaptadores generados son un puente de compatibilidad, no la arquitectura final recomendada.

Después de comprobar el proyecto migrado puedes trasladar progresivamente la lógica del Filter al propio Middleware.

Un Middleware nativo utiliza:

public static function handle(
	string $phase,
	array $data
): array

y devuelve resultados explícitos como:

return [
	'context' => [
		'id' => 42
	]
];

o:

return [
	'stop' => true,
	'status_code' => 401,
	'message' => 'Unauthorized'
];

Proceso recomendado:

Filter legacy
↓
Middleware de compatibilidad generado
↓
verificación funcional
↓
mover lógica al Middleware nativo
↓
eliminar el Filter sin uso

Mantén, cuando sea posible, el nombre de la clase Middleware generada para no tener que cambiar las rutas ya migradas ni los nombres públicos del contexto.

Cuando todos los adaptadores se hayan convertido, src/Filter/ puede eliminarse si ya no contiene lógica legacy necesaria.


17. Nuevas capacidades de Middleware

Los Middlewares nativos no están limitados al comportamiento de los antiguos Filters.

Pueden ejecutarse en:

before
afterRender
afterResponse

Pueden publicar o modificar:

Los Middlewares globales, de grupos anidados y de ruta se acumulan en cada fase en este orden:

global
↓
grupo exterior
↓
grupo interior
↓
ruta

Consulta:

docs/es/concepts/middlewares.md

para la API completa.


18. Acción requerida por el desarrollador

Para aplicaciones que actualicen desde 9.8.5:

  1. Asegura PHP 8.5+.
  2. Autoriza osumionline/plugin-updater en Composer.
  3. Haz commit o stash de cambios locales.
  4. Actualiza Osumi Framework con Composer.
  5. Revisa la salida de la migración automática.
  6. Resuelve manualmente cualquier construcción legacy no soportada que indique el migrador.
  7. Ejecuta los tests completos y pruebas funcionales.
  8. Haz commit del código migrado.
  9. Opcionalmente sustituye los adaptadores de compatibilidad por Middlewares nativos.

En proyectos que no utilicen Filters, la migración 9.9 también crea src/Middleware/Middlewares.php cuando sea necesario y registra el estado de migración.


19. Compatibilidad con versiones anteriores

9.9.0 elimina intencionadamente la arquitectura runtime de Filters.

Los adaptadores automáticos ofrecen una vía de actualización para proyectos legacy compatibles, pero el código nuevo de 9.9 debe utilizar Middlewares.

No añadas nuevos Filters después de migrar.