Ir al contenido

FAQ y troubleshooting

Esta página recopila las preguntas que tienden a aparecer cuando algo no se comporta como se espera. Las respuestas están escritas para PMs, soporte y staff técnico que necesita resolver un caso concreto sin abrir el código fuente.

¿Cómo se agrega un nuevo staff de EMA al Vault?

Sección titulada «¿Cómo se agrega un nuevo staff de EMA al Vault?»

Solo un admin puede crear usuarios nuevos. La operación es ir a Equipo Vault → + Nuevo usuario, completar email @emahealth.io, nombre y rol entre los cinco disponibles (admin/technical/commercial/finance/viewer), y guardar. La creación inserta una fila en vault_users con is_active=true y el usuario puede entrar inmediatamente con Google login.

Si el usuario hace Google login antes de existir en vault_users, recibe un 403 con código NO_VAULT_USER. Es el mecanismo de defensa-en-profundidad: aunque Google OAuth aceptara un dominio incorrecto por mala configuración, el segundo filtro impediría el acceso.

El workflow estándar asume que el cliente ya está en pipeline. Desde ahí, comercial mueve el lead a Ganado y dispara la conversión, lo que crea una organization con tipo cliente, un contacto principal en people y un placeholder de contrato. Finanzas toma el control para llenar el fiscal_config —identificador tributario del país, certificado digital, ambiente del organismo fiscal y tipos de documentos habilitados— y verifica que el slug del subdominio sea único y de formato válido [a-z0-9][a-z0-9-]*. Cuando los datos están listos, admin click en Provisionar productos y selecciona los productos contratados (Lab, Clinic, Well o lo que aplique).

El sistema entonces ejecuta una secuencia de seis pasos en orden: crea la Organization raíz en Aidbox, encripta el client_secret OAuth con AES-GCM, persiste en tenant_aidbox_credentials, llama a cada producto contratado vía X-Platform-Key (loop sobre clinic, lab, well según corresponda), invita al admin del cliente vía Loops, y deja registro completo en el audit log. La operación tarda unos minutos.

El provisioning es idempotente, lo que es la primera buena noticia: re-correr la operación no produce duplicados ni rompe el estado parcial. La UI muestra qué step específico falló y la causa raíz, y el audit log registra el detalle completo de la falla. Las causas más comunes son Aidbox inalcanzable (problema de infraestructura), un producto retornando 503 (ese producto está caído), una X-Platform-Key inválida (el admin debe rotarla con el producto destino), o un slug duplicado (cambiar el slug y reintentar).

Una vez resuelta la causa raíz, basta volver a hacer POST /api/tenants/:id/provision con los productos pendientes.

La causa habitual es un provisioning incompleto. La verificación rápida es consultar emashared.tenant_products para el tenant_id correspondiente: si no hay row para el producto que debería estar disponible, el provisioning del producto no se completó. Re-correr desde Vault resuelve el caso, aprovechando la idempotencia del proceso.

Hay tres condiciones que deben cumplirse simultáneamente. La primera es que el cron esté activado en el dashboard de Cloudflare después del último deploy. La segunda es que GITHUB_TOKEN sea válido y tenga scope repo con permisos de lectura. La tercera es que los logs del Worker muestren la línea [cron] github-sync en cada ejecución programada. El webhook complementario, configurado en cada repositorio de GitHub, opera independientemente del cron y suele ser suficiente cuando el cron no llega a ejecutarse por algún issue puntual.

Tres causas explican la mayoría de los casos. La primera es que ANTHROPIC_API_KEY esté mal configurado o haya expirado, lo que produce un 500 desde el endpoint. La segunda es que la API de Anthropic esté caída temporalmente, lo que se manifiesta como 503 de upstream. La tercera, menos visible, es que el lead tenga poco contexto y Sonnet retorne texto genérico que el comercial percibe como output inútil.

Si el caso es el primero o el segundo, refrescar la página y reintentar suele resolverlo (los problemas suelen ser transitorios). Si persiste, escalar a admin para verificación de la API key. Si el caso es el tercero —Sonnet produciendo texto pobre— la solución pasa por enriquecer el contexto del lead antes de regenerar.

EMI proxy retorna 503 desde un producto cliente

Sección titulada «EMI proxy retorna 503 desde un producto cliente»

Cuatro causas explican el 503. La primera es que el EMI Worker mismo esté caído, lo que se verifica con un health check directo a https://emi.emahealth.io/api/health. La segunda es que el admin haya desactivado tenant_emi_access para ese tenant + app desde la matriz de Vault. La tercera es que la app correspondiente (emi_apps.{product}) siga en estado alpha y todavía no haya sido promovida a ga. La cuarta es que el rate limit del EMI Worker se haya excedido, lo que pasa típicamente en periodos de tráfico alto.

El diagnóstico definitivo lo da GET /api/emi/access, que retorna la razón específica del rechazo.

Las dos causas habituales son configuración faltante. Si las variables EMAWELL_SUPABASE_URL y EMAWELL_SUPABASE_SERVICE_ROLE_KEY no están configuradas en el Worker, el cliente supabase-well no se inicializa y todos los endpoints /api/well/* responden 503 con el mensaje “not configured”. Si las variables existen pero las credenciales son incorrectas, los endpoints fallan con 401 desde el proyecto Ema Well. La verificación queda a cargo del admin con acceso a los secrets del Worker.

La causa habitual es que algún componente tenga un color hex hardcodeado o una clase bg-white directa en lugar de usar tokens del design system. La solución correcta no es editar el componente puntualmente sino aprovechar la regla CSS global [data-theme="dark"] .bg-white que ya existe, o reemplazar el hex por una clase Tailwind semántica como bg-light o bg-card.

Un slug del cliente cambió y la URL antigua no funciona

Sección titulada «Un slug del cliente cambió y la URL antigua no funciona»

Vault preserva las URLs antiguas durante doce meses después de un rename, vía la tabla tenant_slug_history. Si la redirección no funciona, lo primero a chequear es:

SELECT * FROM emashared.tenant_slug_history
WHERE old_slug = 'aurora-old';

Si la fila existe con expires_at > now(), la redirección debería operar y conviene revisar la configuración del DNS o el routing del worker. Si la fila no existe (nunca se registró el rename) o si está expirada, el cliente debe actualizar su URL al slug actual; no es posible recuperar el redirect retroactivamente.

Comportamiento ante caída de Supabase emahub

Sección titulada «Comportamiento ante caída de Supabase emahub»

La degradación es total. Vault depende íntegramente de Supabase para auth y para todas las queries: si el proyecto cae, ni el login funciona ni las páginas internas pueden cargar datos. Los workers que dependen de Vault para su operación (provisioning desde emaclinic, etc.) entran en estado degradado. La única operación parcialmente funcional es el proxy EMI, que no requiere DB para operar pero sí para chequear tenant_emi_access.

Cuando Supabase se restablece, todo vuelve a funcionar sin intervención manual. El cron de GitHub sync acumula durante el outage y procesa lo pendiente en su siguiente ejecución regular.

La caída de Aidbox impide provisionar nuevos tenants —ese paso requiere crear Organization y OAuth client— pero no afecta a los tenants existentes, que tienen sus credenciales encriptadas en tenant_aidbox_credentials. Vault sigue operativo para todos los flujos de back-office (audit, finanzas, pipeline, contratos) y solo queda bloqueada la onboarding de nuevos clientes. El cron de provisioning pendiente, si existiera, reintenta cuando Aidbox vuelve.

Las features AI quedan inoperativas: las propuestas, los resúmenes de contrato y los análisis de leads responden 503 desde sus respectivos endpoints. El resto del producto funciona con normalidad. Como mecanismo de degradación elegante, el admin puede deshabilitar temporalmente los botones AI desde feature flags para evitar que el equipo intente generar drafts que van a fallar.