CreaRack-SL

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 OAuth
  • functions/api/me.ts — endpoint /api/me
  • functions/api/oauth/zoho/start.ts
  • functions/api/oauth/zoho/callback.ts
  • functions/api/zoho/calendar.ts
  • functions/api/tasks/[id]/links/calendar.ts
  • functions/api/tasks/[id]/links/email.ts
  • functions/api/zoho/mail/compose-url.ts
  • functions/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 emailTeamMember
edudomo2@gmail.comEdu
dfuentes@edomo.netDani
tfuentes@edomo.netTxell

⚠️ Para añadir un miembro nuevo: editar STAFF_EMAIL_TO_NAME en 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 tratar null como 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]]