Plugin Permissions
Ogni plugin di Owncast viene eseguito in una sandbox senza accesso implicito a nulla al di fuori del plugin stesso. Per fare del lavoro utile (leggere la chat, pubblicare sul fediverse, recuperare un URL, scrivere in uno store chiave-valore) il tuo plugin richiede all'host tramite i metodi owncast.*. Almost every one of those methods is gated by a permission you declare in your manifest. The exceptions are a handful of ambient methods that reach nothing sensitive and need no permission: owncast.log.*, owncast.timer.*, reading your own bundled assets, and owncast.config.get.
Plugins require Owncast 0.3.0 or later.
Quando un amministratore installa un plugin, la scheda Permessi nella pagina dei dettagli del plugin elenca esattamente cosa ha richiesto il plugin, in linguaggio semplice. Questa è la soglia di fiducia: un amministratore può installare un plugin di terze parti senza dover controllare ogni riga di codice, poiché il manifesto è il limite superiore su ciò che il plugin può fare.
Gli identificatori dei permessi e il modello di fiducia qui sotto sono gli stessi indipendentemente da quale SDK utilizzi. I metodi owncast.* sono qui menzionati con i loro nomi canonici. Per la correttezza ortografica nella tua lingua, vedi il riferimento JavaScript o Python SDK.
Come funziona
-
Dichiari i permessi in
plugin.manifest.json:{ "permissions": ["chat.send", "storage.kv"] } -
L'amministratore li esamina quando abilita. La pagina dei dettagli del plugin di Owncast elenca ciascun permesso con una descrizione leggibile dall'utente.
-
L'host li applica in fase di esecuzione. Calling
owncast.chat.send(...)withoutchat.sendin your manifest never reaches Owncast: the host logs the denial and the call does nothing. Mutating calls that report an outcome raise an error (moderation,users.register,auth.grantSession,kv.set,videoConfig.write,actions.add,actions.clear, and everysqlmethod), readers return an empty or zero value, and calls that return nothing become silent no-ops.fs.write,fs.delete, andstorage.uploadreport failure in their return value instead of raising. -
L'host rileva le deviazioni. Il tuo plugin costruito dichiara i permessi che utilizza in fase di esecuzione. L'host confronta questo con il manifesto e rifiuta di caricare il plugin se l'esecuzione richiede più di quanto concesso dal manifesto. Non puoi ottenere accesso extra sostituendo il file del plugin in un secondo momento.
Ri-approvazione quando i permessi si espandono
If you ship an update that asks for more permissions than the admin previously approved, the old approved version keeps running (it holds only the approved permissions) and the new package waits as pending. The plugin list shows a "needs re-approval" badge. The admin reviews the new permissions in the Permissions tab and clicks Approve to accept the expanded set and load the update. Ridurre i permessi è silenzioso.
Le capacità effettive di un plugin installato non crescono mai senza che l'amministratore dica di sì di nuovo.
Riferimento ai permessi
chat.send
Concede:
owncast.chat.send(text): invia come identità bot del pluginowncast.chat.sendAction(text): invia un messaggio "/me"owncast.chat.sendTo(clientId, text): messaggio privato a un client connessoowncast.chat.replyTo(msg, text): whisper a reply back to whoever sent a chat message (sugar oversendTo)owncast.chat.system(body): invia un messaggio di sistema senza identità utente, visualizzato come annuncio del server (il corpo è HTML)
I messaggi attraversano il normale flusso di chat di Owncast (filtro, limiti di velocità, persistenza, moderazione). I plugin non possono inviare con nomi arbitrari o impersonare utenti reali.
chat.history
Concede:
owncast.chat.history(limit?): legge i messaggi recenti della chatowncast.chat.clients(): elenca i client della chat connessi
Solo per lettura.
chat.moderate
Concede:
owncast.chat.deleteMessage(messageId): nasconde un messaggio dai visualizzatoriowncast.chat.kick(clientId): disconnette un client della chat
chat.filter
Concede la possibilità di definire filterChatMessage(msg): vedere ogni messaggio di chat prima che venga trasmesso, con la possibilità di riscriverlo o scartarlo.
Il filtraggio avviene in tempo reale su ogni messaggio di chat, quindi l'amministratore deve vedere questo segnalato esplicitamente. L'host rifiuta di caricare se un plugin definisce filterChatMessage senza dichiarare questo permesso.
users.read
Grants:
owncast.users.list(): legge l'elenco degli utenti della chatowncast.users.get(id): legge un singolo record utente
users.moderate
Concede:
owncast.users.setEnabled(id, enabled, reason?): abilita o disabilita un utenteowncast.users.banIP(ip): banna un IP dall'unirsi alla chat
users.register
Grants owncast.users.register({ authId, displayName?, scopes?, profileUrl?, handle?, public? }): find or create an authenticated Owncast user for an external identity and return its userId. The authId is a stable, provider-scoped identifier such as "github:583231". Pass it raw, without prefixing your slug. The host records the slug separately and scopes every lookup to that pair, so two plugins cannot collide with or spoof each other's users.
The optional profileUrl, handle, and public fields attach a verified external identity. The profile URL must be empty or an absolute HTTP(S) URL. Set public to true only after the viewer opts into public display. These profile fields are captured on the first registration.
Questo è il modo in cui un plugin trasforma un accesso di terze parti (OAuth, Discord, una password condivisa) in un vero utente di Owncast con un'identità di chat autenticata. Di per sé non né delimita il sito né emette una sessione: abbinalo a auth.gate per costruire un gate di accesso, o usalo da solo per coniare identità di chat verificate.
auth.gate
Concede il gate di autenticazione dell'utente:
owncast.auth.grantSession({ userId, ttl? }): issue a signed session for an already-registered user (seeusers.register)owncast.auth.endSession(): cancella la sessione dell'utente corrente (disconnetti)- il gestore opzionale
onAuthCheck: rivalida la sessione di un utente ad ogni caricamento di pagina
Un plugin che possiede auth.gate è un fornitore di identità. While it is enabled, viewers must authenticate through it before they can reach the page, chat, or the API. The operator selects one cumulative access mode on the plugin's Authentication tab to decide whether Owncast-hosted video and stream status also require a session. Solo un plugin auth.gate può essere attivato alla volta, e il gate fallisce in modo sicuro: se il plugin non è disponibile, gli spettatori non possono entrare piuttosto che essere accolti. Vedi Autenticazione per il modello completo.
storage.kv
Grants owncast.kv.get(key), owncast.kv.set(key, value), and the JSON helpers owncast.kv.getJSON(key, fallback?) and owncast.kv.setJSON(key, value): a per-plugin namespaced key/value store. I plugin non possono leggere le chiavi degli altri.
Lo stato persiste attraverso i ricaricamenti e i riavvii dell'host.
storage.upload
Grants owncast.storage.upload(name, data): upload a file to Owncast's public file area and get back a URL. Utile per badge, immagini generate dinamicamente, allegati ai post del fediverse.
storage.fs
Grants owncast.fs.*: a private, sandboxed filesystem at data/plugin-storage/<your-slug>/files/ that your plugin can read, write, list, and delete within. Utile per cache, file di dati generati, log di tipo append, o qualsiasi cosa tu abbia bisogno di mantenere come file reali piuttosto che stringhe chiave/valore.
A differenza di storage.upload, questi file rimangono lato server: non vengono mai serviti tramite HTTP. Ogni percorso è limitato alla directory del tuo plugin: un plugin non può leggere i file di un altro plugin o fuggire dalla sua sandbox (i percorsi ../ e assoluti vengono collassati all'interno).
storage.sql
Grants owncast.sql.*: one private SQLite database per plugin, at data/plugin-storage/<your-slug>/db/plugin.db. owncast.sql.exec(sql, params?) runs statements, owncast.sql.query(sql, params?) returns matching rows, and owncast.sql.queryRow(sql, params?) reads a single row. Reach for this instead of storage.kv when you need to sort, filter, or aggregate rather than just remember a value. See owncast.sql.* for the methods in both languages, the per-call limits, and the SQL the host refuses.
The database is private to your plugin and separate from Owncast's own database. The storage.fs sandbox is rooted at files/, so db/ is not a path owncast.fs.* refuses but one it cannot express, and the filesystem quota walk covers files/ only, so the two quotas stay independent: the database has its own 128 MiB cap, and files written through storage.fs count against a separate 256 MiB quota.
Plugin databases are not included in Owncast's database backups, so treat the contents as rebuildable or export what matters yourself. SQL data is retained when a plugin is uninstalled, the same as its config and its storage.fs files, so a reinstall finds its tables where it left them. An admin who wants the space back deletes data/plugin-storage/<your-slug>/.
network.fetch
Concede owncast.http.fetch(url, opts?): HTTP in uscita sincrono.
Richiede una lista di network.allowedHosts nel manifesto. L'host rifiuta di caricare se network.fetch è concesso senza una lista di autorizzazione. Ogni chiamata è controllata contro la lista di autorizzazione. Gli host che non corrispondono restituiscono un errore prima che qualsiasi byte lasci il server.
{
"permissions": ["network.fetch"],
"network": { "allowedHosts": ["api.discord.com", "*.weather.com"] }
}
Il carattere jolly "*" è consentito ma deve essere scritto esplicitamente affinché gli amministratori esaminando il manifesto vedano l'ambito. L'interfaccia utente dell'amministratore mostra l'intera lista di allowedHosts nella scheda Permessi accanto alla riga network.fetch, quindi un operatore del server che esamina un plugin vede esattamente quali host può raggiungere senza estrarre il .ocpkg.
events.emit
Grants owncast.events.emit(eventType, payload). Pass the receiving plugin's
fully qualified <recipient-slug>.<hook> name. The host does not rewrite the
emitted name. Declaring and receiving a plugin-owned custom hook does not
require a permission.
http.serve
Consente al router HTTP dell'host di inviare richieste a /plugins/<your-slug>/* al tuo plugin. Questo copre sia i file statici nella tua directory public/ che le richieste dinamiche instradate al tuo gestore onHttpRequest.
Senza questo permesso, l'intero spazio URL /plugins/<your-slug>/ restituisce 404.
http.sse
Concede owncast.sse.send(channel, event, data) ed espone un endpoint di proprietà dell'host a /plugins/<your-slug>/_sse/<channel> a cui i browser si connettono con EventSource. Indipendente da http.serve. Un plugin può inviare eventi senza servire altre rotte.
server.read
Concede le API di stato di lettura e streaming:
owncast.stream.current(): stato di streaming liveowncast.stream.broadcaster(): telemetria di codifica in entrataowncast.server.info(): nome del server, versione, riepilogoowncast.server.socials(): link social configuratiowncast.server.emotes(): custom chat emotes configured on this serverowncast.server.federation(): impostazioni del fediverseowncast.server.tags(): tag configurati
videoconfig.read
Concede owncast.videoConfig.read(): legge la configurazione di output e transcodifica (codec, livello di latenza, varianti di streaming).
videoconfig.write
Concede owncast.videoConfig.write(partial): modifica la configurazione di output video.
Alta fiducia. Le modifiche si applicano all'inizio del prossimo streaming. L'host non riavvia una trasmissione attiva. Gli amministratori dovrebbero concedere con parsimonia.
notifications.send
Concede le API di notifica del broadcaster:
owncast.notifications.discord(text): attraverso il webhook Discord configurato dallo streamerowncast.notifications.browserPush({ title, body, url? }): to subscribed browsersowncast.notifications.fediverse({ type, body, image?, link? }): fediverse-formatted notification
fediverse.inbound
Concede l'iscrizione a tutti e sette gli eventi plugin inbound del Fediverse:
fediverse.followfediverse.likefediverse.repostfediverse.quotefediverse.mentionfediverse.replyfediverse.activity
Il fediverse.activity catch-all riceve l'oggetto JSON grezzo dell'attività verificata. Funziona in aggiunta a qualsiasi evento specializzato corrispondente. Questo permesso copre solo la ricezione dell'attività. Inviare dal account Owncast richiede il separato permesso fediverse.post.
fediverse.post
Concede owncast.fediverse.post(text): pubblica un post pubblico sul fediverse dall'account di Owncast.
Alta fiducia: i post vengono effettuati con l'handle fediverse dello streamer e non possono essere revocati silenziosamente. Gli amministratori dovrebbero concedere con parsimonia.
ui.modify
Concede la possibilità di posizionare l'interfaccia utente all'interno del proprio chrome di Owncast:
- Dichiarare
manifest.actions(pulsanti di azione sotto lo streaming). - Chiamare
owncast.actions.add(...)/.clear()in fase di esecuzione. - Dichiarare
manifest.styles(CSS in linea nella pagina del visualizzatore). - Dichiarare
manifest.scripts(JavaScript in linea nella pagina del visualizzatore). - Dichiarare
manifest.extraPageContent(un blocco HTML inserito nell'area di contenuto extra del visualizzatore). - Dichiarare
manifest.tabs(schede aggiuntive nella riga delle schede della pagina del visualizzatore). - Implementare un gestore
onPageStylesoonPageScripts(CSS o JavaScript restituiti al momento della richiesta, senza campo di manifesto).
Senza questo permesso, i manifesti che dichiarano uno di quei campi vengono rifiutati al caricamento. I gestori onPageStyles e onPageScripts non hanno campo di manifesto, quindi non vengono rifiutati al caricamento. L'host semplicemente non li chiama a meno che il plugin non possieda ui.modify. Ognuna di queste si inserisce nella pagina del visualizzatore piuttosto che rimanere nello spazio URL del plugin, quindi l'amministratore deve vedere il permesso per comprendere che il plugin interviene nell'interfaccia utente dell'host.
Nessuno dei quattro campi di iniezione nel visualizzatore richiede http.serve, e nemmeno i due gestori. L'host legge ogni file dalla directory assets/ del plugin (non da un URL), oppure chiama il gestore, e inserisce il resultato nelle risposte config / custom-JS esistenti, quindi ui.modify da solo è sufficiente.
Tabella di riepilogo
| Permesso | Concessioni |
|---|---|
chat.send | owncast.chat.send, .sendAction, .sendTo, .replyTo, .system |
chat.history | owncast.chat.history, .clients |
chat.moderate | owncast.chat.deleteMessage, .kick |
chat.filter | Iscriviti a filterChatMessage (leggi, modifica o elimina ogni messaggio di chat). |
users.read | owncast.users.list, .get |
users.moderate | owncast.users.setEnabled, .banIP |
users.register | owncast.users.register: trova o crea un utente autenticato per un'identità esterna |
auth.gate | owncast.auth.grantSession, .endSession, e il gestore onAuthCheck: essere il cancello di autenticazione del sito |
storage.kv | Negozio di chiavi/valori con spazio dei nomi per plugin |
storage.upload | Carica file nell'area file pubblica di Owncast |
storage.fs | Private, sandboxed server-side filesystem at data/plugin-storage/<your-slug>/files/ |
storage.sql | Private per-plugin SQLite database at data/plugin-storage/<your-slug>/db/plugin.db |
network.fetch | HTTP in uscita. Richiede anche network.allowedHosts |
events.emit | Emetti eventi personalizzati per altri plugin |
http.serve | Serve HTTP a /plugins/<your-slug>/* |
http.sse | Invia eventi in tempo reale tramite owncast.sse.send e l'endpoint /_sse/ |
server.read | Leggi lo stato del stream, la configurazione del server, codifica dei telemetria |
videoconfig.read | Leggi la configurazione di output/transcodifica |
videoconfig.write | Modifica la configurazione di output video (applicata all'avvio del prossimo stream) |
notifications.send | Invia notifiche Discord, push del browser o notifiche del fediverse |
fediverse.inbound | Iscriviti a tutti e sette gli eventi in ingresso: fediverse.follow, .like, .repost, .quote, .mention, .reply, e .activity |
fediverse.post | Invio pubblico al fediverse (con limitazione di rate) |
ui.modify | Aggiungi pulsanti di azione o schede al chrome del visualizzatore di Owncast. CSS, JavaScript o HTML in linea nel la pagina del visualizzatore |
Principio del minimo privilegio
Dichiarare solo ciò che utilizzi effettivamente. Più è ristretto il tuo manifesto, più semplice sarà la decisione di fiducia dell'amministratore. Se ti ritrovi a elencare ogni permesso, fermati e vedi se il tuo plugin dovrebbe davvero essere due plugin.
Se smetti di usare un permesso durante lo sviluppo, rimuovilo dal manifesto. La riduzione è silenziosa. Non ci sono attriti nella rimozione di voci non utilizzate.
Improve this page
See something missing or incorrect? Edit this page and improve the documentation for everyone.
Gabe Kangas