Maioria dos apps CRUD começa com 'roles' que viram código manual por endpoint. Um ano depois ninguém responde 'quem pode aprovar uma devolução?' sem ler o código.
A descida ao caos de permissão segue um caminho previsível. Primeiro, um simples if user.is_staff nos endpoints mais sensíveis. Depois algumas classes de permissão customizadas. Depois overrides por tenant porque 'nosso maior cliente tem uma estrutura de equipe diferente.' Em um ano, permissões estão espalhadas por views, serializers e condicionais de frontend, e o único jeito de saber o que um usuário pode fazer é logar como ele e tentar.
Quatro grupos, uma matriz O Quotery entrega quatro grupos: admin, manager, commercial, warehouse. A matriz de permissão está documentada no CLAUDE.md — uma tabela só mostrando quem faz CRUD em quê. Toda feature nova começa com 'adiciona a linha na matriz, depois liga o check'.
A matriz é deliberadamente plana e deliberadamente pequena. Admin pode tudo. Manager pode tudo exceto mudanças de configuração no nível do tenant. Commercial pode criar e gerenciar cotações, ver seus próprios clientes, e ver disponibilidade de estoque (não ajustar). Warehouse pode gerenciar estoque, postar entregas, processar devoluções, e ver dados relacionados a fulfillment. Quatro linhas, talvez oito colunas. Se uma permissão não cabe nessa matriz, o design da feature provavelmente está complexo demais.
Visibilidade por linha
Usuário commercial vê as cotações dele; admin e manager veem todo o tenant. O service layer impõe isso — a view só passa request.user adiante.
Essa é a parte sutil. Membership de grupo controla acesso grosso (esse usuário pode fechar cotação?). Escopo por linha controla acesso fino (quais cotações esse usuário pode fechar?). Usuários commercial passam os dois checks: têm a permissão 'pode fechar cotação', e a query deles é escopada às cotações que eles possuem. Um usuário de warehouse falha no primeiro check — nunca chega no segundo. Os dois mecanismos são independentes mas compõem de forma limpa.
Por que não ACL fino A gente escolheu baseado em grupo porque o custo do ACL fino é pago em toda request, para sempre. Equipe de 20 não tem 20 roles; tem 4. A hierarquia é plana de propósito.
ACL fino (permissões no nível de usuário em recursos individuais) é a resposta correta para alguns domínios — plataformas de compartilhamento de documentos, ferramentas de gerenciamento de projetos, qualquer coisa onde compartilhamento ad-hoc é funcionalidade central. Operações de distribuição não são esse domínio. Os fluxos de trabalho são estruturados, os papéis são estáveis, e as fronteiras de permissão se alinham com as fronteiras organizacionais. Um modelo baseado em grupo mapeia diretamente para o negócio real: vendedores fazem coisas de venda, almoxarifes fazem coisas de almoxarifado, gerentes supervisionam ambos, admins configuram o sistema. Adicionar ACL por usuário nesse modelo adicionaria complexidade sem adicionar capacidade.
