Por qué el historial del chat suele quedar como rehén
Pide tus datos a una plataforma de chat alojada y lo que sueles recibir es un archivo de registros: un zip de JSON y adjuntos, útil para cumplimiento normativo y para grep, inútil para continuar la conversación en otro sitio. La comunidad viva, lo que de verdad construiste, no sale. «Exporta tus datos» y «vete con tu comunidad» son promesas distintas, y la mayor parte de la industria solo hace la primera.
En Buzz esa brecha es concreta, no comercial. Cada mensaje lo firma su autor, y la firma cubre la marca de tiempo. Un relay acepta un evento solo de la clave que lo firmó, y solo mientras la marca de tiempo es reciente, unos quince minutos en el relay de serie. Así que nadie puede volver a publicar el historial del año pasado en un relay nuevo por el cable: ni nosotros, ni tú, ni las personas que escribieron los mensajes. No es una política nuestra que podamos relajar; es la forma en que el protocolo se defiende del historial falsificado y reproducido, y obliga a cualquiera que ejecute Buzz en cualquier parte.
Lo aprendimos de la forma honesta. Nuestro primer diseño de exportación suponía que los eventos firmados podían republicarse en cualquier relay; un ensayo lo desmintió, y corregimos nuestros propios textos. Desde entonces la exportación es un registro y lo dice con claridad. Este artículo trata de lo que construimos más allá de eso: una ruta de migración que mueve la comunidad viva en ambas direcciones, sin fingir que el cable puede hacer lo que no puede.
La identidad vive en el hostname
El segundo hecho sobre el que descansa todo: la identidad de una comunidad de Buzz está soldada al hostname del relay. Cuando un cliente se conecta, el relay resuelve a qué comunidad está sirviendo a partir del host por el que llegó la conexión, y cada mensaje, membresía y archivo cuelga del id interno de esa comunidad. El hostname no es tanto dónde vive la comunidad como el nombre que la identifica, y ese vínculo existe en un único lugar: una fila en la base de datos del relay que nombra el host de la comunidad.
Esa fila es la bisagra sobre la que gira toda la migración, y también produce el consejo que ahora damos a todo el mundo antes que cualquier otro: elige tu hostname con cuidado, en ambas direcciones, antes de que la gente se mude. Cincuenta miembros después es el nombre al que responde tu comunidad, y cambiarlo es una migración, no un interruptor en la configuración.
Restaurar, reasignar, arrancar
Como el cable está cerrado al pasado, la migración real corre por debajo, en la base de datos. Tres pasos, y el orden es todo el truco: restaurar, reasignar, arrancar.
Primero restaurar, con el relay todavía parado: carga el volcado de la base de datos en una base vacía y replica los medios en el nuevo almacén de medios. En Buzz los medios se direccionan por contenido, con el hash de sus propios bytes como nombre, así que les da igual qué hostname los sirva. Luego reasignar: actualiza esa única fila del host al nuevo hostname. Luego, y solo entonces, arranca el relay. Al iniciarse busca una comunidad en su host configurado, encuentra la fila que reasignaste y la adopta: la misma comunidad, el mismo id interno, el historial completo, las marcas de tiempo originales.
Arranca primero y te encontrarás con el fallo que hace que todo esto parezca imposible: el relay no encuentra ninguna comunidad en su host, siembra amablemente una nueva y vacía, y tu historial restaurado queda en la misma base de datos, huérfano a su lado. Todo parece sano y todas las salas están vacías. Reasigna antes del primer arranque y el relay nunca tiene ocasión de ser amable. En nuestros ensayos, el historial restaurado se podía leer por una conexión autenticada en cuanto el relay arrancó, y la misma clave de dueño que gestionaba la instancia vieja publicó mensajes nuevos en la nueva.
El mecanismo entero, abreviado. El orden es el truco: un relay arrancado antes de la reasignación siembra una comunidad vacía en su hostname, y tu historial restaurado queda huérfano al lado.
Hacia dentro: cuando te cansas de operar
Primera dirección: hacia dentro. Llevas tiempo autoalojando Buzz, la novedad de las alertas de disco a las 2 de la madrugada ya pasó, y si no te has mudado es porque mudarse suele significar empezar de cero: cuentas nuevas, salas vacías, un enlace de «el historial está en lo viejo» que nadie sigue nunca. Esa es la mudanza que ensayamos de punta a punta esta semana, con las mismas herramientas de importación que usaremos con tu comunidad, y nada de eso sobrevivió al ensayo.
Lo que se trasladó, verificado y no supuesto: el historial completo, con sus marcas de tiempo originales, porque una restauración es una operación de base de datos y la ventana de quince minutos del cable nunca llega a opinar. Cada identidad de miembro, sin ninguna reinscripción, porque una identidad de Buzz es un par de claves Nostr que guarda el propio miembro, no una cuenta que emitimos nosotros: las mismas claves que funcionaban con tu hostname siguen funcionando con el nuevo, y a nadie se le pide que vuelva a registrarse. Y los medios, byte a byte, verificados contra sus direcciones de contenido.
Lo que te pedimos es deliberadamente poco: un volcado de tu base de datos y una forma de leer tu almacén de medios. Nosotros hacemos el resto personalmente, con un respaldo tomado antes de que la importación toque nada, y la lista de verificación del ensayo se ejecuta antes de darlo por terminado. Hoy no hay un botón de importación de autoservicio, y no tenemos prisa por añadirlo: una migración es el único día en que tu comunidad merece un operador con toda su atención puesta en ella.
Hacia fuera: cuando quieres las llaves
Segunda dirección: hacia fuera. Todo espacio de trabajo alojado siempre ha podido descargar una exportación: los eventos firmados, los medios, un README. Esa es la capa de registro, y es honesta sobre ser un registro. Lo que el paquete gana ahora es una capa soberana a su lado: el volcado completo de la base de datos, la referencia exacta de la imagen de contenedor que ejecutaba el espacio de trabajo, un archivo compose y un script de restauración que impone restaurar, reasignar, arrancar, en ese orden.
La prueba a la que lo sometemos es la única que cuenta: ninguna ayuda nuestra. En el ensayo, una máquina limpia que nunca había tocado nuestros sistemas siguió el propio README del paquete y volvió a levantarse autoalojada en un hostname nuevo. La misma clave de dueño inició sesión. El historial completo estaba ahí. Los medios se servían en sus direcciones de contenido. Y la instancia aceptó mensajes nuevos, que es la diferencia entre una pieza de museo y una comunidad que se mudó.
Una exportación que solo puedes restaurar con el proveedor en una llamada de soporte no es una puerta, es una correa con pasos extra. Por eso el README es el estándar contra el que ensayamos: irse debería ser una tarde aburrida siguiendo instrucciones que funcionan. Preferimos ganarnos la operación a adueñarnos de la salida.
Los límites, sin rodeos
Una historia de migración sin sus límites es un anuncio, así que aquí están. Primero: los mensajes viejos que incrustaban URL absolutas (miniaturas dentro de subidas antiguas, respuestas de subida que citaban una dirección completa) siguen apuntando al hostname viejo para siempre. Esas URL viven dentro de contenido firmado, y reescribir contenido firmado sería falsificación, así que ninguna migración honesta puede tocarlas. Los archivos de medios en sí se direccionan por contenido y se sirven correctamente desde el nuevo host; solo las URL literales congeladas dentro de mensajes firmados antiguos siguen nombrando el lugar que dejaste.
Segundo, al salir: la clave de firma propia del relay no viene contigo. Tu instancia restaurada genera una identidad de relay nueva, así que los avisos del sistema que firmó el relay viejo siguen atribuidos a la identidad que de verdad los firmó, que es exactamente para lo que sirven las firmas. El acceso de los miembros no se ve afectado: cada persona es su propia clave, y esas claves viajan porque nunca nos correspondió guardarlas.
Tercero, en ambas direcciones: elige el hostname de destino como si fuera permanente, porque en la práctica lo es. La misma soldadura que hace suficiente reasignar una sola fila convierte el hostname en lo único que no puedes cambiar a la ligera más adelante.
Control, en ambas direcciones
Júntalo todo y la soberanía deja de ser un eslogan para convertirse en una lista de verificación. Tu gente tiene sus propias claves, así que ningún operador, nosotros incluidos, se interpone entre ellos y su identidad. Tu historial se restaura bajo un hostname que tú controlas, en la dirección en que te muevas. El cable rechaza el historial reproducido para todos por igual, y el camino por la base de datos, por debajo, funciona para todos por igual. El control no es una sensación en una tabla de precios; es que la puerta de salida se haya ensayado hasta que se abre. La nuestra lo fue, esta semana, solo con el README.
Dónde te deja esto
La parte alojada del trato vive en hachiflow.com: $50 al mes, precio plano, tu propio relay en name.hachiflow.chat, y la migración descrita aquí hecha contigo, personalmente, en la dirección que lleves.
Y si nunca nos pagas un dólar, quédate con el mecanismo: restaurar, reasignar, arrancar, en ese orden, con la reasignación antes del primer arranque del relay. Ese único orden es casi todo lo que es una migración de Buzz. Lo demostramos en una máquina limpia esta semana, y es tuyo.