Sistema di plugin di WebBlocks CMS

Questo documento registra l'architettura del sistema di plugin di WebBlocks CMS. Il core del CMS è un host generico di plugin con definizioni di plugin basate su un registro, caricamento e installazione manuale di ZIP da parte del super admin, percorsi di installazione gestiti da storage, plugin installati disabilitati per impostazione predefinita, gestione esplicita di attivazione e disattivazione, disinstallazione dei caricamenti manuali, controlli di compatibilità, rotte e comandi solo quando abilitati, impalcatura di impostazioni e dettaglio, report di salute e stato, slot di estensione tipizzati per l'amministrazione, dichiarazioni di blocchi di proprietà del plugin, hook per gli asset pubblici, guardie sulle convenzioni di pacchetto, un ponte di installazione dal Plugin Catalog verificato tramite checksum per gli artefatti compatibili del catalogo pubblico e un'azione di aggiornamento controllata, basata sul catalogo, per i plugin installati con release compatibili più recenti. WebBlocks UI Manager non è più incluso nel runtime del core del CMS; è un artefatto di plugin interno o da operatore installato manualmente solo su installazioni operatore come webblocksui.com. Non esiste alcun marketplace pubblico, né uno store remoto completo di plugin, né un installatore arbitrario di pacchetti Composer, né download o aggiornamento automatico di plugin esterni, né deployment automatico della CDN esterna di produzione di WebBlocks UI, né pubblicazione generica su un update server.

Decisione fondamentale

Il core di WebBlocks CMS è un host di plugin.

Il pacchetto core fornisce la superficie riutilizzabile del prodotto CMS:

  • gestione di contenuti e siti
  • infrastruttura di rendering pubblico
  • fondamenta di utenti, ruoli e permessi
  • shell di amministrazione e superfici standard dell'interfaccia di amministrazione
  • discovery dei plugin, registro e contratti degli slot di estensione

Le funzionalità specifiche di un prodotto o di un dominio di business non devono essere incorporate nel core del CMS, a meno che non facciano parte del prodotto CMS riutilizzabile. Devono essere fornite come plugin, così che un'installazione non erediti menu, comandi, impostazioni, tabelle dati o flussi operativi di un altro prodotto.

Le aree previste per i plugin includono:

  • WebBlocks UI Release/CDN Manager
  • integrazione con QuizTem
  • analytics
  • strumenti SEO avanzati
  • newsletter
  • commercio elettronico
  • ottimizzatore di media
  • gestore dell'update server
  • pacchetti di blocchi personalizzati

Confine tra core e plugin

Funzionalità del core:

  • siti, pagine, blocchi, media, utenti, lingue (locale) e impostazioni di base
  • rendering, shell pubblica, layout, slot e infrastruttura dei blocchi
  • fondamenta di permessi e ruoli
  • shell di amministrazione e superficie standard dell'interfaccia di amministrazione
  • discovery dei plugin, registro e contratti degli slot di estensione

Funzionalità dei plugin:

  • schermate di amministrazione per uno specifico prodotto o dominio di business
  • un namespace di rotte di proprietà del plugin
  • permessi di proprietà del plugin
  • impostazioni di proprietà del plugin
  • comandi da console di proprietà del plugin
  • migrazioni di proprietà del plugin
  • widget della dashboard di proprietà del plugin
  • blocchi o pacchetti di blocchi di proprietà del plugin
  • rotte pubbliche di proprietà del plugin, solo se dichiarate esplicitamente

La sovrascrittura delle viste del core è vietata per impostazione predefinita. I plugin estendono il CMS solo tramite slot di estensione documentati e contratti del registro. Un plugin non deve sostituire le viste del pacchetto, applicare monkey patch ai servizi del core, aggiungere file di rotte nascosti né fare affidamento su effetti collaterali di include arbitrari.

Installazione manuale da ZIP

System -> Plugins consente ai super admin di caricare uno ZIP di plugin locale. Caricare uno ZIP è un'installazione privilegiata di codice eseguibile. L'installer convalida l'archivio prima di scrivere qualsiasi cosa sotto la radice dei plugin configurata, per impostazione predefinita storage/app/webblocks/plugins/{plugin-handle}/{version}.

La convalida richiede webblocks-plugin.json o manifest.json, un handle in kebab-case, una versione in stile semver, metadati di provider/classe, un vincolo di versione CMS compatibile, nessuna collisione con un handle già installato, solo percorsi relativi al pacchetto, nessun path traversal, nessun percorso assoluto, nessuna voce di symlink e nessuna scrittura verso destinazioni vietate del CMS o del core come app, packages, project, storage, vendor o public/cms. I plugin installati restano disabilitati finché non viene completato un passaggio di abilitazione esplicito. I plugin disabilitati sono inerti: rotte, comandi, menu, rotte delle impostazioni, reporter di salute, widget, dichiarazioni di blocchi e asset non vengono registrati né eseguiti, e System -> Plugins riporta lo stato di salute come inattivo o non verificato.

La disinstallazione manuale è disponibile solo per i plugin caricati manualmente e richiede l'autorizzazione di un super admin. Il plugin deve essere prima disabilitato. La disinstallazione rimuove la directory del pacchetto del plugin installato e il file di stato di abilitazione sotto la radice dei plugin configurata, ma non elimina le tabelle di database di proprietà del plugin né esegue migrazioni distruttive. I plugin protetti, del core o non manuali non possono essere disinstallati con questo flusso.

I campi di manifest supportati includono handle, label, description, version, provider, required_cms_version, permissions, commands, routes, settings, migrations, assets e health. Le migrazioni vengono installate come file di proprietà del plugin e non vengono mai eseguite automaticamente al caricamento o all'abilitazione. I super admin possono eseguire l'azione esplicita di setup del plugin dalla schermata di dettaglio del plugin; il runner limita l'esecuzione al percorso del plugin installato e alle directory di migrazione dichiarate nel manifest, registra i risultati del setup nello stato di abilitazione e può riparare un plugin che richiede il setup i cui record di migrazione esistono ma le cui tabelle necessarie mancano.

Il ciclo di vita manuale di un plugin è il seguente:

  1. Caricate e installate lo ZIP. Il plugin è disabilitato per impostazione predefinita.
  2. Esaminate la schermata di dettaglio del plugin.
  3. Abilitate il plugin quando è compatibile.
  4. Eseguite il setup o le migrazioni del plugin se la schermata di dettaglio segnala Setup required o Plugin migrations pending.
  5. Usate le rotte operative del plugin quando il setup è pronto.
  6. Disabilitate il plugin per rendere inerti rotte, comandi, menu, impostazioni, controlli di salute e contributi.
  7. Disinstallate solo dopo la disabilitazione; la disinstallazione preserva le tabelle di proprietà del plugin.

I plugin abilitati con setup in sospeso non devono far fallire le rotte di amministrazione. Se mancano tabelle di proprietà del plugin, le schermate di salute e di rotta devono riportare indicazioni di setup necessario come Plugin migrations pending o Release tables are missing.

Le rotte di amministrazione del plugin devono usare permessi dichiarati con il prefisso dell'handle. Gli utenti super_admin del CMS sono esplicitamente ammessi per i permessi dei plugin attivi e abilitati, inclusi i permessi caricati dai manifest dei plugin installati manualmente. I ruoli non super admin restano negati, a meno che un futuro modello di assegnazione dei permessi del CMS non conceda lo specifico permesso di proprietà del plugin. Le rotte delle impostazioni usano {plugin-handle}.manage quando il plugin lo dichiara, altrimenti ricadono sull'accesso di sistema.

Le rotte di amministrazione dei plugin abilitati e compatibili vengono sempre eseguite all'interno dello stack di rotte di amministrazione del CMS: web, installazione richiesta, autenticazione CMS, accesso amministrativo CMS, guardia di setup del plugin e infine il middleware dei permessi di proprietà del plugin quando la rotta del plugin lo dichiara. Il middleware di autenticazione del CMS usa il guard web e l'utente di sessione di Laravel, reindirizzando gli ospiti tramite la rotta webblocks.auth.login di proprietà del CMS. Le guardie di setup del plugin sono additive e non devono sostituire l'autenticazione del CMS o l'autorizzazione amministrativa; i controller del plugin possono contare sulla presenza dell'utente CMS autenticato dopo il superamento del middleware di autenticazione e amministrazione.

Contratto del plugin e manifest

Ogni plugin deve avere un handle:

  • in kebab-case
  • globalmente univoco all'interno dell'installazione
  • stabile tra le release
  • usato come prefisso predefinito per permessi, rotte, tabelle, impostazioni, asset e identità del pacchetto

Ogni plugin deve dichiarare i propri metadati tramite un manifest o un oggetto di definizione:

  • handle
  • label
  • version
  • classe provider
  • descrizione opzionale
  • versione CMS richiesta o vincolo di versione
  • namespace delle impostazioni
  • prefisso di database/tabelle
  • permessi
  • voci del menu di amministrazione
  • rotte di amministrazione e pubbliche
  • comandi da console
  • schema delle impostazioni o pagine di impostazioni
  • migrazioni
  • blocchi o pacchetti di blocchi
  • asset
  • controlli di salute, quando supportati

I plugin sono registry-first: si collegano al CMS tramite contratti espliciti, non tramite include arbitrari, sovrascritture di viste nella radice o file di rotte specifici dell'installazione.

I plugin installati aggiornati dal catalogo vengono ricaricati tramite il refresh del runtime del core del CMS dopo la scrittura del pacchetto sostitutivo. Il refresh svuota lo stato del registro dei plugin, dei permessi, delle estensioni, della salute e della cache ottimizzata del runtime Laravel, quindi ricostruisce le rotte attive dei plugin per il runtime corrente, così che la versione installata, la versione attiva del manifest, i metadati del provider attivo e il percorso sorgente di rotte e controller restino allineati. Se nello stesso processo PHP è già caricata una classe provider di una versione precedente del pacchetto installato, il CMS considera quel provider obsoleto e ricorre ai metadati aggiornati del manifest invece di riutilizzare i vecchi percorsi delle rotte.

L'autorizzazione dei plugin è risolta centralmente dal core del CMS. I permessi attivi di proprietà del plugin dichiarati dal plugin abilitato consentono l'accesso agli utenti super_admin del CMS, e lo stesso resolver è usato per la visibilità del menu del plugin, i contributi a dashboard e sistema e il middleware di rotta plugin.permission:*. Gli utenti non autorizzati non vedono le corrispondenti voci di menu; l'accesso diretto tramite URL resta un 403 controllato. La gestione del setup necessario rimane dopo l'autorizzazione e le migrazioni del plugin restano esplicite.

Forma attuale dell'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);

L'API esatta può cambiare durante l'implementazione, ma il contratto deve preservare queste regole:

  • i metadati dichiarati sono ispezionabili prima che un plugin venga abilitato
  • la proprietà di menu, rotte, permessi, comandi, migrazioni, blocchi, asset e impostazioni è attribuibile a un handle di plugin
  • i conflitti falliscono durante build, test, diagnostica di avvio o abilitazione del plugin, prima che gli utenti vedano proprietà mista

Regole di convenzione dei pacchetti

Le convenzioni dei pacchetti di plugin sono separate da quelle del core del CMS. Il core del CMS possiede i contratti dell'host; i plugin possiedono il comportamento del proprio dominio.

  • Denominazione dell'handle: usate un kebab-case stabile come analytics-tools; non rinominate mai un handle dopo il rilascio, perché ancora rotte, permessi, impostazioni, tabelle, asset e cronologia degli aggiornamenti.
  • Registrazione del service provider: un pacchetto di plugin dovrebbe esporre un solo service provider Laravel e registrarvi la propria PluginDefinition, oppure farlo tramite il punto di integrazione con il registro del CMS. I piloti first-party inclusi nel pacchetto possono registrarsi direttamente dal provider del pacchetto CMS finché non vengono separati in pacchetti Composer propri.
  • Struttura della definizione o del manifest: dichiarate esplicitamente handle, label, version, provider, description, requiresCms, il namespace delle impostazioni, il prefisso di database, i permessi, le rotte, i comandi, gli slot di estensione, gli asset, i blocchi e il reporter di salute.
  • Namespace delle rotte: le rotte di amministrazione risiedono sotto /webadmin/plugins/{plugin-handle}/... con nomi sotto webblocks.plugins.{plugin_handle}.*.
  • Denominazione dei permessi: ogni permesso di plugin inizia con {plugin-handle}., ad esempio analytics-tools.view.
  • Convenzioni delle impostazioni: i namespace delle impostazioni sono in snake_case e per impostazione predefinita corrispondono all'handle con i trattini convertiti in underscore.
  • Denominazione dei comandi: i nomi dei comandi Artisan risolvibili devono iniziare con {plugin-handle}:, ad esempio analytics-tools:sync.
  • Denominazione di migrazioni e tabelle: le tabelle usano un prefisso snake_case riservato dal registro che termina con _, per impostazione predefinita l'handle convertito in snake_case più _.
  • Contributi di asset: gli handle degli asset pubblici usano l'handle del plugin come namespace separato da punti e i file statici devono essere pubblicati sotto un percorso di proprietà del plugin.
  • Contributi di card della dashboard e di sistema: le chiavi usano l'handle del plugin come namespace separato da punti e restano di sola lettura, a meno che un successivo contratto di estensione non aggiunga un comportamento modificabile.

WebBlocks UI Manager segue queste convenzioni come pilota first-party: handle webblocks-ui-manager, namespace delle impostazioni webblocks_ui_manager, prefisso di database webblocks_ui_manager_, comandi webblocks-ui-manager:prepare-release e webblocks-ui-manager:publish-release, rotte sotto /webadmin/plugins/webblocks-ui-manager e nomi di rotta sotto webblocks.plugins.webblocks_ui_manager.*.

Compatibilità e inerzia

Le versioni dei plugin sono metadati in stile semver. requiresCms() dichiara il vincolo di versione CMS richiesto dal plugin. La base attuale supporta vincoli esatti o con comparatori come >=1.32.0 e vincoli con caret come ^1.32.

Il registro distingue lo stato di abilitazione configurato dallo stato attivo:

  • Abilitato da configurazione: config/webblocks-plugins.php indica che il plugin deve essere abilitato.
  • Compatibile: la versione di CMS installata soddisfa il vincolo CMS richiesto dal plugin.
  • Attivo: il plugin è al tempo stesso abilitato da configurazione e compatibile.

Solo i plugin attivi contribuiscono con menu, rotte, comandi, rotte delle impostazioni, widget della dashboard, card di sistema, dichiarazioni di blocchi, asset pubblici, permessi ed esecuzione del reporter di salute. I plugin disabilitati e incompatibili restano inerti. System -> Plugins mostra Incompatible con le versioni di CMS richiesta e installata quando un plugin configurato non può attivarsi.

Discovery e abilitazione locale

La fase 5 non aggiunge comportamenti da marketplace né installazioni remote arbitrarie. La discovery sicura è locale ed esplicita:

  • i plugin first-party inclusi nel pacchetto possono essere registrati dal provider del pacchetto CMS
  • i futuri plugin distribuiti come pacchetti Composer devono registrare un service provider tramite il package discovery di Laravel o una configurazione esplicita del provider dell'applicazione
  • gli esperimenti locali dell'installazione possono usare repository Composer di tipo path durante lo sviluppo, ma devono comunque registrare un provider e una definizione normali
  • l'abilitazione resta basata sulla configurazione tramite webblocks-plugins.enabled.{plugin-handle}

Nessuna funzionalità di runtime installa pacchetti Composer arbitrari, pubblica cataloghi di marketplace, scrive artefatti di CDN o update server di produzione, abilita automaticamente i plugin, esegue automaticamente migrazioni o setup dei plugin, né effettua aggiornamenti automatici dei plugin. I ponti verso artefatti remoti di plugin sono limitati alle azioni di installazione e aggiornamento dal Plugin Catalog avviate da un super admin e descritte più avanti, ed entrambe sono limitate a URL ZIP controllati del catalogo con metadati SHA-256 corrispondenti.

Direzione del catalogo dell'ecosistema

Il sistema di plugin del CMS è il primo host di implementazione di una direzione più ampia per l'ecosistema di plugin WebBlocks. I futuri contratti di plugin devono essere riutilizzabili da WebBlocks CMS, QuizTem, Herne Panel, WebBlocks Publisher e dai successivi prodotti WebBlocks, in cui ogni host espone i propri punti di estensione specifici del prodotto.

La superficie proposta di catalogo/store è plugins.webblocksui.com. L'obiettivo a breve termine è un Plugin Catalog per discovery, metadati, compatibilità, documentazione, informazioni sulle release, checksum, link di download ZIP controllati e un ponte di installazione conservativo a partire da metadati di artefatti di catalogo affidabili. Il comportamento da marketplace, inclusi account, licenze, plugin a pagamento, recensioni e flussi di approvazione, è rimandato.

System -> Plugins include un'azione Browse Plugin Catalog in /webadmin/plugins/catalog (admin.plugins.catalog.index). L'elenco del catalogo richiede i plugin pubblici elencati per host_product=webblocks-cms a GET /api/plugins e chiede l'ultima release compatibile tramite GET /api/plugins/{handle}/latest quando è disponibile un handle. Le etichette dei plugin del catalogo e l'azione View details aprono /webadmin/plugins/catalog/{handle} (admin.plugins.catalog.show), che richiede GET /api/plugins/{handle} più l'endpoint dell'ultima release compatibile per mostrare i metadati del plugin, la compatibilità, le note di rilascio, i link a documentazione/supporto, l'URL di download dell'artefatto, il checksum SHA-256, il nome del file dell'artefatto, la dimensione dell'artefatto, lo stato della release, lo stato di convalida dell'artefatto, lo stato di scansione dell'artefatto, il canale, la versione e i metadati sicuri sulle capacità dichiarate quando restituiti dall'API. Le attuali risposte di dettaglio dell'API WebBlocks Plugins possono restituire i dati del plugin direttamente sotto data, i dati della release sotto data.latest_release e i metadati dell'artefatto sotto data.latest_release.artifact; le risposte API dell'ultima release compatibile possono anche restituire i metadati della release sotto data.release, con i metadati dell'artefatto nell'elemento adiacente data.artifact. Il CMS normalizza tali formati prima di generare i dettagli, verificare la disponibilità di installazione o elaborare l'azione di installazione dal catalogo lato server. I campi dell'artefatto supportati includono file_name, size_bytes, checksum_sha256, download_url, validation_status e scan_status; i vecchi nomi di campo piatti della release restano accettati per compatibilità. La versione canonica del prodotto WebBlocks CMS viene inviata come version e cms_version per la verifica di compatibilità. L'URL del catalogo pubblico integrato è per impostazione predefinita https://plugins.webblocksui.com; gli operatori non devono modificare .env per la discovery predefinita e possono sovrascrivere la destinazione interna delle richieste con WEBBLOCKS_PLUGIN_CATALOG_BASE_URL (webblocks-plugins.catalog.base_url). Le impostazioni di timeout sono disponibili tramite WEBBLOCKS_PLUGIN_CATALOG_TIMEOUT_SECONDS e WEBBLOCKS_PLUGIN_CATALOG_CONNECT_TIMEOUT_SECONDS. La normale interfaccia del catalogo non espone l'URL di base configurato né la versione della richiesta; gli stati di indisponibilità utilizzano testi comprensibili per l'operatore, mentre le diagnostiche sicure restano nei log.

Il dettaglio del catalogo mantiene i link Website, Documentation, Support e Catalog Detail separati dalle azioni di installazione. La pagina mostra uno stato chiaro di artefatto non disponibile quando una release compatibile non include metadati di artefatto scaricabile. L'azione Download ZIP apre solo il download_url pubblico assoluto e controllato restituito dal catalogo e non deve esporre percorsi di storage grezzi.

Install from Catalog è disponibile solo quando il plugin del catalogo è compatibile, l'ultima release compatibile è published e l'artefatto normalizzato della release include i valori download_url, checksum_sha256 e file_name. I vecchi campi piatti della release sha256/checksum_sha256 e filename/artifact_filename restano accettati per compatibilità. L'azione POST utilizza CSRF, rilegge i metadati del catalogo lato server, scarica l'URL ZIP controllato in uno storage temporaneo, verifica l'esito HTTP, rifiuta risposte non ragionevoli o non ZIP, calcola lo SHA-256, lo confronta esattamente con i metadati del catalogo e infine passa lo ZIP temporaneo attraverso il validatore/installer ZIP dei plugin manuale esistente. I file temporanei vengono rimossi dopo il successo o l'errore e i nomi di file del catalogo/remoti non sono considerati attendibili come percorsi del filesystem.

Le installazioni dal catalogo registrano il plugin come disabilitato per impostazione predefinita, esattamente come il caricamento manuale. Non abilitano il plugin, non eseguono migrazioni/setup del plugin, non eseguono il codice del provider del plugin, non registrano rotte del plugin, non registrano permessi, non registrano comandi, non registrano asset, non registrano blocchi, non aggiungono schede dashboard/sistema, non applicano aggiornamenti e non modificano lo stato di abilitazione. Qualsiasi stato locale installato/abilitato mostrato nella pagina di dettaglio del catalogo proviene solo dal registro dei plugin del CMS, non dalle dichiarazioni del catalogo remoto. Il caricamento/installazione manuale dello ZIP resta disponibile e invariato.

System -> Plugins -> Registered Plugins esegue una verifica di disponibilità nel catalogo, per quanto possibile, per gli handle dei plugin installati. Quando il catalogo non è disponibile o non fornisce metadati attendibili, l'elenco viene comunque mostrato e non compare alcuna azione di aggiornamento. Quando un handle installato ha un'ultima release compatibile più recente secondo version_compare, tale release è published, il plugin è compatibile e l'artefatto normalizzato include download_url, checksum_sha256 e file_name, la colonna Version mostra Update available: {version} e il gruppo di azioni della riga mostra un'azione a icona Update from Catalog solo in POST.

Il POST di aggiornamento rilegge lato server i metadati di dettaglio/ultima release del catalogo, richiede gli stessi metadati di artefatto completi, pubblicati e compatibili, scarica lo ZIP controllato, verifica lo SHA-256, convalida lo ZIP con lo stesso validatore di pacchetti plugin e sostituisce la versione del pacchetto del plugin installato. Le tabelle di database di proprietà del plugin vengono preservate, lo stato del ciclo di vita abilitato o disabilitato viene preservato spostando lo stato abilitato sulla nuova versione solo se la vecchia versione era abilitata, e le migrazioni del plugin non vengono eseguite automaticamente. Se il plugin aggiornato dichiara nuove migrazioni o le sue tabelle sono assenti, restano responsabili della preparazione dello schema le indicazioni esistenti di setup richiesto e il flusso esplicito Run Plugin Migrations.

Consultate WebBlocks Plugin Ecosystem And Catalog per la direzione a livello di prodotto e il piano per fasi.

La pianificazione della superficie di prodotto proposta plugins.webblocksui.com, l'ambito dell'MVP, i modelli di implementazione candidati, le pagine pubbliche del catalogo, le superfici per gli operatori e la possibile forma di un'API in sola lettura si trovano in Plugin Catalog Product Architecture.

Esempio minimo di plugin

Un pacchetto plugin minimo dovrebbe esporre un provider e una definizione simili 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);
  }
}

Il provider dovrebbe registrare le viste, la configurazione, le migrazioni del pacchetto e la definizione del plugin senza aggiungere file di rotte pubbliche di proprietà del CMS in /admin, /cms o nella radice. Le rotte del plugin dovrebbero essere definite in modo relativo al gruppo di rotte del plugin; per esempio, /reports diventa /webadmin/plugins/analytics-tools/reports.

Regole del menu di amministrazione

I plugin possono aggiungere voci al menu di amministrazione, ma ogni voce di menu di un plugin deve essere soggetta a permessi.

Il comportamento preferito è aggiungere voci ai gruppi di amministrazione esistenti, come:

  • System
  • Tools
  • Integrations

Un menu di plugin di primo livello può essere riservato solo a una superficie di prodotto ampia, che risulterebbe poco chiara come singola voce di gruppo.

Regole del menu di amministrazione:

  • le icone devono provenire dal catalogo di icone di WebBlocks UI
  • i nomi delle rotte devono appartenere allo spazio dei nomi delle rotte del plugin
  • l'ordinamento del menu e le regole di collisione devono essere gestiti dal registro
  • i plugin disabilitati o disinstallati non devono generare voci di menu
  • le etichette delle voci di menu dovrebbero descrivere la funzionalità, senza far trapelare nomi di progetto specifici di un'installazione nelle installazioni CMS generiche
  • le voci di menu non devono comparire nelle installazioni core quando il plugin proprietario è assente

Regole dello spazio dei nomi delle rotte

Le rotte di amministrazione dei plugin usano per impostazione predefinita questo prefisso URL:

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

I nomi delle rotte di amministrazione dei plugin usano per impostazione predefinita questo spazio dei nomi:

webblocks.plugins.{plugin_handle}.*

Lo spazio dei nomi dei nomi di rotta utilizza l'handle del plugin trasformato solo quanto necessario per i nomi di rotta di Laravel. Per esempio, webblocks-ui-manager diventa webblocks.plugins.webblocks_ui_manager.* se l'implementazione richiede trattini bassi.

Un plugin può richiedere un prefisso di amministrazione più breve solo tramite il registro. I prefissi brevi riservati devono essere globalmente univoci. I conflitti di prefisso devono generare un errore durante build, test, diagnostica di avvio o abilitazione del plugin.

I plugin non devono inquinare:

  • i nomi delle rotte del core del CMS
  • lo spazio dei nomi delle rotte core /webadmin al di fuori del prefisso riservato al plugin
  • lo spazio dei nomi legacy /admin
  • lo spazio dei nomi degli asset statici /cms

I plugin disabilitati e incompatibili non devono registrare rotte di amministrazione. Il registratore delle sole voci attive è volutamente conservativo: se un plugin è disabilitato tramite config/webblocks-plugins.php o non soddisfa il vincolo di versione del CMS, le sue rotte sono assenti anziché presenti ma vietate.

Le rotte pubbliche sono opzionali e ad adesione esplicita. Un plugin che dichiara rotte pubbliche deve dichiararne la proprietà in modo abbastanza chiaro da poterla verificare con i test. Le rotte pubbliche dei plugin devono evitare collisioni con le pagine del sito, con le rotte pubbliche del CMS e con le rotte del prodotto host.

Regole sui permessi

Ogni menu di amministrazione, rotta e azione deve essere collegato a un permesso del plugin.

I nomi dei permessi devono includere il prefisso dell'handle del plugin:

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

Il comportamento dei permessi deve restare compatibile con il modello dei permessi del CMS. Se esiste un bypass per il super admin, deve utilizzare lo stesso percorso di autorizzazione esplicito del CMS impiegato dai permessi core.

I permessi del plugin devono essere visibili nella gestione dei ruoli dell'amministrazione quando il plugin è installato o rilevabile. I permessi dei plugin disabilitati non devono autorizzare comportamenti attivi, anche se un ruolo conserva ancora una stringa di permesso corrispondente.

Regole delle impostazioni

Le impostazioni del plugin devono essere memorizzate nel suo spazio dei nomi. Non devono entrare in collisione con la configurazione generale del CMS, con la configurazione dell'applicazione host o con le variabili d'ambiente.

Regole delle impostazioni:

  • le chiavi delle impostazioni dovrebbero avere come prefisso l'handle del plugin
  • i valori sensibili devono utilizzare uno storage sicuro per i segreti ove disponibile
  • i valori sensibili non devono mai comparire nei log, nell'output dei controlli di stato, nei messaggi di eccezione o nei messaggi flash dell'amministrazione
  • l'interfaccia delle impostazioni deve trovarsi nello spazio dei nomi delle rotte del plugin oppure all'interno di System -> Plugins -> Plugin detail
  • le variabili d'ambiente possono fornire valori predefiniti iniziali, ma le impostazioni a runtime dovrebbero restare di proprietà del plugin e ispezionabili tramite il registro

La fase 2 fornisce una base di rotta per le impostazioni in sola lettura per i plugin abilitati che dichiarano PluginSettingsDefinition senza un nome di rotta personalizzato. La rotta predefinita è:

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

Il suo nome di rotta predefinito è:

webblocks.plugins.{plugin_handle}.settings.edit

Lo storage modificabile delle impostazioni e gli schemi di convalida sono riservati a una fase successiva. La fase 5 riserva gli spazi dei nomi delle impostazioni tramite PluginDefinition::settingsNamespace(), così i plugin non entrano in collisione con la configurazione del core del CMS o con altri plugin.

Regole di migrazione e ciclo di vita dei dati

Le migrazioni dei plugin non devono entrare in collisione con le migrazioni del core.

I nomi delle tabelle del plugin devono riportare il prefisso dell'handle del plugin oppure un prefisso abbreviato documentato e riservato dal registro dei plugin. Per webblocks-ui-manager, i nomi delle tabelle utilizzano webblocks_ui_manager_. La fase 5 riserva i prefissi di database tramite PluginDefinition::databasePrefix() e rifiuta i prefissi duplicati.

Gli stati del ciclo di vita devono essere distinti:

  • Abilitazione: menu, rotte, comandi, job pianificati, widget, blocchi, impostazioni, controlli di stato e azioni del plugin diventano disponibili in base a permessi e compatibilità.
  • Disabilitazione: menu, job pianificati, rotte, azioni, rotte delle impostazioni, controlli di stato, widget, blocchi e asset del plugin non sono disponibili; i dati restano al loro posto.
  • Disinstallazione: i plugin disabilitati caricati manualmente possono essere rimossi dalla radice di installazione gestita dallo storage. Le tabelle di database di proprietà del plugin e i dati storici restano al loro posto.
  • Disinstallazione: riservata a una progettazione futura; per impostazione predefinita non deve eliminare dati.
  • Dismissione o purge: futuro flusso distruttivo di eliminazione dei dati che richiederà una conferma distruttiva esplicita.

La disinstallazione non deve essere distruttiva per il database. L'eliminazione di tabelle del plugin, artefatti, file caricati al di fuori della directory del pacchetto del plugin o record storici richiede una progettazione separata con conferma distruttiva esplicita.

Gli aggiornamenti dello schema dovrebbero essere additivi e reversibili ove praticabile. Una release di plugin che modifica lo schema deve documentare:

  • versione minima compatibile del CMS
  • versione del plugin che introduce lo schema
  • prefisso di migrazione/tabella utilizzato
  • se i plugin disabilitati possono lasciare in modo sicuro i dati esistenti al loro posto
  • note operative per il rollback o la dismissione

L'esecutore manuale delle migrazioni dei plugin ha un ambito volutamente limitato. Esegue solo le directory di migrazione dichiarate dal plugin installato e solo dopo aver risolto tali directory all'interno della radice di installazione dei plugin configurata. Non esegue le migrazioni dell'applicazione host né migrazioni di altri plugin. Le migrazioni dei plugin dovrebbero essere additive, reversibili ove praticabile e sicure da ripetere quando è necessaria una riparazione del setup.

Regole per asset e file statici

Gli asset dei plugin devono essere pubblicati sotto il proprio spazio dei nomi. Non devono mescolarsi con gli asset core in public/cms.

Per WebBlocks UI Manager, l'output CDN versionato dovrebbe utilizzare percorsi immutabili come:

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

Regole per gli asset:

  • le directory degli artefatti versionati sono immutabili
  • le vecchie directory versionate non devono essere eliminate come parte di una normale pubblicazione
  • latest non deve essere utilizzato per il consumo da CDN di prima parte
  • la pubblicazione dry-run deve riportare scritture, elementi ignorati e operazioni bloccate senza scrivere file
  • la pubblicazione effettiva deve convalidare i file dist attesi, i percorsi di origine, la versione della release, i percorsi di destinazione, i checksum e la coerenza del manifest prima di scrivere
  • i file esistenti con checksum corrispondenti vengono ignorati; i file esistenti con checksum diversi bloccano l'esecuzione
  • la CDN o l'hosting statico dovrebbero essere serviti da Nginx o da un altro servizio statico quando possibile
  • lo streaming degli asset tramite rotte Laravel non deve essere l'impostazione predefinita per i file CDN
  • gli asset di amministrazione dei plugin devono essere isolati dagli asset di amministrazione del core del CMS e pubblicati sotto uno spazio dei nomi del plugin

Il flusso di pubblicazione locale di WebBlocks UI Manager scrive solo nella destinazione statica configurata di proprietà del progetto, con valore predefinito public/cdn/webblocks-ui/{version}/.... Non effettua deployment su infrastruttura di produzione esterna, non pubblica metadati di update server, non modifica gli URL di consumo di WebBlocks UI del core del CMS e non installa pacchetti remoti.

La fase 3 aggiunge dichiarazioni di asset pubblici gestite dal registro per i plugin abilitati. Queste dichiarazioni sono attualmente limitate a URL di asset espliciti e vengono generate come asset di pagina pubblica solo quando il plugin proprietario è abilitato:

  • il CSS di head viene generato come <link rel="stylesheet"> nel <head> pubblico
  • il JS di head viene generato come tag <script> con defer o async/module nel <head> pubblico
  • il JS di fine body viene generato in prossimità della fine del <body> pubblico
  • gli handle degli asset devono avere lo spazio dei nomi con punto dell'handle del plugin, come analytics-tools.public-js
  • gli asset dei plugin disabilitati sono assenti dalla raccolta e dalla generazione

Questa è una base per l'hook di contributo degli asset, non un installer di pacchetti plugin né un publisher di asset. I plugin restano responsabili della pubblicazione dei propri file statici sotto uno spazio dei nomi di loro proprietà.

Regole per eventi, hook e slot di estensione

I plugin non devono applicare monkey patch né sovrascrivere il core. Gli slot di estensione del core devono essere espliciti, documentati e verificabili con i test.

Candidati iniziali per gli slot di estensione:

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

I contratti di slot dovrebbero essere tipizzati e basati su value object. Evitate per quanto possibile i contratti ad array grezzo, così che collisioni, forme non valide e proprietà possano essere convalidate presto.

La fase 3 implementa questi oggetti tipizzati di slot di estensione:

  • PluginDashboardWidget per le schede di dashboard in sola lettura
  • PluginSystemCard per schede o link di sistema in sola lettura
  • PluginBlockTypeDefinition per le dichiarazioni di tipi di blocco di proprietà del plugin
  • PluginBlockPackDefinition per dichiarazioni raggruppate di blocchi del plugin
  • PluginPublicAsset per le dichiarazioni di asset pubblici nell'head e a fine body
  • PluginAdminExtensionRegistry, PluginBlockRegistry e PluginPublicAssetRegistry per la raccolta dei soli elementi abilitati

Le chiavi dei widget di dashboard e delle schede di sistema devono avere un namespace con punti che includa l'handle del plugin, per esempio analytics-tools.overview. Gli handle degli asset pubblici seguono la stessa regola di namespace con punti. Gli handle di blocco di un plugin devono usare un namespace di proprietà del plugin come analytics-tools::score-card; gli handle di blocco non qualificati in stile core, come hero, vengono rifiutati. Questi hook rendono i contributi dei plugin individuabili e attribuibili senza sostituire le view del pacchetto core.

I widget di dashboard vengono mostrati nella dashboard super-admin solo quando il plugin è abilitato e l'utente corrente soddisfa il permesso del widget, se dichiarato. Le schede di sistema vengono mostrate solo sulle superfici di panoramica di sistema previste, con gli stessi controlli di abilitazione e permessi. La pagina di gestione System -> Plugins non mostra schede generiche di contributo dei plugin: resta focalizzata sull'installazione manuale dei plugin e sulle azioni di ciclo di vita, stato, configurazione iniziale, impostazioni e disinstallazione, a meno che in futuro non venga progettato esplicitamente uno slot di estensione per la gestione dei plugin. Entrambi gli slot sono, intenzionalmente, fondamenta in sola lettura.

Gli hook di blocco sono fondamenta puramente dichiarative. Permettono ai plugin abilitati di esporre tipi di blocco e block pack di propria proprietà tramite il registro, ma non sostituiscono i contratti di blocco del core, le sue view, i suoi seeder o i servizi di modifica dei blocchi.

Ciclo di vita del plugin

L'obiettivo del ciclo di vita completo:

  1. scoprire
  2. installare
  3. abilitare
  4. disabilitare
  5. stato/salute
  6. aggiornare
  7. disinstallare o dismettere, in una successiva progettazione con dati distruttivi

L'obiettivo di runtime implementato dalla fase 1 alla fase 5 è intenzionalmente più ridotto del ciclo di vita completo:

  • registro
  • configurazione di abilitazione
  • elenco System -> Plugins
  • superfici di dettaglio e impostazioni in sola lettura in System -> Plugins
  • registrazione dei menu di amministrazione
  • registrazione dei permessi
  • registrazione delle rotte di amministrazione solo per i plugin abilitati
  • registrazione dei comandi solo per i plugin abilitati
  • reportistica di base su stato/salute
  • slot di estensione tipizzati in sola lettura per dashboard e schede di sistema
  • hook di dichiarazione di blocchi e block pack di proprietà del plugin
  • hook di contributo di asset pubblici nell'head e a fine body
  • plugin pilota di prima parte WebBlocks UI Manager con metadati di release, preparazione sicura del manifest locale e pubblicazione controllata su CDN locale con dry-run/apply
  • metadati di versione del plugin e di compatibilità CMS richiesta
  • reportistica di stato attivo e salute per i plugin incompatibili
  • guardie sulle convenzioni di pacchetto e sulle collisioni
  • guardie sulla proprietà delle rotte

Queste fondamenta danno al CMS un confine host sicuro prima che i plugin acquisiscano un comportamento di ciclo di vita più profondo.

Nota di implementazione della fase 1

Il runtime iniziale della fase 1 include ora:

  • i value object PluginDefinition, PluginRegistry, PluginMenuItem e PluginPermission nel namespace del pacchetto Support\Plugins
  • validazione deterministica per handle in kebab-case, handle duplicati, chiavi di voce di menu duplicate, versioni in stile semver e permessi di plugin prefissati con l'handle
  • stato di abilitazione basato sulla configurazione tramite config/webblocks-plugins.php
  • un elenco System -> Plugins di proprietà del pacchetto su /webadmin/system/plugins
  • copertura delle guardie di rotta che dimostra che /webadmin resta canonico mentre le rotte /admin di proprietà del CMS e le rotte Laravel /cms restano assenti

La fase 1 non include la scoperta dinamica dei plugin via Composer, le migrazioni dei plugin, le azioni di interfaccia di installazione/abilitazione/disabilitazione, le rotte pubbliche dei plugin, il comportamento di marketplace/catalogo o la logica applicativa di WebBlocks UI Manager. Lo stato di abilitazione basato sulla configurazione è intenzionalmente un ponte: una fase successiva del ciclo di vita potrebbe spostare lo stato di installazione/abilitazione/disabilitazione su storage persistente.

Nota di implementazione della fase 2

Il runtime della fase 2 include ora:

  • registrazione delle rotte di amministrazione dei plugin solo per i plugin abilitati tramite PluginRouteRegistrar
  • URL di amministrazione dei plugin predefiniti sotto /webadmin/plugins/{plugin-handle}/...
  • nomi di rotta di amministrazione dei plugin predefiniti sotto webblocks.plugins.{plugin_handle}.*
  • pagine di impostazioni in sola lettura predefinite per i plugin abilitati che dichiarano PluginSettingsDefinition
  • raccolta dei comandi da console solo per i plugin abilitati tramite PluginCommandRegistrar
  • PluginHealthResult, PluginLifecycleStatus e PluginHealthMonitor per la reportistica di base sullo stato
  • pagine di dettaglio di System -> Plugins che espongono riepiloghi di ciclo di vita, salute, impostazioni, rotte, comandi, permessi e contributi ai menu
  • copertura delle guardie di rotta che dimostra che le rotte dei plugin di test abilitati vengono registrate, che le rotte dei plugin disabilitati sono assenti, che /webadmin resta canonico, che /cms non è un namespace di rotte di amministrazione Laravel e che le rotte /admin di proprietà del CMS restano assenti

Questa fase lascia intenzionalmente fuori ambito la scoperta delle migrazioni, le azioni di installazione/applicazione/esecuzione dei plugin, le azioni distruttive del ciclo di vita, la scoperta dinamica via Composer, le rotte pubbliche dei plugin e il comportamento a runtime di WebBlocks UI Manager.

Nota di implementazione della fase 3

Il runtime della fase 3 include ora:

  • contratti tipizzati di estensione dell'amministrazione sotto Support\Plugins\Contracts
  • i value object PluginDashboardWidget e PluginSystemCard raccolti tramite PluginAdminExtensionRegistry
  • rendering dei widget di dashboard solo per i plugin abilitati nella dashboard super-admin
  • raccolta delle schede di sistema solo per i plugin abilitati sulle superfici di panoramica di sistema previste, tenuta separata dalla pagina di gestione del ciclo di vita System -> Plugins
  • PluginBlockTypeDefinition, PluginBlockPackDefinition e PluginBlockRegistry per le dichiarazioni di blocchi di proprietà del plugin
  • PluginPublicAsset e PluginPublicAssetRegistry per dichiarazioni sicure di asset pubblici nell'head e a fine body
  • guardie di validazione per chiavi di estensione, chiavi di widget, chiavi di scheda di sistema, handle di blocco, namespace dei block pack, handle degli asset, proprietà del plugin e dichiarazioni duplicate
  • comportamento inerte dei plugin disabilitati per widget di dashboard, schede di sistema, hook di blocco e asset pubblici
  • copertura delle guardie di rotta che conferma che /webadmin e /webadmin/plugins/... restano validi mentre le rotte di amministrazione /admin e Laravel /cms restano assenti

Questa fase lascia intenzionalmente fuori ambito il comportamento reale di marketplace, l'installazione di pacchetti, gli esecutori di migrazioni dei plugin, le rotte pubbliche dei plugin, i widget modificabili, gli hook di sostituzione dei blocchi core e il plugin WebBlocks UI Manager. I plugin continuano a non poter sostituire le view del pacchetto né applicare patch ai servizi core.

Nota di implementazione della fase 4

Il runtime della fase 4 include ora il plugin pilota di prima parte webblocks-ui-manager. Il plugin è registrato dal registro del pacchetto ma è disabilitato per impostazione predefinita tramite config/webblocks-plugins.php.

Quando è abilitato, il pilota contribuisce con:

  • permessi prefissati con l'handle: webblocks-ui-manager.view, webblocks-ui-manager.manage e webblocks-ui-manager.publish
  • un namespace di rotte di amministrazione del plugin sotto /webadmin/plugins/webblocks-ui-manager/... con nomi di rotta sotto webblocks.plugins.webblocks_ui_manager.*
  • una voce di menu del plugin per i record di release di WebBlocks UI
  • schede di dashboard e di sistema in sola lettura tramite gli slot di estensione della fase 3
  • visibilità di impostazioni/dettaglio in sola lettura tramite le fondamenta delle impostazioni della fase 2
  • controlli di salute del plugin per la disponibilità dei metadati di release, lo stato di configurazione richiesta/tabella mancante e la disponibilità del percorso base CDN configurato
  • tabelle e modelli di proprietà del plugin: webblocks_ui_manager_releases, webblocks_ui_manager_artifacts e webblocks_ui_manager_publish_runs
  • un comando locale sicuro webblocks-ui-manager:prepare-release che registra i metadati di release, calcola i checksum SHA-256 degli artefatti e può facoltativamente scrivere un manifest.json locale
  • un flusso controllato webblocks-ui-manager:publish-release {version} --dry-run e webblocks-ui-manager:publish-release {version} che registra le esecuzioni di pubblicazione e scrive solo dopo il superamento della validazione
  • convenzioni di destinazione CDN di prima parte sotto public/cdn/webblocks-ui/{version}/...

Lo stato disabilitato resta inerte: rotte, comandi, menu, rotte delle impostazioni, permessi, schede di dashboard/di sistema, comportamento di salute e contributi di asset sono assenti dalla raccolta attiva. Lo stato abilitato ma non configurato resta sicuro: il menu può essere visibile, ma la rotta Releases verifica la disponibilità dello schema prima di interrogare e mostra indicazioni di configurazione richiesta quando mancano le tabelle di release. Gli URL di amministrazione manuali dei plugin abilitati e compatibili non devono ripiegare sulla dashboard quando l'idratazione dinamica delle rotte è obsoleta o è in gioco la cache delle rotte; il fallback delle rotte di plugin mantiene le pagine di amministrazione note del plugin sul loro URL /webadmin/plugins/{plugin-handle}/... e reidrata rotte e sorgente di proprietà del plugin prima di mostrare schermate controllate di configurazione o operative. Le azioni Releases di WebBlocks UI Manager di prima parte, le azioni di creazione/salvataggio/visualizzazione/modifica/aggiornamento/dry-run/pubblicazione delle release e gli URL di Settings sono inoltre instradati tramite il core del CMS prima che i file di rotta del plugin vengano eseguiti, così che una sorgente di artefatto installata obsoleta non possa rimandare quelle azioni alla dashboard.

La fase 4 non aggiunge intenzionalmente l'automazione del deploy su CDN di produzione esterna, il comportamento di marketplace, i flussi generici di installazione/aggiornamento di plugin di terze parti, gli esecutori generici di migrazioni dei plugin, le rotte pubbliche dei plugin, le sostituzioni delle view core, la pubblicazione sull'update server o modifiche agli URL con cui il core del CMS consuma WebBlocks UI.

Nota di implementazione della fase 5

Il runtime della fase 5 include ora le fondamenta di packaging e di preparazione per l'ecosistema:

  • controlli della versione del plugin e di requiresCms() rispetto alla versione del CMS installata
  • stato abilitato in configurazione separato dallo stato attivo, così che i plugin configurati incompatibili restino inerti
  • messaggistica di ciclo di vita in System -> Plugins per Enabled, Disabled e Incompatible
  • risultati di salute dei plugin incompatibili che non eseguono i reporter di salute del plugin
  • metadati di convenzione per i namespace delle impostazioni e per i prefissi di database/tabella
  • guardie sui nomi dei comandi per classi di comando Artisan risolvibili, che richiedono {plugin-handle}:...
  • guardie sulle collisioni dei prefissi di database
  • test mirati per i metadati di compatibilità, il comportamento in caso di incompatibilità, le collisioni di comandi e prefissi, l'inerzia in stato disabilitato/incompatibile, la regressione di WebBlocks UI Manager, i confini del pacchetto e la proprietà delle rotte
  • documentazione su convenzioni di pacchetto, scoperta locale, creazione minima di un plugin, strategia di aggiornamento dello schema e politica di compatibilità tra release

La fase 5 non aggiunge intenzionalmente un'interfaccia di marketplace/catalogo, l'installazione di pacchetti remoti arbitrari, la scoperta dinamica remota via Composer, esecutori generici di migrazioni per plugin di terze parti, il deploy automatico su CDN di produzione esterna, la pubblicazione generica sull'update server o rotte pubbliche dei plugin.

Test e salvaguardie di rilascio

Il sistema di plugin deve essere protetto da test sulla proprietà delle rotte, sui confini del pacchetto e sulla coesistenza.

Salvaguardie obbligatorie:

  • la proprietà delle rotte di plugin è verificabile con test
  • le installazioni del core CMS non mostrano menu di plugin quando nessun plugin è abilitato
  • i menu dei plugin disabilitati non vengono mostrati
  • le rotte e le azioni dei plugin disabilitati non sono disponibili o falliscono l'autorizzazione
  • widget, schede di sistema, dichiarazioni di blocco e asset pubblici dei plugin disabilitati sono assenti
  • rotte, comandi, menu, permessi, widget, schede di sistema, dichiarazioni di blocco, asset pubblici, rotte delle impostazioni e comportamento dei reporter di salute dei plugin incompatibili sono assenti
  • nomi dei comandi, prefissi di database, handle, slot di estensione, widget, blocchi, asset e namespace dei permessi restano protetti dalle collisioni
  • le schede di estensione di dashboard/sistema di un plugin vengono mostrate solo quando è abilitato e consentito
  • le dichiarazioni di blocco di proprietà di un plugin sono individuabili senza sostituire i contratti di blocco core
  • gli asset pubblici di un plugin vengono raccolti per posizione sicura e sono assenti quando è disabilitato
  • la registrazione delle rotte di plugin non deve ripristinare un namespace /admin di proprietà del CMS
  • /webadmin resta il prefisso canonico di amministrazione del CMS
  • /cms resta territorio di asset statici, non un namespace di rotte di plugin Laravel
  • i tentativi di un plugin di sostituire tabelle, nomi di rotta o view del core dovrebbero far fallire i test o la diagnostica
  • i test sui confini del pacchetto si estendono a rotte, view, asset, migrazioni e comandi di proprietà dei plugin
  • i test di coesistenza dovrebbero coprire gli scenari CMS + QuizTem + plugin previsti nella roadmap

I test dei plugin dovrebbero includere sia i casi senza plugin sia quelli con plugin disabilitato, affinché il core CMS resti pulito nelle installazioni generiche. Il pilota WebBlocks UI Manager porta con sé anche test di migrazione/schema, sui comandi, su manifest/checksum, sul solo stato abilitato, sull'inerzia da disabilitato, sul rendering in amministrazione, sulle guardie di rotta e sui confini del pacchetto.

Decisioni sul plugin pilota WebBlocks UI Manager

WebBlocks UI Manager non è integrato nel comportamento del core del CMS. Attualmente nasce come plugin pilota di prima parte di proprietà del pacchetto, nel namespace del pacchetto CMS, così che l'host dei plugin possa dimostrare una superficie operativa reale e specifica di prodotto senza spostare la gestione delle release/CDN di WebBlocks UI nel core generico del CMS.

Il modello preferito a lungo termine potrebbe comunque diventare un pacchetto Composer separato o un repository separato, una volta maturate le convenzioni di ciclo di vita e di packaging dei plugin.

La responsabilità del plugin:

  • record degli artefatti di release di WebBlocks UI
  • validazione del dist sorgente
  • preparazione locale sicura della pubblicazione
  • esecuzioni controllate di pubblicazione statica locale in dry-run e in applicazione
  • cronologia delle esecuzioni di pubblicazione
  • generazione di manifest e checksum
  • controlli di salute della CDN

La build di WebBlocks UI resta nel repository di WebBlocks UI. Il plugin non compila WebBlocks UI: riceve o convalida gli artefatti di release, registra i metadati locali per i percorsi CDN di prima parte e può pubblicare i file convalidati nella destinazione statica locale o di proprietà del progetto configurata. Il deploy su una CDN di produzione esterna è intenzionalmente rimandato e deve restare esplicito.

I nostri prodotti possono consumare cdn.webblocksui.com per gli asset di prima parte fissati a una versione. La documentazione destinata agli utenti esterni dovrebbe continuare a raccomandare il consumo da GitHub o dalla CDN jsDelivr, salvo che tale politica cambi separatamente.

Regole CDN per il pilota:

  • utilizzate percorsi versionati
  • non utilizzate latest
  • non modificate mai una directory di artefatti versionata esistente
  • non eliminate le vecchie directory CDN versionate durante una pubblicazione normale
  • eseguite il dry-run prima di applicare quando operate manualmente
  • bloccate le discrepanze di checksum invece di sostituire i file in modo silenzioso
  • preferite la distribuzione statica allo streaming tramite le rotte di Laravel

Flusso di pubblicazione di WebBlocks UI Manager

Preparate i metadati della release e i checksum:

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

Eseguite la pubblicazione in modalità dry-run:

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

Applicate la pubblicazione locale:

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

La schermata di dettaglio della release nell'area di amministrazione espone le stesse azioni di dry-run e di pubblicazione quando il plugin è abilitato, è compatibile e l'utente dispone di webblocks-ui-manager.publish. L'azione di pubblicazione reale utilizza una finestra modale di conferma. Il dry-run non è distruttivo.

Impostazioni obbligatorie:

  • WEBBLOCKS_UI_MANAGER_ENABLED=true abilita il plugin.
  • WEBBLOCKS_UI_MANAGER_CDN_BASE_PATH=cdn/webblocks-ui controlla la radice statica locale, di proprietà del progetto, sotto public/.
  • WEBBLOCKS_UI_MANAGER_CDN_BASE_URL è un metadato di visualizzazione facoltativo per gli URL pubblici generati.
  • webblocks-plugins.webblocks_ui_manager.expected_dist_files elenca i nomi dei file dist obbligatori.

Controlli di validazione della pubblicazione:

  • i metadati della release esistono e non sono in bozza
  • la versione della release ha un formato simile a semver
  • il percorso CDN della release corrisponde alla radice configurata più la versione della release
  • i file dist attesi sono presenti
  • i file sorgente esistono all'interno della radice del progetto e non sono fughe tramite collegamenti simbolici
  • i percorsi di destinazione degli artefatti restano all'interno della radice CDN configurata
  • i checksum degli artefatti memorizzati corrispondono ai file sorgente correnti e ai metadati del manifest
  • i file già pubblicati corrispondono ai checksum e vengono saltati oppure bloccano l'esecuzione
  • il contenuto del manifest esistente deve corrispondere al contenuto del manifest preparato

Le esecuzioni di pubblicazione vengono memorizzate in webblocks_ui_manager_publish_runs con modalità, stato, percorsi di destinazione, dettagli dell'operazione e messaggi di errore privi di segreti.