staff.ts — Resolución de identidad CF Access → TeamMember
functions/_lib/staff.ts — Resolución de identidad CF Access → TeamMember
Módulo helper añadido en s68 (commit 7617371, 2026-05-17). Centraliza el mapeo de emails de Cloudflare Access a los tres miembros del staff interno de CreaRack SL.
Propósito
Antes de s68, cada endpoint que necesitaba saber “quién es este request” duplicaba inline el mismo mapa email → nombre. staff.ts elimina esa duplicación: es el único lugar donde vive la tabla de identidad del staff.
Consumidores actuales:
functions/_lib/zoho.ts— per-user OAuthfunctions/api/me.ts— endpoint/api/mefunctions/api/oauth/zoho/start.tsfunctions/api/oauth/zoho/callback.tsfunctions/api/zoho/calendar.tsfunctions/api/tasks/[id]/links/calendar.tsfunctions/api/tasks/[id]/links/email.tsfunctions/api/zoho/mail/compose-url.tsfunctions/api/zoho/mail/search.ts
API pública
Tipos
export type TeamMember = 'Edu' | 'Dani' | 'Txell';
export const TEAM_MEMBERS: readonly TeamMember[] = ['Edu', 'Dani', 'Txell'] as const;
Funciones
resolveTeamMember(request: Request): TeamMember | null
Lee el header cf-access-authenticated-user-email (lowercase), busca en la tabla interna y devuelve el TeamMember o null si no está en el mapa.
Usar en: endpoints protegidos por CF Access (todos excepto el callback OAuth).
const teamMember = resolveTeamMember(request);
if (!teamMember) return Response.json({ error: 'No autenticado' }, { status: 403 });
resolveTeamMemberFromEmail(email: string | null | undefined): TeamMember | null
Variante sin Request. Útil cuando el email ya está disponible como string (p.ej. extraído de un row de D1, o del state del flujo OAuth).
Usar en: callback.ts donde el request viene de Zoho, no pasa por CF Access.
isTeamMember(value: unknown): value is TeamMember
Type guard. Devuelve true si value es exactamente 'Edu', 'Dani' o 'Txell'.
Tabla de mapeo actual
| CF Access email | TeamMember |
|---|---|
edudomo2@gmail.com | Edu |
dfuentes@edomo.net | Dani |
tfuentes@edomo.net | Txell |
⚠️ Para añadir un miembro nuevo: editar
STAFF_EMAIL_TO_NAMEen este archivo. El cambio se propaga automáticamente a todos los consumidores.
Invariantes
- El mapa es case-insensitive en entrada (
.toLowerCase()antes de lookup). - Si un email CF Access válido no está en el mapa, las funciones devuelven
null. Los endpoints deben tratarnullcomo 403. - No hay lógica de roles/permisos — todos los miembros tienen los mismos permisos sobre Zoho. Si en el futuro se necesitan roles, este archivo es el punto de extensión.
Véase también
- [[feature—zoho—per-user-oauth]]
- [[decision—20260517—integracion-zoho-calendar-mail-pivot]]
- [[entity—workers—service—zoho-lib]]
- [[entity—workers—endpoint—task-calendar-links]]
- [[entity—workers—endpoint—task-email-links]]