You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
taskbot/docs/plan-interfaz-web.md

257 lines
12 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# Plan de implementación: Interfaz Web (SvelteKit) + Bot/Webhook (separado)
Este documento define el plan para añadir una interfaz web al sistema, manteniendo el bot/webhook existente como proceso independiente y compartiendo la misma base de datos SQLite (WAL). El objetivo es proporcionar al usuario un acceso seguro, rápido y cómodo a sus tareas, configuración y feeds de calendario, con especial atención a la seguridad y a la mínima fricción.
## 1) Decisiones fijadas
- Arquitectura: dos procesos (apps/bot y apps/web). SvelteKit para la web (SSR, rutas de API, cookies).
- Acceso: enlace mágico por DM con token de 10 minutos, de un solo uso. Sin “recordarme”.
- Sesión: cookie de sesión (HttpOnly, SameSite=Lax, Secure en prod) + expiración por inactividad de servidor de 2 horas.
- Orden por defecto: tareas por creación descendente (más recientes primero).
- ICS:
- Horizonte temporal: 12 meses.
- Excluir tareas sin fecha.
- Feeds:
- B (por usuario+grupo, solo tareas sin responsable) como opción por defecto, con autogeneración.
- C (personal multigrupo, solo sin responsable) opcional para power users.
- Monorepo: estructura apps/bot y apps/web. Posible “shared” en el futuro para reutilizar utilidades.
## 2) Alcance funcional (MVP)
- Mis tareas: lista (orden creación desc), filtros (abiertas, vencen pronto), búsqueda por texto simple.
- Tareas de mis grupos: solo grupos permitidos y en los que el usuario está activo; sección destacada de “sin responsable”.
- Preferencias de recordatorios: ver y modificar frecuencia (daily/weekly/weekdays/off) y hora. Visualización de próximo recordatorio según TZ.
- Autenticación: comando /t web que devuelve URL con token. Canje en /login y cookie de sesión.
- Integraciones:
- ICS personal (solo “mis tareas” con due_date).
- ICS por usuario+grupo (solo sin responsable), autogenerados (sin clic de creación).
- ICS personal multigrupo opcional (solo sin responsable).
## 3) Arquitectura técnica
- apps/web (SvelteKit):
- SSR + endpoints (rutas +server.ts) para login, APIs, ICS.
- Gestión de cookies/sesión en hooks.server.ts.
- UI con Svelte (sin framework adicional salvo CSS utilitario si se desea).
- apps/bot:
- Se mantiene el webhook/servicios actuales.
- Emisión de tokens de login: puede implementarse desde el bot (insertando en DB) o delegarse al web (si el bot solo notifica al usuario la URL base + token emitido por la web). Para MVP: el bot crea el token directamente en DB y envía la URL.
- Concurrencia DB:
- SQLite en modo WAL con PRAGMA busy_timeout para ambos procesos. Reutilizar convenciones actuales de PRAGMA.
## 4) Autenticación y sesiones
- Emisión de token (bot):
- En /t web por DM: crear token aleatorio, guardar hash (no el token en claro), TTL 10 min, uso único, rate-limit por usuario.
- Devolver URL del tipo: https://app.example.com/login?token=XYZ
- Canje (web):
- Validar hash y caducidad; si ok, invalidar token (marcar usado).
- Crear sesión en DB (web_sessions) y emitir cookie de sesión (solo cookie de sesión, sin persistencia en disco).
- Redirigir a /app (sin token en la URL).
- Expiración:
- Idle timeout: 2 horas de inactividad. Si excede, pedir un nuevo token /t web.
- Seguridad:
- Cookies: HttpOnly, SameSite=Lax, Secure (en prod), path acotado.
- Rate limit en /login para evitar bruteforce de tokens.
- Redirección inmediata tras canje para evitar fugas por Referer.
## 5) Calendario ICS
- Contenido:
- Solo tareas con due_date, dentro de los próximos 12 meses.
- Título con id y descripción, notas con URL a la tarea (opcional).
- Feeds:
- Personal (usuario): “mis tareas” con due_date.
- Por usuario+grupo (B, por defecto): “sin responsable” del grupo.
- Autogeneración: “perezosa” (on-demand) al solicitar listado de feeds en la UI o al primer acceso a la URL; o proactiva (sembrado) mediante tarea que cree un token por cada par usuario+grupo activo. Recomendado: perezosa, con garantía de existencia al cargar la página “Integraciones”.
- Un feed activo por usuario+grupo (regla de unicidad). Rotación manual por el usuario (revocar y crear nuevo).
- Personal multigrupo (C, opcional): “sin responsable” agregadas de todos los grupos en los que el usuario esté activo. Un único token; revocable.
- Seguridad y control:
- Tokens largos, no caducan por tiempo (estilo ICS), siempre revocables.
- Para B/C: revocación automática al detectar que el usuario dejó de ser miembro activo del grupo (B) o de todos los grupos (C), en conciliaciones de miembros.
- Rate limit de peticiones por token/IP (ligero) y soporte de ETag/Last-Modified para minimizar carga.
## 6) Estructura del repo (monorepo)
- apps/bot: código actual del webhook, servicios, schedulers, migraciones.
- apps/web: SvelteKit (adapter-node).
- data/: carpeta con la base de datos SQLite compartida (ya existente).
- docs/: documentación (este archivo).
- Opcional futuro: packages/shared para extraer utilidades (normalizeWhatsAppId, métricas, tipos, etc.).
## 7) Migraciones de base de datos (nuevas tablas)
- web_tokens
- id, user_id, token_hash, created_at, expires_at, used_at (nullable), metadata (JSON opcional).
- Índices: (user_id), (expires_at), (token_hash único).
- web_sessions
- id (session_id), user_id, session_hash, created_at, last_seen_at, expires_at (idle cutoff), user_agent, ip (opcional).
- Índices: (user_id), (expires_at), (session_hash único).
- calendar_tokens
- id, type (personal, group, aggregate), user_id, group_id (nullable), token_hash, created_at, revoked_at (nullable), last_used_at.
- Unicidad: (type, user_id, group_id) activa (si revoked_at IS NULL).
- Índices: (user_id), (group_id), (token_hash único).
Notas:
- Guardar siempre hashes de tokens (no tokens en claro).
- Para autogeneración perezosa: crear on-demand si no existe registro activo para (user_id, group_id).
## 8) Endpoints (apps/web)
- Autenticación:
- GET /login?token=… (canjea token, crea sesión, redirige a /app)
- POST /api/logout (revoca sesión actual)
- APIs (todas requieren sesión válida):
- GET /api/me/tasks?status=open&search=...&page=...&limit=...
- GET /api/me/groups (grupos en los que está activo; solo allowed)
- GET /api/groups/:id/tasks?unassignedFirst=true (respeta gating y membresía)
- GET /api/me/preferences
- POST /api/me/preferences (actualiza frecuencia/hora)
- GET /api/integrations/feeds
- Genera automáticamente (si faltan) tokens B por cada grupo activo del usuario.
- Devuelve URLs para: ICS personal (mis tareas), ICS por grupo (B), y opcional ICS multigrupo (C).
- POST /api/integrations/feeds/rotate { type, groupId? } (revoca y recrea token)
- ICS (no requieren sesión; usan token en la URL):
- GET /ics/personal/:token.ics
- GET /ics/group/:token.ics
- GET /ics/aggregate/:token.ics
## 9) UI (apps/web)
- Páginas:
- /app (dashboard): “Mis tareas” por defecto.
- /app/groups: lista de grupos del usuario; en cada uno, “sin responsable” prominente.
- /app/preferences: frecuencia y hora de recordatorios; vista “próximo recordatorio”.
- /app/integrations: enlaces ICS
- Autogenerados: mostrar directamente botones “Copiar” y breve guía (Google/Apple/Outlook).
- Rotar/revocar: botones por feed. Avisar que rotar invalida suscripción previa.
- Interacciones:
- Filtros rápidos, búsqueda, paginación liviana.
- Estado de sesión (2h de inactividad): al expirar, mostrar mensaje con instrucción de enviar /t web.
## 10) Seguridad
- Tokens:
- Aleatorios criptográficos; hash en DB; TTL 10 min (web_tokens); uso único.
- calendar_tokens sin TTL (estilo ICS), siempre revocables.
- Cookies: HttpOnly, SameSite=Lax, Secure en prod, path acotado. No almacenar PII en cookies.
- CSRF: bajo riesgo con SameSite y API same-origin; añadir token anti-CSRF a mutaciones como defensa en profundidad.
- Cabeceras:
- X-Frame-Options: DENY, Referrer-Policy: no-referrer, X-Content-Type-Options: nosniff, Content-Security-Policy básica.
- Robots: noindex, nofollow.
- Gating:
- Todas las consultas filtran por user_id y validan AllowedGroups + membresía activa (group_members).
- Logs: nunca registrar tokens en claro; solo hashes o IDs.
## 11) Observabilidad y límites
- Métricas (via Metrics):
- web_tokens_issued_total, web_tokens_redeemed_total, web_login_success_total, web_login_failed_total
- web_sessions_active, web_api_requests_total{route=…}, ics_requests_total{type=…}
- ics_tokens_revoked_total, ics_tokens_created_total
- Rate limiting:
- Emisión de token /t web (en el bot) y /login (web).
- ICS por token/IP (p. ej., 4 req/min).
- Caching ICS:
- ETag/Last-Modified y Cache-Control: public, max-age=300 (suave), para que los clientes no abusen.
## 12) DevOps y despliegue
- Entornos:
- WEB_BASE_URL, COOKIE_SECRET, SESSION_IDLE_TTL_MIN=120, ICS_HORIZON_MONTHS=12, ICS_RATE_LIMIT, etc.
- Reutilizar EVOLUTION_API_* donde aplique (si se consulta API desde web).
- Build:
- SvelteKit con adapter-node; ejecución con Bun o Node en producción.
- Reverse proxy:
- apps/web servido en app.example.com (o /app).
- apps/bot mantiene su endpoint de webhook. Compartir .env según necesidad.
- Schedulers:
- Permanecen en el proceso del bot. apps/web no arranca ningún scheduler.
## 13) Plan de trabajo por etapas
Etapa 0 — Preparación
- Crear estructura apps/web (SvelteKit con adapter-node).
- Configurar ESLint/Prettier y CI mínimos (lint, build).
- Asegurar que la web abre la misma DB (PRAGMAs coherentes).
Etapa 1 — Autenticación
- Migraciones: web_tokens, web_sessions.
- Bot: emisión de token de 10 min (hash, rate limit) en /t web.
- Web: endpoint /login, cookie de sesión, redirect limpio; hooks de sesión con idle timeout 2h.
- Páginas de error/expiración.
Etapa 2 — Lectura de datos (MVP)
- APIs: /api/me/tasks, /api/me/groups, /api/groups/:id/tasks, /api/me/preferences (GET).
- UI: “Mis tareas” y “Grupos” (solo lectura).
- Orden de creación desc, filtros básicos, búsqueda.
Etapa 3 — Preferencias
- APIs: GET/POST /api/me/preferences.
- UI: edición de frecuencia/hora y vista del próximo recordatorio.
Etapa 4 — ICS
- Migraciones: calendar_tokens.
- APIs/UI Integraciones: autogeneración perezosa de feeds B (por usuario+grupo) y C (multigrupo opcional).
- Endpoints ICS: personal, group (B), aggregate (C), con horizonte 12 meses y solo con due_date.
- Revocación/rotación manual. Revocación automática al perder membresía (cron en bot o check dinámico).
Etapa 5 — Pulido y observabilidad
- Métricas, rate limits, ETag/Last-Modified en ICS.
- CSP y cabeceras de seguridad.
- UX: copiar enlace, avisos claros, vacíos de estado.
Etapa 6 — Evolutivos (posteriores)
- Edición de tareas (claim/unassign, fechas).
- Búsqueda avanzada y atajos.
- Notificaciones (SSE/polling).
- Panel admin (opcional).
## 14) Pruebas
- Unit:
- Emisión/canje de token, expiración, cookie y expiración por inactividad.
- Autorización de endpoints (gating, membresía).
- Generación ICS y filtros (due_date, horizonte).
- Integración:
- Flujo end-to-end: /t web → /login → /app.
- Listado de feeds y autogeneración B.
- Regresión:
- Aislar que schedulers solo corran en el bot.
## 15) Riesgos y mitigaciones
- Fuga de enlace de ICS:
- Tokens largos, revocación sencilla, métricas y rate-limit. Evitar ICS compartido de grupo. B y C permiten revocar por usuario.
- Doble arranque de tareas en web:
- Flag para no iniciar schedulers en apps/web.
- Concurrencia SQLite:
- WAL + busy_timeout ya configurados; operaciones ICE (lectura) mayoritarias en web.
- Fricción de login:
- /t web es rápido; expiración 10 min adecuada; mensajes claros si expira.
## 16) Variables de entorno (propuestas, apps/web)
- WEB_BASE_URL
- COOKIE_SECRET
- SESSION_IDLE_TTL_MIN=120
- ICS_HORIZON_MONTHS=12
- ICS_RATE_LIMIT_PER_MIN=4
- NODE_ENV / BUN_ENV
- (Opcional) METRICS_ENABLED
## 17) Métricas (nombres sugeridos)
- web_tokens_issued_total
- web_tokens_redeemed_total
- web_login_success_total
- web_login_failed_total
- web_sessions_active
- web_api_requests_total{route}
- ics_tokens_created_total{type}
- ics_tokens_revoked_total{type}
- ics_requests_total{type}
- ics_rate_limit_hits_total
Fin del documento.