Permissões limitadas
Uma função diz ao GCM o que um usuário pode fazer. Um escopo diz onde ele pode fazer. Sem um escopo, um Leader pode ver cada membro no seu espaço de trabalho; com um escopo definido para Filial Leste → Centro Anderson, esse mesmo Leader vê apenas membros atribuídos ao Centro Anderson e quaisquer células abaixo dele. Os verbos da função permanecem inalterados — ainda cobrem view, create, edit, mark e send — mas as linhas às quais eles se aplicam encolhem para a fatia da árvore organizacional à qual o usuário foi atribuído.
É assim que a maioria das igrejas constrói pastores, pastores de campus, líderes de zona, e qualquer outra função que deve tocar uma parte da organização sem ver o todo.

Atribuindo uma unidade a um usuário
Abra a linha do usuário em Usuários e Funções, clique no botão Unidades e escolha uma ou mais unidades organizacionais no seletor. O salvamento grava em user_unit_assignments_v2 o id do usuário, o id da unidade organizacional e o id da organização. Diferentemente das atribuições de função — que são tipicamente um único chip por usuário — um usuário pode ser atribuído a múltiplas unidades (um supervisor regional pode cobrir três filiais), e os escopos se unem.
Deixe o seletor vazio para acesso em toda a organização. Uma atribuição vazia significa nenhum filtro de escopo se aplica; o usuário vê tudo que a função permite. Este é o padrão certo para admins da organização, pastores principais e o admin executivo.
TIP
O botão Unidades só aparece em usuários cujas funções incluem recursos limitáveis por unidade. Um Viewer apenas com dashboard.view não recebe um botão Unidades — não há nada para o escopo filtrar.
Como o filtro é computado
Quando um usuário limitado entra, o GCM computa o conjunto de IDs de unidades organizacionais que ele pode ver. O trabalho é feito por user_visible_unit_ids(org_id), uma função PL/pgSQL SECURITY DEFINER no banco de dados:
- Procura cada linha em
user_unit_assignments_v2para aquele usuário naquela organização. - Para cada unidade atribuída, percorre para baixo na árvore via uma CTE recursiva em
org_units.parent_unit_id, coletando cada descendente. - A união é retornada como um
uuid[]— o conjunto visível completo do usuário.
Um pastor atribuído ao Centro Anderson (filho de Filial Leste) vê:
- O próprio Centro Anderson.
- Cada célula sob Centro Anderson (ex.: Célula Anderson Leste, Célula Anderson Oeste).
- Novas células adicionadas sob Centro Anderson depois — automaticamente, porque a recursão roda em tempo de consulta.
Ele não vê:
- A Filial Leste em si (o pai).
- Centro Wilson ou qualquer outro irmão sob Filial Leste.
- Qualquer coisa sob Filial Oeste.
Um platform admin recebe NULL desta função, que o RLS trata como sem filtro — ele vê tudo em cada inquilino.
Onde o filtro roda
O escopo é aplicado no nível do banco de dados por políticas RLS restritivas. Cada tabela limitável (members, attendances, member_unit_assignments, e mais) carrega uma política unit_scope_read que diz: a linha deve pertencer à organização atual, E seu org_unit_id deve estar no conjunto visível do usuário, OU o conjunto visível deve ser NULL.
Como a política é restritiva, ela intersecta com a verificação de permissão. Um Leader com members.view e um escopo de Centro Anderson vê apenas membros do Centro Anderson — ambas as condições devem passar. A permissão sozinha não vai mostrar linhas extras; o escopo sozinho não vai permitir que ele veja se a função não tem members.view.
A mesma política restritiva se aplica a escritas. Um Leader limitado não pode editar um membro fora da unidade dele, mesmo que o id da linha seja forjado na requisição. A cláusula WITH CHECK reexecuta o filtro de visibilidade para INSERT e UPDATE.
Desempenho: o wrapper em cache
Chamar user_visible_unit_ids() por linha seria lento — a CTE recursiva se reexpandiria para cada membro escaneado. O Postgres nem sempre pode içar isso porque passar uma referência de coluna derrota a verificação de invariância do planejador.
Para resolver isso, o GCM usa um wrapper sem parâmetros, current_user_visible_unit_ids(), que armazena o resultado em cache em um GUC com escopo de transação (app.uv_units). A primeira chamada expande a árvore; cada chamada subsequente dentro da mesma requisição HTTP lê a string uuid[] em cache e retorna instantaneamente. Isso levou consultas da lista de membros de 4,8 segundos para menos de 200ms em um espaço de trabalho de 1.400 membros.
Você não precisa pensar nisso — cada política RLS usa o wrapper, e cada carregamento de página recebe o valor em cache de graça.
Escopo para escrita vs. leitura
O escopo se aplica a todo verbo que a função concede em um recurso limitável. Um Leader com escopo de Centro Anderson:
- Vê apenas membros e presenças do Centro Anderson.
- Pode editar apenas membros do Centro Anderson.
- Pode marcar presença apenas para eventos do Centro Anderson.
- Pode registrar doações apenas para membros do Centro Anderson (o membro da doação é conferido contra o conjunto visível dele).
Não há forma de conceder leitura em toda a organização e escrita em uma fatia — o escopo é uniforme em todos os verbos da função. Se você precisa dessa divisão, crie duas funções (uma somente leitura, em toda a organização; uma leitura-escrita, limitada) e atribua ambas ao usuário.
O que não é limitável
Alguns recursos são inerentemente em toda a organização e ignoram o filtro de unidade:
- Faturamento — não existe fatura limitada por unidade; um espaço de trabalho tem uma assinatura.
- Configurações, canais, módulos — são configurações em nível de espaço de trabalho.
- O próprio catálogo de funções — funções são em todo o espaço de trabalho.
- Fundos — um fundo de doação se aplica a toda a organização, não a uma unidade só.
Se uma permissão controla um desses recursos (billing.manage, config.manage, users.manage, giving.manage), o escopo é ignorado quando a verificação roda. Um Leader limitado ao Centro Anderson que de alguma forma também detém billing.manage veria a página de faturamento inteira — mas você não deveria conceder essas chaves a um usuário limitado em primeiro lugar.
Removendo um escopo
Abra a caixa de diálogo Unidades e limpe o seletor. As linhas em user_unit_assignments_v2 são excluídas; o usuário volta ao acesso em toda a organização (sujeito ao que sua função ainda permite). A mudança tem efeito no próximo carregamento de página.
Suspender um usuário não limpa suas atribuições de unidade — quando você o reativa, ele retoma exatamente de onde parou.
Próximo
- Funções padrão — o que as funções iniciadas incluem antes de você limitá-las.
- Concedendo permissões — combine escopo com os verbos certos.
- Registro de auditoria — veja quem limitou quem.
- Estrutura organizacional — como a árvore é construída em primeiro lugar.
