Salta ai contenuti

I plugin e il catalogo dei plugin

Modalità e tipi di annotazione sono plugin: quelli integrati (ygg.*) sono inclusi nell’app, e un’installazione può aggiungerne altri dal suo catalogo dei plugin. Un superamministratore aggiunge un pacchetto plugin nella sezione Plugin della console e lo abilita; l’app di ogni membro lo carica poi all’avvio, e i tipi di annotazione del plugin compaiono nella procedura guidata di configurazione accanto a quelli integrati.

Un plugin è codice che gira nel browser di ogni membro con i privilegi dell’app. Vede ciò che l’app decifra su quella pagina (le immagini e le risposte che un membro apre), come fanno i plugin integrati; non vede mai le chiavi private, che restano nel worker crittografico dell’app. Abilitare un plugin significa quindi fidarsi del suo codice come di quello dell’app stessa: abilita solo codice che hai esaminato, proveniente da persone di cui ti fidi.

Cosa garantisce la piattaforma:

  • I byte sono quelli che hai abilitato. Un pacchetto indica l’hash Subresource Integrity (SHA-384) del suo modulo. Il catalogo rifiuta un modulo che non corrisponde, e i browser si rifiutano di eseguirlo. L’hash non protegge dal server stesso, che serve l’intera app.
  • Nessun codice da testo. La Content Security Policy dell’app consente script solo dalla sua origine, e mai eval. Il catalogo serve ogni modulo dall’origine dell’app, quindi i plugin girano sotto la stessa policy; un plugin che compila codice a runtime, o carica script da altrove, non funziona.
  • Namespace. L’ID di un pacchetto sta fuori dal namespace riservato ygg, e tutto ciò che fornisce sta sotto quell’ID (org.example.rating fornisce org.example.rating@1 o org.example.rating.stars@1), quindi due pacchetti non forniscono mai lo stesso plugin.
  • Esattamente ciò che dichiara. L’app carica un plugin solo quando il suo modulo registra esattamente i plugin elencati nel suo manifest, e ciascuno supera i controlli del contratto dei plugin. Un plugin che non si carica viene escluso, e la console dice perché; l’app si avvia senza di esso.

Il server conserva il catalogo come metadati in chiaro dell’istanza (programmi, non pazienti) e registra ogni aggiunta, abilitazione, disabilitazione e rimozione nella catena di audit dell’istanza.

Un pacchetto è composto da due file:

File Cos’è
yggdrasil-plugin.json Il manifest del pacchetto (schema plugin/package-v1): ID, versione, nome, descrizione, autore, licenza, homepage, la versione dell’API dei plugin per cui è compilato, il nome del file del modulo e la sua integrità, e i ref che fornisce.
plugin.js Un modulo ES (al massimo 4 MiB) il cui export predefinito è una factory di plugin. Non importa nulla a runtime: React, React Intl, il design system e il runtime dell’API dei plugin vengono dall’app.
yggdrasil-plugin.json
{
"id": "org.example.rating",
"version": "1.0.0",
"name": "Star rating",
"apiVersion": "1.6.0",
"module": "plugin.js",
"integrity": "sha384-…",
"provides": { "annotationTypes": ["org.example.rating@1"] }
}

Il catalogo contiene una voce per ogni ID e versione di pacchetto. Abilitare una versione disabilita le altre versioni del pacchetto.

L’API dei plugin è il pacchetto @yggdrasil/plugin-api (il suo README), con un proprio versionamento semantico: PLUGIN_API_VERSION, attualmente 1.6.0. Un plugin indica in apiVersion la versione per cui è stato compilato; un’app lo carica quando la sua API dei plugin ha la stessa major e almeno quella minor. Una release minor si limita ad aggiungere al contratto; una release major lo rompe, e i plugin vengono ricompilati per essa.

  1. Nella console, apri Plugin e scegli Aggiungi un pacchetto plugin. Seleziona entrambi i file del pacchetto.
  2. Controlla i dettagli: l’ID, la versione, ciò che fornisce e la sua integrità. Aggiungi, disabilitato.
  3. Scegli Abilita. Le app dei membri lo caricano dal loro avvio successivo; ricarica l’app per caricarlo nella tua. La voce indica poi Caricato in questo browser, oppure perché non è stato caricato.

Disabilitare un plugin smette di caricarlo. Le annotazioni scritte dai suoi tipi restano, cifrate come tutte le altre, ma nessuna app può mostrarle o modificarle finché il plugin non viene abilitato di nuovo. Solo un plugin disabilitato può essere rimosso.

  • I componenti di un plugin usano i componenti del design system e gli stili dell’app: l’app non include stili per nomi di classe che non usa essa stessa.
  • Testi: i plugin forniscono il proprio testo inglese tramite i message descriptor di React Intl; le traduzioni dell’app non li coprono.
  • Il server non può verificare le annotazioni di un plugin (non le vede mai decifrate). Le esportazioni le includono come qualsiasi risposta, con il ref del plugin.
  • Il worker di acquisizione di un plugin di modalità gira senza controllo di integrità, come i worker dell’app stessa: i browser non ne prevedono per i worker.