Sistema de plugins de WebBlocks CMS

Este documento recoge la arquitectura del sistema de plugins de WebBlocks CMS. El núcleo del CMS es un host genérico de plugins con definiciones de plugin respaldadas por un registro, carga e instalación manual de ZIP por parte del super admin, rutas de instalación gestionadas por storage, plugins instalados desactivados por defecto, gestión explícita de activación y desactivación, desinstalación de las cargas manuales, comprobaciones de compatibilidad, rutas y comandos solo cuando están activados, andamiaje de ajustes y de detalle, informes de salud y estado, slots de extensión tipados para el admin, declaraciones de bloques propiedad del plugin, hooks de assets públicos, guardas de convención de paquetes, un puente de instalación desde el Plugin Catalog verificado por checksum para artefactos compatibles del catálogo público y una acción de actualización controlada, respaldada por el catálogo, para los plugins instalados con versiones compatibles más recientes. WebBlocks UI Manager ya no se incluye en el runtime del núcleo del CMS; es un artefacto de plugin interno o de operador que se instala manualmente solo en instalaciones de operador como webblocksui.com. No existe un marketplace público, ni una tienda remota completa de plugins, ni un instalador arbitrario de paquetes Composer, ni descarga o actualización automática de plugins externos, ni despliegue automático de la CDN externa de producción de WebBlocks UI, ni publicación genérica en un servidor de actualizaciones.

Decisión fundamental

El núcleo de WebBlocks CMS es un host de plugins.

El paquete del núcleo proporciona la superficie reutilizable del producto CMS:

  • gestión de contenido y de sitios
  • infraestructura de renderizado público
  • bases de usuarios, roles y permisos
  • shell de administración y superficies estándar de la interfaz de administración
  • descubrimiento de plugins, registro y contratos de slots de extensión

Las capacidades específicas de un producto o de un dominio de negocio no deben integrarse en el núcleo del CMS salvo que formen parte del producto CMS reutilizable. Deben entregarse como plugins para que una instalación no herede los menús, comandos, ajustes, tablas de datos o flujos operativos de otro producto.

Entre las áreas previstas para plugins se incluyen:

  • WebBlocks UI Release/CDN Manager
  • integración con QuizTem
  • analítica
  • herramientas SEO avanzadas
  • boletín
  • comercio electrónico
  • optimizador de medios
  • gestor del servidor de actualizaciones
  • packs de bloques personalizados

Frontera entre núcleo y plugin

Capacidades del núcleo:

  • sitios, páginas, bloques, medios, usuarios, idiomas (locales) y ajustes base
  • renderizado, shell público, layout, slots e infraestructura de bloques
  • base de permisos y roles
  • shell de administración y superficie estándar de la interfaz de administración
  • descubrimiento de plugins, registro y contratos de slots de extensión

Capacidades de los plugins:

  • pantallas de administración para un producto o dominio de negocio concreto
  • un espacio de nombres de rutas propiedad del plugin
  • permisos propiedad del plugin
  • ajustes propiedad del plugin
  • comandos de consola propiedad del plugin
  • migraciones propiedad del plugin
  • widgets de panel propiedad del plugin
  • bloques o packs de bloques propiedad del plugin
  • rutas públicas propiedad del plugin, solo cuando se declaran explícitamente

La sobrescritura de vistas del núcleo está prohibida por defecto. Los plugins amplían el CMS únicamente mediante slots de extensión documentados y contratos del registro. Un plugin no debe reemplazar vistas del paquete, parchear servicios del núcleo, añadir archivos de rutas ocultos ni depender de efectos secundarios de inclusiones arbitrarias.

Instalación manual por ZIP

System -> Plugins permite a los super admins subir un ZIP de plugin local. Subir un ZIP es una instalación privilegiada de código ejecutable. El instalador valida el archivo antes de escribir nada bajo la raíz de plugins configurada, que por defecto es storage/app/webblocks/plugins/{plugin-handle}/{version}.

La validación exige webblocks-plugin.json o manifest.json, un handle en kebab-case, una versión de tipo semver, metadatos de provider/clase, una restricción de versión de CMS compatible, ausencia de colisión con un handle ya instalado, solo rutas relativas dentro del paquete, sin path traversal, sin rutas absolutas, sin entradas de enlaces simbólicos y sin escrituras en destinos prohibidos del CMS o del núcleo como app, packages, project, storage, vendor o public/cms. Los plugins instalados permanecen desactivados mientras no se complete un paso de activación explícito. Los plugins desactivados son inertes: rutas, comandos, menús, rutas de ajustes, reporters de salud, widgets, declaraciones de bloques y assets no se registran ni se ejecutan, y System -> Plugins informa de la salud como inactiva o no comprobada.

La desinstalación manual solo está disponible para los plugins subidos manualmente y requiere autorización de super admin. El plugin debe desactivarse primero. La desinstalación elimina el directorio del paquete del plugin instalado y el archivo de estado de activación bajo la raíz de plugins configurada, pero no elimina las tablas de base de datos propiedad del plugin ni ejecuta migraciones destructivas. Los plugins protegidos, del núcleo o no manuales no pueden desinstalarse mediante este flujo.

Los campos de manifiesto admitidos incluyen handle, label, description, version, provider, required_cms_version, permissions, commands, routes, settings, migrations, assets y health. Las migraciones se instalan como archivos propiedad del plugin y nunca se ejecutan automáticamente al subirlo o activarlo. Los super admins pueden ejecutar la acción explícita de setup del plugin desde la pantalla de detalle del plugin; el runner limita la ejecución a la ruta del plugin instalado y a los directorios de migración declarados en el manifiesto, registra los resultados del setup en el estado de activación y puede reparar un plugin que requiere setup cuyos registros de migración existen pero al que le faltan las tablas necesarias.

El ciclo de vida manual de un plugin es el siguiente:

  1. Suba e instale el ZIP. El plugin queda desactivado por defecto.
  2. Revise la pantalla de detalle del plugin.
  3. Active el plugin cuando sea compatible.
  4. Ejecute el setup o las migraciones del plugin si la pantalla de detalle indica Setup required o Plugin migrations pending.
  5. Use las rutas operativas del plugin una vez que el setup esté listo.
  6. Desactive el plugin para dejar inertes rutas, comandos, menús, ajustes, comprobaciones de salud y contribuciones.
  7. Desinstale solo después de desactivar; la desinstalación conserva las tablas propiedad del plugin.

Los plugins activados con el setup pendiente no deben provocar fallos en las rutas de administración. Si faltan tablas propiedad del plugin, las pantallas de salud y de rutas deben mostrar indicaciones de setup requerido como Plugin migrations pending o Release tables are missing.

Las rutas de administración del plugin deben usar permisos declarados con el prefijo del handle. Los usuarios super_admin del CMS están permitidos explícitamente para los permisos de plugins activos y habilitados, incluidos los permisos cargados desde manifiestos de plugins instalados manualmente. Los roles que no son super admin siguen denegados salvo que un futuro modelo de asignación de permisos del CMS conceda el permiso concreto propiedad del plugin. Las rutas de ajustes usan {plugin-handle}.manage cuando el plugin lo declara; en caso contrario, recurren al acceso de sistema.

Las rutas de administración de plugins activados y compatibles siempre se ejecutan dentro de la pila de rutas de administración del CMS: web, instalación requerida, autenticación del CMS, acceso de administración del CMS, guarda de setup del plugin y, después, el middleware de permisos propiedad del plugin cuando la ruta del plugin lo declara. El middleware de autenticación del CMS usa el guard web y el usuario de sesión de Laravel, y redirige a los invitados a través de la ruta webblocks.auth.login propiedad del CMS. Las guardas de setup del plugin son aditivas y no deben sustituir a la autenticación del CMS ni a la autorización de administración; los controladores del plugin pueden dar por hecho que el usuario del CMS autenticado está presente una vez superado el middleware de autenticación y administración.

Contrato del plugin y manifiesto

Todo plugin debe tener un handle:

  • en kebab-case
  • globalmente único dentro de la instalación
  • estable entre versiones
  • usado como prefijo por defecto para permisos, rutas, tablas, ajustes, assets e identidad del paquete

Cada plugin debe declarar sus metadatos mediante un manifiesto o un objeto de definición:

  • handle
  • label
  • version
  • clase provider
  • descripción opcional
  • versión de CMS requerida o restricción de versión
  • espacio de nombres de ajustes
  • prefijo de base de datos/tablas
  • permisos
  • entradas del menú de administración
  • rutas de administración y públicas
  • comandos de consola
  • esquema de ajustes o páginas de ajustes
  • migraciones
  • bloques o packs de bloques
  • assets
  • comprobaciones de salud, cuando se admiten

Los plugins son registry-first: se conectan al CMS mediante contratos explícitos, no mediante inclusiones arbitrarias, sobrescrituras de vistas en la raíz o archivos de rutas específicos de la instalación.

Los plugins instalados que se actualizan desde el catálogo se recargan mediante el refresco del runtime del núcleo del CMS después de escribir el paquete de reemplazo. El refresco limpia el estado del registro de plugins, de permisos, de extensiones, de salud y de la caché optimizada del runtime de Laravel, y luego reconstruye las rutas activas de los plugins para el runtime actual, de modo que la versión instalada, la versión activa del manifiesto, los metadatos del provider activo y la ruta de origen de rutas y controladores queden alineados. Si en el mismo proceso PHP ya está cargada una clase provider de una versión anterior del paquete instalado, el CMS considera ese provider obsoleto y recurre a los metadatos actualizados del manifiesto en lugar de reutilizar las rutas antiguas.

La autorización de los plugins la resuelve de forma centralizada el núcleo del CMS. Los permisos activos propiedad del plugin declarados por el plugin activado permiten a los usuarios super_admin del CMS, y el mismo resolutor se usa para la visibilidad del menú del plugin, las contribuciones al panel y al sistema y el middleware de rutas plugin.permission:*. Los usuarios no autorizados no ven las entradas de menú correspondientes; el acceso directo por URL sigue devolviendo un 403 controlado. El tratamiento de setup requerido se mantiene después de la autorización y las migraciones del plugin siguen siendo explícitas.

Forma actual de la API del registro:

PluginDefinition::make('webblocks-ui-manager')
  ->label('WebBlocks UI Manager')
  ->version('1.0.0')
  ->requiresCms('^1.32')
  ->provider(WebBlocksUiManagerServiceProvider::class)
  ->settingsNamespace('webblocks_ui_manager')
  ->databasePrefix('webblocks_ui_manager_')
  ->menu([
    PluginMenuItem::make('releases')
      ->label('WebBlocks UI Releases')
      ->icon('package')
      ->route('webblocks.plugins.webblocks_ui_manager.releases.index')
      ->permission('webblocks-ui-manager.view'),
  ])
  ->permissions([
    PluginPermission::make('webblocks-ui-manager.view')->label('View releases'),
    PluginPermission::make('webblocks-ui-manager.manage')->label('Manage release metadata'),
    PluginPermission::make('webblocks-ui-manager.publish')->label('Prepare CDN artifacts'),
  ])
  ->adminRoutes(__DIR__.'/../routes/admin.php')
  ->commands([
    PrepareWebBlocksUiReleaseCommand::class,
  ])
  ->settings(
    PluginSettingsDefinition::make()
      ->label('Release Settings')
      ->description('Controls WebBlocks UI release publishing defaults.')
  )
  ->dashboardWidgets([
    PluginDashboardWidget::make('webblocks-ui-manager.release-status')
      ->title('WebBlocks UI Releases')
      ->description('Read-only release publishing summary.')
      ->permission('webblocks-ui-manager.view'),
  ])
  ->systemCards([
    PluginSystemCard::make('webblocks-ui-manager.cdn-status')
      ->title('CDN Status')
      ->description('Read-only CDN artifact status.')
      ->permission('webblocks-ui-manager.view'),
  ])
  ->blockTypes([
    PluginBlockTypeDefinition::make('webblocks-ui-manager::release-card')
      ->label('Release Card'),
  ])
  ->publicAssets([
    PluginPublicAsset::cssHead('webblocks-ui-manager.public-css', '/cms/plugins/webblocks-ui-manager/public.css'),
    PluginPublicAsset::jsBodyEnd('webblocks-ui-manager.public-js', '/cms/plugins/webblocks-ui-manager/public.js'),
  ])
  ->health(WebBlocksUiManagerHealth::class);

La API exacta puede cambiar durante la implementación, pero el contrato debe preservar estas reglas:

  • los metadatos declarados se pueden inspeccionar antes de activar un plugin
  • la propiedad de menús, rutas, permisos, comandos, migraciones, bloques, assets y ajustes es atribuible a un handle de plugin
  • los conflictos fallan durante la compilación, los tests, los diagnósticos de arranque o la activación del plugin, antes de que los usuarios vean propiedad mezclada

Reglas de convención de paquetes

Las convenciones de los paquetes de plugin son independientes de las del núcleo del CMS. El núcleo del CMS es propietario de los contratos del host; los plugins son propietarios del comportamiento de su dominio.

  • Nomenclatura del handle: use kebab-case estable, como analytics-tools; nunca renombre un handle tras su publicación, porque ancla rutas, permisos, ajustes, tablas, assets y el historial de actualizaciones.
  • Registro del service provider: un paquete de plugin debe exponer un único service provider de Laravel y registrar allí su PluginDefinition, o hacerlo mediante el punto de integración con el registro del CMS. Los pilotos propios incluidos en el paquete pueden registrarse directamente desde el provider del paquete del CMS hasta que se separen en sus propios paquetes Composer.
  • Estructura de la definición o del manifiesto: declare explícitamente handle, label, version, provider, description, requiresCms, el espacio de nombres de ajustes, el prefijo de base de datos, los permisos, las rutas, los comandos, los slots de extensión, los assets, los bloques y el reporter de salud.
  • Espacio de nombres de rutas: las rutas de administración viven bajo /webadmin/plugins/{plugin-handle}/... con nombres bajo webblocks.plugins.{plugin_handle}.*.
  • Nomenclatura de permisos: todo permiso de plugin empieza por {plugin-handle}., por ejemplo analytics-tools.view.
  • Convenciones de ajustes: los espacios de nombres de ajustes son snake_case y por defecto corresponden al handle con los guiones convertidos en guiones bajos.
  • Nomenclatura de comandos: los nombres de comandos Artisan resolubles deben empezar por {plugin-handle}:, por ejemplo analytics-tools:sync.
  • Nomenclatura de migraciones y tablas: las tablas usan un prefijo snake_case reservado en el registro que termina en _, por defecto el handle convertido a snake_case más _.
  • Contribuciones de assets: los handles de assets públicos usan el handle del plugin como espacio de nombres separado por puntos, y los archivos estáticos deben publicarse bajo una ruta propiedad del plugin.
  • Contribuciones de tarjetas de panel y de sistema: las claves usan el handle del plugin como espacio de nombres separado por puntos y permanecen de solo lectura salvo que un contrato de extensión posterior añada comportamiento editable.

WebBlocks UI Manager sigue estas convenciones como piloto propio: handle webblocks-ui-manager, espacio de nombres de ajustes webblocks_ui_manager, prefijo de base de datos webblocks_ui_manager_, comandos webblocks-ui-manager:prepare-release y webblocks-ui-manager:publish-release, rutas bajo /webadmin/plugins/webblocks-ui-manager y nombres de ruta bajo webblocks.plugins.webblocks_ui_manager.*.

Compatibilidad e inercia

Las versiones de los plugins son metadatos de tipo semver. requiresCms() declara la restricción de versión de CMS que necesita el plugin. La base actual admite restricciones exactas o con comparadores, como >=1.32.0, y restricciones con caret, como ^1.32.

El registro distingue el estado de activación configurado del estado activo:

  • Activado por configuración: config/webblocks-plugins.php indica que el plugin debe estar activado.
  • Compatible: la versión de CMS instalada satisface la restricción de CMS requerida por el plugin.
  • Activo: el plugin está a la vez activado por configuración y es compatible.

Solo los plugins activos aportan menús, rutas, comandos, rutas de ajustes, widgets de panel, tarjetas de sistema, declaraciones de bloques, assets públicos, permisos y la ejecución del reporter de salud. Los plugins desactivados e incompatibles permanecen inertes. System -> Plugins muestra Incompatible junto con las versiones de CMS requerida e instalada cuando un plugin configurado no puede activarse.

Descubrimiento y activación local

La fase 5 no añade comportamiento de marketplace ni instalación remota arbitraria. El descubrimiento seguro es local y explícito:

  • los plugins propios incluidos en el paquete pueden registrarse desde el provider del paquete del CMS
  • los futuros plugins distribuidos como paquetes Composer deben registrar un service provider mediante el package discovery de Laravel o una configuración explícita del provider de la aplicación
  • los experimentos locales de la instalación pueden usar repositorios Composer de tipo path durante el desarrollo, pero igualmente deben registrar un provider y una definición normales
  • la activación sigue estando respaldada por configuración mediante webblocks-plugins.enabled.{plugin-handle}

Ninguna función en tiempo de ejecución instala paquetes Composer arbitrarios, publica catálogos de marketplace, escribe artefactos de CDN o de servidor de actualizaciones de producción, activa plugins automáticamente, ejecuta automáticamente migraciones o el setup de plugins, ni realiza actualizaciones automáticas de plugins. Los puentes hacia artefactos remotos de plugins se limitan a las acciones de instalación y actualización del Plugin Catalog iniciadas por un super admin y descritas más abajo, y ambas se limitan a URLs controladas de ZIP del catálogo con metadatos SHA-256 coincidentes.

Dirección del catálogo del ecosistema

El sistema de plugins del CMS es el primer host de implementación de una dirección más amplia para el ecosistema de plugins de WebBlocks. Los futuros contratos de plugin deben poder reutilizarse en WebBlocks CMS, QuizTem, Herne Panel, WebBlocks Publisher y posteriores productos WebBlocks, donde cada host expone sus propios puntos de extensión específicos del producto.

La superficie propuesta de catálogo/tienda es plugins.webblocksui.com. El objetivo a corto plazo es un Plugin Catalog para descubrimiento, metadatos, compatibilidad, documentación, información de versiones, checksums, enlaces controlados de descarga de ZIP y un puente de instalación conservador a partir de metadatos de artefactos de catálogo fiables. El comportamiento de marketplace, incluidas cuentas, licencias, plugins de pago, reseñas y flujos de aprobación, queda aplazado.

System -> Plugins incluye una acción Browse Plugin Catalog en /webadmin/plugins/catalog (admin.plugins.catalog.index). La lista del catálogo solicita los plugins públicos listados para host_product=webblocks-cms a GET /api/plugins y pide la última versión compatible mediante GET /api/plugins/{handle}/latest cuando hay un identificador disponible. Las etiquetas de los plugins del catálogo y la acción View details abren /webadmin/plugins/catalog/{handle} (admin.plugins.catalog.show), que solicita GET /api/plugins/{handle} junto con el endpoint de la última versión compatible para mostrar los metadatos del plugin, la compatibilidad, las notas de la versión, los enlaces de documentación/soporte, la URL de descarga del artefacto, la suma de comprobación SHA-256, el nombre de archivo del artefacto, el tamaño del artefacto, el estado de la versión, el estado de validación del artefacto, el estado de análisis del artefacto, el canal, la versión y los metadatos seguros de capacidades declaradas cuando los devuelve la API. Las respuestas de detalle actuales de la API de WebBlocks Plugins pueden devolver los datos del plugin directamente en data, los datos de la versión en data.latest_release y los metadatos del artefacto en data.latest_release.artifact; las respuestas de la API de última versión compatible también pueden devolver los metadatos de la versión en data.release, con los metadatos del artefacto en el elemento hermano data.artifact. El CMS normaliza esas formas antes de renderizar los detalles, comprobar la disponibilidad de instalación o procesar la acción de instalación desde el catálogo en el servidor. Los campos de artefacto admitidos incluyen file_name, size_bytes, checksum_sha256, download_url, validation_status y scan_status; los nombres de campo planos más antiguos de la versión se siguen aceptando por compatibilidad. La versión canónica del producto WebBlocks CMS se envía como version y cms_version para la comprobación de compatibilidad. La URL del catálogo público integrada tiene como valor predeterminado https://plugins.webblocksui.com; los operadores no necesitan cambios en .env para el descubrimiento predeterminado, y pueden sustituir el destino interno de las peticiones con WEBBLOCKS_PLUGIN_CATALOG_BASE_URL (webblocks-plugins.catalog.base_url). Los ajustes de tiempo de espera están disponibles mediante WEBBLOCKS_PLUGIN_CATALOG_TIMEOUT_SECONDS y WEBBLOCKS_PLUGIN_CATALOG_CONNECT_TIMEOUT_SECONDS. La interfaz normal del catálogo no expone la URL base configurada ni la versión de la petición; los estados de no disponibilidad utilizan textos amables para el operador, mientras que los diagnósticos seguros permanecen en los registros.

El detalle del catálogo mantiene los enlaces de Website, Documentation, Support y Catalog Detail separados de las acciones de instalación. La página muestra un estado claro de artefacto no disponible cuando una versión compatible no incluye metadatos de artefacto descargable. La acción Download ZIP abre únicamente la download_url pública absoluta controlada que devuelve el catálogo y no debe exponer rutas de almacenamiento en bruto.

Install from Catalog solo está disponible cuando el plugin del catálogo es compatible, la última versión compatible está published y el artefacto normalizado de la versión incluye los valores download_url, checksum_sha256 y file_name. Los antiguos campos planos de versión sha256/checksum_sha256 y filename/artifact_filename se siguen aceptando por compatibilidad. La acción POST utiliza CSRF, vuelve a leer los metadatos del catálogo en el servidor, descarga la URL ZIP controlada a almacenamiento temporal, comprueba el éxito HTTP, rechaza respuestas irrazonables o que no sean ZIP, calcula el SHA-256, lo compara exactamente con los metadatos del catálogo y después pasa el ZIP temporal por el validador/instalador de ZIP de plugins manual existente. Los archivos temporales se eliminan tras el éxito o el fallo, y los nombres de archivo del catálogo o remotos no se consideran rutas de confianza del sistema de archivos.

Las instalaciones desde el catálogo registran el plugin deshabilitado de forma predeterminada, igual que la carga manual. No habilitan el plugin, no ejecutan las migraciones/configuración del plugin, no ejecutan el código del proveedor del plugin, no registran rutas del plugin, no registran permisos, no registran comandos, no registran recursos, no registran bloques, no añaden tarjetas de panel/sistema, no aplican actualizaciones ni cambian el estado de habilitación. Cualquier estado local de instalación/habilitación mostrado en la página de detalle del catálogo procede únicamente del registro de plugins del CMS, no de afirmaciones del catálogo remoto. La carga/instalación manual de ZIP sigue disponible y sin cambios.

System -> Plugins -> Registered Plugins realiza una consulta de disponibilidad en el catálogo, en la medida de lo posible, para los identificadores de plugins instalados. Cuando el catálogo no está disponible o no proporciona metadatos de confianza, la lista se sigue mostrando y no aparece ninguna acción de actualización. Cuando un identificador instalado tiene una última versión compatible más reciente según version_compare, esa versión está published, el plugin es compatible y el artefacto normalizado incluye download_url, checksum_sha256 y file_name, la columna Version muestra Update available: {version} y el grupo de acciones de la fila muestra una acción de icono Update from Catalog solo por POST.

El POST de actualización vuelve a leer en el servidor los metadatos de detalle/última versión del catálogo, exige los mismos metadatos de artefacto completos, publicados y compatibles, descarga el ZIP controlado, verifica el SHA-256, valida el ZIP con el mismo validador de paquetes de plugin y sustituye la versión del paquete del plugin instalado. Las tablas de base de datos propiedad del plugin se conservan, el estado del ciclo de vida habilitado o deshabilitado se conserva trasladando el estado habilitado a la nueva versión únicamente cuando la versión anterior estaba habilitada, y las migraciones del plugin no se ejecutan automáticamente. Si el plugin actualizado declara nuevas migraciones o faltan sus tablas, la guía existente de configuración requerida y el flujo explícito Run Plugin Migrations siguen siendo responsables de la preparación del esquema.

Consulte WebBlocks Plugin Ecosystem And Catalog para conocer la dirección a nivel de producto y el plan por fases.

La planificación de la superficie de producto propuesta plugins.webblocksui.com, el alcance del MVP, los modelos de implementación candidatos, las páginas públicas del catálogo, las superficies de operador y la posible forma de una API de solo lectura se encuentran en Plugin Catalog Product Architecture.

Ejemplo mínimo de plugin

Un paquete de plugin mínimo debería exponer un proveedor y una definición similares a:

final class AnalyticsToolsPlugin
{
  public static function definition(): PluginDefinition
  {
    return PluginDefinition::make('analytics-tools')
      ->label('Analytics Tools')
      ->version('0.1.0')
      ->provider(AnalyticsToolsServiceProvider::class)
      ->requiresCms('^1.32')
      ->settingsNamespace('analytics_tools')
      ->databasePrefix('analytics_tools_')
      ->permissions([
        PluginPermission::make('analytics-tools.view')->label('View analytics tools'),
      ])
      ->adminRoutes(__DIR__.'/../routes/admin.php')
      ->commands([
        SyncAnalyticsCommand::class,
      ])
      ->health(AnalyticsToolsHealth::class);
  }
}

El proveedor debería registrar las vistas, la configuración, las migraciones y la definición del plugin del paquete sin añadir archivos de rutas públicas propiedad del CMS en /admin, /cms o la raíz. Las rutas del plugin deberían definirse de forma relativa al grupo de rutas del plugin; por ejemplo, /reports pasa a ser /webadmin/plugins/analytics-tools/reports.

Reglas del menú de administración

Los plugins pueden añadir entradas al menú de administración, pero cada entrada de menú de un plugin debe estar restringida por permisos.

El comportamiento preferido es añadir elementos a grupos de administración existentes, como:

  • System
  • Tools
  • Integrations

Un menú de plugin de nivel superior solo puede reservarse para una superficie de producto amplia que resultaría confusa como un único elemento de grupo.

Reglas del menú de administración:

  • los iconos deben proceder del catálogo de iconos de WebBlocks UI
  • los nombres de ruta deben pertenecer al espacio de nombres de rutas del plugin
  • el orden del menú y las reglas de colisión deben gestionarse desde el registro
  • los plugins deshabilitados o desinstalados no deben mostrar entradas de menú
  • las etiquetas de los elementos de menú deberían describir la capacidad, sin filtrar nombres de proyecto específicos de una instalación a instalaciones genéricas del CMS
  • las entradas de menú no deben aparecer en instalaciones del núcleo cuando el plugin propietario no está presente

Reglas del espacio de nombres de rutas

Las rutas de administración de los plugins utilizan de forma predeterminada este prefijo de URL:

/webadmin/plugins/{plugin-handle}/...

Los nombres de las rutas de administración de los plugins utilizan de forma predeterminada este espacio de nombres:

webblocks.plugins.{plugin_handle}.*

El espacio de nombres de los nombres de ruta utiliza el identificador del plugin transformado solo en la medida necesaria para los nombres de ruta de Laravel. Por ejemplo, webblocks-ui-manager pasa a ser webblocks.plugins.webblocks_ui_manager.* si la implementación requiere guiones bajos.

Un plugin solo puede solicitar un prefijo de administración más corto a través del registro. Los prefijos cortos reservados deben ser globalmente únicos. Los conflictos de prefijo deben provocar un fallo durante la compilación, las pruebas, los diagnósticos de arranque o la habilitación del plugin.

Los plugins no deben contaminar:

  • los nombres de ruta del núcleo del CMS
  • el espacio de nombres de rutas del núcleo /webadmin fuera de su prefijo de plugin reservado
  • el espacio de nombres heredado /admin
  • el espacio de nombres de recursos estáticos /cms

Los plugins deshabilitados e incompatibles no deben registrar rutas de administración. El registrador de solo elementos activos es deliberadamente conservador: si un plugin está deshabilitado mediante config/webblocks-plugins.php o no cumple su restricción de versión del CMS, sus rutas están ausentes en lugar de presentes pero prohibidas.

Las rutas públicas son opcionales y de adhesión explícita. Un plugin que declare rutas públicas debe declarar su propiedad con suficiente claridad como para que la propiedad de las rutas pueda comprobarse. Las rutas públicas de un plugin deben evitar colisiones con las páginas del sitio, las rutas públicas del CMS y las rutas del producto anfitrión.

Reglas de permisos

Cada menú de administración, ruta y acción debe estar asociado a un permiso del plugin.

Los nombres de los permisos deben incluir el prefijo del identificador del plugin:

webblocks-ui-manager.view
webblocks-ui-manager.publish
webblocks-ui-manager.settings

El comportamiento de los permisos debe seguir siendo compatible con el modelo de permisos del CMS. Si existe un mecanismo de omisión para el superadministrador, debe utilizar la misma vía de autorización explícita del CMS que los permisos del núcleo.

Los permisos de un plugin deben ser visibles en la gestión de roles de la administración cuando el plugin esté instalado o sea detectable. Los permisos de plugins deshabilitados no deben autorizar comportamiento activo, aunque un rol siga almacenando una cadena de permiso coincidente.

Reglas de ajustes

Los ajustes de un plugin deben almacenarse en su propio espacio de nombres. No deben colisionar con la configuración general del CMS, la configuración de la aplicación anfitriona ni las variables de entorno.

Reglas de los ajustes:

  • las claves de ajustes deberían llevar como prefijo el identificador del plugin
  • los valores sensibles deben utilizar un almacenamiento seguro para secretos cuando esté disponible
  • los valores sensibles nunca deben aparecer en registros, salidas de comprobaciones de estado, mensajes de excepción ni mensajes flash de la administración
  • la interfaz de ajustes debe residir en el espacio de nombres de rutas del plugin o dentro de System -> Plugins -> Plugin detail
  • las variables de entorno pueden proporcionar valores predeterminados iniciales, pero los ajustes en ejecución deberían seguir siendo propiedad del plugin e inspeccionables a través del registro

La fase 2 proporciona una base de ruta de ajustes de solo lectura para los plugins habilitados que declaren PluginSettingsDefinition sin un nombre de ruta personalizado. La ruta predeterminada es:

/webadmin/plugins/{plugin-handle}/settings

Su nombre de ruta predeterminado es:

webblocks.plugins.{plugin_handle}.settings.edit

El almacenamiento editable de los ajustes y los esquemas de validación se reservan para una fase posterior. La fase 5 reserva los espacios de nombres de ajustes mediante PluginDefinition::settingsNamespace() para que los plugins no colisionen con la configuración del núcleo del CMS ni con otros plugins.

Reglas de migración y ciclo de vida de los datos

Las migraciones de los plugins no deben colisionar con las migraciones del núcleo.

Los nombres de las tablas de un plugin deben llevar el prefijo del identificador del plugin o un prefijo abreviado documentado y reservado por el registro de plugins. Para webblocks-ui-manager, los nombres de tabla utilizan webblocks_ui_manager_. La fase 5 reserva los prefijos de base de datos mediante PluginDefinition::databasePrefix() y rechaza los prefijos duplicados.

Los estados del ciclo de vida deben ser distintos:

  • Habilitar: el menú, las rutas, los comandos, las tareas programadas, los widgets, los bloques, los ajustes, las comprobaciones de estado y las acciones del plugin pasan a estar disponibles según los permisos y la compatibilidad.
  • Deshabilitar: el menú, las tareas programadas, las rutas, las acciones, las rutas de ajustes, las comprobaciones de estado, los widgets, los bloques y los recursos del plugin dejan de estar disponibles; los datos permanecen en su sitio.
  • Desinstalar: los plugins deshabilitados subidos manualmente pueden eliminarse de la raíz de instalación gestionada por el almacenamiento. Las tablas de base de datos propiedad del plugin y los datos históricos permanecen en su sitio.
  • Desinstalar: reservado para un diseño futuro; de forma predeterminada no debe eliminar datos.
  • Retirada o purga: futuro flujo destructivo de eliminación de datos que requerirá una confirmación destructiva explícita.

La desinstalación no debe ser destructiva para la base de datos. Eliminar tablas del plugin, artefactos, archivos subidos fuera del directorio del paquete del plugin o registros históricos requiere un diseño de confirmación destructiva explícita e independiente.

Las actualizaciones de esquema deberían ser aditivas y reversibles cuando sea práctico. Una versión de plugin que cambie el esquema debe documentar:

  • versión mínima compatible del CMS
  • versión del plugin que introduce el esquema
  • prefijo de migración/tabla utilizado
  • si los plugins deshabilitados pueden dejar los datos existentes en su sitio de forma segura
  • notas operativas para la reversión o la retirada

El ejecutor manual de migraciones de plugins tiene un alcance deliberadamente limitado. Solo ejecuta los directorios de migración declarados por el plugin instalado y únicamente después de resolver esos directorios dentro de la raíz de instalación de plugins configurada. No ejecuta migraciones de la aplicación anfitriona ni migraciones de otros plugins. Las migraciones de los plugins deberían ser aditivas, reversibles cuando sea práctico y seguras de repetir cuando sea necesario reparar la configuración.

Reglas de recursos y archivos estáticos

Los recursos de un plugin deben publicarse bajo su propio espacio de nombres. No deben mezclarse con los recursos del núcleo en public/cms.

Para WebBlocks UI Manager, la salida versionada de la CDN debería utilizar rutas inmutables como:

public/cdn/webblocks-ui/v2.7.9/...

Reglas de los recursos:

  • los directorios de artefactos versionados son inmutables
  • los directorios versionados antiguos no deben eliminarse como parte de una publicación normal
  • latest no debe utilizarse para el consumo desde la CDN propia
  • la publicación en modo de prueba debe informar de escrituras, omisiones y operaciones bloqueadas sin escribir archivos
  • la publicación efectiva debe validar los archivos dist esperados, las rutas de origen, la versión de publicación, las rutas de destino, las sumas de comprobación y la coherencia del manifiesto antes de escribir
  • los archivos existentes con sumas de comprobación coincidentes se omiten; los archivos existentes con sumas distintas bloquean la ejecución
  • la CDN o el alojamiento estático deberían servirse mediante Nginx u otro servicio estático siempre que sea posible
  • la transmisión de recursos basada en rutas de Laravel no debe ser la opción predeterminada para los archivos de la CDN
  • los recursos de administración de un plugin deben estar aislados de los recursos de administración del núcleo del CMS y publicarse bajo un espacio de nombres del plugin

El flujo de publicación local de WebBlocks UI Manager escribe únicamente en el destino estático configurado propiedad del proyecto, con el valor predeterminado public/cdn/webblocks-ui/{version}/.... No despliega en infraestructura de producción externa, no publica metadatos de servidor de actualizaciones, no cambia las URL de consumo de WebBlocks UI del núcleo del CMS ni instala paquetes remotos.

La fase 3 añade declaraciones de recursos públicos respaldadas por el registro para los plugins habilitados. Estas declaraciones se limitan actualmente a URL de recursos explícitas y se renderizan como recursos de página pública solo cuando el plugin propietario está habilitado:

  • el CSS de head se renderiza como <link rel="stylesheet"> en el <head> público
  • el JS de head se renderiza como etiquetas <script> con defer o async/module en el <head> público
  • el JS de final de cuerpo se renderiza cerca del final del <body> público
  • los identificadores de recursos deben llevar el espacio de nombres con puntos del identificador del plugin, como analytics-tools.public-js
  • los recursos de plugins deshabilitados no se recopilan ni se renderizan

Esto es una base para el hook de aportación de recursos, no un instalador de paquetes de plugin ni un publicador de recursos. Los plugins siguen siendo responsables de publicar sus propios archivos estáticos bajo un espacio de nombres de su propiedad.

Reglas de eventos, hooks y slots de extensión

Los plugins no deben aplicar parches sobre la marcha ni sobrescribir el núcleo. Los slots de extensión del núcleo deben ser explícitos, estar documentados y ser comprobables.

Slots de extensión candidatos iniciales:

  • admin.menu
  • admin.dashboard.widgets
  • admin.system.cards
  • permissions.registry
  • block.registry
  • public.head.assets
  • public.body_end.assets

Los contratos de slot deberían estar tipados y basarse en objetos de valor. Evite en lo posible los contratos de array sin tipo, para que las colisiones, las formas no válidas y la pertenencia puedan validarse pronto.

La fase 3 implementa estos objetos tipados de slot de extensión:

  • PluginDashboardWidget para tarjetas de panel de solo lectura
  • PluginSystemCard para tarjetas o enlaces de sistema de solo lectura
  • PluginBlockTypeDefinition para declaraciones de tipos de bloque propiedad del plugin
  • PluginBlockPackDefinition para declaraciones agrupadas de bloques de plugin
  • PluginPublicAsset para declaraciones de recursos públicos en la cabecera y al final del body
  • PluginAdminExtensionRegistry, PluginBlockRegistry y PluginPublicAssetRegistry para la recopilación exclusiva de elementos habilitados

Las claves de los widgets de panel y de las tarjetas de sistema deben llevar un espacio de nombres con puntos que incluya el handle del plugin, por ejemplo analytics-tools.overview. Los handles de recursos públicos siguen la misma regla de espacio de nombres con puntos. Los handles de bloque de un plugin deben usar un espacio de nombres propiedad del plugin, como analytics-tools::score-card; los handles de bloque sin cualificar al estilo del núcleo, como hero, se rechazan. Estos hooks hacen que las aportaciones de los plugins sean localizables y atribuibles sin sustituir las vistas del paquete del núcleo.

Los widgets de panel se muestran en el panel de super-admin solo cuando el plugin está habilitado y el usuario actual cumple el permiso del widget, si se ha declarado alguno. Las tarjetas de sistema se muestran únicamente en las superficies de resumen del sistema previstas, con las mismas comprobaciones de habilitación y permisos. La página de gestión System -> Plugins no muestra tarjetas genéricas de aportaciones de plugins; se centra en la instalación manual de plugins y en las acciones de ciclo de vida, estado, configuración inicial, ajustes y desinstalación, salvo que en el futuro se diseñe explícitamente un slot de extensión para la gestión de plugins. Ambos slots son, de forma intencionada, bases de solo lectura.

Los hooks de bloque son bases exclusivamente declarativas. Permiten que los plugins habilitados expongan tipos de bloque y packs de bloques propios a través del registro, pero no sustituyen a los contratos de bloque del núcleo, ni a sus vistas, ni a sus seeders, ni a los servicios de edición de bloques.

Ciclo de vida del plugin

El objetivo del ciclo de vida completo:

  1. descubrir
  2. instalar
  3. habilitar
  4. deshabilitar
  5. estado/salud
  6. actualizar
  7. desinstalar o dar de baja, en un diseño posterior con datos destructivos

El objetivo de runtime implementado de la fase 1 a la fase 5 es intencionadamente menor que el ciclo de vida completo:

  • registro
  • configuración de habilitación
  • listado System -> Plugins
  • superficies de detalle y ajustes de solo lectura en System -> Plugins
  • registro de menús de administración
  • registro de permisos
  • registro de rutas de administración solo para plugins habilitados
  • registro de comandos solo para plugins habilitados
  • informes básicos de estado/salud
  • slots de extensión tipados de solo lectura para panel y tarjetas de sistema
  • hooks de declaración de bloques y packs de bloques propiedad del plugin
  • hooks de aportación de recursos públicos en la cabecera y al final del body
  • plugin piloto propio WebBlocks UI Manager con metadatos de versión, preparación segura de manifiestos locales y publicación controlada en CDN local con dry-run/apply
  • metadatos de versión del plugin y de compatibilidad requerida con el CMS
  • informes de estado activo y de salud para plugins incompatibles
  • protecciones de convención de paquete y de colisiones
  • protecciones de pertenencia de rutas

Esa base dota al CMS de un límite de host seguro antes de que los plugins adquieran un comportamiento de ciclo de vida más profundo.

Nota de implementación de la fase 1

El runtime inicial de la fase 1 incluye ahora:

  • los objetos de valor PluginDefinition, PluginRegistry, PluginMenuItem y PluginPermission bajo el espacio de nombres del paquete Support\Plugins
  • validación determinista para handles en kebab-case, handles duplicados, claves de elemento de menú duplicadas, versiones de estilo semver y permisos de plugin prefijados con el handle
  • estado de habilitación respaldado por configuración a través de config/webblocks-plugins.php
  • un listado System -> Plugins propiedad del paquete en /webadmin/system/plugins
  • cobertura de guardas de ruta que demuestra que /webadmin sigue siendo la ruta canónica mientras que las rutas /admin propiedad del CMS y las rutas /cms de Laravel siguen ausentes

La fase 1 no incluye el descubrimiento dinámico de plugins vía Composer, migraciones de plugins, acciones de interfaz de instalación/habilitación/deshabilitación, rutas públicas de plugin, comportamiento de marketplace/catálogo ni la lógica de negocio de WebBlocks UI Manager. El estado de habilitación respaldado por configuración es intencionadamente un puente; una fase posterior del ciclo de vida podría trasladar el estado de instalación/habilitación/deshabilitación a almacenamiento persistente.

Nota de implementación de la fase 2

El runtime de la fase 2 incluye ahora:

  • registro de rutas de administración de plugin solo para plugins habilitados mediante PluginRouteRegistrar
  • URL de administración de plugin por defecto bajo /webadmin/plugins/{plugin-handle}/...
  • nombres de ruta de administración de plugin por defecto bajo webblocks.plugins.{plugin_handle}.*
  • páginas de ajustes de solo lectura por defecto para los plugins habilitados que declaran PluginSettingsDefinition
  • recopilación de comandos de consola solo para plugins habilitados mediante PluginCommandRegistrar
  • PluginHealthResult, PluginLifecycleStatus y PluginHealthMonitor para informes básicos de estado
  • páginas de detalle de System -> Plugins que exponen resúmenes de ciclo de vida, salud, ajustes, rutas, comandos, permisos y aportaciones de menú
  • cobertura de guardas de ruta que demuestra que las rutas de los plugins de prueba habilitados se registran, que las rutas de los plugins deshabilitados están ausentes, que /webadmin sigue siendo canónica, que /cms no es un espacio de nombres de rutas de administración de Laravel y que las rutas /admin propiedad del CMS siguen ausentes

Esta fase deja intencionadamente fuera del alcance el descubrimiento de migraciones, las acciones de instalación/aplicación/ejecución de plugins, las acciones destructivas del ciclo de vida, el descubrimiento dinámico vía Composer, las rutas públicas de plugin y el comportamiento en runtime de WebBlocks UI Manager.

Nota de implementación de la fase 3

El runtime de la fase 3 incluye ahora:

  • contratos tipados de extensión de administración bajo Support\Plugins\Contracts
  • los objetos de valor PluginDashboardWidget y PluginSystemCard recopilados a través de PluginAdminExtensionRegistry
  • renderizado de widgets de panel solo para plugins habilitados en el panel de super-admin
  • recopilación de tarjetas de sistema solo para plugins habilitados en las superficies de resumen del sistema previstas, separada de la página de gestión del ciclo de vida System -> Plugins
  • PluginBlockTypeDefinition, PluginBlockPackDefinition y PluginBlockRegistry para las declaraciones de bloques propiedad del plugin
  • PluginPublicAsset y PluginPublicAssetRegistry para declaraciones seguras de recursos públicos en la cabecera y al final del body
  • guardas de validación para claves de extensión, claves de widget, claves de tarjeta de sistema, handles de bloque, espacios de nombres de packs de bloques, handles de recursos, pertenencia al plugin y declaraciones duplicadas
  • comportamiento inerte de los plugins deshabilitados para widgets de panel, tarjetas de sistema, hooks de bloque y recursos públicos
  • cobertura de guardas de ruta que confirma que /webadmin y /webadmin/plugins/... siguen siendo válidas mientras que las rutas de administración /admin y /cms de Laravel siguen ausentes

Esta fase deja intencionadamente fuera del alcance el comportamiento real de marketplace, la instalación de paquetes, los ejecutores de migraciones de plugins, las rutas públicas de plugin, los widgets editables, los hooks de sustitución de bloques del núcleo y el plugin WebBlocks UI Manager. Los plugins siguen sin poder sustituir vistas del paquete ni parchear servicios del núcleo.

Nota de implementación de la fase 4

El runtime de la fase 4 incluye ahora el plugin piloto propio webblocks-ui-manager. El plugin queda registrado por el registro del paquete, pero está deshabilitado por defecto a través de config/webblocks-plugins.php.

Cuando está habilitado, el piloto aporta:

  • permisos prefijados con el handle: webblocks-ui-manager.view, webblocks-ui-manager.manage y webblocks-ui-manager.publish
  • un espacio de nombres de rutas de administración de plugin bajo /webadmin/plugins/webblocks-ui-manager/... con nombres de ruta bajo webblocks.plugins.webblocks_ui_manager.*
  • un elemento de menú de plugin para los registros de versión de WebBlocks UI
  • tarjetas de panel y de sistema de solo lectura a través de los slots de extensión de la fase 3
  • visibilidad de ajustes/detalle en modo solo lectura mediante la base de ajustes de la fase 2
  • comprobaciones de salud del plugin para la disponibilidad de los metadatos de versión, el estado de configuración requerida/tabla ausente y la disponibilidad de la ruta base de CDN configurada
  • tablas y modelos propiedad del plugin: webblocks_ui_manager_releases, webblocks_ui_manager_artifacts y webblocks_ui_manager_publish_runs
  • un comando local seguro webblocks-ui-manager:prepare-release que registra los metadatos de la versión, calcula las sumas de comprobación SHA-256 de los artefactos y, opcionalmente, puede escribir un manifest.json local
  • un flujo controlado webblocks-ui-manager:publish-release {version} --dry-run y webblocks-ui-manager:publish-release {version} que registra las ejecuciones de publicación y solo escribe cuando la validación se supera
  • convenciones de destino de CDN propias bajo public/cdn/webblocks-ui/{version}/...

El estado deshabilitado sigue siendo inerte: las rutas, los comandos, los menús, las rutas de ajustes, los permisos, las tarjetas de panel y de sistema, el comportamiento de salud y las aportaciones de recursos están ausentes de la recopilación activa. El estado habilitado pero sin configurar sigue siendo seguro: el menú puede estar visible, pero la ruta Releases comprueba la disponibilidad del esquema antes de consultar y muestra indicaciones de configuración requerida cuando faltan las tablas de versiones. Las URL de administración manuales de plugins compatibles y habilitados no deben caer de vuelta al panel cuando la hidratación dinámica de rutas está obsoleta o entra en juego el almacenamiento en caché de rutas; el mecanismo de reserva de rutas de plugin mantiene las páginas de administración de plugin conocidas en su URL /webadmin/plugins/{plugin-handle}/... y rehidrata las rutas y el origen propiedad del plugin antes de mostrar pantallas controladas de configuración u operación. Las acciones Releases de WebBlocks UI Manager propias, las acciones de creación/guardado/visualización/edición/actualización/dry-run/publicación de versiones y las URL de Settings se puentean además a través del núcleo del CMS antes de que se ejecuten los archivos de rutas del plugin, de modo que un origen de artefacto instalado obsoleto no pueda devolver esas acciones al panel.

La fase 4 no añade intencionadamente automatización de despliegue en CDN de producción externa, comportamiento de marketplace, flujos genéricos de instalación/actualización de plugins de terceros, ejecutores genéricos de migraciones de plugins, rutas públicas de plugin, sustituciones de vistas del núcleo, publicación en el servidor de actualizaciones ni cambios en las URL de consumo de WebBlocks UI del núcleo del CMS.

Nota de implementación de la fase 5

El runtime de la fase 5 incluye ahora las bases de empaquetado y de preparación para el ecosistema:

  • comprobaciones de la versión del plugin y de requiresCms() frente a la versión del CMS instalada
  • estado habilitado en configuración separado del estado activo, de modo que los plugins configurados incompatibles permanezcan inertes
  • mensajes de ciclo de vida en System -> Plugins para Enabled, Disabled e Incompatible
  • resultados de salud de plugins incompatibles que no ejecutan los reporteros de salud del plugin
  • metadatos de convención para espacios de nombres de ajustes y prefijos de base de datos/tabla
  • guardas de nombre de comando para clases de comando de Artisan resolubles, que exigen {plugin-handle}:...
  • guardas de colisión de prefijos de base de datos
  • pruebas específicas para los metadatos de compatibilidad, el comportamiento ante incompatibilidades, las colisiones de comandos y prefijos, la inercia en estado deshabilitado/incompatible, la regresión de WebBlocks UI Manager, los límites del paquete y la pertenencia de rutas
  • documentación sobre convenciones de paquete, descubrimiento local, creación mínima de un plugin, estrategia de actualización de esquema y política de compatibilidad entre versiones

La fase 5 no añade intencionadamente una interfaz de marketplace/catálogo, la instalación de paquetes remotos arbitrarios, el descubrimiento dinámico remoto vía Composer, ejecutores genéricos de migraciones de plugins de terceros, el despliegue automático en una CDN de producción externa, la publicación genérica en el servidor de actualizaciones ni rutas públicas de plugin.

Pruebas y salvaguardas de publicación

El sistema de plugins debe estar protegido por pruebas de pertenencia de rutas, de límites del paquete y de coexistencia.

Salvaguardas obligatorias:

  • la pertenencia de las rutas de plugin es comprobable mediante pruebas
  • las instalaciones del núcleo del CMS no muestran menús de plugin cuando no hay ningún plugin habilitado
  • los menús de los plugins deshabilitados no se muestran
  • las rutas y acciones de los plugins deshabilitados no están disponibles o fallan en la autorización
  • los widgets, tarjetas de sistema, declaraciones de bloque y recursos públicos de los plugins deshabilitados están ausentes
  • las rutas, comandos, menús, permisos, widgets, tarjetas de sistema, declaraciones de bloque, recursos públicos, rutas de ajustes y el comportamiento de los reporteros de salud de los plugins incompatibles están ausentes
  • los nombres de comando, los prefijos de base de datos, los handles, los slots de extensión, los widgets, los bloques, los recursos y los espacios de nombres de permisos siguen protegidos frente a colisiones
  • las tarjetas de extensión de panel/sistema de un plugin solo se muestran cuando está habilitado y permitido
  • las declaraciones de bloque propiedad de un plugin son localizables sin sustituir los contratos de bloque del núcleo
  • los recursos públicos de un plugin se recopilan por ubicación segura y están ausentes cuando está deshabilitado
  • el registro de rutas de plugin no debe restaurar un espacio de nombres /admin propiedad del CMS
  • /webadmin sigue siendo el prefijo canónico de administración del CMS
  • /cms sigue siendo territorio de recursos estáticos, no un espacio de nombres de rutas de plugin de Laravel
  • los intentos de un plugin de sustituir tablas, nombres de ruta o vistas del núcleo deberían hacer fallar las pruebas o los diagnósticos
  • las pruebas de límites del paquete se amplían para cubrir rutas, vistas, recursos, migraciones y comandos propiedad de los plugins
  • las pruebas de coexistencia deberían cubrir escenarios de CMS + QuizTem + plugin en la hoja de ruta

Las pruebas de plugins deberían incluir tanto casos sin plugin como casos con plugin deshabilitado, para que el núcleo del CMS siga limpio en instalaciones genéricas. El piloto WebBlocks UI Manager incorpora además pruebas de migración/esquema, de comandos, de manifiesto/suma de comprobación, de solo habilitado, de inercia en estado deshabilitado, de renderizado en administración, de guardas de ruta y de límites del paquete.

Decisiones sobre el plugin piloto WebBlocks UI Manager

WebBlocks UI Manager no está integrado en el comportamiento del núcleo del CMS. Actualmente arranca como plugin piloto propio del paquete, bajo el espacio de nombres del paquete del CMS, para que el host de plugins pueda demostrar una superficie operativa real y específica del producto sin trasladar la gestión de versiones/CDN de WebBlocks UI al núcleo genérico del CMS.

El modelo preferido a largo plazo aún podría convertirse en un paquete de Composer independiente o en un repositorio aparte, una vez que maduren las convenciones de ciclo de vida y de empaquetado de plugins.

La responsabilidad del plugin:

  • registros de artefactos de versión de WebBlocks UI
  • validación del dist de origen
  • preparación local segura de la publicación
  • ejecuciones controladas de publicación estática local en modo dry-run y de aplicación
  • historial de ejecuciones de publicación
  • generación de manifiestos y sumas de comprobación
  • comprobaciones de salud de la CDN

La compilación de WebBlocks UI permanece en el repositorio de WebBlocks UI. El plugin no compila WebBlocks UI: recibe o valida los artefactos de versión, registra metadatos locales para las rutas de CDN propias y puede publicar los archivos validados en el destino estático local o propiedad del proyecto que se haya configurado. El despliegue en una CDN de producción externa se pospone intencionadamente y debe seguir siendo explícito.

Nuestros propios productos pueden consumir cdn.webblocksui.com para los recursos propios fijados a una versión. La documentación destinada a usuarios externos debería seguir recomendando el consumo desde GitHub o desde la CDN jsDelivr, salvo que esa política cambie por separado.

Reglas de CDN para el piloto:

  • utilice rutas versionadas
  • no utilice latest
  • nunca modifique un directorio de artefactos versionado existente
  • no elimine directorios CDN versionados antiguos durante una publicación normal
  • ejecute el dry-run antes de aplicar cuando opere manualmente
  • bloquee las discrepancias de checksum en lugar de reemplazar archivos de forma silenciosa
  • prefiera el servicio estático frente al streaming mediante rutas de Laravel

Flujo de publicación de WebBlocks UI Manager

Prepare los metadatos de la versión y los checksums:

php artisan webblocks-ui-manager:prepare-release v2.7.9 --artifact=/path/to/webblocks-ui.css --artifact=/path/to/webblocks-icons.css --artifact=/path/to/webblocks-ui.js

Ejecute la publicación en modo dry-run:

php artisan webblocks-ui-manager:publish-release v2.7.9 --dry-run

Aplique la publicación local:

php artisan webblocks-ui-manager:publish-release v2.7.9

La pantalla de detalle de versión del administrador expone las mismas acciones de dry-run y de publicación cuando el plugin está habilitado, es compatible y el usuario dispone de webblocks-ui-manager.publish. La acción de publicación real utiliza un modal de confirmación. El dry-run no es destructivo.

Ajustes obligatorios:

  • WEBBLOCKS_UI_MANAGER_ENABLED=true habilita el plugin.
  • WEBBLOCKS_UI_MANAGER_CDN_BASE_PATH=cdn/webblocks-ui controla la raíz estática local, propiedad del proyecto, bajo public/.
  • WEBBLOCKS_UI_MANAGER_CDN_BASE_URL son metadatos de visualización opcionales para las URL públicas generadas.
  • webblocks-plugins.webblocks_ui_manager.expected_dist_files enumera los nombres de archivo dist obligatorios.

Comprobaciones de validación de la publicación:

  • los metadatos de la versión existen y no están en borrador
  • la versión sigue un formato similar a semver
  • la ruta CDN de la versión coincide con la raíz configurada más la versión
  • los archivos dist esperados están presentes
  • los archivos de origen existen dentro de la raíz del proyecto y no son escapes mediante enlaces simbólicos
  • las rutas de destino de los artefactos permanecen dentro de la raíz CDN configurada
  • los checksums almacenados de los artefactos coinciden con los archivos de origen actuales y con los metadatos del manifiesto
  • los archivos ya publicados coinciden con los checksums y se omiten, o bien bloquean la ejecución
  • el contenido del manifiesto existente debe coincidir con el contenido del manifiesto preparado

Las ejecuciones de publicación se almacenan en webblocks_ui_manager_publish_runs con el modo, el estado, las rutas de destino, los detalles de la operación y mensajes de error sin secretos.