Lib staff.ts — Resolución de TeamMember desde CF Access
Lib staff.ts — Resolución de TeamMember desde CF Access
Ubicación: functions/_lib/staff.ts
Tipo: Módulo compartido (CF Pages Functions)
Introducido en: PR#45 (s68)
Propósito
staff.ts es el único punto de verdad del proyecto para mapear un email de CF Access a un miembro del staff (TeamMember). Antes de s68, cada función CF Pages mantenía su propia tabla local de emails (p.ej. STAFF_EMAIL_TO_NAME inline en api/me.ts). Esto creaba riesgo de divergencia.
El módulo se comparte entre:
functions/api/me.ts— endpoint/api/meque devuelve el usuario actual.functions/_lib/zoho.ts— resolución del actor para OAuth per-user.functions/api/oauth/zoho/start.ts— validación antes de iniciar el flujo OAuth.functions/api/oauth/zoho/callback.ts— validación del email en elstate.functions/api/tasks/[id]/links/calendar.ts— autoría de vínculos task↔calendario.functions/api/tasks/[id]/links/email.ts— autoría de vínculos task↔email.functions/api/zoho/calendar.ts— resolución del actor para GET/POST calendar.
Tipos exportados
export type TeamMember = 'Edu' | 'Dani' | 'Txell';
export const TEAM_MEMBERS: readonly TeamMember[];
Funciones exportadas
resolveTeamMember(request: Request): TeamMember | null
Lee el header Cf-Access-Authenticated-User-Email (lowercased) del Request de CF Pages y lo mapea a un TeamMember. Devuelve null si el email no está en el mapa o si el header está ausente.
Uso típico en endpoints:
const teamMember = resolveTeamMember(request);
if (!teamMember) {
return Response.json({ error: 'No autenticado' }, { status: 403 });
}
resolveTeamMemberFromEmail(email: string | null | undefined): TeamMember | null
Versión que acepta el email como string (no Request). Usado en el callback OAuth donde el email viene del state persistido en D1, no del request actual.
isTeamMember(value: unknown): value is TeamMember
Type guard. Útil para validar input de usuario o datos serializados.
Mapeo de emails (hardcoded)
| CF Access Email | TeamMember |
|---|---|
edudomo2@gmail.com | Edu |
dfuentes@edomo.net | Dani |
tfuentes@edomo.net | Txell |
Nota: Este mapeo es intencional y hardcoded. El equipo es fijo (3 personas). Añadir un nuevo miembro requiere modificar este archivo y redesplegar.
Seguridad
- El header
Cf-Access-Authenticated-User-Emailes inyectado por Cloudflare Access y no puede ser falsificado por un cliente externo mientras la política “Team only” esté activa. - Endpoints que reciben requests sin pasar por CF Access (p.ej. el callback OAuth, que está en
PUBLIC_PATHS) usanresolveTeamMemberFromEmailsobre elstatealmacenado en D1, no sobre headers del request externo.
Véase también
- [[decision—20260517—integracion-zoho-calendar-mail-pivot]]
- [[feature—zoho—calendar-mail-per-user]]
- [[entity—workers—service—zoho-lib]]
- [[entity—workers—table—zoho-oauth-tokens]]