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.
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.
| Subject | Quem é |
|---|---|
| client | O seu client de jogo — a key pública pk_..., com ou sem um Player logado |
| server | O seu próprio servidor — uma key secreta sk_... (game servers, scripts, CI) |
| backend | As 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.
- Autoridade da Table — este subject pode ler ou escrever nesta Table, de todo modo? Se não, a chamada é recusada com
403e nada mais é avaliado. - 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.
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.
| Subject | Read padrão | Write padrão |
|---|---|---|
| client | off | off |
| server | on | on |
| backend | on | on |
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.
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.
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ção | Resultado |
|---|---|
| O subject não tem Read na Table | 403 table_read_forbidden |
| O subject não tem Write na Table | 403 table_write_forbidden |
| O subject não tem Execute na Function | 403 function_execute_forbidden |
| Client anônimo lê uma Table com escopo owner | 403 owner_read_requires_player |
| Client anônimo escreve em uma Table owned | 422 acting_player_required |
Client chama uma Function com auth player sem Player | 401 player_auth_required |
| Client mexe em uma linha pertencente a outro Player | 404 not_found (invisível) |
| Client lê a conta de outro Player | 403 player_read_forbidden |
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
- Data Mutation & Model Extending — as chamadas
Update()/Delete()que estas regras controlam - Schema Object Reference — a configuração owned-by-player e a política de leitura em uma Table
- Functions — onde o Execute por Function e o requisito de Auth são configurados