Volver a la wiki

Integración Zoho ↔ Workspace · Pivot a Calendar + Mail · per-user OAuth · task como hub de acciones

Contexto

Esta decisión reemplaza [[decision—20260516—integracion-zoho-workspace]] (s67, Fase A en PROD desde 16-05-2026) tras la conversación s68 (17-05-2026) en la que Edu replanteó la premisa de fondo.

Premisa que cambió

El ADR s67 asumía que Zoho era SoT también para tasks. Tras 1 día con Fase A en PROD, Edu verbalizó:

“Nuestro gestor de tareas actual es muy completo y funciona perfectamente, creo que es más capaz que el de Zoho, además lo hemos construido a nuestra medida. He estado pensando que lo que realmente necesitamos es sincronizar nuestro gestor de tareas con el calendario y los emails de Zoho, pero no necesariamente utilizar el gestor de tareas de Zoho.”

Observación correcta: Zoho Tasks (lista plana, sin kanban, sin vinculación cross-entidad, sin asignación múltiple nativa) es objetivamente menos capaz que KanbanMini + página /tasks del workspace (drag-drop, multi-assignee, attachments, notas vinculadas del Cuaderno, integración MCP para crear desde Claude).

Estado heredado de s67

Decisión

Pivot arquitectónico de 3 ejes:

  1. D1 sigue como SoT único para tasks. Zoho Tasks no se utiliza. Se cancela cualquier sync bidireccional, edición remota y migración masiva de tasks.
  2. Zoho Calendar y Zoho Mail entran como canales de acción explícita desde la task del workspace. La task se convierte en hub de operaciones; Zoho son brazos ejecutores.
  3. Per-user OAuth sustituye al Service Account de la Fase A. Cada miembro del staff (Edu, Dani, Txell) autoriza su propio refresh_token. Obligatorio para Mail (cada uno solo puede ver su propio buzón), coherente para Calendar (los eventos van al primary de cada uno).

Modelo “task como hub”

Acciones explícitas en TaskModal.tsx (no sync silenciosa):

Acción en taskComportamiento
+ Crear eventoAPI directa a Zoho Calendar. Evento creado en el primary del creador (organizer). Otros assignees añadidos como attendees (Zoho envía invitación nativa). Disabled si la task no tiene assignees.
+ Vincular emailPicker con filtro from/subject que lista los últimos N emails del usuario. Selección → vínculo persistente en D1.
+ Nuevo emailDeep-link a Zoho Mail compose con subject y body pre-rellenados desde la task. El usuario revisa firma/adjuntos antes de enviar.

Indicadores en cards (KanbanMini + TaskTableView + TaskKanban) muestran counts vinculados como badges numéricos sin iconos (Regla workspace feedback_workspace_buttons_text_only): por ejemplo [2 ev] [5 mail]. Sólo aparecen si count > 0.

Decisión per-user OAuth (cambio crítico vs s67)

EjeService Account (s67)Per-user OAuth (s68 · este ADR)
Tokens en D11 fila singleton (id = 1)1 fila por team_member (Edu / Dani / Txell)
Setup inicialEdu autoriza una vez, todos heredanCada uno autoriza una vez (~30 s)
Calendar — quién es organizerSiempre Edu (raro si task asignada a Dani+Txell)El creador real de la task. Otros como attendees
Mail — visibilidadSolo emails de Edu (resto ven los de Edu, sin sentido)Cada uno ve los suyos (único viable)
Página settings1 botón “Conectar Zoho”3 cards de estado (una por persona)

El driver del cambio es Mail: Service Account es incompatible con cuentas de email separadas por persona. Una vez forzados a per-user OAuth para Mail, mantener Service Account para Calendar es asimétrico y empeora UX (invitaciones aceptadas, organizer raro).

Plan operativo en una sola fase

Toda la Fase B revisada se entrega en una sesión (estimado ~10 h netas). El concepto de “fases C/D” del ADR s67 desaparece.

Pasos

  1. Migration 0027 — altera zoho_oauth_tokens (singleton → multi-user con team_member TEXT PRIMARY KEY) + crea task_calendar_events + task_emails.
  2. Lib functions/_lib/zoho.ts acepta userKey (team_member) en todas sus funciones. OAuth handlers per-user (state lleva quién autoriza).
  3. Backend nuevos endpoints: /api/zoho/calendar POST + /api/zoho/mail/search GET + /api/zoho/mail/compose-url GET + /api/tasks/{id}/links/{type} CRUD.
  4. Frontend TaskModal con secciones “Eventos vinculados” + “Emails vinculados” replicando el patrón existente de “Notas del Cuaderno”.
  5. Cards (KanbanMini, TaskTableView, TaskKanban) con badges numéricos.
  6. Widget Fase A: ZohoAgendaWidget → ZohoCalendarWidget (quita sección “Tareas Zoho”, mantiene agenda + filtro).
  7. Settings UI con 3 cards de estado de conexión por persona.

Scopes Zoho actualizados

Cada miembro debe re-autorizar tras el cambio de scopes.

Alternativas consideradas y descartadas

Alternativa 1 · Continuar ADR s67 (Zoho = SoT también para tasks)

Descartada tras observación de Edu. KanbanMini + página /tasks ya supera funcionalmente a Zoho Tasks. Migrar 27 tasks D1 → Zoho introduciría regresión UX (sin drag-drop, sin notas vinculadas, sin attachments en Zoho Tasks free) y dependencia en una herramienta inferior para el caso de uso del equipo. La complejidad de Fase C/D del ADR s67 (sync bidireccional + conflict resolution) deja de tener justificación.

Alternativa 2 · Sync automática task → Calendar event (puente silencioso)

Descartada. Propuesta por mí (assistant) tras el pivot inicial: cuando una task tiene due_date, generar evento en Calendar automáticamente. Edu la rechazó explícitamente: “sin puente, acciones explícitas desde la task”. Razones implícitas: control del usuario sobre qué se publica en Calendar, evitar ruido en agenda con tasks que no son reuniones, sin necesidad de conflict resolution en sync invertida.

Alternativa 3 · Mantener Service Account + emails compartidos

Inviable técnicamente. Service Account de Edu solo puede acceder a la INBOX de Edu. Mostrar emails de Edu a Dani y Txell rompe principio de privacidad mínima y no aporta valor (cada uno opera sus propios emails). Sin solución técnica vía Zoho — sería per-user obligatorio aunque quisiéramos mantener el modelo singleton.

Alternativa 4 · Esperar a tener feedback de uso de Fase A antes de pivotar

Descartada. Fase A solo lleva 1 día en PROD. El coste de mantener el rumbo del ADR s67 supera el de pivotar ahora: pivotar ahora = ~10 h de trabajo + cancela Fases C/D del ADR original (~3-4 días); seguir con s67 = invertir 3-4 días más en una arquitectura que sabemos subóptima.

Consecuencias

Esperadas positivas

Esperadas negativas / riesgos

Mitigaciones

Criterios de éxito (medibles a 3 meses)

Estado

Reapertura futura

Véase también

Subir