Arquitetura do Vault
Esta página é uma referência técnica para operadores e colaboradores preocupados com segurança que desejam entender como a integração do vault da Switchbord funciona de ponta a ponta. Para instruções de configuração, veja Configuração do Vault.Modelo de Armazenamento
A Switchbord usa duas camadas de objetos de banco de dados para armazenar segredos de workspace:vault.secrets (nativo do Supabase)
Os valores dos segredos efetivamente criptografados residem aqui. Cada linha contém uma coluna secret criptografada com pgsodium (AES-256-GCM), uma coluna name para identificação legível por humanos, e um key_id referenciando a chave pgsodium usada para a criptografia. As linhas são identificadas por um UUID.
app_private.workspace_secret_bindings (personalizado da Switchbord)
Esta tabela mapeia um workspace aos seus segredos:
vault.secrets.
Por que o Schema app_private
O schema app_private é usado para tabelas e funções que não devem ser expostas via PostgREST (a API REST auto-gerada do Supabase). Por padrão, o PostgREST expõe apenas objetos do schema public (e schemas explicitamente listados em db_schema). Colocar workspace_secret_bindings em app_private garante que:
- Nenhum cliente anônimo ou autenticado possa executar
SELECTdiretamente na tabela de bindings via a biblioteca cliente do Supabase - Nenhum endpoint REST para
/app_private/workspace_secret_bindingsseja gerado - O acesso só seja possível por meio de funções explicitamente definidas que executam como
SECURITY DEFINER
workspace_secret_bindings como uma medida de defesa em profundidade, mas a colocação no schema app_private é a camada de isolamento primária.
O padrão de schema
app_private é uma convenção padrão do Supabase para objetos de schema sensíveis. Ele é documentado nos próprios guias de “Row Level Security” e “Functions” do Supabase como a forma recomendada de proteger dados que nunca devem ser acessíveis diretamente.Arquitetura do Caminho de Leitura
O caminho de leitura foi projetado para evitar exigir uma conexão direta ao banco de dados a partir do serviço worker. Todas as leituras sensíveis passam por funções RPC do Supabase definidas comSECURITY DEFINER.
Funções SECURITY DEFINER
Para garantir que os itens do vault nunca sejam expostos via o schema public padrão ou endpoints REST auto-gerados, a Switchbord usa o padrão de schema app_private.
app_private.read_workspace_secret
Junta app_private.workspace_secret_bindings com vault.decrypted_secrets para retornar o valor em texto puro. Executa como SECURITY DEFINER, permitindo acesso ao schema vault, que normalmente é restrito.
app_private.resolve_workspace_by_verify_token
Usada durante a verificação de webhook da Meta para rotear requisições ao workspace correto sem expor tokens ao cliente.
Wrappers RPC Públicos
Como o PostgREST expõe apenas o schemapublic, fornecemos wrappers finos que aplicam a autorização:
public.sb_read_workspace_secret: Validaauth.role() == 'service_role'antes de delegar à função privada.public.sb_resolve_workspace_by_verify_token: Segue o mesmo padrão de segurança para resolução de token.
Caminho de Gravação
O caminho de gravação passa pela aplicação web da Switchbord e não envolve o worker:SUPABASE_DB_URL) ao chamar vault.create_secret() de fora do servidor da aplicação, mas a rota de API Next.js trata isso usando o cliente de service role do Supabase. Quem faz self-hosting não precisa de SUPABASE_DB_URL no worker — apenas na aplicação web, se gravações no vault forem necessárias a partir de código do lado do servidor.
Criptografia em Repouso
O Supabase Vault usa pgsodium, uma extensão do PostgreSQL que envolve a libsodium.- Algoritmo: XChaCha20-Poly1305 (uma cifra de fluxo com autenticação)
- Gestão de chaves: o pgsodium usa uma chave raiz derivada de um segredo armazenado fora do banco de dados (na infraestrutura de gestão de chaves do Supabase para Cloud, ou configurada separadamente para self-hosted)
- Escopo de criptografia: cada segredo em
vault.secretsé criptografado com uma chave derivada da chave raiz. O texto cifrado e o ID da chave são armazenados juntos; o texto puro nunca é persistido. - Descriptografia: a view
vault.decrypted_secretsrealiza a descriptografia de forma transparente usandopgsodium.crypto_aead_det_decrypt(). Somente papéis de banco de dados com permissão de SELECT nessa view podem ler valores em texto puro.
Para implantações Supabase Cloud, a chave raiz do pgsodium é gerenciada pelo Supabase e nunca é exposta aos proprietários do projeto. Para Supabase self-hosted, você é responsável por proteger a chave raiz — veja o guia de self-hosting do Supabase para configuração de chaves.
Resumo do Controle de Acesso
O worker autentica todas as chamadas RPC usando o JWT de service role (
SUPABASE_SECRET_KEY). Essa chave deve permanecer secreta e nunca deve ser exposta a clientes de navegador ou registrada em logs.
Referência de Migração
A integração do vault é composta por duas camadas: Nativo do Supabase (nenhuma ação necessária)- Schema
vaulte tabelavault.secrets - View
vault.decrypted_secrets - Função
vault.create_secret() - Extensão pgsodium
CREATE EXTENSION supabase_vault.
Personalizado da Switchbord (aplicado via migrations)
- Criação do schema
app_private - Tabela
app_private.workspace_secret_bindings - Função
app_private.read_workspace_secret() - Função
app_private.resolve_workspace_by_verify_token() - Wrapper
public.sb_read_workspace_secret() - Wrapper
public.sb_resolve_workspace_by_verify_token()
supabase/migrations/. Executar supabase db push aplica todas as migrations pendentes e garante que esses objetos existam.
Se você precisar inspecionar as definições de função diretamente:
Considerações de Segurança para Quem Faz Self-Hosting
Exposição da chave de service role ASUPABASE_SECRET_KEY pode chamar qualquer função RPC e contorna o RLS. Trate-a com o mesmo cuidado que uma senha raiz de banco de dados. Rotacione-a imediatamente se suspeitar de exposição.
Chave pgsodium do Supabase self-hosted
Se estiver executando o Supabase localmente ou em sua própria infraestrutura, a chave raiz do pgsodium deve ser definida antes que qualquer segredo seja armazenado. Se a chave for alterada ou perdida, todos os segredos do vault armazenados se tornam irrecuperáveis — não há custódia de chave (key escrow).
Integridade das migrations
As funções SECURITY DEFINER em app_private são tão seguras quanto o papel proprietário do banco de dados. Garanta que somente partes de confiança tenham a capacidade de redefinir ou substituir essas funções via migrations.
Guias Relacionados
- Configuração do Vault — configuração de self-hosting, variáveis de ambiente e solução de problemas
- Segredos e Criptografia — política de segurança, hash de chave de API e cabeçalhos de segurança HTTP
- Multi-Tenancy — modelo de isolamento de workspace
- Autenticação — tratamento de JWT e modelo de sessão