Pular para o conteúdo principal

Controle de acesso

Última atualização: 26 de agosto de 2026

O controle de acesso decide quem tem permissão de mexer em cada Table. Ele responde a uma pergunta diferente da autenticação: o login estabelece quem é quem chama; o controle de acesso estabelece o que essa pessoa pode fazer. O modelo é deliberadamente simples — Read e Write por Table, Execute por Function, para três tipos de chamador — combinado com a posse de linhas por Player.

informação

Por padrão, um client de jogo pode ler mas não escrever, e uma Table recém-criada está completamente fechada para o client. Você abre o acesso de propósito, por chamador e por Table. Se uma chamada de client for recusada por falta de acesso, quem manda é o runtime — uma checagem no lado do cliente pode recusar antes, mas nunca concede.


Os três subjects​

Toda chamada em runtime resolve para um único subject, deduzido da credencial que ela já carrega.

SubjectQuem é
clientO seu client de jogo — a key pública pk_..., com ou sem um Player logado
serverO seu próprio servidor — uma key secreta sk_... (game servers, scripts, CI)
backendAs suas Functions do lado do servidor — o plano de cloud functions

O plano do Backoffice (operador) é separado e nunca é limitado por essas configurações de Table.


Duas camadas que se combinam​

O acesso é decidido em uma ordem fixa: primeiro a autoridade, depois o escopo de linha.

  1. Autoridade da Table — este subject pode ler ou escrever nesta Table, de todo modo? Se não, a chamada é recusada com 403 e nada mais é avaliado.
  2. Escopo de linha — para um client em uma Table owned by a player, quais linhas ficam visíveis? Um Player vê as próprias linhas; a linha de outro Player é invisível.
Chamada + credencial→ subjectautoridadeFlag de Read / Writenão → 403 forbiddenescopo de linhaclient em Table ownedsó as próprias linhasLinha de outro404 — invisível

Autoridade da Table​

Cada Table carrega uma flag de Read e uma de Write para cada subject. Write cobre toda mutação — criar, atualizar e excluir igualmente; não existe uma permissão de delete separada.

SubjectRead padrãoWrite padrão
clientoffoff
serveronon
backendonon

Uma Table recém-criada nasce fechada para o client nos dois eixos, e aberta para server e backend. É por isso que um Update() de client em uma Table nova é recusado até você conceder client.write — a barreira de escrita é o padrão seguro, não um defeito.

aviso

Conceder client.write em uma Table que não é owned by a player deixa qualquer client escrever em qualquer linha dela — o caso de estado compartilhado ou de mundo. Só Tables owned by a player restringem as escritas do client a quem chamou (veja abaixo). Conceda escrita aberta ao client de propósito.


Posse de linhas para clients​

Em uma Table marcada como owned by player, a autoridade da Table ainda decide se um client pode mexer nela; a posse de linhas decide então quais linhas.

  • Read owner — o client vê apenas as próprias linhas.
  • Read public — o client vê todas as linhas (a posse não restringe as leituras).
  • Write — ao criar, o client carimba o Player que agiu como dono; uma atualização ou exclusão só funciona na própria linha de quem chamou.
  • server e backend nunca são restringidos — eles leem e escrevem qualquer linha.

Uma linha pertencente a outro Player é tratada como invisível, não como "proibida": ler, atualizar ou excluir retorna 404 — o mesmo resultado de uma linha que não existe. Isso é intencional, para que o caminho de escrita nunca revele uma linha que o caminho de leitura esconde.

observação

Como uma linha de outro e uma linha inexistente são indistinguíveis por design, não dependa dessa diferença no código do client — as duas voltam como um simples not-found.


Execute em Functions​

Cada Function carrega uma flag de Execute por subject — client, server, backend — todas ligadas por padrão. Um subject sem Execute é recusado com 403.

Execute é separado do requisito de Auth da Function (none ou player): Auth é se um client anônimo pode chamar, Execute é se aquele subject é admitido de todo modo. Uma chamada de client a uma Function com auth player, sem Player logado, é recusada com 401 independentemente do Execute.


Quando uma chamada é recusada​

SituaçãoResultado
O subject não tem Read na Table403 table_read_forbidden
O subject não tem Write na Table403 table_write_forbidden
O subject não tem Execute na Function403 function_execute_forbidden
Client anônimo lê uma Table com escopo owner403 owner_read_requires_player
Client anônimo escreve em uma Table owned422 acting_player_required
Client chama uma Function com auth player sem Player401 player_auth_required
Client mexe em uma linha pertencente a outro Player404 not_found (invisível)
Client lê a conta de outro Player403 player_read_forbidden
dica

Se uma escrita de client for recusada sem que você espere, confira primeiro a flag client.write da Table, depois se a Table é owned by a player e se você está agindo como dono daquela linha. Essas duas coisas juntas explicam quase todo 403/404 no plano de dados.


Próximos passos​