Permisos limitados
Un rol le dice a GCM qué le está permitido hacer a un usuario. Un alcance le dice dónde le está permitido hacerlo. Sin un alcance, un Leader puede ver cada miembro en tu espacio de trabajo; con un alcance establecido a Sede Este → Centro Anderson, ese mismo Leader ve solo miembros asignados a Centro Anderson y cualquier célula debajo de él. Los verbos del rol no cambian — todavía cubren ver, crear, editar, marcar y enviar — pero las filas a las que aplican se reducen a la porción del árbol organizacional a la que el usuario ha sido asignado.
Así es como la mayoría de iglesias construyen shepherds, pastores de sede, líderes de zona, y cualquier otro rol que deba operar una pieza de la organización sin ver el todo.

Asignar una unidad a un usuario
Abre la fila del usuario en Usuarios y Roles, haz clic en el botón Unidades, y elige una o más unidades organizacionales del selector. El guardado escribe en user_unit_assignments_v2 con el id del usuario, el id de la unidad organizacional y el id de la organización. A diferencia de las asignaciones de rol — que típicamente son un solo chip por usuario — un usuario puede ser asignado a múltiples unidades (un supervisor regional podría cubrir tres sedes), y los alcances se unen.
Deja el selector vacío para acceso a nivel de toda la organización. Una asignación vacía significa no aplica filtro de alcance; el usuario ve todo lo que el rol permite. Este es el predeterminado correcto para org admins, pastores principales y el administrador ejecutivo.
TIP
El botón Unidades solo aparece en usuarios cuyos roles incluyen recursos limitables por unidad. Un Viewer con solo dashboard.view no obtiene un botón Unidades — no hay nada para que el alcance filtre.
Cómo se calcula el filtro
Cuando un usuario limitado inicia sesión, GCM calcula el conjunto de IDs de unidades organizacionales que puede ver. El trabajo lo hace user_visible_unit_ids(org_id), una función PL/pgSQL SECURITY DEFINER en la base de datos:
- Busca cada fila en
user_unit_assignments_v2para ese usuario en esa organización. - Para cada unidad asignada, camina hacia abajo por el árbol vía una CTE recursiva en
org_units.parent_unit_id, recolectando cada descendiente. - La unión es devuelta como un
uuid[]— el conjunto visible completo del usuario.
Un shepherd asignado a Centro Anderson (un hijo de Sede Este) ve:
- Centro Anderson mismo.
- Cada célula bajo Centro Anderson (por ejemplo, Célula Este Anderson, Célula Oeste Anderson).
- Nuevas células agregadas bajo Centro Anderson después — automáticamente, porque la recursión se ejecuta al momento de la consulta.
No ven:
- Sede Este misma (el padre).
- Centro Wilson o cualquier otro hermano bajo Sede Este.
- Cualquier cosa bajo Sede Oeste.
Un platform admin obtiene NULL de esta función, que RLS trata como sin filtro — ven todo en cada tenant.
Dónde se ejecuta el filtro
El alcance se aplica a nivel de base de datos por políticas RLS restrictivas. Cada tabla limitable (members, attendances, member_unit_assignments, y más) lleva una política unit_scope_read que dice: la fila debe pertenecer a la org actual, Y su org_unit_id debe estar en el conjunto visible del usuario, O el conjunto visible debe ser NULL.
Debido a que la política es restrictiva, se interseca con la verificación de permiso. Un Leader con members.view y un alcance de Centro Anderson ve solo miembros de Centro Anderson — ambas condiciones deben pasar. El permiso por sí solo no mostrará filas adicionales; el alcance por sí solo no les dejará ver si el rol carece de members.view.
La misma política restrictiva se aplica a las escrituras. Un Leader limitado no puede editar un miembro fuera de su unidad, incluso si el id de fila es falsificado en la petición. La cláusula WITH CHECK re-ejecuta el filtro de visibilidad para INSERT y UPDATE.
Rendimiento: el envoltorio cacheado
Llamar a user_visible_unit_ids() por fila sería lento — la CTE recursiva se re-expandiría para cada miembro escaneado. Postgres no siempre puede izarla porque pasar una referencia de columna derrota la verificación de invariancia del planificador.
Para arreglar esto, GCM usa un envoltorio sin parámetros, current_user_visible_unit_ids(), que cachea el resultado en un GUC con alcance de transacción (app.uv_units). La primera llamada expande el árbol; cada llamada subsecuente dentro de la misma petición HTTP lee la cadena uuid[] cacheada y devuelve instantáneamente. Esto llevó las consultas de listas de miembros de 4.8 segundos a menos de 200ms en un espacio de trabajo de 1,400 miembros.
No tienes que pensar en esto — cada política RLS usa el envoltorio, y cada carga de página obtiene el valor cacheado gratis.
Limitar para escritura vs. lectura
El alcance aplica a cada verbo que el rol otorga en un recurso limitable. Un Leader con un alcance de Centro Anderson:
- Ve solo miembros y asistencias de Centro Anderson.
- Puede editar solo miembros de Centro Anderson.
- Puede marcar asistencia solo para eventos de Centro Anderson.
- Puede registrar donaciones solo para miembros de Centro Anderson (el miembro de la donación se verifica contra su conjunto visible).
No hay forma de otorgar lectura en toda la org y escritura en una porción — el alcance es uniforme en los verbos del rol. Si necesitas esa división, crea dos roles (uno de solo lectura, a nivel de toda la organización; uno de lectura-escritura, limitado) y asigna ambos al usuario.
Lo que no es limitable
Algunos recursos son inherentemente a nivel de toda la organización e ignoran el filtro de unidad:
- Facturación — no existe tal cosa como una factura limitada por unidad; un espacio de trabajo tiene una suscripción.
- Configuración, channels, modules — estas son configuraciones a nivel de espacio de trabajo.
- El catálogo de roles mismo — los roles son a nivel de espacio de trabajo.
- Fondos — un fondo de donaciones aplica a toda la org, no a una sola unidad.
Si un permiso controla uno de estos recursos (billing.manage, config.manage, users.manage, giving.manage), el alcance es ignorado cuando se ejecuta la verificación. Un Leader limitado a Centro Anderson que de alguna manera también tiene billing.manage vería toda la página de facturación — pero no deberías otorgar esas llaves a un usuario limitado en primer lugar.
Eliminar un alcance
Abre el diálogo Unidades y limpia el selector. Las filas en user_unit_assignments_v2 son eliminadas; el usuario regresa al acceso a nivel de toda la organización (sujeto a lo que su rol aún permita). El cambio toma efecto en su próxima carga de página.
Suspender un usuario no limpia sus asignaciones de unidad — cuando lo reactivas, retoman exactamente donde lo dejaron.
Siguiente
- Roles predeterminados — qué incluyen los roles sembrados antes de limitarlos.
- Otorgar permisos — empareja el alcance con los verbos correctos.
- Registro de auditoría — ver quién limitó a quién.
- Estructura organizacional — cómo se construye el árbol en primer lugar.
