Postgres, PostGraphile, RLS e SQL
Visão Geral
Mecanismo da camada de dados para esta stack. Implementa defesa em profundidade (RLS como parede final) e o caminho de dados legal único. Específico da stack — não se aplica a projetos sem PostGraphile/Postgres.
O Caminho de Dados
Browser → Servidor App → PostGraphile → PostgreSQL. Exatamente um caminho legal.
- O navegador nunca fala diretamente com GraphQL/BD; o app nunca consulta o BD diretamente para dados de aplicação.
- O app passa contexto de sessão apenas como cabeçalhos (id do usuário, dica de org) — nenhuma lógica de autorização no app; o contexto é validado downstream, não confiado.
- Um único caminho = um único lugar para aplicar contexto de auth, validação e RLS. Canais laterais são os buracos que burlam a imposição.
Regras de Segurança
- RLS é a camada de enforcement final. Verificações na camada do app são UX; o banco de dados é a parede. Mesmo um bug nas camadas acima não pode vazar linhas de outro tenant.
- Roles modelam estados reais de sessão — não-logado, logado-sem-org, logado-com-org, um role de conexão, um role de migração. Roles significam algo.
- O role de conexão privilegiado nunca executa consultas de aplicação. Consultas do app são executadas sob um role restrito, sujeito a RLS.
- Funções
SECURITY DEFINERdefinemsearch_pathinline em sua definição — toda vez, sem exceção. - Ausência é
NULL, nunca string vazia. Sentinelas de string vazia são proibidos; omita o valor quando ausente. - GraphQL é uma superfície de DoS — limite-a. Aplique limites de profundidade de consulta e análise de custo/complexidade; rejeite consultas acima do orçamento. Limite o tamanho da paginação. Defina um
statement_timeoutno BD para roles de app. Desabilite introspecção em produção a menos que deliberadamente necessária.
Estilo SQL
- Um objeto por arquivo — cada tabela, função, política, conjunto de grants em seu próprio arquivo.
- Organizado em
schema/object_type/name— diretório espelha a organização do banco de dados. - Ordem de inclusão é ordem de dependência; o manifesto de inclusão é o sumário da estrutura.
- Documente inline.
COMMENT ONvive no mesmo arquivo que o objeto — o que e por quê. - Aliases descritivos (singular do nome da tabela, não letras únicas); siga os idiomas do Postgres (
current_*getters). - Tipos e roles voltados ao usuário são dados, não restrições hardcoded — tabelas de lookup com chave/rótulo/descrição, validados por FK, extensíveis sem mudanças no schema.
Referência Rápida
| Regra | Verificação |
|---|---|
Nova função SECURITY DEFINER | search_path definido inline? |
| Nova tabela com dados de tenant | Política RLS + testes de negação (veja graphql-contract-testing)? |
| Valor ausente | NULL, não ''? |
| Nova superfície GraphQL | Limite de profundidade/custo e limite de paginação? |
| Novo objeto | Arquivo próprio, include ordenado por dependência, COMMENT ON inline? |
Justificativa completa: Artigos XIII, XIV, XVIII da constituição, agrupados em engineering-constitution/references/engineering-constitution.md. Migrações: zero-downtime-migrations. Testes de contrato: graphql-contract-testing.