rilo
Rilo, el zorro mascota, de pie junto a un escudo con un candado

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.

accounts se conserva hasta que la elimines
  • 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í
Tu cuenta permanece hasta que la elimines, y eliminarla en la aplicación se lleva esta fila y todo lo asociado. Estamos preparando una limpieza de las familias que han dejado de usar Rilo por completo. Hasta que se active, aquí no desaparece nada por sí solo.
server_state se guarda
  • keyqué se está recordando
  • valuey qué dice
La única tabla de aquí que no trata de tu familia en absoluto. Hoy guarda una sola cosa: el momento en que esta versión del servidor arrancó por primera vez. Toda pregunta sobre quién se ha quedado en silencio se mide desde entonces, para que una base de datos escrita antes de que pudiéramos saberlo nunca se lea como meses de silencio.
guardians se guarda
  • account_id
  • guardian_keyuna clave autorizada a actuar por este niño
  • added_at
  • removed_at
La retirada se anota, no se borra. Los contactos se comprueban contra quién era tutor cuando se firmó el contacto, para que un padre que deja la cuenta no corte en silencio todas las amistades que aprobó.
devices se guarda
  • 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
Los teléfonos y tabletas desde los que habla una persona. Dice cuántos dispositivos tiene tu familia y absolutamente nada sobre con quién hablas: no más que las dos tablas de arriba. A un teléfono lo deja entrar la firma de un dispositivo que ya está en la lista, nunca nosotros, y esa firma se guarda aquí para que cualquier teléfono pueda comprobarla en vez de creerse la lista. Retirar un teléfono marca la fila en lugar de borrarla, por la misma razón por la que se marca la salida de una persona adulta: todo lo que firmó mientras era tuyo tiene que seguir siendo verificable.
push_tokens se guarda
  • account_id
  • device_keycuál de tus teléfonos hace sonar este
  • platformapns o fcm
  • tokenun identificador opaco de Apple o Google
  • updated_at
Uno por dispositivo, para que una llamada pueda hacer sonar un teléfono dormido. La notificación no lleva nombre ni contenido.
used_nonces se purga
  • nonce
  • expires_at
Una lista de números de un solo uso ya gastados, para que una petición interceptada no pueda repetirse. Se borra al caducar.
denied_edges se purga
  • edge_hashun hash del par, no de las dos personas
  • denied_at
  • expires_at
Cuando un adulto dice no a una presentación, ese no se recuerda durante tres días, para que el teléfono del otro adulto, apagado en ese momento, no pueda completarla por accidente. Un escaneo nuevo entre las mismas familias lo borra antes. Sin nombres, sin claves: un hash y dos fechas.
pending_grants se purga
  • 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
Este es el único sitio donde el servidor guarda algo parecido a un grafo social, y solo lo guarda mientras una presentación está sin terminar. Nadie respondió en 72 horas: caduca. Respondida, pero el teléfono al que iba dirigida nunca se conectó: 30 días. En cuanto los dos teléfonos tienen el contacto terminado, la fila se borra. Por eso en esta página no hay una tabla de contactos. No hay tabla de contactos.
messages se borra al entregarse
  • 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
Un teléfono está apagado la mayor parte del día, y un mensaje que desaparece en silencio es un producto roto. Por eso aquí espera una caja sellada: 30 días como mucho, y borrada en cuanto quien la recibe confirma que la tiene. Nosotros no podemos abrir ninguna.
revocations se guarda
  • 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
Lo único que conservamos indefinidamente. Deja constancia de que se cortó un contacto sin ser una lista legible de quién conocía a quién.
roster_changes se guarda
  • 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
Las dos noches entre que alguien firma un cambio en las personas adultas de una criatura y que ese cambio se hace real. Un teléfono que entra en una familia, o uno al que se aparta, espera aquí, donde todos los demás teléfonos de la cuenta pueden verlo y oponerse. La fila permanece una vez resuelto, porque un teléfono que estaba apagado tiene que poder comprobar qué pasó en vez de creernos sin más. Contiene la cuenta y las claves implicadas, que es más de lo que contienen la mayoría de las tablas de aquí.
roster_change_votes se guarda
  • change_idqué cambio en espera
  • voter_keyqué persona adulta
  • decisiondejarlo pasar, o pararlo
  • recordsu firma
  • at
Una fila por persona adulta en lugar de un contador. Una mayoría de las personas adultas de una criatura puede acortar la espera de dos noches, y si hay mayoría hay que volver a preguntarlo contra las personas adultas que hay ahora. Quien se ha ido no es un voto, y un contador no sabría distinguirlo.
device_revocations se guarda
  • 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
Un teléfono robado, y la diferencia entre esto y retirar uno. Retirar significa que deja de poder actuar a partir de ahora, que es la respuesta correcta para un teléfono que alguien ha sustituido. Esto significa: desconfía de todo lo que haya firmado alguna vez, y eso lo tienen que poder comprobar los demás teléfonos sin preguntarnos. Solo un robo tiene fila aquí.
retirements se guarda
  • account_idla cuenta que ya no está
  • retired_at
  • recordla prueba firmada, hecha con la clave propia de esa cuenta antes de destruirla
Una lista de ausencias, y la buena noticia es la segunda columna. Cuando alguien deja Rilo, los teléfonos de sus amistades reciben una firma hecha con la clave propia de esa persona. Así una familia se entera de que alguien ya no está por una prueba, y no porque lo digamos nosotros. Nada que digamos por nuestra cuenta puede quitar una cara de la pantalla de tu peque. Es la única tabla de aquí sin enlace a una cuenta, porque tiene que sobrevivir a la cuenta de la que habla.
entitlements se guarda
  • 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
Nada de esto identifica a una persona: ni cuenta de tienda, ni Apple ID, ni cuenta de Google, ni nombre, ni correo, ni tarjeta. Qué peques cubre un pago se deduce de la tabla de tutores en el momento de preguntarlo, y nunca se guarda.
roster_notices se purga
  • 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
Una cola, y la razón por la que añadir o quitar un teléfono se hace en voz alta. Todos los teléfonos de la familia se enteran, y en el caso de un niño también todos los adultos responsables, incluido el teléfono que se acaba de quitar. Así es como alguien que no debería tenerlo descubre que te has dado cuenta. Un aviso no contiene nada que no esté ya en el propio cambio, y se borra al caducar, hayamos conseguido entregarlo o no.
reports se guarda
  • 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
La única tabla aquí que existe para que algo ocurra. La mayor parte de una denuncia está sellada en el teléfono que la envió y no podemos abrirla. Lo que queda legible es sobre quién trata, porque una denuncia sobre la que nadie puede actuar no es una protección. Sobrevive a la cuenta de la que habla. Si no, cualquiera podría borrarse de ella. No contiene ninguna grabación de ninguna llamada, ni aquí ni en ningún sitio, porque nunca se hace ninguna.

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.