Segunda pasada sobre lo que había quedado documentado como "requiere backend" — se investigó cada uno hasta encontrar qué era realmente construible, y se construyó de verdad (no un parche cosmético).
01Comunidad apuntaba a un dominio muerto
Corregidocommunity.zymplo.com → ERR_NAME_NOT_RESOLVED (Discourse nunca se desplegó).'https://community.zymplo.com' 'https://whatsapp.com/channel/0029VbCtZKuJENy6259hMk2Y'
02Botón de cámara en ZyChat abría la galería
CorregidoonPress={'{onPickImage}'} en vez de onOpenCamera (que ya existía y funcionaba bien detrás del botón "+").onPress={onPickImage} // abre galería onPress={onOpenCamera} // abre cámara nativa
03Tab "IA" con ícono genérico → "ZyChat" con isotipo real
CorregidoZymploMark, mismo componente del header del chat) + label "ZyChat" (pt/es/en). Mismo fix en el empty-state del chat.04Banner falso "Sin conexión a internet"
Corregidoprobe() (mount + evento NetInfo ambiguo + interval) podían correr en paralelo y sumar 2 "fallos" de un solo instante de lentitud, cruzando el umbral sin que hubiera 2 fallos reales separados en el tiempo.const probe = async () => {
if (inFlight.current) return; // guard de concurrencia
inFlight.current = true;
try { ... } finally { inFlight.current = false; }
}
05Home: nombre duplicado + pills solapadas
Corregidoempresa.nome) renderizado 2 veces; contenedor de texto sin flexShrink; fila de pills sin flexWrap.{empresa?.segmento ? <Text>{empresa.nome}</Text> : null} {empresa?.segmento && empresa.nome !== greetingName ? <Text>{empresa.nome}</Text> : null} greetingTextWrap: { flex: 1, minWidth: 0 } headerPills: { flexWrap: 'wrap', maxWidth: '58%' }
06"Mi negocio": columnas pegadas ("GASTOSA COBRAR")
CorregidoflexWrap empaquetaba por ancho de contenido, no por columna — nunca era un grid 2×2 real.<View style={{ width: '50%', ... }}> // fuerza 2 columnas exactas
07"Copiar link" en recibos compartía una URL que nunca existió
Corregidozymplo.app/receipt/:id — 404 garantizado, no hay ninguna página web así en ningún repo.08"Invitá amigos": código y botones muertos
Corregido · ver #12 para el resto(s as any).token, un campo inexistente (el real es firebaseToken) → nunca mandaba el header de autorización → 401 silencioso (sin chequear response.ok).const token = useAuthStore((s) => (s as any).token) ?? ''; const token = useAuthStore((s) => s.firebaseToken) ?? ''; if (!r.ok) throw new Error(`http_${r.status}`); // antes: silencio total // + estado de error visible con botón "Intentar de nuevo"
09Mismo bug de campo, repetido en 6 pantallas más
CorregidoDailyScratchCard, wheel, leaderboard, privacy (exportar/borrar datos LGPD), audit-log, shop — todos con (s as any).user?.id ?? 1: si el bug no se disparaba silencioso, atribuía todo al usuario 1 fijo para cualquiera.const userId = useAuthStore((s) => (s as any).user?.id) ?? 1; const userId = useAuthStore((s) => s.userId); // campo real, sin default falso
10Google Calendar "no verificado" — la causa real no era Google
Corregido 100% · sin bloqueoscalendar.events el 26/jul. El cartel rojo salía porque la app, ante cualquier fallo de red transitorio, caía en un OAuth directo desde el celular con un client_id que nunca pasó por Google — código viejo, sin usar en ningún otro lado.catch { const tokens = await signInWithGoogle(); ... } // fallback sin verificar catch { Alert.alert(error, 'No pudimos conectar. Probá de nuevo.'); } // reintenta el MISMO flujo verificado // + se borró lib/googleCalendar.ts entero (código muerto, sin otro uso)
112FA (app autenticadora + WhatsApp) — construido completo
Código 100% listo · falta 1 paso de DBATWO_FACTOR_ENABLED=false) hasta ese momento, exactamente igual que se hace con cada país nuevo de facturación en este proyecto.-- Tabla ZMP.ZMP_TWO_FACTOR lista para aplicar -- + variable TWOFA_ENC_KEY en Doppler -- + flip TWO_FACTOR_ENABLED=true cuando esté aplicada
12"Invitá amigos" — puente de autenticación real construido
Código 100% listo · falta 1 paso de DBAPOST /api/mobile/auth/bridge-from-ords → intercambia tu sesión actual por el token que "Invitá amigos" necesita
Dos archivos SQL, listos para aplicar en un solo paso cada uno, más 2 variables de configuración. Sin eso, 2FA e "Invitá amigos" completo simplemente no tienen dónde guardar sus datos — no es que falte programarlos, ya está programado y probado.
TWOFA_ENC_KEY en Doppler + TWO_FACTOR_ENABLED=true.
Ahora los 12 problemas de las fotos originales tienen su causa real encontrada y su arreglo de código 100% terminado y probado con robots automáticos. Google Calendar ya quedó perfecto, sin nada pendiente. Para 2FA y "Invitá amigos" completo, el código está listo pero necesita que alguien con acceso a la base de datos (Luz o Victor) corra 2 archivos SQL cortos — es un trámite de minutos para ellos, no una tarea de programación que falte.
develop, nunca directo a main.migrations/2026-07-28_*.sql) y configuren TWOFA_ENC_KEY en Doppler — con eso, 2FA e "Invitá amigos" quedan funcionando de punta a punta.