Zum Hauptinhalt springen

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.

Plugin permissions require Owncast v0.3.0

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 Berechtigungsregisterkarte auf der Detailseite eines Plugins, die jede angeforderte Berechtigung mit einer Beschreibung in einfacher Sprache auflistet
Owncat informs youIn jedem SDK verfügbar

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

  1. Sie erklären Berechtigungen in plugin.manifest.json:

    { "permissions": ["chat.send", "storage.kv"] }
  2. Der Administrator überprüft diese beim Aktivieren. Die Detailseite des Owncast-Plugins listet jede Berechtigung mit einer für Menschen lesbaren Beschreibung auf.

  3. Der Host durchsetzt sie zur Laufzeit. Calling owncast.chat.send(...) without chat.send in 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 every sql method), readers return an empty or zero value, and calls that return nothing become silent no-ops. fs.write, fs.delete, and storage.upload report failure in their return value instead of raising.

  4. 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 posten
  • owncast.chat.sendAction(text): eine "/me"-Nachricht posten
  • owncast.chat.sendTo(clientId, text): private Nachricht an einen verbundenen Client
  • owncast.chat.replyTo(msg, text): whisper a reply back to whoever sent a chat message (sugar over sendTo)
  • 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-Nachrichten
  • owncast.chat.clients(): listet verbundene Chat-Clients auf

Nur Leseberechtigung.

chat.moderate

Gewährt:

  • owncast.chat.deleteMessage(messageId): eine Nachricht vor Zuschauern verbergen
  • owncast.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-Benutzerliste
  • owncast.users.get(id): lese einen einzelnen Benutzerdatensatz

users.moderate

Gewährt:

  • owncast.users.setEnabled(id, enabled, reason?): Benutzer aktivieren oder deaktivieren
  • owncast.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 (siehe users.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-Streams
  • owncast.stream.broadcaster(): eingehende codierte Telemetrie
  • owncast.server.info(): Servername, Version, Zusammenfassung
  • owncast.server.socials(): konfigurierte soziale Links
  • owncast.server.emotes(): custom chat emotes configured on this server
  • owncast.server.federation(): Fediverse-Einstellungen
  • owncast.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 Streamers
  • owncast.notifications.browserPush({ title, body, url? }): an abonnierte Browser
  • owncast.notifications.fediverse({ type, body, image?, link? }): fediverse-formatiert Benachrichtigung

fediverse.inbound

Gewährt die Abonnierung aller sieben eingehenden Fediverse-Plugin-Ereignisse:

  • fediverse.follow
  • fediverse.like
  • fediverse.repost
  • fediverse.quote
  • fediverse.mention
  • fediverse.reply
  • fediverse.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 onPageStyles oder onPageScripts-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

BerechtigungGewährungen
chat.sendowncast.chat.send, .sendAction, .sendTo, .replyTo, .system
chat.historyowncast.chat.history, .clients
chat.moderateowncast.chat.deleteMessage, .kick
chat.filterAbonnieren Sie filterChatMessage (lesen, ändern oder löschen Sie jede Chatnachricht).
users.readowncast.users.list, .get
users.moderateowncast.users.setEnabled, .banIP
users.registerowncast.users.register: einen authentifizierten Benutzer für eine externe Identität finden oder erstellen
auth.gateowncast.auth.grantSession, .endSession und der onAuthCheck-Handler: die Authentifizierungsgate der Seite sein
storage.kvPro-Plugin benamter Schlüssel/Wert-Speicher
storage.uploadDateien in Owncasts öffentlichem Datei-Bereich hochladen
storage.fsPrivate, sandboxed server-side filesystem at data/plugin-storage/<your-slug>/files/
storage.sqlPrivate per-plugin SQLite database at data/plugin-storage/<your-slug>/db/plugin.db
network.fetchAusgehendes HTTP. Erfordert auch network.allowedHosts
events.emitBenutzerdefinierte Ereignisse für andere Plugins ausgeben
http.serveHTTP unter /plugins/<your-slug>/* bereitstellen
http.sseEchtzeitevents über owncast.sse.send und den /_sse/-Endpunkt senden
server.readStreamstatus lesen, Serverkonfiguration, Telemetrie kodieren
videoconfig.readDie Ausgabekonfiguration/transcoding-Konfiguration lesen
videoconfig.writeDie Videoausgabekonfiguration ändern (wirkt sich beim nächsten Streamstart aus)
notifications.sendDiscord-, Browser-Push- oder Fediverse-Benachrichtigungen senden
fediverse.inboundAbonnieren Sie alle sieben eingehenden Ereignisse: fediverse.follow, .like, .repost, .quote, .mention, .reply und .activity
fediverse.postÖffentliche Posts an das Fediverse (rate-limitiert)
ui.modifyAktionsschaltflä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.

Contributors to this documentation
Gabe KangasGabe Kangas
G
Gabe Kangas