Banco de dados e fronteira SQL
O banco participa da segurança do COBRES. O backend não se conecta como superusuário para atender requisições e não usa apenas filtros de tela para separar clientes.
Papéis e pools
A API usa os pools tenant, platform e audience; o worker usa o pool worker. Cada pool se conecta com sua role específica. O contexto estabelece o ator, a organização e, quando aplicável, o relacionamento Audience.
As conexões são reutilizadas. Por isso, sessões anteriores à autenticação começam com app.reset_request_context(). Uma operação não pode herdar o ator de quem usou a conexão antes.
Escritas de domínio
Escritas em identidades, sessões, memberships, papéis, chaves, webhooks e eventos passam por funções SECURITY DEFINER, chamadas por exec_fn. As roles de requisição recebem leitura com RLS e não recebem DML livre nessas tabelas.
Uma função nova precisa de proprietário, search_path controlado, revogação de execução pública e grants explícitos aos chamadores corretos. Esquecer o grant deve impedir a operação. As exceções já previstas, como linhas de arquivo e tabelas de trabalho do worker, não autorizam novos atalhos em outros módulos.
RLS e autorização
RLS controla o limite entre organizações. RBAC controla o que o ator pode fazer dentro desse limite. Os módulos do COBRES acrescentam escopos de empresa, carteira e atribuição. Uma rota pode exigir permissão e ainda responder 404 quando o recurso está fora do escopo.
O plano Audience não recebe leitura direta das tabelas do plano de equipe. Projeções específicas retornam os dados permitidos ao relationship. Uma função de equipe também precisa recusar atores Audience.
Transações e concorrência
Dependências de sessão usam Depends(get_session, scope="function"). Assim, o commit acontece antes da resposta. Não retorne uma chave, vínculo ou token de uma operação ainda não confirmada.
Deadlocks e falhas de serialização são traduzidos para 409 concurrency_conflict com Retry-After: 1. A API não repete automaticamente a transação. Dependendo da ação, um token de uso único ou uma chamada externa já pode ter sido utilizado.
Evolução do schema
O schema base está na revisão 0001_baseline (api/app/sql/baseline.sql), que não é editada depois de publicada. Cada mudança de schema é uma revisão nova do Alembic, que aplica um arquivo SQL numerado novo em api/app/sql/ (idempotente: CREATE OR REPLACE, IF NOT EXISTS, com os grants repetidos). Roles são objetos do cluster, criados pelo bootstrap e não por Alembic. Alterações precisam manter os testes de fronteira SQL. Execute os testes SQL antes de publicar uma mudança em grants, políticas ou funções.
Veja testes e isolamento.