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.
¿Cómo se provisiona un cliente nuevo?
Sección titulada «¿Cómo se provisiona un cliente nuevo?»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 falló a mitad de camino
Sección titulada «El provisioning falló a mitad de camino»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.
El tenant no aparece en su producto
Sección titulada «El tenant no aparece en su producto»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.
El cron de GitHub sync no actualiza issues
Sección titulada «El cron de GitHub sync no actualiza issues»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.
La propuesta AI no se genera
Sección titulada «La propuesta AI no se genera»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 métricas de Ema Well dan 503
Sección titulada «Las métricas de Ema Well dan 503»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.
El theme dark se ve roto en una página
Sección titulada «El theme dark se ve roto en una página»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_historyWHERE 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.
Comportamiento ante caída de Aidbox
Sección titulada «Comportamiento ante caída de Aidbox»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.
Comportamiento ante caída de Anthropic API
Sección titulada «Comportamiento ante caída de Anthropic API»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.