Usuarios
/dashboard/usuarios es el panel de gestión de staff (no
jugadores) de la org. Permite invitar nuevos miembros por email,
cambiar su rol, resetearles password y revocar el acceso. La fuente
de verdad multi-tenant es user_org_memberships. Solo hop y dir
acceden.
Para comercial
Sección titulada «Para comercial»- Problema que resuelve: los clubes tienen rotación de staff y necesitan dar acceso (o sacarlo) sin pasar por soporte. Más, necesitan controlar el límite de colaboradores incluido en el plan: esencial está limitado a X usuarios, pro/enterprise no.
- Casos de uso típicos: invitar al nuevo fisio cuando arranca la pretemporada, dar de baja al S&C que se fue al verano, promover a un sport scientist a HoP cuando hay cambio de comando técnico.
- Planes que lo incluyen: todos (la gestión existe en todos).
Lo que cambia es el límite de colaboradores:
getPlanLimits(plan) .collaborators. - Diferenciador: revoke “soft” — el auth user queda y su email puede volver a ser invitado por otra org (multi-org listo).
Cómo lo usa el staff
Sección titulada «Cómo lo usa el staff»Acceso y permisos
Sección titulada «Acceso y permisos»- Solo
hopydir. Cualquier otro rol que intente entrar a/dashboard/usuarioses redirigido a/dashboard. - Las server actions (
inviteOrgUser,revokeOrgUser,updateUserRole,resetUserPassword) revalidan el rol del caller en cada invocación conassertCallerRole.
Flujos paso a paso
Sección titulada «Flujos paso a paso»- Invitar un usuario nuevo. Form “Invitar” → email + rol
(
hop,dir,sc,ss,rtp,fisio,med,nut,psi) →inviteOrgUser. Genera link tipoinvitecon Supabase admin (fallback amagiclinksi falla), creauser_profilesy la membership activa, y manda el email via Resend apuntando a/auth/set-password?next=/dashboard. - Invitar usuario que ya está en otra org. Si el email ya tiene
un
user_profilespero sin membership activa en esta org, se crea la membership directo. Si ya tiene membership activa en esta org con otro rol, el action retorna{ needsConfirmation: true }con el rol existente y el nuevo — la UI pide confirmación al caller para evitar cambios silenciosos de privilegios. - Cambiar rol. Inline en la tabla →
updateUserRole. Actualizauser_profiles.roley la membership activa. Toma efecto en el próximo render. - Resetear password. Acción admin →
resetUserPasswordusaadmin.auth.admin.updateUserByIdpara setear una password directa (sin email). - Revocar acceso.
revokeOrgUsermarca la membership comorevoked(no borra el auth user — el mail queda libre para otra org). Limpiastaff_team_assignmentsyorganization_idenuser_profilespor compatibilidad con readers legacy. Bloqueo importante: no se puede revocar al último admin (hopodir) activo de la org — si no, la org queda sin nadie que pueda invitar/revocar y requeriría intervención de superadmin.
Configuración relacionada
Sección titulada «Configuración relacionada»- El límite de colaboradores sale de
getPlanLimits(plan) .collaborators. La UI avisa con warning al 80% del límite. - La pantalla de invitación complementaria del staff vive también
en Settings → Accesos (
AccessTabcorre las mismas actions deactions-access.ts).
Sub-páginas
Sección titulada «Sub-páginas»Dentro del flujo de Usuarios hay dos páginas dedicadas al onboarding del plantel (jugadores, no staff):
Nota técnica: las rutas en código viven en
/dashboard/onboarding-linky/dashboard/onboarding-status(no anidadas bajo/dashboard/usuarios/). La doc las agrupa acá porque conceptualmente son parte de la gestión de cuentas.
FAQ / casos límite
Sección titulada «FAQ / casos límite»- Email no llega: chequear que
RESEND_API_KEYesté en Workers Secrets. Si no,sendEmailfalla silenciosamente yinviteOrgUserretorna'No se pudo enviar el email...'. - Usuario revocado quiere volver: invitarlo de nuevo crea una nueva membership activa. El auth user nunca se borró.
Cómo lo ve el jugador
Sección titulada «Cómo lo ve el jugador»Player surface: N/A. Este módulo gestiona staff. El onboarding del plantel es flujo aparte.
Datos y métricas
Sección titulada «Datos y métricas»Tablas DB
Sección titulada «Tablas DB»user_org_memberships— fuente de verdad.(user_id, organization_id, role, status, revoked_at). Único parcial sobre activos.user_profiles— perfil del staff (legacy reader sincronizado para compatibilidad).staff_team_assignments— qué staff ve qué sub-equipo (se borra al revocar).auth.users(Supabase) — fuente de verdad de emails. Solo se consulta via admin SDK (admin.auth.admin.getUserById).
Integraciones
Sección titulada «Integraciones»- Resend — envío del email de invitación con magic-link.
- Supabase Admin SDK —
generateLink({ type: 'invite' })y fallback amagiclink. - Settings → Accesos — mismas actions.
Limitaciones / roadmap
Sección titulada «Limitaciones / roadmap»- No hay log de “quién invitó / quién revocó”. Los triggers de
audit_log(migration-010) cubrenplayers,injuries,medical_consultations,wellness_entries,rtp_phasesyuser_profiles— pero NOuser_org_memberships, donde viven las invitaciones y revocaciones. Si Enterprise lo pide, agregar trigger sobreuser_org_memberships. - No hay SSO ni MFA — todos los logins son email/password o magic-link de Supabase.
- El reset de password lo hace el HoP/Dir manualmente; no hay flujo self-service “olvidé mi password” custom (se delega a Supabase auth nativo).