Ir para o conteúdo principal

Plugin Permissions

Todo plugin Owncast é executado em um sandbox sem acesso implícito a nada fora do próprio plugin. Para realizar um trabalho útil (ler chat, publicar no fediverse, buscar uma URL, escrever em uma loja de chave-valor) seu plugin solicita ao host através dos métodos 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.

Plugin permissions require Owncast v0.3.0

Plugins require Owncast 0.3.0 or later.

Quando um administrador instala um plugin, a aba Permissões na página de detalhes do plugin lista exatamente o que o plugin pediu, em linguagem simples. Essa é a fronteira de confiança: um administrador pode instalar um plugin de terceiros sem revisar cada linha de código, porque o manifesto é o limite superior do que o plugin pode fazer.

A aba de Permissões na página de detalhes do plugin, listando cada permissão solicitada com uma descrição em linguagem simples
Owncat informs youDisponível em todos os SDKs

Os identificadores de permissões e o modelo de confiança abaixo são os mesmos, independentemente de qual SDK você use. Os métodos owncast.* são referenciados aqui por seus nomes canônicos. Para a grafia exata no seu idioma, consulte a referência do SDK JavaScript ou Python.

Como funciona

  1. Você declara permissões em plugin.manifest.json:

    { "permissions": ["chat.send", "storage.kv"] }
  2. O administrador as revisa ao habilitá-las. A página de detalhes do plugin do Owncast lista cada permissão com uma descrição legível por humanos.

  3. O host as aplica em tempo de execução. 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. O host capta desvios. Seu plugin construído declara as permissões que usa em tempo de execução. O host compara isso com o manifesto e se recusa a carregar o plugin se o tempo de execução solicitar mais do que o manifesto concede. Você não pode obter acesso extra trocando o arquivo do plugin depois.

Reaprovação quando as permissões se expandem

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. Reduzir permissões é silencioso.

As capacidades efetivas de um plugin instalado nunca aumentam sem que o administrador diga sim novamente.

Referência de permissões

chat.send

Concede:

  • owncast.chat.send(text): publica como a identidade do bot do plugin
  • owncast.chat.sendAction(text): publica uma mensagem "/me"
  • owncast.chat.sendTo(clientId, text): envie uma mensagem privada a um cliente conectado
  • owncast.chat.replyTo(msg, text): whisper a reply back to whoever sent a chat message (sugar over sendTo)
  • owncast.chat.system(body): publica uma mensagem do sistema sem identidade de usuário, exibida como um anúncio de servidor (o corpo é HTML)

As mensagens passam pelo pipeline de chat normal do Owncast (filtros, limites de taxa, persistência, moderação). Os plugins não podem enviar sob nomes arbitrários ou se passar por usuários reais.

chat.history

Concede:

  • owncast.chat.history(limit?): lê mensagens de chat recentes
  • owncast.chat.clients(): lista clientes de chat conectados

Somente leitura.

chat.moderate

Concede:

  • owncast.chat.deleteMessage(messageId): oculta uma mensagem dos espectadores
  • owncast.chat.kick(clientId): desconecta um cliente de chat

chat.filter

Concede a capacidade de definir filterChatMessage(msg): vê cada mensagem de chat antes de ser transmitida, com a capacidade de reescrever ou descartar.

A filtragem acontece em linha em cada mensagem de chat, então o administrador precisa ver isso explicitamente mencionado. O host rejeita o carregamento se um plugin definir filterChatMessage sem declarar esta permissão.

users.read

Grants:

  • owncast.users.list(): lê a lista de usuários do chat
  • owncast.users.get(id): lê um único registro de usuário

users.moderate

Concede:

  • owncast.users.setEnabled(id, enabled, reason?): habilita ou desabilita um usuário
  • owncast.users.banIP(ip): banir um IP de participar do 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.

Essa é a forma como um plugin transforma um login de terceiros (OAuth, Discord, uma senha compartilhada) em um usuário Owncast real com uma identidade de chat autenticada. Sozinho não fornece acesso ao site nem emite uma sessão: combine-o com auth.gate para construir um portão de login, ou use-o sozinho para criar identidades de chat verificadas.

auth.gate

Concede o portão de autenticação do visualizador:

  • owncast.auth.grantSession({ userId, ttl? }): issue a signed session for an already-registered user (see users.register)
  • owncast.auth.endSession(): limpa a sessão do visualizador atual (sair)
  • o manipulador opcional onAuthCheck: revalida a sessão de um visualizador em cada carga de página

Um plugin segurando auth.gate é um provedor de identidade. 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. Apenas um plugin auth.gate pode ser ativado por vez, e o portão falha fechado: se o plugin estiver indisponível, os visualizadores são mantidos fora, em vez de deixados entrar. Veja Autenticação para o modelo 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. Os plugins não podem ler as chaves uns dos outros.

O estado persiste entre recargas e reinicializações do host.

storage.upload

Grants owncast.storage.upload(name, data): upload a file to Owncast's public file area and get back a URL. Útil para emblemas, imagens geradas dinamicamente, anexos de publicações do 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. Útil para caches, arquivos de dados gerados, logs de estilo de anexação, ou qualquer coisa que você precise persistir como arquivos reais em vez de strings de chave/valor.

Ao contrário de storage.upload, esses arquivos permanecem do lado do servidor: eles nunca são servidos via HTTP. Cada caminho é restrito ao diretório do seu próprio plugin: um plugin não pode ler os arquivos de outro plugin ou escapar do seu sandbox (../ e caminhos absolutos são colapsados de volta dentro).

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 de saída síncrono.

Requer uma lista de network.allowedHosts no manifesto. O host rejeita o carregamento se network.fetch for concedido sem uma lista de permitidos. Cada chamada é verificada contra a lista de permitidos. Hosts que não correspondem retornam um erro antes que quaisquer bytes deixem o servidor.

{
"permissions": ["network.fetch"],
"network": { "allowedHosts": ["api.discord.com", "*.weather.com"] }
}

O caractere curinga "*" é permitido, mas deve ser escrito explicitamente para que os administradores que revisam o manifesto vejam o escopo. A UI de administrador exibe a lista completa de allowedHosts na aba Permissões ao lado da linha network.fetch, para que um operador de servidor que revisar um plugin veja exatamente quais hosts ele pode alcançar sem desembalar o .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

Concede permissão ao roteador HTTP do host para enviar requisições para /plugins/<seu-slug>/* ao seu plugin. Isso abrange tanto arquivos estáticos no seu diretório public/ quanto requisições dinâmicas direcionadas ao seu manipulador onHttpRequest.

Sem essa permissão, todo o espaço de URL /plugins/<seu-slug>/ retorna 404.

http.sse

Concede owncast.sse.send(channel, event, data) e expõe um endpoint propriedade do host em /plugins/<seu-slug>/_sse/<channel> ao qual os navegadores se conectam com EventSource. Independente de http.serve. Um plugin pode enviar eventos sem fornecer outras rotas.

server.read

Concede as APIs de stream somente leitura e estado do servidor:

  • owncast.stream.current(): estado da transmissão ao vivo
  • owncast.stream.broadcaster(): telemetria de codificação de entrada
  • owncast.server.info(): nome do servidor, versão, resumo
  • owncast.server.socials(): links sociais configurados
  • owncast.server.emotes(): custom chat emotes configured on this server
  • owncast.server.federation(): configurações do fediverse
  • owncast.server.tags(): tags configuradas

videoconfig.read

Concede owncast.videoConfig.read(): lê a configuração de saída e transcodificação (codecs, nível de latência, variantes de stream).

videoconfig.write

Concede owncast.videoConfig.write(partial): modifica a configuração de saída do vídeo.

Alta confiança. As mudanças se aplicam na próxima início do stream. O host não reinicia uma transmissão ativa. Os administradores devem conceder com moderação.

notifications.send

Concede as APIs de notificação do broadcaster:

  • owncast.notifications.discord(text): através do webhook do Discord configurado pelo streamer
  • owncast.notifications.browserPush({ title, body, url? }): to subscribed browsers
  • owncast.notifications.fediverse({ type, body, image?, link? }): fediverse-formatted notification

fediverse.inbound

Concede a assinatura de todos os sete eventos de plugin inbound do Fediverse:

  • fediverse.follow
  • fediverse.like
  • fediverse.repost
  • fediverse.quote
  • fediverse.mention
  • fediverse.reply
  • fediverse.activity

O fediverse.activity genérico recebe o objeto JSON bruto da atividade verificada. Ele é executado além de qualquer evento especializado correspondente. Esta permissão cobre apenas o recebimento de atividade. Publicar da conta Owncast requer a permissão separada fediverse.post.

fediverse.post

Concede owncast.fediverse.post(text): faz uma postagem pública no fediverse da conta Owncast.

Alta confiança: as postagens saem sob o próprio handle do streamer no fediverse e não podem ser revogadas silenciosamente. Os administradores devem conceder com moderação.

ui.modify

Concede a capacidade de colocar UI dentro do próprio chrome do Owncast:

  • Declarando manifest.actions (botões de ação abaixo do stream).
  • Chamando owncast.actions.add(...) / .clear() em tempo de execução.
  • Declarando manifest.styles (CSS inlined na página do visualizador).
  • Declarando manifest.scripts (JavaScript inlined na página do visualizador).
  • Declarando manifest.extraPageContent (um bloco HTML prependido à área de conteúdo extra do visualizador).
  • Declarando manifest.tabs (abas adicionais na linha de abas da página do visualizador).
  • Implementando um manipulador onPageStyles ou onPageScripts (CSS ou JavaScript retornados no momento da requisição, sem campo manifesto).

Sem essa permissão, manifestos que declaram qualquer um desses campos são rejeitados ao carregar. Os manipuladores onPageStyles e onPageScripts não têm campo manifesto, então não são rejeitados ao carregar. O host simplesmente não os chama a menos que o plugin possua ui.modify. Cada um desses alcança a página do visualizador em vez de ficar dentro do próprio espaço de URL do plugin, então o administrador precisa ver a permissão para entender que o plugin está pintando na UI do host.

Nenhum dos quatro campos de injeção de visualizador requer http.serve, e nem os dois manipuladores. O host lê cada arquivo do diretório assets/ do plugin (não a partir de uma URL), ou chama o manipulador, e insere o resultado nas respostas de configuração existentes / custom-JS, então ui.modify por si só é suficiente.

Tabela de resumo

PermissãoConcede
chat.sendowncast.chat.send, .sendAction, .sendTo, .replyTo, .system
chat.historyowncast.chat.history, .clients
chat.moderateowncast.chat.deleteMessage, .kick
chat.filterInscreva-se em filterChatMessage (ler, modificar ou descartar cada mensagem de chat).
users.readowncast.users.list, .get
users.moderateowncast.users.setEnabled, .banIP
users.registerowncast.users.register: encontrar ou criar um usuário autenticado para uma identidade externa
auth.gateowncast.auth.grantSession, .endSession, e o manipulador onAuthCheck: ser o portão de autenticação do site
storage.kvArmazenamento de chave/valor com namespace por plugin
storage.uploadCarregar arquivos na área pública de arquivos do Owncast
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.fetchSaída HTTP. Também requer network.allowedHosts
events.emitEmitir eventos personalizados para outros plugins
http.serveServir HTTP em /plugins/<your-slug>/*
http.sseEnviar eventos em tempo real via owncast.sse.send e o endpoint /_sse/
server.readLer o estado do fluxo, configuração do servidor, codificar telemetria
videoconfig.readLer a configuração de saída/transcodificação
videoconfig.writeModificar a configuração de saída de vídeo (aplica-se na próxima inicialização do fluxo)
notifications.sendEnviar notificações do Discord, push do navegador ou notificações do fediverse
fediverse.inboundInscrever-se em todos os sete eventos de entrada: fediverse.follow, .like, .repost, .quote, .mention, .reply, e .activity
fediverse.postPublicar para o fediverse (com limitação de taxa)
ui.modifyAdicionar botões de ação ou abas ao chrome do visualizador do Owncast. CSS, JavaScript ou HTML de plugin embutido na página do visualizador

Princípio do privilégio mínimo

Declare apenas o que você realmente usa. Quanto mais restrito for seu manifesto, mais fácil será a decisão de confiança do administrador. Se você se encontrar listando todas as permissões, recuar e ver se seu plugin não deveria ser realmente dois plugins.

Se você parar de usar uma permissão durante o desenvolvimento, remova-a do manifesto. Encolher é silencioso. Não há atrito em remover entradas não utilizadas.


Improve this page

See something missing or incorrect? Edit this page and improve the documentation for everyone.

Contributors to this documentation
Gabe KangasGabe Kangas
G
Gabe Kangas