Plugin Permissions
Jedes Owncast-Plugin läuft in einer Sandbox ohne impliziten Zugriff auf alles außerhalb des Plugins selbst. Um nützliche Arbeiten auszuführen (Chat lesen, im Fediverse posten, eine URL abrufen, in ein Schlüsselwertspeicher schreiben), fragt Ihr Plugin den Host über owncast.*-Methoden. 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.
Wenn ein Administrator ein Plugin installiert, listet die Registerkarte Berechtigungen auf der Detailseite des Plugins genau auf, was das Plugin angefragt hat, in einfacher Sprache. Das ist die Vertrauensgrenze: Ein Administrator kann ein Drittanbieter-Plugin installieren, ohne jede Codezeile zu prüfen, da das Manifest das obere Limit ist, was das Plugin tun kann.
Die Berechtigungsidentifikatoren und das Vertrauensmodell unten sind unabhängig vom verwendeten SDK identisch. owncast.*-Methoden werden hier mit ihren kanonischen Namen referenziert. Für die genaue Schreibweise in Ihrer Sprache, siehe die JavaScript- oder Python-SDK-Dokumentation.
Wie es funktioniert
-
Sie erklären Berechtigungen in
plugin.manifest.json:{ "permissions": ["chat.send", "storage.kv"] } -
Der Administrator überprüft diese beim Aktivieren. Die Detailseite des Owncast-Plugins listet jede Berechtigung mit einer für Menschen lesbaren Beschreibung auf.
-
Der Host durchsetzt sie zur Laufzeit. 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. -
Der Host erkennt Drift. Ihr gebautes Plugin erklärt die Berechtigungen, die es zur Laufzeit verwendet. Der Host vergleicht dies mit dem Manifest und verweigert das Laden des Plugins, wenn zur Laufzeit um mehr gebeten wird, als das Manifest gewährt. Sie können keinen zusätzlichen Zugriff erlangen, indem Sie die Plugin-Datei nachträglich auswechseln.
Neue Genehmigung bei erweiterten Berechtigungen
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. Das Reduzieren von Berechtigungen erfolgt still.
Die effektiven Fähigkeiten eines installierten Plugins wachsen niemals ohne die Zustimmung des Administrators.
Berechtigungsreferenz
chat.send
Gewährt:
owncast.chat.send(text): als Identität des Plugins-Bots postenowncast.chat.sendAction(text): eine "/me"-Nachricht postenowncast.chat.sendTo(clientId, text): private Nachricht an einen verbundenen Clientowncast.chat.replyTo(msg, text): whisper a reply back to whoever sent a chat message (sugar oversendTo)owncast.chat.system(body): poste eine Systemmeldung ohne Benutzeridentität, dargestellt als Serverankündigung (der Inhalt ist HTML)
Nachrichten durchlaufen Owncasts normalen Chat-Pipeline (Filter, Ratenbeschränkungen, Persistenz, Moderation). Plugins können nicht unter beliebigen Namen senden oder tatsächliche Benutzer nachahmen.
chat.history
Gewährt:
owncast.chat.history(limit?): ließt aktuelle Chat-Nachrichtenowncast.chat.clients(): listet verbundene Chat-Clients auf
Nur Leseberechtigung.
chat.moderate
Gewährt:
owncast.chat.deleteMessage(messageId): eine Nachricht vor Zuschauern verbergenowncast.chat.kick(clientId): einen Chat-Client trennen
chat.filter
Gewährt die Möglichkeit, filterChatMessage(msg) zu definieren: jede Chatnachricht zu sehen, bevor sie übertragen wird, mit der Möglichkeit, sie umzuschreiben oder zu verwerfen.
Das Filtern erfolgt inline bei jeder Chatnachricht, sodass der Administrator dies explizit sehen muss. Der Host lehnt das Laden ab, wenn ein Plugin filterChatMessage definiert, ohne diese Berechtigung zu erklären.
users.read
Grants:
owncast.users.list(): lese die Chat-Benutzerlisteowncast.users.get(id): lese einen einzelnen Benutzerdatensatz
users.moderate
Gewährt:
owncast.users.setEnabled(id, enabled, reason?): Benutzer aktivieren oder deaktivierenowncast.users.banIP(ip): eine IP vom Beitritt zum Chat ausschließen
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.
So verwandelt ein Plugin ein Drittanbieter-Login (OAuth, Discord, ein gemeinsames Passwort) in einen echten Owncast-Benutzer mit einer authentifizierten Chat-Identität. Für sich alleine schränkt es weder die Seite ein noch gibt es eine Sitzung aus: Kombinieren Sie es mit auth.gate, um ein Login-Gate zu erstellen, oder verwenden Sie es allein, um verifizierte Chat-Identitäten zu generieren.
auth.gate
Gewährt das Authentifizierungs-Gate für Zuschauer:
owncast.auth.grantSession({ userId, ttl? }): gibt eine signierte Sitzung für einen bereits registrierten Benutzer aus (sieheusers.register)owncast.auth.endSession(): löscht die Sitzung des aktuellen Zuschauers (abmelden)- Der optionale
onAuthCheck-Handler: validiert die Sitzung eines Zuschauers bei jedem Seitenaufruf erneut
Ein Plugin, das auth.gate hält, ist ein Identitätsanbieter. 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. Nur ein auth.gate-Plugin kann gleichzeitig aktiviert sein, und das Gate schlägt fehl, wenn es geschlossen bleibt: Wenn das Plugin nicht verfügbar ist, werden die Zuschauer ausgeschlossen, anstatt hereingelassen zu werden. Siehe Authentifizierung für das vollständige Modell.
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. Plugins können die Schlüssel anderer nicht lesen.
Der Zustand bleibt über Reloads und Host-Neustarts hinweg bestehen.
storage.upload
Grants owncast.storage.upload(name, data): upload a file to Owncast's public file area and get back a URL. Nützlich für Abzeichen, dynamisch generierte Bilder, Attachments für Fediverse-Posts.
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. Nützlich für Caches, generierte Datendateien, Protokolle im Anhang-Stil oder alles, was Sie als echte Dateien anstelle von Schlüssel/Wert-Strings speichern müssen.
Im Gegensatz zu storage.upload bleiben diese Dateien serverseitig: Sie werden niemals über HTTP bereitgestellt. Jeder Pfad ist auf das Verzeichnis des Plugins beschränkt: Ein Plugin kann die Dateien eines anderen Plugins nicht lesen oder aus seiner Sandbox entkommen (../ und absolute Pfade werden zurückgekollabiert).
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
Gewährt owncast.http.fetch(url, opts?): synchrone ausgehende HTTP-Anfragen.
Erfordert eine begleitende network.allowedHosts-Liste im Manifest. Der Host lehnt das Laden ab, wenn network.fetch ohne eine Genehmigungsliste gewährt wird. Jeder Aufruf wird gegen die Genehmigungsliste überprüft. Hosts, die nicht übereinstimmen, geben einen Fehler zurück, bevor Daten den Server verlassen.
{
"permissions": ["network.fetch"],
"network": { "allowedHosts": ["api.discord.com", "*.weather.com"] }
}
Das Wildcard "*" ist erlaubt, muss jedoch ausdrücklich geschrieben werden, damit die Administratoren, die das Manifest überprüfen, den Umfang sehen. Die Administratorenoberfläche zeigt die vollständige Liste der allowedHosts in der Registerkarte Berechtigungen neben der Zeile network.fetch, sodass ein Serverbetreiber, der ein Plugin überprüft, genau sieht, zu welchen Hosts es gelangen kann, ohne die .ocpkg zu entpacken.
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
Gewährt dem HTTP-Router des Hosts die Erlaubnis, Anfragen an /plugins/<your-slug>/* an Ihr Plugin zu senden. Dies umfasst sowohl statische Dateien in Ihrem public/-Verzeichnis als auch dynamische Anfragen, die an Ihren onHttpRequest-Handler weitergeleitet werden.
Ohne diese Berechtigung gibt die gesamte URL /plugins/<your-slug>/ einen 404 zurück.
http.sse
Gewährt owncast.sse.send(channel, event, data) und expose einen hosteigenen Endpunkt unter /plugins/<your-slug>/_sse/<channel>, zu dem Browser mit EventSource verbinden. Unabhängig von http.serve. Ein Plugin kann Ereignisse senden, ohne andere Routen zu bedienen.
server.read
Gewährt die schreibgeschützten Stream- und Serverstatus-APIs:
owncast.stream.current(): Status des Live-Streamsowncast.stream.broadcaster(): eingehende codierte Telemetrieowncast.server.info(): Servername, Version, Zusammenfassungowncast.server.socials(): konfigurierte soziale Linksowncast.server.emotes(): custom chat emotes configured on this serverowncast.server.federation(): Fediverse-Einstellungenowncast.server.tags(): konfigurierte Tags
videoconfig.read
Gewährt owncast.videoConfig.read(): die Ausgabe- und Transcodierungs-Konfiguration lesen (Codecs, Latenzgrad, Stream-Varianten).
videoconfig.write
Gewährt owncast.videoConfig.write(partial): modifizieren der Videoausgabekonfiguration.
Hohes Vertrauen. Änderungen treten beim nächsten Stream-Start in Kraft. Der Host startet eine aktive Übertragung nicht neu. Administratoren sollten vorsichtig Genehmigungen erteilen.
notifications.send
Gewährt die APIs zur Benachrichtigung des Senders:
owncast.notifications.discord(text): über den konfigurierten Discord-Web-Hook des Streamersowncast.notifications.browserPush({ title, body, url? }): an abonnierte Browserowncast.notifications.fediverse({ type, body, image?, link? }): fediverse-formatiert Benachrichtigung
fediverse.inbound
Gewährt die Abonnierung aller sieben eingehenden Fediverse-Plugin-Ereignisse:
fediverse.followfediverse.likefediverse.repostfediverse.quotefediverse.mentionfediverse.replyfediverse.activity
Das fediverse.activity-Catch-All erhält das überprüfte Aktivitäts-JSON-Objekt. Es läuft zusätzlich zu jedem übereinstimmenden spezialisierten Ereignis. Diese Berechtigung deckt nur den Empfang von Aktivitäten ab. Das Posten vom Owncast-Konto erfordert die separate Berechtigung fediverse.post.
fediverse.post
Gewährt owncast.fediverse.post(text): eine öffentliche Nachricht im Fediverse vom Owncast-Konto abgeben.
Hohes Vertrauen: Beiträge werden unter dem eigenen Fediverse-Namen des Streamers veröffentlicht und können nicht stillschweigend widerrufen werden. Administratoren sollten vorsichtig Genehmigungen erteilen.
ui.modify
Gewährt die Fähigkeit, das UI im eigenen Chrome von Owncast zu platzieren:
- Deklarieren von
manifest.actions(Aktionsschaltflächen unter dem Stream). - Aufruf von
owncast.actions.add(...)/.clear()zur Laufzeit. - Deklarieren von
manifest.styles(CSS, das in die Zuschauerseite eingefügt wird). - Deklarieren von
manifest.scripts(JavaScript, das in die Zuschauerseite eingefügt wird). - Deklarieren von
manifest.extraPageContent(ein HTML-Block, der dem Zusatzbereich des Zuschauers vorangestellt ist). - Deklarieren von
manifest.tabs(zusätzliche Registerkarten in der Registerzeile der Zuschauerseite). - Implementierung eines
onPageStylesoderonPageScripts-Handlers (CSS oder JavaScript, das zum Anforderungszeitpunkt zurückgegeben wird, ohne ein manifest-Feld).
Ohne diese Berechtigung werden manisfeste, die eines dieser Felder deklarieren, beim Laden abgelehnt. Die Handler onPageStyles und onPageScripts haben kein manifest-Feld, sodass sie beim Laden nicht abgelehnt werden. Der Host ruft sie einfach nicht auf, es sei denn, das Plugin verfügt über ui.modify. Jedes dieser Elemente greift auf die Zuschauerseite zu, anstatt innerhalb des eigenen URL-Raums des Plugins zu bleiben, sodass der Administrator die Genehmigung sehen muss, um zu verstehen, dass das Plugin in die Host-UI eingreifen kann.
Keines der vier Felder zur Zuschauerinjection erfordert http.serve, und auch die beiden Handler nicht. Der Host liest jede Datei aus dem assets/-Verzeichnis des Plugins (nicht von einer URL) oder ruft den Handler auf und fügt das Ergebnis in die bestehenden Konfigurations-/Custom-JS-Antworten ein, sodass ui.modify allein nicht ausreicht.
Zusammenfassungstabelle
| Berechtigung | Gewährungen |
|---|---|
chat.send | owncast.chat.send, .sendAction, .sendTo, .replyTo, .system |
chat.history | owncast.chat.history, .clients |
chat.moderate | owncast.chat.deleteMessage, .kick |
chat.filter | Abonnieren Sie filterChatMessage (lesen, ändern oder löschen Sie jede Chatnachricht). |
users.read | owncast.users.list, .get |
users.moderate | owncast.users.setEnabled, .banIP |
users.register | owncast.users.register: einen authentifizierten Benutzer für eine externe Identität finden oder erstellen |
auth.gate | owncast.auth.grantSession, .endSession und der onAuthCheck-Handler: die Authentifizierungsgate der Seite sein |
storage.kv | Pro-Plugin benamter Schlüssel/Wert-Speicher |
storage.upload | Dateien in Owncasts öffentlichem Datei-Bereich hochladen |
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 | Ausgehendes HTTP. Erfordert auch network.allowedHosts |
events.emit | Benutzerdefinierte Ereignisse für andere Plugins ausgeben |
http.serve | HTTP unter /plugins/<your-slug>/* bereitstellen |
http.sse | Echtzeitevents über owncast.sse.send und den /_sse/-Endpunkt senden |
server.read | Streamstatus lesen, Serverkonfiguration, Telemetrie kodieren |
videoconfig.read | Die Ausgabekonfiguration/transcoding-Konfiguration lesen |
videoconfig.write | Die Videoausgabekonfiguration ändern (wirkt sich beim nächsten Streamstart aus) |
notifications.send | Discord-, Browser-Push- oder Fediverse-Benachrichtigungen senden |
fediverse.inbound | Abonnieren Sie alle sieben eingehenden Ereignisse: fediverse.follow, .like, .repost, .quote, .mention, .reply und .activity |
fediverse.post | Öffentliche Posts an das Fediverse (rate-limitiert) |
ui.modify | Aktionsschaltflächen oder Registerkarten in Owncasts Viewer-Oberfläche hinzufügen. Inline-Plugin-CSS, JavaScript oder HTML in die Viewer-Seite einfügen |
Prinzip der minimalen Berechtigung
Deklarieren Sie nur, was Sie tatsächlich verwenden. Je enger Ihr Manifest, desto einfacher die Vertrauensentscheidung des Administrators. Wenn Sie feststellen, dass Sie jede Berechtigung auflisten, treten Sie einen Schritt zurück und prüfen Sie, ob Ihr Plugin wirklich zwei Plugins sein sollte.
Wenn Sie während der Entwicklung eine Berechtigung nicht mehr verwenden, entfernen Sie sie aus dem Manifest. Reduzieren ist still. Es gibt keine Schwierigkeiten beim Entfernen nicht verwendeter Einträge.
Improve this page
See something missing or incorrect? Edit the English version of this page or help improve translations.
Gabe Kangas