Finyvo Legal
Seguridad
Esta página cuenta cómo está construida Finyvo por dentro. La política de privacidad responde a qué datos tuyos se tratan, para qué y con quién; aquí está el cómo: dónde vive cada cosa, qué la protege, qué decisiones tomamos y cuáles todavía no. Sin sellos ni superlativos.
Tabla de contenidos
Esta página cuenta cómo está construida Finyvo por dentro. La política de privacidad responde a qué datos tuyos se tratan, para qué y con quién; aquí está el cómo: dónde vive cada cosa, qué la protege, qué decisiones tomamos y cuáles todavía no. Sin sellos ni superlativos.
Lo esencial
| Pregunta | Respuesta corta |
|---|---|
| ¿Dónde viven tus datos financieros? | En tu iPhone y, si dejas la sincronización activada, en la base privada de tu propia cuenta de iCloud. En ningún servidor nuestro |
| ¿Hay cuenta o contraseña? | No. La app se identifica con una llave criptográfica que nace dentro del Secure Enclave de tu iPhone y nunca sale de ahí |
| ¿Qué protege el tráfico? | HTTPS con TLS 1.2 o superior, en todas las conexiones |
| ¿Dónde corre el backend? | En Cloudflare Workers, con D1 y KV como único almacenamiento |
| ¿Dónde están las claves de los proveedores? | Sólo en el backend, como secretos de Cloudflare. Ninguna viaja dentro de la app |
| ¿Puedes apagar lo que sale a internet? | Sí. La sincronización con iCloud y la inteligencia artificial tienen interruptor propio |
| ¿Hay certificaciones de seguridad? | No. Ni SOC 2 ni ISO 27001. El detalle está en Lo que todavía no hay |
En tu iPhone
Casi todo Finyvo ocurre en tu dispositivo. La base de datos, los cálculos, los presupuestos, los informes y la exportación: nada de eso necesita un servidor.
La base de datos. Tus transacciones, billeteras, categorías, etiquetas, presupuestos, metas y suscripciones viven en SwiftData, el framework de almacenamiento local de Apple, que por debajo es SQLite. Los archivos están dentro del contenedor de la Aplicación con la protección de datos de iOS, en la clase NSFileProtectionCompleteUntilFirstUserAuthentication: si tu iPhone tiene código de acceso, están cifrados en reposo hasta el primer desbloqueo tras encenderlo.
Las preferencias. El idioma, el tema, la moneda preferida, el modo privado y el estado de los interruptores de inteligencia artificial se guardan en UserDefaults, el almacén de ajustes del sistema. Ahí no va nada financiero.
El Llavero. Guardamos ahí exactamente dos cosas, y ninguna es un dato tuyo:
| Qué | Clase de accesibilidad | Qué significa en la práctica |
|---|---|---|
| Identificador de la llave de App Attest | kSecAttrAccessibleWhenUnlockedThisDeviceOnly |
Sólo se lee con el iPhone desbloqueado, y sólo en este dispositivo |
| Token de sesión del backend (15 minutos) | kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly |
Se lee tras el primer desbloqueo desde que encendiste el teléfono, para que la app pueda trabajar en segundo plano —reprogramar avisos, refrescar tasas— sin esperar a que la desbloquees. También sólo en este dispositivo |
Ninguno se marca como sincronizable: no viajan al Llavero de iCloud ni se restauran en otro dispositivo. Por diseño de iOS, los elementos del Llavero pueden sobrevivir a la desinstalación de la app; se eliminan al restablecer el dispositivo.
La llave privada no está en esa tabla porque no la tenemos. Vive dentro del Secure Enclave, el coprocesador de seguridad del iPhone. Ni la Aplicación ni nosotros podemos leerla: sólo pedirle firmas. Lo que guardamos en el Llavero es su identificador.
Los respaldos. Antes de cada cambio de formato interno de la base de datos, la Aplicación guarda una copia dentro de su propio contenedor y mantiene hasta 7, rotativas. Son locales: no se suben a ningún servidor nuestro. Si una actualización de formato falla, la app restaura la última copia sola y lo vuelve a intentar; también puedes elegir una a mano en Ajustes → Zona avanzada → Recuperar desde respaldo.
El modo privado, y hasta dónde llega. El icono del ojo en la pantalla de Inicio oculta todos los montos de una vez, incluido lo que lee VoiceOver en voz alta. Es un control visual: no cifra nada ni bloquea el acceso a la app. Finyvo no incluye bloqueo por Face ID, Touch ID ni código propio; el código de acceso de iOS es hoy la única puerta.
Tu copia en iCloud
Si dejas activada la sincronización —viene activada—, tus datos se replican a la base de datos privada de tu propia cuenta de iCloud, dentro del contenedor iCloud.com.moiszr.finyvo. Es infraestructura de Apple y la cuenta es tuya: Apple la cifra en tránsito y en reposo, y Finyvo no puede consultarla. No aparece en ninguna consola nuestra. Si tienes activada la Protección de Datos Avanzada de Apple, esa copia queda además cifrada de extremo a extremo.
Puedes apagarla en Ajustes → Sincronización → iCloud. El cambio se aplica la próxima vez que abras la app, y con ella apagada tus datos financieros no salen del dispositivo.
Apagarla no borra lo que ya se subió. La Aplicación no tiene un botón de “borrar mi copia de iCloud”: para eliminarla hay que ir a Ajustes de iOS → [Tu nombre] → iCloud → Gestionar almacenamiento de la cuenta → Finyvo.
Qué se replica exactamente, y qué ocurre con tu nombre de visualización, está en la política de privacidad.
Cómo la app se autentica
Finyvo no tiene cuentas. No hay correo, ni contraseña, ni inicio de sesión que alguien pueda adivinar, filtrar o robarte. El backend comprueba algo distinto: que quien llama es la app real, corriendo en un dispositivo real.
La llave. En el primer arranque, la Aplicación genera una llave criptográfica dentro del Secure Enclave. La parte privada nunca sale de ese chip: no la puede leer la app, ni iOS, ni nosotros. Sólo se le puede pedir que firme.
El handshake, paso a paso:
- La app pide un reto a
/auth/challenge. El backend devuelve un número aleatorio de un solo uso, con 5 minutos de vida. - La app pide al Secure Enclave una atestación sobre ese reto y la envía a
/attest/verify. Aquí interviene Apple: la atestación demuestra que la llave nació en un dispositivo real y que quien la usa es una copia legítima de Finyvo. - Si cuadra, el backend quema el reto —uno ya usado no se acepta dos veces— y emite dos cosas: un identificador de instalación y un token de sesión que caduca a los 15 minutos.
- Desde ahí, cada llamada a
/fx/*,/brand/*,/ai/*e/import/*viaja con ese token. Ninguna función de la Aplicación usa un token anónimo compartido. - Cuando al token le quedan un par de minutos, la app lo renueva sola: reto nuevo, firma nueva del Secure Enclave, token nuevo. Si una petición se cruza con la expiración y vuelve un 401, se renueva y se reintenta una vez.
La clave que sí está en el binario. Las tres peticiones del handshake no pueden llevar todavía un token de sesión —existen para obtenerlo—, así que se identifican con una clave de aplicación incluida en el binario y, por tanto, común a todas las copias de Finyvo. Cualquiera que extraiga el binario puede leerla, y por eso no es la frontera de seguridad: sirve para filtrar ruido de fondo. La frontera real es la atestación del Secure Enclave, que no se falsifica copiando una cadena de texto. Esa clave tampoco te identifica a ti.
El simulador. App Attest no existe en el simulador de Xcode, así que las compilaciones de desarrollo tienen un atajo para saltárselo. Ese atajo no viaja en el binario que se publica en el App Store, y el backend sólo lo acepta cuando tiene configurado un secreto de desarrollo, que en producción no está.
Qué es el identificador de instalación. Es seudónimo y persiste mientras la app siga instalada; el backend lo usa para contar tu cupo mensual de inteligencia artificial, resolver si tienes Finyvo Plus y bloquear abusos. Qué significa como dato personal y con qué se cruza lo explica la política de privacidad.
En tránsito
Todo viaja cifrado con HTTPS / TLS 1.2 o superior: entre la Aplicación y nuestro backend, y entre nuestro backend y los proveedores externos. No hay ningún camino en texto plano.
Nuestro backend exige TLS y responde siempre con estas cabeceras:
| Cabecera | Valor | Para qué |
|---|---|---|
Strict-Transport-Security |
max-age=31536000; includeSubDomains; preload |
Un año de HTTPS obligatorio, subdominios incluidos |
Content-Security-Policy |
default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'none' |
La API no sirve páginas: no puede cargar recursos, ni ser incrustada, ni enviar formularios |
X-Frame-Options |
DENY |
Lo mismo, para navegadores antiguos |
X-Content-Type-Options |
nosniff |
Nadie reinterpreta el tipo de una respuesta |
Referrer-Policy |
no-referrer |
Ninguna dirección nuestra se filtra hacia fuera |
Permissions-Policy |
geolocation=(), microphone=(), camera=() |
La API no pide sensores, y queda escrito |
Cross-Origin-Resource-Policy / Cross-Origin-Opener-Policy |
same-site / same-origin |
Aísla las respuestas de otros orígenes |
Cache-Control |
no-store |
Nada queda en cachés intermedias. La excepción son los logotipos de marca, que son públicos y sí se cachean |
El sitio finyvo.com no instala cookies ni carga recursos de terceros: las tipografías están alojadas en nuestro propio dominio.
Cómo está construido el backend
api.finyvo.com corre sobre Cloudflare Workers: código que se ejecuta en el borde de la red, en el centro de datos más cercano a ti. No hay una máquina nuestra encendida en ningún sitio, y por tanto no hay servidor que parchear, ni puerto abierto que vigilar, ni disco donde las cosas se acumulen por olvido.
El backend hace dos trabajos: proxy hacia los proveedores externos y portero de las funciones de pago.
Todo lo que persiste cabe en dos servicios, y ninguno guarda información financiera tuya:
| Dónde | Qué guarda |
|---|---|
| Cloudflare D1 (base de datos SQL) | Tasas de cambio históricas, el registro de instalaciones y métricas técnicas de uso de inteligencia artificial: qué función, qué modelo, cuántos tokens, cuánto tardó y si tuvo éxito |
| Cloudflare KV (clave-valor) | Cachés de tasas, símbolos y búsquedas de marca, los retos del handshake y los contadores de los límites de tasa. Todo con caducidad automática |
Cloudflare cifra en reposo lo que guarda en D1. Fuera de D1 y KV, los Workers no tienen almacenamiento persistente.
El cuerpo de las peticiones de inteligencia artificial no se guarda. Ni la solicitud ni la respuesta. Lo único que queda es la métrica técnica de la tabla de arriba.
Las claves de los proveedores externos viven únicamente aquí, como secretos de Cloudflare: la del proveedor de tasas de cambio, la de Brandfetch y la del proveedor de modelos de lenguaje. Ninguna viaja dentro de la Aplicación ni se entrega al cliente en ninguna respuesta. Ésa es la razón de que el backend exista como proxy en lugar de que la app llame directo a cada proveedor: una clave embebida en una app instalada en miles de teléfonos es una clave publicada.
Los registros operativos —ruta, código de estado, duración, identificador de solicitud— los conserva Cloudflare hasta 30 días y no se exportan a ningún otro servicio nuestro. Qué datos personales pueden aparecer en ellos, y durante cuánto, lo detalla la política de privacidad.
Las alertas internas de salud se envían por ntfy con metadatos operativos: código de estado, ruta, identificador de solicitud y contadores. La dirección IP no se envía a ese servicio, y eso es una decisión del diseño, no una casualidad.
Límites y anti-abuso
Los límites existen para que un abuso no tumbe el servicio ni dispare la factura de un proveedor. Hoy son estos:
| Límite | Alcance |
|---|---|
| 60 peticiones por minuto | Por dirección IP, sobre las rutas de la API |
| 10 peticiones por minuto | Por dirección IP, sólo en /attest/verify — el paso más caro del handshake |
| 10 peticiones por minuto | Por instalación, en /import/* |
/health y las rutas que no son API quedan exentas: los escáneres automáticos que rondan cualquier dominio público no consumen contadores.
Ya no existen límites por token. Desaparecieron con App Attest: cuando la app usaba un token estático compartido, el límite era del token y no de quien llamaba, así que no medía nada útil.
Cuando algo se pasa de la raya, la respuesta es un 429 con las cabeceras Retry-After y X-RateLimit-*, para que el cliente sepa cuánto esperar. Y si el almacén de contadores se cae, el limitador deja pasar en lugar de bloquear: entre que un fallo nuestro te deje sin tasas de cambio y que un minuto de peticiones no se cuente, elegimos lo segundo.
Aparte de esto, y distinto: el cupo mensual de inteligencia artificial del plan gratuito, que el backend cuenta por instalación. Es un límite de plan, no de seguridad; está descrito en la política de privacidad.
Los interruptores son tuyos
Dos cosas sacan datos de tu dispositivo, y las dos se apagan desde Ajustes:
- Sincronización con iCloud — Ajustes → Sincronización → iCloud. Con ella apagada, tus datos financieros no salen del iPhone. El cambio se aplica al siguiente arranque.
- Inteligencia artificial — Ajustes → Inteligencia artificial. Un interruptor maestro y cinco por función. Con el maestro apagado no sale ninguna llamada de inteligencia artificial, incluidas las del flujo de importación de archivos. La Aplicación pasa a usar sólo sus motores locales, que funcionan sin conexión, y la importación va directa al mapeo manual de columnas.
Dos advertencias sobre el momento en que esos datos salen:
- La categorización por inteligencia artificial se dispara al salir del campo de descripción, antes de guardar. Si escribes una descripción y luego cancelas la transacción, ese texto y ese monto ya se enviaron.
- El nombre que le pongas a una suscripción se usa tal cual para buscar su logotipo, y sale de tu dispositivo dentro de la dirección de la petición. No escribas ahí datos personales ni de otras personas. Puedes cambiarlo cuando quieras desde el editor.
La salida. Ajustes → Datos → Exportar mis datos genera un ZIP con tus datos completos dentro del iPhone: sin conexión, sin pasar por ningún servidor y sin necesitar Finyvo Plus. Ese archivo sale sin cifrar y sin contraseña: en cuanto lo compartes o lo guardas fuera de la app deja de estar protegido por el contenedor de la Aplicación. Guárdalo en un lugar seguro.
El borrado. Ajustes → Zona avanzada → Restablecer todos los datos vacía la base de datos de la Aplicación. Ten en cuenta que eso no elimina por sí solo el contenedor de iCloud: para eso están los ajustes del sistema, como se explica arriba.
Lo que todavía no hay
Finyvo la desarrolla una persona. Esto es lo que hoy no tiene, dicho con la misma precisión que lo que sí:
- Certificaciones. No tenemos SOC 2, ni ISO 27001, ni ningún sello equivalente. Son auditorías pensadas para empresas que custodian los datos de sus clientes en sus propios servidores; Finyvo no custodia los tuyos, viven en tu iPhone y en tu iCloud. Si algún día ese modelo cambia, esta página lo dirá antes.
- Auditoría externa y programa de recompensas. No publicamos un informe de pentest ni tenemos un programa de bug bounty. El canal para reportar está justo debajo, y se lee.
- Bloqueo dentro de la app. No hay Face ID, Touch ID ni código propio. Si alguien tiene tu iPhone desbloqueado, puede abrir Finyvo.
- Exportación cifrada. El ZIP de exportación sale en claro.
- Borrar tu copia de iCloud desde la app. Ese botón no existe; se hace desde los ajustes de iOS.
- Elementos del Llavero tras desinstalar. Por diseño de iOS pueden sobrevivir a la desinstalación. Son dos credenciales técnicas, no datos tuyos, y se eliminan al restablecer el dispositivo.
Cuando alguna de estas cambie, esta página cambia con ella.
Reportar un fallo de seguridad
Si encuentras algo —en la app, en el backend o en el sitio web— escríbenos a [email protected] con el asunto Seguridad.
Cuenta qué encontraste y cómo reproducirlo. Si puedes, incluye la versión de la app y la hora aproximada: ayuda a localizar la petición en los registros, que sólo viven 30 días.
Lo que te pedimos: danos tiempo de arreglarlo antes de publicarlo, y no accedas a datos de otras personas ni degrades el servicio mientras investigas. No hay recompensa económica; sí crédito público aquí, si lo quieres.
Respondemos dentro de 30 días naturales como máximo, el mismo compromiso que aplicamos a cualquier solicitud de privacidad.