CreaRack-SL

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/me que 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 el state.
  • 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 EmailTeamMember
edudomo2@gmail.comEdu
dfuentes@edomo.netDani
tfuentes@edomo.netTxell

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-Email es 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) usan resolveTeamMemberFromEmail sobre el state almacenado 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]]