Système de plugins de WebBlocks CMS

Ce document consigne l'architecture du système de plugins de WebBlocks CMS. Le cœur du CMS est un hôte de plugins générique doté de définitions de plugins adossées à un registre, d'un téléversement et d'une installation manuels de ZIP par le super admin, de chemins d'installation gérés par storage, de plugins installés désactivés par défaut, d'une gestion explicite de l'activation et de la désactivation, d'une désinstallation des téléversements manuels, de vérifications de compatibilité, de routes et de commandes actives uniquement lorsque le plugin est activé, d'un échafaudage de paramètres et de détail, de rapports de santé et d'état, de slots d'extension typés pour l'administration, de déclarations de blocs appartenant au plugin, de hooks d'assets publics, de garde-fous sur les conventions de paquet, d'un pont d'installation depuis le Plugin Catalog vérifié par somme de contrôle pour les artefacts compatibles du catalogue public, ainsi que d'une action de mise à jour contrôlée, adossée au catalogue, pour les plugins installés disposant de versions compatibles plus récentes. WebBlocks UI Manager n'est plus intégré au runtime du cœur du CMS ; c'est un artefact de plugin interne / opérateur installé manuellement uniquement sur les installations opérateur telles que webblocksui.com. Il n'existe ni place de marché publique, ni boutique de plugins distante complète, ni installateur arbitraire de paquets Composer, ni téléchargement ou mise à jour automatique de plugins externes, ni déploiement automatique de la CDN externe de production de WebBlocks UI, ni publication générique sur un serveur de mises à jour.

Décision fondamentale

Le cœur de WebBlocks CMS est un hôte de plugins.

Le paquet du cœur fournit la surface réutilisable du produit CMS :

  • gestion du contenu et des sites
  • infrastructure de rendu public
  • fondations d'utilisateurs, de rôles et de permissions
  • shell d'administration et surfaces standard de l'interface d'administration
  • découverte des plugins, registre et contrats de slots d'extension

Les capacités propres à un produit ou à un domaine métier ne doivent pas être intégrées au cœur du CMS, sauf si elles font partie du produit CMS réutilisable. Elles doivent être livrées sous forme de plugins afin qu'une installation n'hérite pas des menus, commandes, paramètres, tables de données ou flux opérationnels d'un autre produit.

Les domaines de plugins attendus comprennent :

  • WebBlocks UI Release/CDN Manager
  • intégration QuizTem
  • analytique
  • outils SEO avancés
  • newsletter
  • commerce
  • optimiseur de médias
  • gestionnaire de serveur de mises à jour
  • packs de blocs personnalisés

Frontière entre cœur et plugin

Capacités du cœur :

  • sites, pages, blocs, médias, utilisateurs, langues (locales) et paramètres de base
  • rendu, shell public, layout, slots et infrastructure de blocs
  • fondation des permissions et des rôles
  • shell d'administration et surface standard de l'interface d'administration
  • découverte des plugins, registre et contrats de slots d'extension

Capacités des plugins :

  • écrans d'administration pour un produit ou un domaine métier spécifique
  • un espace de noms de routes appartenant au plugin
  • des permissions appartenant au plugin
  • des paramètres appartenant au plugin
  • des commandes console appartenant au plugin
  • des migrations appartenant au plugin
  • des widgets de tableau de bord appartenant au plugin
  • des blocs ou packs de blocs appartenant au plugin
  • des routes publiques appartenant au plugin, uniquement lorsqu'elles sont déclarées explicitement

La surcharge des vues du cœur est interdite par défaut. Les plugins étendent le CMS uniquement via des slots d'extension documentés et des contrats de registre. Un plugin ne doit pas remplacer les vues du paquet, patcher les services du cœur, ajouter des fichiers de routes cachés ni s'appuyer sur des effets de bord d'inclusions arbitraires.

Installation manuelle par ZIP

System -> Plugins permet aux super admins de téléverser un ZIP de plugin local. Téléverser un ZIP constitue une installation privilégiée de code exécutable. L'installateur valide l'archive avant d'écrire quoi que ce soit sous la racine de plugins configurée, par défaut storage/app/webblocks/plugins/{plugin-handle}/{version}.

La validation exige webblocks-plugin.json ou manifest.json, un handle en kebab-case, une version de type semver, des métadonnées de provider / classe, une contrainte de version CMS compatible, l'absence de collision avec un handle déjà installé, uniquement des chemins relatifs au paquet, aucun path traversal, aucun chemin absolu, aucune entrée de lien symbolique et aucune écriture vers des cibles interdites du CMS ou du cœur telles que app, packages, project, storage, vendor ou public/cms. Les plugins installés restent désactivés tant qu'une étape d'activation explicite n'a pas été effectuée. Les plugins désactivés sont inertes : routes, commandes, menus, routes de paramètres, rapporteurs de santé, widgets, déclarations de blocs et assets ne sont ni enregistrés ni exécutés, et System -> Plugins indique une santé inactive ou non vérifiée.

La désinstallation manuelle n'est disponible que pour les plugins téléversés manuellement et requiert une autorisation de super admin. Le plugin doit d'abord être désactivé. La désinstallation supprime le répertoire de paquet du plugin installé et le fichier d'état d'activation sous la racine de plugins configurée, mais elle ne supprime pas les tables de base de données appartenant au plugin et n'exécute aucune migration destructive. Les plugins protégés, du cœur ou non manuels ne peuvent pas être désinstallés par ce flux.

Les champs de manifeste pris en charge comprennent handle, label, description, version, provider, required_cms_version, permissions, commands, routes, settings, migrations, assets et health. Les migrations sont installées comme fichiers appartenant au plugin et ne sont jamais exécutées automatiquement au téléversement ou à l'activation. Les super admins peuvent lancer l'action explicite de setup du plugin depuis l'écran de détail du plugin ; le runner restreint l'exécution au chemin du plugin installé et aux répertoires de migration déclarés dans le manifeste, enregistre les résultats du setup dans l'état d'activation et peut réparer un plugin nécessitant un setup dont les enregistrements de migration existent mais dont les tables requises sont absentes.

Le cycle de vie manuel d'un plugin est le suivant :

  1. Téléversez et installez le ZIP. Le plugin est désactivé par défaut.
  2. Examinez l'écran de détail du plugin.
  3. Activez le plugin lorsqu'il est compatible.
  4. Lancez le setup ou les migrations du plugin si l'écran de détail signale Setup required ou Plugin migrations pending.
  5. Utilisez les routes opérationnelles du plugin une fois le setup prêt.
  6. Désactivez le plugin pour rendre inertes les routes, commandes, menus, paramètres, contrôles de santé et contributions.
  7. Ne désinstallez qu'après la désactivation ; la désinstallation préserve les tables appartenant au plugin.

Les plugins activés dont le setup est en attente ne doivent pas faire échouer les routes d'administration. Si des tables appartenant au plugin manquent, les écrans de santé et de routes doivent afficher des indications de setup requis telles que Plugin migrations pending ou Release tables are missing.

Les routes d'administration du plugin doivent utiliser des permissions déclarées et préfixées par le handle. Les utilisateurs super_admin du CMS sont explicitement autorisés pour les permissions des plugins actifs et activés, y compris celles chargées depuis les manifestes de plugins installés manuellement. Les rôles non super admin restent refusés, sauf si un futur modèle d'attribution des permissions du CMS accorde la permission spécifique appartenant au plugin. Les routes de paramètres utilisent {plugin-handle}.manage lorsque le plugin la déclare, sinon elles se rabattent sur l'accès système.

Les routes d'administration des plugins activés et compatibles s'exécutent toujours dans la pile de routes d'administration du CMS : web, installation requise, authentification CMS, accès administration CMS, garde de setup du plugin, puis le middleware de permission appartenant au plugin lorsque la route du plugin le déclare. Le middleware d'authentification du CMS utilise le guard web et l'utilisateur de session de Laravel, tout en redirigeant les invités via la route webblocks.auth.login appartenant au CMS. Les gardes de setup de plugin sont additives et ne doivent pas remplacer l'authentification du CMS ni l'autorisation d'administration ; les contrôleurs de plugin peuvent compter sur la présence de l'utilisateur CMS authentifié une fois le middleware d'authentification et d'administration franchi.

Contrat du plugin et manifeste

Tout plugin doit posséder un handle :

  • en kebab-case
  • globalement unique au sein de l'installation
  • stable d'une version à l'autre
  • utilisé comme préfixe par défaut pour les permissions, routes, tables, paramètres, assets et l'identité du paquet

Chaque plugin doit déclarer ses métadonnées via un manifeste ou un objet de définition :

  • handle
  • label
  • version
  • classe provider
  • description optionnelle
  • version de CMS requise ou contrainte de version
  • espace de noms des paramètres
  • préfixe de base de données / de tables
  • permissions
  • entrées du menu d'administration
  • routes d'administration et publiques
  • commandes console
  • schéma de paramètres ou pages de paramètres
  • migrations
  • blocs ou packs de blocs
  • assets
  • contrôles de santé, lorsqu'ils sont pris en charge

Les plugins sont registry-first : ils se connectent au CMS via des contrats explicites, et non via des inclusions arbitraires, des surcharges de vues à la racine ou des fichiers de routes propres à l'installation.

Les plugins installés mis à jour depuis le catalogue sont rechargés via le rafraîchissement du runtime du cœur du CMS après l'écriture du paquet de remplacement. Ce rafraîchissement vide l'état du registre des plugins, des permissions, des extensions, de la santé et du cache optimisé du runtime Laravel, puis reconstruit les routes actives des plugins pour le runtime courant, afin que la version installée, la version active du manifeste, les métadonnées du provider actif et le chemin source des routes et contrôleurs restent alignés. Si une classe provider issue d'une version antérieure du paquet installé est déjà chargée dans le même processus PHP, le CMS considère ce provider comme obsolète et se rabat sur les métadonnées du manifeste mises à jour plutôt que de réutiliser les anciens chemins de routes.

L'autorisation des plugins est résolue de façon centralisée par le cœur du CMS. Les permissions actives appartenant au plugin, déclarées par le plugin activé, autorisent les utilisateurs super_admin du CMS, et le même résolveur sert à la visibilité du menu du plugin, aux contributions au tableau de bord et au système ainsi qu'au middleware de route plugin.permission:*. Les utilisateurs non autorisés ne voient pas les entrées de menu correspondantes ; l'accès direct par URL reste un 403 contrôlé. La gestion du setup requis intervient après l'autorisation, et les migrations de plugin restent explicites.

Forme actuelle de l'API du registre :

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);

L'API exacte peut évoluer pendant l'implémentation, mais le contrat doit préserver ces règles :

  • les métadonnées déclarées sont inspectables avant l'activation d'un plugin
  • la propriété des menus, routes, permissions, commandes, migrations, blocs, assets et paramètres est attribuable à un handle de plugin
  • les conflits échouent pendant le build, les tests, les diagnostics de démarrage ou l'activation du plugin, avant que les utilisateurs ne constatent une propriété mêlée

Règles de convention des paquets

Les conventions des paquets de plugins sont distinctes de celles du cœur du CMS. Le cœur du CMS possède les contrats de l'hôte ; les plugins possèdent le comportement de leur domaine.

  • Nommage du handle : utilisez un kebab-case stable tel que analytics-tools ; ne renommez jamais un handle après publication, car il ancre les routes, permissions, paramètres, tables, assets et l'historique de mise à niveau.
  • Enregistrement du service provider : un paquet de plugin doit exposer un seul service provider Laravel et y enregistrer sa PluginDefinition, ou le faire via le point d'intégration du registre du CMS. Les pilotes internes inclus dans le paquet peuvent s'enregistrer directement depuis le provider du paquet CMS jusqu'à leur séparation en paquets Composer distincts.
  • Structure de la définition ou du manifeste : déclarez explicitement handle, label, version, provider, description, requiresCms, l'espace de noms des paramètres, le préfixe de base de données, les permissions, les routes, les commandes, les slots d'extension, les assets, les blocs et le rapporteur de santé.
  • Espace de noms des routes : les routes d'administration se trouvent sous /webadmin/plugins/{plugin-handle}/... avec des noms sous webblocks.plugins.{plugin_handle}.*.
  • Nommage des permissions : toute permission de plugin commence par {plugin-handle}., par exemple analytics-tools.view.
  • Conventions de paramètres : les espaces de noms de paramètres sont en snake_case et correspondent par défaut au handle dont les tirets sont convertis en underscores.
  • Nommage des commandes : les noms de commandes Artisan résolvables doivent commencer par {plugin-handle}:, par exemple analytics-tools:sync.
  • Nommage des migrations et des tables : les tables utilisent un préfixe snake_case réservé par le registre et terminé par _, par défaut le handle converti en snake_case suivi de _.
  • Contributions d'assets : les handles d'assets publics sont préfixés par le handle du plugin séparé par un point, et les fichiers statiques doivent être publiés sous un chemin appartenant au plugin.
  • Contributions de cartes de tableau de bord et de système : les clés sont préfixées par le handle du plugin séparé par un point et restent en lecture seule, sauf si un contrat d'extension ultérieur ajoute un comportement modifiable.

WebBlocks UI Manager suit ces conventions en tant que pilote interne : handle webblocks-ui-manager, espace de noms de paramètres webblocks_ui_manager, préfixe de base de données webblocks_ui_manager_, commandes webblocks-ui-manager:prepare-release et webblocks-ui-manager:publish-release, routes sous /webadmin/plugins/webblocks-ui-manager et noms de routes sous webblocks.plugins.webblocks_ui_manager.*.

Compatibilité et inertie

Les versions de plugins sont des métadonnées de type semver. requiresCms() déclare la contrainte de version CMS requise par le plugin. La base actuelle prend en charge les contraintes exactes ou à comparateur telles que >=1.32.0 et les contraintes à caret telles que ^1.32.

Le registre distingue l'état d'activation configuré de l'état actif :

  • Activé par configuration : config/webblocks-plugins.php indique que le plugin doit être activé.
  • Compatible : la version de CMS installée satisfait la contrainte CMS requise par le plugin.
  • Actif : le plugin est à la fois activé par configuration et compatible.

Seuls les plugins actifs apportent des menus, routes, commandes, routes de paramètres, widgets de tableau de bord, cartes système, déclarations de blocs, assets publics, permissions et l'exécution du rapporteur de santé. Les plugins désactivés et incompatibles restent inertes. System -> Plugins affiche Incompatible avec les versions de CMS requise et installée lorsqu'un plugin configuré ne peut pas s'activer.

Découverte et activation locale

La phase 5 n'ajoute ni comportement de place de marché ni installation distante arbitraire. La découverte sûre est locale et explicite :

  • les plugins internes inclus dans le paquet peuvent être enregistrés par le provider du paquet CMS
  • les futurs plugins distribués comme paquets Composer doivent enregistrer un service provider via le package discovery de Laravel ou une configuration explicite du provider de l'application
  • les expérimentations locales à l'installation peuvent utiliser des dépôts Composer de type path pendant le développement, mais elles doivent tout de même enregistrer un provider et une définition normaux
  • l'activation reste adossée à la configuration via webblocks-plugins.enabled.{plugin-handle}

Aucune fonctionnalité d'exécution n'installe de paquets Composer arbitraires, ne publie de catalogues de place de marché, n'écrit d'artefacts de CDN ou de serveur de mises à jour de production, n'active automatiquement des plugins, n'exécute automatiquement les migrations ou le setup des plugins, ni ne procède à des mises à jour automatiques de plugins. Les ponts vers des artefacts distants de plugins se limitent aux actions d'installation et de mise à jour du Plugin Catalog déclenchées par un super admin et décrites ci-dessous, toutes deux restreintes à des URL ZIP contrôlées du catalogue avec des métadonnées SHA-256 correspondantes.

Orientation du catalogue de l'écosystème

Le système de plugins du CMS est le premier hôte d'implémentation d'une orientation plus large pour l'écosystème de plugins WebBlocks. Les futurs contrats de plugins doivent être réutilisables par WebBlocks CMS, QuizTem, Herne Panel, WebBlocks Publisher et les produits WebBlocks ultérieurs, chaque hôte exposant ses propres points d'extension spécifiques au produit.

La surface de catalogue / boutique proposée est plugins.webblocksui.com. L'objectif à court terme est un Plugin Catalog pour la découverte, les métadonnées, la compatibilité, la documentation, les informations de version, les sommes de contrôle, des liens de téléchargement ZIP contrôlés et un pont d'installation conservateur à partir de métadonnées d'artefacts de catalogue de confiance. Le comportement de place de marché, y compris comptes, licences, plugins payants, avis et flux d'approbation, est reporté.

System -> Plugins comprend une action Browse Plugin Catalog à l'adresse /webadmin/plugins/catalog (admin.plugins.catalog.index). La liste du catalogue demande les plugins publics référencés pour host_product=webblocks-cms à GET /api/plugins et sollicite la dernière version compatible via GET /api/plugins/{handle}/latest lorsqu'un identifiant est disponible. Les libellés des plugins du catalogue et l'action View details ouvrent /webadmin/plugins/catalog/{handle} (admin.plugins.catalog.show), qui interroge GET /api/plugins/{handle} ainsi que le point de terminaison de la dernière version compatible afin d'afficher les métadonnées du plugin, la compatibilité, les notes de version, les liens de documentation/support, l'URL de téléchargement de l'artefact, la somme de contrôle SHA-256, le nom de fichier de l'artefact, la taille de l'artefact, l'état de la version, l'état de validation de l'artefact, l'état d'analyse de l'artefact, le canal, la version et les métadonnées sûres des capacités déclarées lorsque l'API les renvoie. Les réponses de détail actuelles de l'API WebBlocks Plugins peuvent renvoyer les données du plugin directement sous data, les données de version sous data.latest_release et les métadonnées d'artefact sous data.latest_release.artifact ; les réponses de l'API de dernière version compatible peuvent aussi renvoyer les métadonnées de version sous data.release, avec les métadonnées d'artefact dans l'élément voisin data.artifact. Le CMS normalise ces formes avant d'afficher les détails, de vérifier la disponibilité d'installation ou de traiter l'action d'installation depuis le catalogue côté serveur. Les champs d'artefact pris en charge comprennent file_name, size_bytes, checksum_sha256, download_url, validation_status et scan_status ; les anciens noms de champs plats de version restent acceptés pour la compatibilité. La version canonique du produit WebBlocks CMS est envoyée sous version et cms_version pour la correspondance de compatibilité. L'URL du catalogue public intégrée vaut par défaut https://plugins.webblocksui.com ; les opérateurs n'ont pas besoin de modifier .env pour la découverte par défaut et peuvent remplacer la cible interne des requêtes avec WEBBLOCKS_PLUGIN_CATALOG_BASE_URL (webblocks-plugins.catalog.base_url). Les réglages de délai d'attente sont disponibles via WEBBLOCKS_PLUGIN_CATALOG_TIMEOUT_SECONDS et WEBBLOCKS_PLUGIN_CATALOG_CONNECT_TIMEOUT_SECONDS. L'interface normale du catalogue n'expose ni l'URL de base configurée ni la version de la requête ; les états d'indisponibilité utilisent des textes clairs pour l'opérateur, tandis que les diagnostics sûrs restent dans les journaux.

Le détail du catalogue conserve les liens Website, Documentation, Support et Catalog Detail séparés des actions d'installation. La page affiche un état clair d'artefact indisponible lorsqu'une version compatible ne comporte pas de métadonnées d'artefact téléchargeable. L'action Download ZIP n'ouvre que l'URL download_url publique absolue et contrôlée renvoyée par le catalogue, et ne doit pas exposer de chemins de stockage bruts.

Install from Catalog n'est disponible que lorsque le plugin du catalogue est compatible, que la dernière version compatible est published et que l'artefact normalisé de la version comporte les valeurs download_url, checksum_sha256 et file_name. Les anciens champs plats de version sha256/checksum_sha256 et filename/artifact_filename restent acceptés pour la compatibilité. L'action POST utilise CSRF, relit les métadonnées du catalogue côté serveur, télécharge l'URL ZIP contrôlée vers un stockage temporaire, vérifie la réussite HTTP, rejette les réponses déraisonnables ou non-ZIP, calcule le SHA-256, le compare exactement aux métadonnées du catalogue, puis transmet le ZIP temporaire au validateur/installateur ZIP de plugins manuel existant. Les fichiers temporaires sont supprimés après succès ou échec, et les noms de fichiers du catalogue ou distants ne sont pas considérés comme des chemins de système de fichiers fiables.

Les installations depuis le catalogue enregistrent le plugin désactivé par défaut, comme le téléversement manuel. Elles n'activent pas le plugin, n'exécutent pas les migrations/la configuration du plugin, n'exécutent pas le code du fournisseur du plugin, n'enregistrent pas de routes de plugin, pas de permissions, pas de commandes, pas de ressources, pas de blocs, n'ajoutent pas de cartes de tableau de bord/système, n'appliquent pas de mises à jour et ne modifient pas l'état d'activation. Tout état local installé/activé affiché sur la page de détail du catalogue provient uniquement du registre des plugins du CMS, et non des déclarations du catalogue distant. Le téléversement/l'installation manuelle de ZIP reste disponible et inchangé.

System -> Plugins -> Registered Plugins effectue, dans la mesure du possible, une recherche de disponibilité dans le catalogue pour les identifiants des plugins installés. Lorsque le catalogue est indisponible ou ne fournit pas de métadonnées fiables, la liste s'affiche tout de même et aucune action de mise à jour n'est proposée. Lorsqu'un identifiant installé dispose d'une dernière version compatible plus récente selon version_compare, que cette version est published, que le plugin est compatible et que l'artefact normalisé comporte download_url, checksum_sha256 et file_name, la colonne Version affiche Update available: {version} et le groupe d'actions de la ligne affiche une action iconique Update from Catalog en POST uniquement.

Le POST de mise à jour relit côté serveur les métadonnées de détail/de dernière version du catalogue, exige les mêmes métadonnées d'artefact complètes, publiées et compatibles, télécharge le ZIP contrôlé, vérifie le SHA-256, valide le ZIP avec le même validateur de paquets de plugin et remplace la version du paquet du plugin installé. Les tables de base de données appartenant au plugin sont conservées, l'état de cycle de vie activé ou désactivé est préservé en reportant l'état activé sur la nouvelle version uniquement si l'ancienne version était activée, et les migrations du plugin ne sont pas exécutées automatiquement. Si le plugin mis à jour déclare de nouvelles migrations ou si ses tables sont absentes, les indications existantes de configuration requise et le flux explicite Run Plugin Migrations restent responsables de la mise en place du schéma.

Consultez WebBlocks Plugin Ecosystem And Catalog pour l'orientation au niveau produit et le plan par phases.

La planification de la surface produit proposée plugins.webblocksui.com, le périmètre du MVP, les modèles d'implémentation candidats, les pages publiques du catalogue, les surfaces opérateur et la forme possible d'une API en lecture seule figurent dans Plugin Catalog Product Architecture.

Exemple minimal de plugin

Un paquet de plugin minimal devrait exposer un fournisseur et une définition semblables à :

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);
  }
}

Le fournisseur devrait enregistrer les vues, la configuration, les migrations du paquet et la définition du plugin sans ajouter de fichiers de routes publiques appartenant au CMS sous /admin, /cms ou à la racine. Les routes du plugin devraient être définies relativement au groupe de routes du plugin ; par exemple, /reports devient /webadmin/plugins/analytics-tools/reports.

Règles du menu d'administration

Les plugins peuvent ajouter des entrées au menu d'administration, mais chaque entrée de menu d'un plugin doit être soumise à une permission.

Le comportement à privilégier consiste à ajouter des éléments aux groupes d'administration existants, tels que :

  • System
  • Tools
  • Integrations

Un menu de plugin de premier niveau ne peut être réservé qu'à une surface produit importante qui prêterait à confusion en tant qu'élément unique d'un groupe.

Règles du menu d'administration :

  • les icônes doivent provenir du catalogue d'icônes de WebBlocks UI
  • les noms de routes doivent relever de l'espace de noms de routes du plugin
  • l'ordre du menu et les règles de collision doivent être gérés par le registre
  • les plugins désactivés ou désinstallés ne doivent pas afficher d'entrées de menu
  • les libellés des éléments de menu devraient décrire la capacité, sans faire apparaître des noms de projet propres à une installation dans des installations CMS génériques
  • les entrées de menu ne doivent pas apparaître dans les installations du cœur lorsque le plugin propriétaire est absent

Règles de l'espace de noms des routes

Les routes d'administration des plugins utilisent par défaut ce préfixe d'URL :

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

Les noms des routes d'administration des plugins utilisent par défaut cet espace de noms :

webblocks.plugins.{plugin_handle}.*

L'espace de noms des noms de routes utilise l'identifiant du plugin, transformé uniquement dans la mesure requise par les noms de routes de Laravel. Par exemple, webblocks-ui-manager devient webblocks.plugins.webblocks_ui_manager.* si l'implémentation exige des tirets bas.

Un plugin ne peut demander un préfixe d'administration plus court que via le registre. Les préfixes courts réservés doivent être globalement uniques. Les conflits de préfixe doivent provoquer un échec lors de la compilation, des tests, des diagnostics de démarrage ou de l'activation du plugin.

Les plugins ne doivent pas polluer :

  • les noms de routes du cœur du CMS
  • l'espace de noms de routes du cœur /webadmin en dehors de leur préfixe de plugin réservé
  • l'espace de noms hérité /admin
  • l'espace de noms des ressources statiques /cms

Les plugins désactivés et incompatibles ne doivent pas enregistrer de routes d'administration. L'enregistreur limité aux éléments actifs est volontairement prudent : si un plugin est désactivé via config/webblocks-plugins.php ou ne satisfait pas sa contrainte de version du CMS, ses routes sont absentes plutôt que présentes mais interdites.

Les routes publiques relèvent d'une adhésion explicite. Un plugin qui déclare des routes publiques doit en déclarer la propriété de façon suffisamment claire pour que celle-ci puisse être testée. Les routes publiques d'un plugin doivent éviter les collisions avec les pages du site, les routes publiques du CMS et les routes du produit hôte.

Règles de permissions

Chaque menu d'administration, route et action doit être rattaché à une permission du plugin.

Les noms des permissions doivent comporter le préfixe de l'identifiant du plugin :

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

Le comportement des permissions doit rester compatible avec le modèle de permissions du CMS. Si un contournement pour le super administrateur existe, il doit emprunter le même chemin d'autorisation explicite du CMS que les permissions du cœur.

Les permissions d'un plugin doivent être visibles dans la gestion des rôles de l'administration lorsque le plugin est installé ou détectable. Les permissions d'un plugin désactivé ne doivent autoriser aucun comportement actif, même si un rôle conserve une chaîne de permission correspondante.

Règles de réglages

Les réglages d'un plugin doivent être stockés dans son propre espace de noms. Ils ne doivent pas entrer en collision avec la configuration générale du CMS, la configuration de l'application hôte ou les variables d'environnement.

Règles des réglages :

  • les clés de réglages devraient être préfixées par l'identifiant du plugin
  • les valeurs sensibles doivent utiliser un stockage sûr pour les secrets lorsqu'il est disponible
  • les valeurs sensibles ne doivent jamais apparaître dans les journaux, la sortie des contrôles de santé, les messages d'exception ou les messages flash de l'administration
  • l'interface des réglages doit se trouver dans l'espace de noms de routes du plugin ou à l'intérieur de System -> Plugins -> Plugin detail
  • les variables d'environnement peuvent fournir des valeurs par défaut initiales, mais les réglages d'exécution devraient rester la propriété du plugin et rester inspectables via le registre

La phase 2 fournit une base de route de réglages en lecture seule pour les plugins activés qui déclarent PluginSettingsDefinition sans nom de route personnalisé. La route par défaut est :

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

Son nom de route par défaut est :

webblocks.plugins.{plugin_handle}.settings.edit

Le stockage modifiable des réglages et les schémas de validation sont réservés à une phase ultérieure. La phase 5 réserve les espaces de noms de réglages via PluginDefinition::settingsNamespace() afin que les plugins n'entrent pas en collision avec la configuration du cœur du CMS ou avec d'autres plugins.

Règles de migration et de cycle de vie des données

Les migrations des plugins ne doivent pas entrer en collision avec les migrations du cœur.

Les noms de tables d'un plugin doivent porter le préfixe de l'identifiant du plugin ou un préfixe abrégé documenté et réservé par le registre des plugins. Pour webblocks-ui-manager, les noms de tables utilisent webblocks_ui_manager_. La phase 5 réserve les préfixes de base de données via PluginDefinition::databasePrefix() et rejette les préfixes en double.

Les états du cycle de vie doivent être distincts :

  • Activation : le menu, les routes, les commandes, les tâches planifiées, les widgets, les blocs, les réglages, les contrôles de santé et les actions du plugin deviennent disponibles selon les permissions et la compatibilité.
  • Désactivation : le menu, les tâches planifiées, les routes, les actions, les routes de réglages, les contrôles de santé, les widgets, les blocs et les ressources du plugin sont indisponibles ; les données restent en place.
  • Désinstallation : les plugins désactivés téléversés manuellement peuvent être retirés de la racine d'installation gérée par le stockage. Les tables de base de données appartenant au plugin et les données historiques restent en place.
  • Désinstallation : réservée à une conception future ; par défaut, elle ne doit pas supprimer de données.
  • Mise hors service ou purge : futur flux destructif de suppression de données exigeant une confirmation destructive explicite.

La désinstallation ne doit pas être destructive pour la base de données. Supprimer les tables du plugin, les artefacts, les fichiers téléversés hors du répertoire du paquet du plugin ou les enregistrements historiques nécessite une conception distincte avec confirmation destructive explicite.

Les mises à niveau de schéma devraient être additives et réversibles lorsque c'est possible. Une version de plugin qui modifie le schéma doit documenter :

  • la version minimale compatible du CMS
  • la version du plugin qui introduit le schéma
  • le préfixe de migration/de table utilisé
  • si les plugins désactivés peuvent laisser les données existantes en place en toute sécurité
  • les notes opérationnelles pour la restauration ou la mise hors service

L'exécuteur manuel des migrations de plugins a une portée volontairement restreinte. Il n'exécute que les répertoires de migration déclarés par le plugin installé, et uniquement après avoir résolu ces répertoires à l'intérieur de la racine d'installation des plugins configurée. Il n'exécute ni les migrations de l'application hôte ni les migrations d'autres plugins. Les migrations des plugins devraient être additives, réversibles lorsque c'est possible et sûres à relancer lorsqu'une réparation de la configuration est nécessaire.

Règles relatives aux ressources et aux fichiers statiques

Les ressources d'un plugin doivent être publiées sous leur propre espace de noms. Elles ne doivent pas se mélanger aux ressources du cœur situées dans public/cms.

Pour WebBlocks UI Manager, la sortie CDN versionnée devrait utiliser des chemins immuables tels que :

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

Règles relatives aux ressources :

  • les répertoires d'artefacts versionnés sont immuables
  • les anciens répertoires versionnés ne doivent pas être supprimés lors d'une publication normale
  • latest ne doit pas être utilisé pour la consommation depuis le CDN propriétaire
  • la publication en mode simulation doit signaler les écritures, les éléments ignorés et les opérations bloquées sans écrire de fichiers
  • la publication effective doit valider les fichiers dist attendus, les chemins source, la version de la release, les chemins cibles, les sommes de contrôle et la cohérence du manifeste avant d'écrire
  • les fichiers existants dont la somme de contrôle correspond sont ignorés ; les fichiers existants dont la somme diffère bloquent l'exécution
  • le CDN ou l'hébergement statique devrait être servi par Nginx ou un autre service statique lorsque c'est possible
  • la diffusion de ressources via des routes Laravel ne doit pas être le mode par défaut pour les fichiers CDN
  • les ressources d'administration d'un plugin doivent être isolées des ressources d'administration du cœur du CMS et publiées sous un espace de noms du plugin

Le processus de publication locale de WebBlocks UI Manager n'écrit que dans la cible statique configurée appartenant au projet, par défaut public/cdn/webblocks-ui/{version}/.... Il ne déploie pas vers une infrastructure de production externe, ne publie pas de métadonnées de serveur de mises à jour, ne modifie pas les URL de consommation de WebBlocks UI du cœur du CMS et n'installe pas de paquets distants.

La phase 3 ajoute des déclarations de ressources publiques adossées au registre pour les plugins activés. Ces déclarations se limitent actuellement à des URL de ressources explicites et ne sont restituées comme ressources de page publique que lorsque le plugin propriétaire est activé :

  • le CSS de head est restitué sous forme de <link rel="stylesheet"> dans le <head> public
  • le JS de head est restitué sous forme de balises <script> avec defer ou async/module dans le <head> public
  • le JS de fin de corps est restitué près de la fin du <body> public
  • les identifiants de ressources doivent être préfixés, séparés par un point, avec l'identifiant du plugin, par exemple analytics-tools.public-js
  • les ressources des plugins désactivés sont absentes de la collecte et du rendu

Il s'agit d'une base de hook de contribution de ressources, et non d'un installateur de paquets de plugin ni d'un publicateur de ressources. Les plugins restent responsables de la publication de leurs propres fichiers statiques sous un espace de noms leur appartenant.

Règles relatives aux événements, aux hooks et aux slots d'extension

Les plugins ne doivent pas recourir au monkey patching ni surcharger le cœur. Les slots d'extension du cœur doivent être explicites, documentés et testables.

Premiers slots d'extension candidats :

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

Les contrats de slot devraient être typés et fondés sur des objets valeur. Évitez autant que possible les contrats à tableau brut, afin que les collisions, les formes invalides et la propriété puissent être validées tôt.

La phase 3 implémente ces objets typés de slot d'extension :

  • PluginDashboardWidget pour les cartes de tableau de bord en lecture seule
  • PluginSystemCard pour les cartes ou liens système en lecture seule
  • PluginBlockTypeDefinition pour les déclarations de types de bloc appartenant au plugin
  • PluginBlockPackDefinition pour les déclarations groupées de blocs de plugin
  • PluginPublicAsset pour les déclarations d'assets publics dans le head et en fin de body
  • PluginAdminExtensionRegistry, PluginBlockRegistry et PluginPublicAssetRegistry pour la collecte des seuls éléments activés

Les clés des widgets de tableau de bord et des cartes système doivent être préfixées par un espace de noms pointé contenant le handle du plugin, par exemple analytics-tools.overview. Les handles d'assets publics suivent la même règle d'espace de noms pointé. Les handles de bloc d'un plugin doivent utiliser un espace de noms appartenant au plugin, tel que analytics-tools::score-card ; les handles de bloc non qualifiés de style cœur, comme hero, sont rejetés. Ces hooks rendent les contributions des plugins repérables et attribuables sans remplacer les vues du paquet du cœur.

Les widgets de tableau de bord ne s'affichent sur le tableau de bord super-admin que lorsque le plugin est activé et que l'utilisateur courant satisfait la permission du widget, si elle est déclarée. Les cartes système ne s'affichent que sur les surfaces de vue d'ensemble système prévues, sous les mêmes contrôles d'activation et de permission. La page de gestion System -> Plugins n'affiche pas de cartes génériques de contribution de plugin ; elle reste centrée sur l'installation manuelle des plugins et sur les actions de cycle de vie, d'état de santé, de configuration initiale, de paramètres et de désinstallation, sauf si un slot d'extension dédié à la gestion des plugins est explicitement conçu plus tard. Les deux slots sont volontairement des fondations en lecture seule.

Les hooks de bloc sont des fondations purement déclaratives. Ils permettent aux plugins activés d'exposer des types de bloc et des packs de blocs qui leur appartiennent via le registre, mais ils ne remplacent ni les contrats de bloc du cœur, ni ses vues, ni ses seeders, ni les services d'édition de blocs.

Cycle de vie du plugin

L'objectif du cycle de vie complet :

  1. découvrir
  2. installer
  3. activer
  4. désactiver
  5. état/santé
  6. mettre à niveau
  7. désinstaller ou mettre hors service, dans une conception ultérieure aux effets destructifs

L'objectif de runtime implémenté de la phase 1 à la phase 5 est volontairement plus restreint que le cycle de vie complet :

  • registre
  • configuration d'activation
  • liste System -> Plugins
  • surfaces de détail et de paramètres en lecture seule dans System -> Plugins
  • enregistrement des menus d'administration
  • enregistrement des permissions
  • enregistrement des routes d'administration pour les seuls plugins activés
  • enregistrement des commandes pour les seuls plugins activés
  • rapports d'état/de santé de base
  • slots d'extension typés en lecture seule pour le tableau de bord et les cartes système
  • hooks de déclaration de blocs et de packs de blocs appartenant au plugin
  • hooks de contribution d'assets publics dans le head et en fin de body
  • plugin pilote maison WebBlocks UI Manager avec métadonnées de version, préparation sécurisée du manifeste local et publication contrôlée sur CDN local en dry-run/apply
  • métadonnées de version du plugin et de compatibilité CMS requise
  • rapports d'état actif et de santé pour les plugins incompatibles
  • garde-fous de convention de paquet et de collision
  • garde-fous de propriété des routes

Cette fondation dote le CMS d'une frontière d'hôte sûre avant que les plugins n'acquièrent un comportement de cycle de vie plus poussé.

Note d'implémentation de la phase 1

Le runtime initial de la phase 1 comprend désormais :

  • les objets valeur PluginDefinition, PluginRegistry, PluginMenuItem et PluginPermission dans l'espace de noms du paquet Support\Plugins
  • une validation déterministe des handles en kebab-case, des handles en double, des clés d'élément de menu en double, des versions de style semver et des permissions de plugin préfixées par le handle
  • un état d'activation adossé à la configuration via config/webblocks-plugins.php
  • une liste System -> Plugins appartenant au paquet à l'adresse /webadmin/system/plugins
  • une couverture par garde-fous de routes prouvant que /webadmin reste canonique tandis que les routes /admin appartenant au CMS et les routes Laravel /cms restent absentes

La phase 1 n'inclut ni la découverte dynamique de plugins via Composer, ni les migrations de plugins, ni les actions d'interface d'installation/activation/désactivation, ni les routes publiques de plugin, ni un comportement de place de marché/catalogue, ni la logique métier de WebBlocks UI Manager. L'état d'activation adossé à la configuration est volontairement une passerelle ; une phase ultérieure du cycle de vie pourra déplacer l'état d'installation/activation/désactivation vers un stockage persistant.

Note d'implémentation de la phase 2

Le runtime de la phase 2 comprend désormais :

  • l'enregistrement des routes d'administration de plugin pour les seuls plugins activés via PluginRouteRegistrar
  • des URL d'administration de plugin par défaut sous /webadmin/plugins/{plugin-handle}/...
  • des noms de route d'administration de plugin par défaut sous webblocks.plugins.{plugin_handle}.*
  • des pages de paramètres en lecture seule par défaut pour les plugins activés qui déclarent PluginSettingsDefinition
  • la collecte des commandes console pour les seuls plugins activés via PluginCommandRegistrar
  • PluginHealthResult, PluginLifecycleStatus et PluginHealthMonitor pour des rapports d'état de base
  • des pages de détail System -> Plugins qui exposent des synthèses de cycle de vie, de santé, de paramètres, de routes, de commandes, de permissions et de contributions aux menus
  • une couverture par garde-fous de routes prouvant que les routes des plugins de test activés sont bien enregistrées, que les routes des plugins désactivés sont absentes, que /webadmin reste canonique, que /cms n'est pas un espace de noms de routes d'administration Laravel et que les routes /admin appartenant au CMS restent absentes

Cette phase laisse volontairement hors périmètre la découverte des migrations, les actions d'installation/d'application/d'exécution de plugins, les actions destructives du cycle de vie, la découverte dynamique via Composer, les routes publiques de plugin et le comportement à l'exécution de WebBlocks UI Manager.

Note d'implémentation de la phase 3

Le runtime de la phase 3 comprend désormais :

  • des contrats typés d'extension d'administration sous Support\Plugins\Contracts
  • les objets valeur PluginDashboardWidget et PluginSystemCard collectés via PluginAdminExtensionRegistry
  • le rendu des widgets de tableau de bord pour les seuls plugins activés sur le tableau de bord super-admin
  • la collecte des cartes système pour les seuls plugins activés sur les surfaces de vue d'ensemble système prévues, tenue à l'écart de la page de gestion du cycle de vie System -> Plugins
  • PluginBlockTypeDefinition, PluginBlockPackDefinition et PluginBlockRegistry pour les déclarations de blocs appartenant au plugin
  • PluginPublicAsset et PluginPublicAssetRegistry pour des déclarations sûres d'assets publics dans le head et en fin de body
  • des garde-fous de validation pour les clés d'extension, les clés de widget, les clés de carte système, les handles de bloc, les espaces de noms de packs de blocs, les handles d'assets, la propriété du plugin et les déclarations en double
  • un comportement inerte des plugins désactivés pour les widgets de tableau de bord, les cartes système, les hooks de bloc et les assets publics
  • une couverture par garde-fous de routes confirmant que /webadmin et /webadmin/plugins/... restent valides tandis que les routes d'administration /admin et Laravel /cms restent absentes

Cette phase laisse volontairement hors périmètre le comportement réel de place de marché, l'installation de paquets, les exécuteurs de migrations de plugins, les routes publiques de plugin, les widgets modifiables, les hooks de remplacement des blocs du cœur et le plugin WebBlocks UI Manager. Les plugins ne doivent toujours pas remplacer les vues du paquet ni modifier à la volée les services du cœur.

Note d'implémentation de la phase 4

Le runtime de la phase 4 comprend désormais le plugin pilote maison webblocks-ui-manager. Le plugin est enregistré par le registre du paquet mais désactivé par défaut via config/webblocks-plugins.php.

Lorsqu'il est activé, le pilote apporte :

  • des permissions préfixées par le handle : webblocks-ui-manager.view, webblocks-ui-manager.manage et webblocks-ui-manager.publish
  • un espace de noms de routes d'administration de plugin sous /webadmin/plugins/webblocks-ui-manager/... avec des noms de route sous webblocks.plugins.webblocks_ui_manager.*
  • un élément de menu de plugin pour les enregistrements de version de WebBlocks UI
  • des cartes de tableau de bord et système en lecture seule via les slots d'extension de la phase 3
  • une visibilité des paramètres/du détail en lecture seule via la fondation de paramètres de la phase 2
  • des contrôles de santé du plugin portant sur la disponibilité des métadonnées de version, l'état configuration requise/table manquante et la disponibilité du chemin de base CDN configuré
  • des tables et modèles appartenant au plugin : webblocks_ui_manager_releases, webblocks_ui_manager_artifacts et webblocks_ui_manager_publish_runs
  • une commande locale sûre webblocks-ui-manager:prepare-release qui enregistre les métadonnées de version, calcule les sommes de contrôle SHA-256 des artefacts et peut éventuellement écrire un manifest.json local
  • un flux contrôlé webblocks-ui-manager:publish-release {version} --dry-run et webblocks-ui-manager:publish-release {version} qui enregistre les exécutions de publication et n'écrit qu'après validation réussie
  • des conventions de cible CDN maison sous public/cdn/webblocks-ui/{version}/...

L'état désactivé reste inerte : routes, commandes, menus, routes de paramètres, permissions, cartes de tableau de bord/système, comportement de santé et contributions d'assets sont absents de la collecte active. L'état activé mais non configuré reste sûr : le menu peut être visible, mais la route Releases vérifie la disponibilité du schéma avant d'interroger la base et affiche des indications de configuration requise lorsque les tables de versions sont absentes. Les URL d'administration manuelles des plugins activés et compatibles ne doivent pas retomber sur le tableau de bord lorsque l'hydratation dynamique des routes est obsolète ou que la mise en cache des routes entre en jeu ; le repli des routes de plugin maintient les pages d'administration de plugin connues sur leur URL /webadmin/plugins/{plugin-handle}/... et réhydrate les routes et la source appartenant au plugin avant d'afficher des écrans contrôlés de configuration ou d'exploitation. Les actions Releases de WebBlocks UI Manager maison, les actions de création/enregistrement/affichage/modification/mise à jour/dry-run/publication de version et les URL de Settings sont en outre relayées par le cœur du CMS avant l'exécution des fichiers de routes du plugin, afin qu'une source d'artefact installée obsolète ne puisse pas renvoyer ces actions vers le tableau de bord.

La phase 4 n'ajoute volontairement ni automatisation de déploiement sur un CDN de production externe, ni comportement de place de marché, ni flux génériques d'installation/mise à jour de plugins tiers, ni exécuteurs génériques de migrations de plugins, ni routes publiques de plugin, ni remplacements de vues du cœur, ni publication sur le serveur de mises à jour, ni modification des URL par lesquelles le cœur du CMS consomme WebBlocks UI.

Note d'implémentation de la phase 5

Le runtime de la phase 5 comprend désormais les fondations de packaging et de préparation à l'écosystème :

  • des contrôles de la version du plugin et de requiresCms() par rapport à la version du CMS installée
  • un état activé en configuration distinct de l'état actif, afin que les plugins configurés mais incompatibles restent inertes
  • des messages de cycle de vie dans System -> Plugins pour Enabled, Disabled et Incompatible
  • des résultats de santé pour les plugins incompatibles qui n'exécutent pas les rapporteurs de santé du plugin
  • des métadonnées de convention pour les espaces de noms de paramètres et les préfixes de base de données/de table
  • des garde-fous sur les noms de commande pour les classes de commande Artisan résolvables, exigeant {plugin-handle}:...
  • des garde-fous contre les collisions de préfixes de base de données
  • des tests ciblés sur les métadonnées de compatibilité, le comportement en cas d'incompatibilité, les collisions de commandes et de préfixes, l'inertie en état désactivé/incompatible, la non-régression de WebBlocks UI Manager, les frontières du paquet et la propriété des routes
  • de la documentation sur les conventions de paquet, la découverte locale, la création minimale d'un plugin, la stratégie de mise à niveau du schéma et la politique de compatibilité des versions

La phase 5 n'ajoute volontairement ni interface de place de marché/catalogue, ni installation de paquets distants arbitraires, ni découverte distante dynamique via Composer, ni exécuteurs génériques de migrations pour plugins tiers, ni déploiement automatique sur un CDN de production externe, ni publication générique sur le serveur de mises à jour, ni routes publiques de plugin.

Tests et garde-fous de publication

Le système de plugins doit être protégé par des tests de propriété des routes, de frontières du paquet et de coexistence.

Garde-fous obligatoires :

  • la propriété des routes de plugin est vérifiable par des tests
  • les installations du cœur du CMS n'affichent aucun menu de plugin lorsqu'aucun plugin n'est activé
  • les menus des plugins désactivés ne s'affichent pas
  • les routes et actions des plugins désactivés sont indisponibles ou échouent à l'autorisation
  • les widgets, cartes système, déclarations de bloc et assets publics des plugins désactivés sont absents
  • les routes, commandes, menus, permissions, widgets, cartes système, déclarations de bloc, assets publics, routes de paramètres et le comportement des rapporteurs de santé des plugins incompatibles sont absents
  • les noms de commande, les préfixes de base de données, les handles, les slots d'extension, les widgets, les blocs, les assets et les espaces de noms de permissions restent protégés contre les collisions
  • les cartes d'extension de tableau de bord/système d'un plugin ne s'affichent que lorsqu'il est activé et autorisé
  • les déclarations de bloc appartenant à un plugin sont repérables sans remplacer les contrats de bloc du cœur
  • les assets publics d'un plugin sont collectés par emplacement sûr et sont absents lorsqu'il est désactivé
  • l'enregistrement des routes de plugin ne doit pas rétablir un espace de noms /admin appartenant au CMS
  • /webadmin reste le préfixe d'administration canonique du CMS
  • /cms reste un territoire d'assets statiques, et non un espace de noms de routes de plugin Laravel
  • les tentatives d'un plugin de remplacer des tables, des noms de route ou des vues du cœur doivent faire échouer les tests ou les diagnostics
  • les tests de frontières du paquet s'étendent aux routes, vues, assets, migrations et commandes appartenant aux plugins
  • les tests de coexistence devraient couvrir les scénarios CMS + QuizTem + plugin prévus dans la feuille de route

Les tests de plugins devraient couvrir aussi bien les cas sans plugin que les cas avec plugin désactivé, afin que le cœur du CMS reste propre dans les installations génériques. Le pilote WebBlocks UI Manager porte en outre des tests de migration/schéma, de commandes, de manifeste/somme de contrôle, d'activation exclusive, d'inertie à l'état désactivé, de rendu en administration, de garde-fous de routes et de frontières du paquet.

Décisions concernant le plugin pilote WebBlocks UI Manager

WebBlocks UI Manager n'est pas intégré au comportement du cœur du CMS. Il démarre actuellement comme plugin pilote maison appartenant au paquet, dans l'espace de noms du paquet CMS, afin que l'hôte de plugins puisse démontrer une véritable surface opérationnelle propre au produit sans déplacer la gestion des versions/du CDN de WebBlocks UI dans le cœur générique du CMS.

Le modèle privilégié à long terme pourrait encore devenir un paquet Composer distinct ou un dépôt séparé, une fois les conventions de cycle de vie et de packaging des plugins arrivées à maturité.

La responsabilité du plugin :

  • les enregistrements d'artefacts de version de WebBlocks UI
  • la validation du dist source
  • la préparation locale sécurisée de la publication
  • les exécutions contrôlées de publication statique locale en dry-run et en application
  • l'historique des exécutions de publication
  • la génération de manifestes et de sommes de contrôle
  • les contrôles de santé du CDN

La compilation de WebBlocks UI reste dans le dépôt WebBlocks UI. Le plugin ne compile pas WebBlocks UI : il reçoit ou valide les artefacts de version, enregistre les métadonnées locales pour les chemins CDN maison et peut publier les fichiers validés dans la cible statique locale ou appartenant au projet qui a été configurée. Le déploiement sur un CDN de production externe est volontairement différé et doit rester explicite.

Nos propres produits peuvent consommer cdn.webblocksui.com pour les assets maison épinglés à une version. La documentation destinée aux utilisateurs externes devrait continuer à recommander la consommation depuis GitHub ou depuis le CDN jsDelivr, sauf si cette politique évolue séparément.

Règles CDN pour le pilote :

  • utilisez des chemins versionnés
  • n'utilisez pas latest
  • ne modifiez jamais un répertoire d'artefacts versionné existant
  • ne supprimez pas les anciens répertoires CDN versionnés lors d'une publication normale
  • exécutez le dry-run avant d'appliquer lorsque vous opérez manuellement
  • bloquez les différences de checksum au lieu de remplacer les fichiers silencieusement
  • privilégiez la diffusion statique au streaming via les routes Laravel

Flux de publication de WebBlocks UI Manager

Préparez les métadonnées de la version et les 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

Exécutez la publication en mode dry-run :

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

Appliquez la publication locale :

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

L'écran de détail de la version dans l'administration expose les mêmes actions de dry-run et de publication lorsque le plugin est activé, compatible, et que l'utilisateur dispose de webblocks-ui-manager.publish. L'action de publication réelle utilise une fenêtre modale de confirmation. Le dry-run n'est pas destructif.

Réglages obligatoires :

  • WEBBLOCKS_UI_MANAGER_ENABLED=true active le plugin.
  • WEBBLOCKS_UI_MANAGER_CDN_BASE_PATH=cdn/webblocks-ui contrôle la racine statique locale, détenue par le projet, sous public/.
  • WEBBLOCKS_UI_MANAGER_CDN_BASE_URL est une métadonnée d'affichage facultative pour les URL publiques générées.
  • webblocks-plugins.webblocks_ui_manager.expected_dist_files énumère les noms de fichiers dist obligatoires.

Contrôles de validation de la publication :

  • les métadonnées de la version existent et ne sont pas à l'état de brouillon
  • la version de la release respecte un format proche de semver
  • le chemin CDN de la version correspond à la racine configurée suivie de la version
  • les fichiers dist attendus sont présents
  • les fichiers sources existent dans la racine du projet et ne sont pas des échappements par lien symbolique
  • les chemins cibles des artefacts restent à l'intérieur de la racine CDN configurée
  • les checksums d'artefacts enregistrés correspondent aux fichiers sources actuels et aux métadonnées du manifeste
  • les fichiers déjà publiés correspondent aux checksums et sont ignorés, ou bien bloquent l'exécution
  • le contenu du manifeste existant doit correspondre au contenu du manifeste préparé

Les exécutions de publication sont enregistrées dans webblocks_ui_manager_publish_runs avec le mode, le statut, les chemins cibles, les détails de l'opération et des messages d'échec exempts de secrets.