Vamos a lo técnico.
Todo lo que dice la portada, escrito como aquello de lo que salió: la base de datos real, cómo se crea de verdad un contacto y quién más toca una llamada.
No necesitas esta página para usar Rilo, y nada de lo que hay aquí contradice la versión sencilla. Es el mismo producto, descrito con precisión.
La base de datos entera
Todo lo que nuestro servidor sabe de tu familia.
No es un resumen. Estas son las diecisiete tablas que tiene el servidor, con las columnas que tienen. Cuatro son tu familia: quiénes son, quién puede actuar por una criatura, los teléfonos desde los que hablan y dónde llamarles. Cuatro guardan algo para un teléfono que estaba apagado, y las cuatro se borran solas. Tres tratan de quién puede actuar por una criatura y de qué teléfono dejó de ser de fiar. Dos son registros firmados de un final: un contacto cortado, o alguien que se ha ido. Se conservan para que un teléfono que estuvo sin conexión pueda comprobarlos en lugar de creernos. Una son números de un solo uso ya gastados, barridos al caducar. Una es la suscripción, y no contiene nada que nombre a nadie. Una es una denuncia que nos envió una persona adulta, y es la única tabla aquí que existe para que pase algo. La última no trata de tu familia en absoluto.
- idun hash de la clave pública, no un nombre
- public_keyla clave del dispositivo, que es la cuenta
- typeadulto o niño
- type_certla firma que lo demuestra. Una cuenta infantil la firma un padre o una madre, así que no hay ninguna casilla que cambiar
- created_at
- last_activela última vez que alguno de tus teléfonos dijo hola
- dormant_warned_atvacío
- consent_sealedtu correo de registro, sellado con una clave que vive en papel con el fundador. Ningún servidor puede leerlo
- uncovered_sincevacío, salvo que tu suscripción haya dejado de cubrir a este niño — entonces el día en que lo vimos, para que el mes previo a que algo se detenga empiece ahí
- keyqué se está recordando
- valuey qué dice
- account_id
- guardian_keyuna clave autorizada a actuar por este niño
- added_at
- removed_at
- account_id
- device_keyla clave propia de un teléfono: se puede hablar desde más de uno
- agreement_keyla clave con la que se sella un mensaje, para que solo ese teléfono pueda abrirlo
- certla firma que dejó entrar a este teléfono, guardada palabra por palabra para que tu teléfono pueda comprobarla en vez de creernos
- kindun teléfono, o la hoja de recuperación impresa
- added_at
- removed_at
- account_id
- device_keycuál de tus teléfonos hace sonar este
- platformapns o fcm
- tokenun identificador opaco de Apple o Google
- updated_at
- nonce
- expires_at
- edge_hashun hash del par, no de las dos personas
- denied_at
- expires_at
- edge_hashun hash del par, no de las dos personas
- grant_recordel permiso que se está decidiendo, y las firmas reunidas hasta ahora
- waiting_keyqué firma falta todavía
- requested_byel teléfono que lo pidió, para que un solo teléfono no pueda inundar de preguntas a una familia
- originescaneado en persona, o un adulto actuando por su peque
- delivered_toqué teléfonos ya lo tienen
- declaredel nombre que declara quien pregunta, sellado para que solo la familia escaneada pueda leerlo
- created_at
- expires_at
- id
- recipient_idel enrutado necesita este en claro
- recipient_devicepara cuál de sus teléfonos está sellada la caja: cada teléfono tiene su propia clave, así que cada uno recibe la suya
- sender_idpara que el teléfono sepa con qué clave abrirlo
- sender_devicecuál de sus teléfonos lo selló, para que la copia correcta encuentre la cerradura correcta
- edge_hashel par, con hash, para que esto no pueda leerse como un mapa de quién habla con quién
- sealedtexto cifrado. No hay columna de texto y nunca la habrá
- sent_at
- expires_at
- edge_hashel par, con hash
- revoked_at
- recordel registro firmado, para que un teléfono que estaba sin conexión pueda verificar el corte por su cuenta en vez de creernos a nosotros
- id
- account_idqué lista de teléfonos y personas adultas cambia
- kindentrar, o salir
- subject_keyel teléfono o la persona adulta de la que trata
- subject_kindcuál de los dos
- agreement_keyla segunda clave que necesita un teléfono, vacía para el papel
- recordla propia firma, guardada palabra por palabra para que un teléfono la compruebe en vez de creernos
- signed_byqué clave la firmó
- by_authoritysi la firmó una hoja de recuperación, que es lo que hace que espere
- issued_atel momento que indica quien firma, nunca nuestro reloj
- reasonvacío, salvo que quien firma escribiera uno
- proposed_at
- effective_atcuándo se hace real, dos noches después de proponerse
- contested_at
- contested_byquién se opuso, y con qué firma
- contest_record
- resolved_at
- resolutionaplicado o cancelado, una vez resuelto
- change_idqué cambio en espera
- voter_keyqué persona adulta
- decisiondejarlo pasar, o pararlo
- recordsu firma
- at
- account_idde quién era el teléfono
- device_keyla clave que fue robada
- revoked_at
- recordla prueba firmada, para que un teléfono la compruebe sin preguntarnos
- account_idla cuenta que ya no está
- retired_at
- recordla prueba firmada, hecha con la clave propia de esa cuenta antes de destruirla
- account_id
- storeapple, google, o invitación de la casa
- store_refuna referencia opaca de la tienda. Es lo único que nos permite hacerle una consulta más adelante
- store_ref_hashuna huella de la referencia anterior. Es lo que impide que una misma compra cubra dos cuentas
- environment
- stateactive, grace, lapsed, lapsed_trial o disabled
- seatscuántos niños cubre. Un número, nunca sus nombres
- expires_at
- acts_at
- updated_at
- device_keyel teléfono al que todavía no se le ha dicho
- change_idde qué cambio se trata
- whatpropuesto, impugnado o resuelto
- account_idde quién es la lista de teléfonos que cambió. Cuando se avisa a un adulto sobre su peque, aquí va el peque
- subject_keyel teléfono que se añadió o se quitó
- effective_at
- created_at
- expires_at
- delivered_atcuándo conseguimos decirlo, o vacío porque aún no lo hemos hecho
- id
- about_keysobre quién es la denuncia. Legible, para que alguien pueda actuar
- reasoncuál de seis cosas ocurrió, según lo eligió la persona adulta que denuncia
- csa
- sealedlo que se escribió, sellado en el teléfono que lo envía con una clave que está en papel en poder del fundador. Ningún servidor puede leerlo
- sealed_digestuna huella de la parte sellada, para probar que lo que se abra después es lo que llegó
- received_at
- edge_snapshotquién tenía permiso para llegar a quién, y qué adulto lo permitió, tal como estaba en ese momento. Esto no se puede reconstruir después
- reporter_keyquién lo envió, o nada en absoluto cuando se envió sin nombre
- source
- sealed_key
- receiptla referencia que guarda quien la envía. Es la única forma de responder a alguien sobre una denuncia que no podemos abrir
- acknowledged_at
- decided_at
- actioned_at
- escalated_at
- decided_by
- outcome
Columnas que no existen
- correo
- nombre
- edad
- foto
- texto de los mensajes
- contenido de las llamadas
- historial de llamadas
- lista de contactos
- ubicación
- modelo del dispositivo
Tu correo se comprueba una vez al registrarte y se sella en el mismo movimiento, con una clave que vive en papel con el fundador y que nunca ha tocado un servidor. La ley nos pide poder demostrar que un adulto dio su consentimiento. No podríamos volver a leerlo aunque quisiéramos. Los nombres y las fotos se ponen en cada teléfono y pasan directamente al otro. Nunca llegan hasta nosotros, y por eso también puedes llamar «Yayo» al abuelo sin que lo sepamos jamás. No podríamos enseñarle nada de esto a nadie aunque quisiéramos, y tampoco podrían obligarnos.
Esta sección se genera a partir del propio esquema del servidor, en accounts.ts y roster-changes.ts, los dos archivos que crean la base de datos. Si alguna vez no coinciden, los archivos tienen razón y esta página es el error.
Contactos
Cómo se crea de verdad un contacto.
El teléfono de alguien crea una invitación de un solo uso. El otro teléfono la lee, escaneada de una pantalla en la misma habitación o abierta desde un enlace que envió ese adulto. Esa lectura inicia la presentación y, en el mismo momento, registra la clave pública del otro teléfono, así que los dos saben desde ese momento qué clave es de quién. Eso es lo que hace imposible colarse después en una llamada, también para nosotros. No se conecta nada hasta que un adulto del otro lado ha dicho que sí.
Todavía no hay nada conectado. Un adulto responsable tiene que firmar el contacto en su propio teléfono, tras una comprobación biométrica hecha en ese momento. Lo que firma es el conjunto. Quién, con quién y en qué sentido. Esa firma es lo que comprueba el servidor antes de encaminar nada. El servidor no tiene ninguna clave capaz de firmar, así que no puede crear un contacto, y quien robe la base de datos tampoco.
Cuando los dos teléfonos tienen el contacto terminado, la fila se borra y el contacto solo existe en los dos dispositivos. Cortarlo más tarde escribe una revocación firmada, lo único que se conserva indefinidamente. Se guarda como un hash del par, de forma que dice que un contacto terminó sin decir quién conocía a quién.
Quién más interviene
Tres empresas tocan una llamada. Ninguna puede oírla.
Otras seis empresas tocan el servicio, y todas están en la política de privacidad. Tres de ellas intervienen para que suene una llamada. Esto es lo que cada una de esas tres puede y no puede ver.
-
Apple y Google
Las notificaciones push, para que una llamada haga sonar un teléfono dormido. Inevitables en ambas plataformas. Llevan un identificador opaco y nada más. Sin nombre, sin número, sin contenido.
-
Cloudflare
Más o menos una de cada seis llamadas no consigue conectar los dos teléfonos directamente, en el wifi de un hotel o en algunas redes móviles, y se desvía por un relé. El relé reenvía paquetes cifrados que no puede abrir, pero sí ve que dos identificadores anónimos estuvieron conectados, cuándo, cuánto tiempo y desde qué direcciones. Esos son metadatos que nosotros no guardamos, en manos de otro.
-
Nosotros
La tabla de arriba. Un servidor pequeño en los Países Bajos que presenta dos teléfonos y luego se aparta.