feat: conexiones OAuth (Gmail/Outlook) para el agente + rediseño del orquestador

Backend:
- UmindConexion: cuenta de correo conectada por tenant vía OAuth2
  (golang.org/x/oauth2, promovida de indirecta a directa), tokens cifrados
  en reposo con el mismo AES-GCM+APP_KEY que ya usan tools/canales.
- Flujo completo: /app/umind/conexiones/conectar redirige a Google/Microsoft,
  /callback/:proveedor intercambia el code (state autoverificable por HMAC,
  sin tabla de estados pendientes), refresh on-demand antes de cada uso.
- Dos tools nuevas para el agente (enviar_correo/leer_bandeja) que aparecen
  solo si el tenant tiene una conexión activa, vía Gmail API / Microsoft
  Graph directo (sin el SDK pesado de Google).
- Requiere que el dueño del proyecto cree las apps OAuth en Google Cloud
  Console / Azure y cargue GOOGLE_OAUTH_CLIENT_ID/SECRET y
  MS_OAUTH_CLIENT_ID/SECRET — sin eso los botones de conectar fallan con un
  mensaje claro, no en silencio.

Frontend: rediseño del orquestador — layout de sidebar fijo (reemplaza el
navbar + lista de página completa), modo oscuro vía prefers-color-scheme,
tabs en pill, y la nueva tab "Conexiones".

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Lizandro Guarnizo
2026-08-12 10:25:13 -05:00
co-authored by Claude Sonnet 5
parent b2f6b518b6
commit 5ba41786d6
27 changed files with 1254 additions and 396 deletions
+9 -12
View File
@@ -1,17 +1,14 @@
<script setup>
import Sidebar from './components/Sidebar.vue'
</script>
<template>
<div class="min-h-screen">
<header class="bg-white border-b border-gray-200">
<div class="max-w-6xl mx-auto px-6 py-4 flex items-center justify-between">
<router-link to="/" class="text-lg font-semibold text-gray-800">
uMind <span class="text-brand">Orquestador</span>
</router-link>
<a href="/app/dashboard" class="text-sm text-gray-500 hover:text-gray-700">
&larr; Volver al panel
</a>
<div class="min-h-screen flex bg-gray-50 dark:bg-gray-950">
<Sidebar />
<main class="flex-1 min-w-0">
<div class="max-w-4xl mx-auto px-8 py-10">
<router-view />
</div>
</header>
<main class="max-w-6xl mx-auto px-6 py-8">
<router-view />
</main>
</div>
</template>