CreaRack-SL

Runbook · Integración Zoho ↔ Workspace · setup, autorización, troubleshooting

Runbook operativo para todo lo relacionado con la integración Zoho (Calendar + Mail) del workspace tras el pivot s68 (17-05-2026).

Arquitectura en una frase

D1 sigue siendo SoT único para tasks (KanbanMini intacto). Zoho Calendar + Mail entran como canales de acción explícita desde TaskModal — la task es el hub, Zoho es el brazo ejecutor. Per-user OAuth (cada miembro del staff autoriza su propia cuenta).

Quién debe leer esto

  • Edu / Dani / Txell — para autorizar su cuenta Zoho o re-autorizar tras cambio de scopes.
  • Operador de incidentes — si algún evento Calendar no aparece, falla un cierre de task, o el panel /settings/integrations/zoho muestra “sesión desconocida”.

Para el usuario final

Autorizar mi cuenta Zoho (primera vez)

  1. Inicia sesión en el workspace con tu email @esfericlabs.com.
  2. Visita https://workspace.crearack.com/settings/integrations/zoho/.
  3. En tu propia card pulsa “Conectar Zoho”.
  4. Zoho te pide login con tus credenciales y muestra el consent screen. Acepta todos los permisos.
  5. Volverás a la página con tu card marcada como “Conectado”.

Crear una task con evento Calendar (manual)

  1. Modal “Nueva tarea” → título + assignees + due_date.
  2. Despliega ”+ Crear evento” → ajusta start/end → “Añadir a la tarea”.
  3. (Opcional) ”+ Vincular email” → busca un email del Mail → selecciona.
  4. Pulsa Crear.
  5. La task aparece en KanbanMini con badge 1 evento (o 2 eventos).

Crear/cerrar una task (automático)

Cuando creas una task con assignees + due_date, automáticamente:

  • Aparece un evento all-day “Inicio · [task]” hoy en el Calendar de cada implicado.
  • Aparece un evento all-day “Fin previsto · [task]” en la fecha límite.

Cuando pasas la task a Completada:

  • “Fin previsto” desaparece.
  • Aparece “Cerrado · [task]” en hoy.

Cuando borras la task:

  • Todos los eventos auto desaparecen del Calendar de cada implicado.

Truco operativo

Si refrescas el Zoho Calendar y no aparecen los cambios, recarga con Ctrl+Shift+R o reset de sesión. El cliente Zoho cachea aggressivamente. Los eventos sí están creados — es solo cosmética del navegador.

Para el administrador (Edu)

Autorizar Zoho en nombre de Dani o Txell (modo admin)

Útil para pre-configurar las cuentas antes del onboarding.

1. mail.zoho.eu → avatar → Sign out (CADA VEZ entre miembros)
2. (cerrar la pestaña de mail.zoho.eu)
3. https://workspace.crearack.com/api/oauth/zoho/start?as=<TeamMember>
   donde <TeamMember> = Edu | Dani | Txell
4. Zoho pide login fresh → metes credenciales del miembro correcto → Accept
5. Verifica en /settings/integrations/zoho que la card muestra el email correcto
6. Repetir desde 1 para el siguiente miembro

FOOTGUN crítico: si NO haces logout en mail.zoho.eu entre cada ?as=, Zoho usa la sesión activa anterior y el token se guarda mapeado al wrong team_member. Ver memoria feedback_zoho_logout_between_admin_oauth.

Revocar el token de un miembro

Solo Edu puede revocar otros (endpoint admin):

https://workspace.crearack.com/api/zoho/admin-revoke?member=Dani
https://workspace.crearack.com/api/zoho/admin-revoke?member=Txell

Cada miembro puede revocar el suyo desde /settings/integrations/zoho con el botón “Revocar” en su propia card.

Verificar estado de las 3 cuentas

https://workspace.crearack.com/api/zoho/status

Devuelve JSON con members[] (los 3) + current (el actor del request).

Diagnosticar fallo de DELETE/UPDATE auto-events

https://workspace.crearack.com/api/zoho/calendar/debug-close

Auto-detecta la task más reciente con auto_end_planned y ejecuta el DELETE síncrono devolviendo el response Zoho raw. Útil cuando un cierre de task no borra el evento “Fin previsto” en Zoho.

Para el operador de incidentes

Síntoma: el panel dice “sesión actual desconocida” / botón Re-autorizar no aparece

Causa: el header Cf-Access-Authenticated-User-Email no llega y el mapeo STAFF_EMAIL_TO_NAME en functions/_lib/staff.ts no resuelve al usuario.

Fix:

  1. Verificar que el email CF Access del usuario está en STAFF_EMAIL_TO_NAME. Si no, actualizar el código.
  2. Si está, comprobar que CF Access tiene “Include identity in JWT” activado. El fallback JWT decode requiere el claim email en el JWT.

Ver memoria footguns_staff_email_mapping_workspace.

Síntoma: la task se cierra pero el evento “Fin previsto” sigue en Zoho

Causa probable: scope ZohoCalendar.event.DELETE no autorizado en el token actual, o el header etag no se está mandando en el DELETE.

Diagnóstico:

  1. /api/zoho/calendar/debug-close → mira el JSON.
    • Si devuelve status: 400 ETAG_MISSING → bug en el código (regresión).
    • Si devuelve status: 401 o 403 → token sin scope DELETE. Re-autorizar.
    • Si devuelve status: 204 o 200 → arreglado, sigue normal.
  2. Verificar que todos los miembros tienen scope DELETE/UPDATE en su autorización actual (re-autorizar tras cualquier cambio en ZOHO_SCOPES).

Ver memoria footguns_zoho_calendar_etag_required.

Síntoma: las 3 cards muestran la misma cuenta Zoho

Causa: Edu autorizó las 3 cuentas sin hacer logout en mail.zoho.eu entre cada ?as=. Zoho usó la misma sesión activa para los 3 consents.

Fix:

  1. Revocar los tokens cruzados: admin-revoke?member=Dani + admin-revoke?member=Txell.
  2. Re-autorizar siguiendo el protocolo arriba (logout entre cada).

Síntoma: hooks auto fallan silenciosamente

Los hooks onTaskCreated / onTaskUpdated / onTaskDeleted corren en context.waitUntil (background). Si fallan, log con console.warn. Para inspeccionar:

  1. wrangler tail crearacksl-workspace (en local con auth).
  2. Filtrar por [task-zoho-auto].
  3. Identificar la causa (scope, ETag, calendar no encontrado, etc).

Schema D1 relevante

TablaPropósito
zoho_oauth_tokensTokens per-user. PK team_member. Columnas: zoho_email, refresh_token, access_token, dc, granted_by_cf_email.
zoho_oauth_stateState efímero anti-CSRF del flujo OAuth (TTL 1h).
task_calendar_eventsVínculos task ↔ evento Calendar. PK (task_id, zoho_event_uid). Columna link_type distingue manual de los 3 tipos auto.
task_emailsVínculos task ↔ mensaje Mail. PK (task_id, zoho_message_id).

Endpoints relevantes

EndpointFunción
GET /api/meIdentidad del actor (resuelve email + team_member).
GET /api/zoho/statusEstado de las 3 cuentas + actor actual.
DELETE /api/zoho/statusRevocar token del actor (no de otros).
GET /api/oauth/zoho/start[?as=X]Inicia OAuth para sí mismo o (admin Edu) para otro.
GET /api/oauth/zoho/callbackCallback Zoho. Público (en PUBLIC_PATHS).
GET /api/zoho/admin-revoke?member=XRevocar token de cualquier miembro (solo Edu).
GET /api/zoho/calendar[?from=&to=]Eventos del calendar del actor.
POST /api/zoho/calendarCrear evento manual con organizer + attendees.
GET /api/zoho/mail/search?q=&from=&subject=Picker emails para vincular.
GET /api/zoho/mail/compose-url?subject=&body=Deep-link Zoho Mail compose.
GET/POST/DELETE /api/tasks/{id}/links/calendarCRUD vínculos eventos por task.
GET/POST/DELETE /api/tasks/{id}/links/emailCRUD vínculos emails por task.
GET /api/zoho/calendar/debug-closeDebug DELETE síncrono de auto_end_planned. Solo Edu.

Scopes Zoho activos (s68)

  • ZohoCalendar.event.READ — leer eventos
  • ZohoCalendar.event.CREATE — crear eventos
  • ZohoCalendar.event.UPDATE — mover fechas / editar eventos
  • ZohoCalendar.event.DELETE — borrar eventos
  • ZohoCalendar.calendar.READ — listar calendarios
  • ZohoMail.messages.READ — buscar y leer emails para vincular
  • ZohoMail.accounts.READ — identidad de la cuenta Mail

Cualquier cambio en estos scopes requiere re-autorización de las 3 cuentas.

Limitaciones conocidas

  1. Cambiar assignees de una task después de crear NO propaga a los eventos auto ya creados. Los nuevos assignees no aparecen como attendees.
  2. Refresh UI Zoho lento: los cambios aparecen tras refresh manual del navegador (~10-30 s).
  3. Sesión Zoho compartida en navegador entre cuentas → ojo al modo admin ?as= (ver footgun).
  4. Multi-region: solo testeado en dc=eu. Para dc=com o dc=in debería funcionar igual pero sin verificación.

Véase también

  • [[decision—20260517—integracion-zoho-calendar-mail-pivot]]
  • [[decision—20260516—integracion-zoho-workspace]]
  • [[entity—ops—catalogo-servicios-externos]]