Pular para o conteúdo principal

Tenancy

Uma instância do SlotBattle serve vários casinos ao mesmo tempo. Um tenant é um casino: as próprias batalhas, a própria allowlist de jogos, as próprias credenciais, o próprio endpoint de webhook. Você é um tenant na instância da plataforma.

O que é do tenant e o que é da plataforma

Essa divisão define a multi-tenancy no SlotBattle. Confira antes de prometer aos jogadores algo que a instância não pode entregar.

É do tenantÉ da plataforma (a instância)
Batalhas e assentosA chave de assinatura de token de viewer
Allowlist de jogosAs três janelas de lobby
Credenciais SoftSwiss do backendConfiguração de e-mail
Endpoint e segredo do webhook de resultadoO gravador e o segredo do callback dele
Chaves de API e seus escoposStorage, CDN, banco, Redis
Usuários de console e seus papéis

Você pode mudar tudo na coluna da esquerda e nada na da direita. Uma janela de lobby diferente é um pedido à plataforma, não uma configuração sua.

Veja O que o host controla.

Como um tenant é identificado numa requisição

Duas superfícies, dois mecanismos, sem sobreposição.

A API S2S deriva o tenant da chave de API. Não há header de tenant nem campo de tenant para enviar: respostas e webhooks ecoam o id, e nada o aceita como entrada.

O tenant nunca vem do corpo da requisição

Um id de tenant lido de um payload transforma toda rota de recurso numa leitura cross-tenant para qualquer um disposto a editar um campo JSON. Derivá-lo da credencial torna essa classe de bug irrepresentável.

O console admin carrega o tenant ativo num header X-Tenant-Id, ao lado do cookie de sessão. É um header, e não um claim no token, para que um operador com acesso a vários casinos possa trocar entre eles sem se reautenticar. A associação é checada em toda requisição, então o header declara uma intenção, e não um direito.

Leitura cross-tenant responde 404

Pedir uma batalha que pertence a outro casino retorna 404 Not Found, a mesma resposta de pedir uma batalha que não existe.

Um 403 confirmaria que a batalha existe, transformando um erro de permissão num oráculo de enumeração: sonde ids, e os que responderem 403 são reais. Toda rota com escopo de batalha carrega a batalha e checa a propriedade antes de mutar qualquer coisa, então uma escrita cross-tenant não pode surtir efeito e depois ser recusada.

Um tenant suspenso é a exceção e recebe um 403. O chamador é legítimo, então nomear o motivo é o correto.

Onde vivem as credenciais de um tenant

Dois lugares, resolvidos numa ordem fixa.

Documentos de settings, por tenant, editáveis pelo console:

CategoriaEscopoGuarda
softswissTenantAs credenciais de backend daquele casino
webhookTenantO endpoint de resultado e o segredo de assinatura daquele casino
lobbyPlataformaAs três janelas de lobby

As credenciais da própria plataforma são o fallback, e não são suas para mudar. Numa instância em que cada casino traz as suas, o fallback fica vazio, e é por isso que um documento softswiss ausente aparece como sessões de bot emitidas sob o id de casino errado, e não como erro.

Três regras de resolução que evitam vazamento de credencial

Um documento completo vence; um vazio cai para o ambiente.

Um grupo de credencial é tudo ou nada. Preencher a sua URL de backend e deixar o token de auth em branco é recusado na escrita, enquanto ainda há um operador presente para corrigir. Pela metade, ele mandaria a credencial da plataforma para o seu endpoint.

Falha de resolução é erro, nunca fallback. Se a leitura de settings falhar, ou um segredo armazenado não puder ser decifrado, a operação falha. Cair para o fallback deixaria uma falha transitória de banco apresentar a credencial da plataforma sob a identidade de um casino.

Segredos nunca voltam

Ler um documento de settings responde "<campo>Set": true|false em vez do valor. Um corpo enviado que omite um segredo deixa o armazenado intacto, porque o cliente não teria como tê-lo recebido. Tratar campo ausente como "limpe isto" faria o Salvar apagar uma credencial que funciona.

Settings salvos são cacheados brevemente e invalidados explicitamente na escrita. Só com TTL, um salvamento do console ficaria invisível até a entrada expirar: o banco correto, o sistema em execução ainda na credencial antiga, e nada reportando erro.

A allowlist no nível da instância

Separada da tabela de tenants, SLOTBATTLE_TENANTS lista quais ids de tenant um processo vai servir. Ela não carrega credencial e não faz autorização; é uma lista de associação. Um tenant ausente dela é desconhecido para aquele processo mesmo que a linha no banco exista.

Allowlists de jogos

Cada tenant tem uma allowlist de jogos, e o endpoint de catálogo retorna só os liberados.

Allowlist vazia significa catálogo vazio

Não significa "todos os jogos". Um tenant recém-criado sem nada liberado vê zero jogos e toda criação de batalha falha, o que se parece com integração quebrada. Liberar jogos faz parte do onboarding.

A tela de jogos do console responde o catálogo inteiro com um booleano por jogo, porque uma tela limitada aos jogos liberados não poderia ser usada para liberar um novo.

Próximo