Archivo y republicación de redes · en producción

reply2social

Trae material de una cuenta de red social, se queda con los bytes y lo vuelve a publicar en otras — con permiso registrado y, por defecto, después de que una persona lo mire.

Suena a un puente. La diferencia está en el medio: las URLs de los CDN vencen en horas o días, así que un sistema que guardara sólo el enlace tendría al año un catálogo de links muertos. Acá se descargan los bytes; que además sirvan para republicar es una consecuencia, no el objetivo.

★ Lo distintivo

Cauce: la instalación entera, en un archivo

Cauce es un TOML que describe por dónde puede correr el material: qué cuentas hay y qué va de cuál a cuál. No publica nada —eso lo sigue haciendo el worker, con su grifo y sus guardas—, pero sirve para las cuatro cosas que importan cuando algo se rompe: respaldo y desastre, alta masiva, versionar la configuración en git, y replicar a otra instalación.

instalacion.toml credenciales = ausentes
formato_version = 1
credenciales = "ausentes"   # sin tokens: se commitea

[[cuentas]]
handle     = "fuente-ig"
plataforma = "instagram"
rol        = "lectura"
poll_horas = 6

[[cuentas]]
handle       = "difusion-masto"
plataforma   = "mastodon"
rol          = "escritura"
max_por_hora = 4            # el grifo

[[flujos]]
clave     = "fuente-a-difusion"   # inmutable
origen    = "fuente-ig"
destino   = "difusion-masto"
condicion = { tipo = ["VIDEO"] }
plan · sólo mira no escribe nada
$ cauce importar instalacion.toml

  + cuenta  fuente-ig        se crearía
  = cuenta  difusion-masto   sin cambios
  ~ flujo   fuente-a-difu…   cambia: condicion
  ⚠ activa = true            se crea PAUSADO

  nada se escribió.
  --aplicar para hacerlo.

Como terraform plan y apply, y el corte no es estético: mirar no pide identidad, aplicar sí — «muta la base = firma». Es idempotente: correrlo dos veces dice «sin cambios» en todo.

Manifiesto

Credenciales ausentes. Sale por HTTP y por el panel; se puede commitear. No restaura: hay que recargar los tokens.

Respaldo

Credenciales cifradas, y sale sólo por CLI. Ningún endpoint de este servicio devuelve ni acepta texto cifrado — sin excepciones que recordar.

Las guardas, y por qué existen

Cada una nació de un modo de fallo concreto, no de una buena práctica general. Por eso están escritas con su motivo al lado.

La cabecera no puede mentir

Si el archivo se declara «ausentes» y trae una credencial, o dice «cifradas» y no trae el bloque que dice con qué clave, la validación lo rechaza. No es un aviso: de esto depende que nadie archive un manifiesto creyendo que tiene un respaldo.

Un solo conflicto detiene todo

Aplicar «lo que se pueda» dejaría la instalación a mitad de camino entre dos descripciones, y nadie sabría en cuál está.

Importar es aditivo, y no aplica tres cosas que sí declara

El consentimiento se vuelve a otorgar a mano —un permiso es una afirmación personal y fechada, no un trámite de lote—, los flujos se crean pausados y la publicación automática queda apagada. Los tres se avisan, no se callan.

Un filtro que no se entiende es un ERROR

Escribir «tags» en vez de «tag» daba antes un archivo válido cuyo flujo publicaba todo: el motor ignoraba lo que no entendía. El filtro más peligroso es el que parece estar y no está.

Restaurar con otra clave se niega antes de tocar nada

El respaldo trae la huella de la clave con que se cifró. Escribir igual dejaría cuentas que parecen tener credencial, y el fallo aparecería recién al publicar.

Lo restaurado queda «degradado», nunca «ok»

La credencial está cargada y nadie la ejercitó contra la red. Declararla sana sería el verde falso justo donde más caro sale: quien restaura se va tranquilo.

El formato completo, con sus diagramas y siete archivos de ejemplo: cauce · cauce en ejemplos.

★ Sin verde falso

Qué corre, qué no, y qué es plan

El sistema está en producción y publica de verdad. Al mismo tiempo, hay partes verificadas sólo contra servidores falsos que corren dentro de los tests, y partes que todavía son plan. Distinguirlas es parte del producto: un sistema que dice «ok» sin haberlo comprobado falla justo cuando alguien se fue tranquilo.

● Corre en producción

  • 12 cuentas y 5 flujos en una instalación real
  • Entra de Instagram, Telegram y feeds RSS
  • Sale a Mastodon, Telegram y un sitio propio
  • Publicó de verdad: video con atribución a la cuenta de origen
  • Guarda los bytes, no el enlace: el archivo sobrevive al CDN
  • Corta video largo en partes sin recodificar

◐ Verificado sólo contra servidores falsos

  • Facebook y LinkedIn: el código está, la red real no lo desmintió todavía
  • Los modos de fallo del worker —429, timeout, fallo parcial— se provocan dentro de los tests, que es donde se pueden provocar a voluntad

○ En génesis

  • El empaquetado instalable: un rol Ansible como artefacto primario
  • Los envoltorios de interfaz más allá de Svelte (React, Vue, Angular): el núcleo TypeScript sin framework ya está escrito y con tests, los ports no
  • El purgador del archivo: todo estado que crece necesita su drenaje

Las dos publicaciones se pueden mirar: un video de 23 s en Mastodon (3 de agosto de 2026) y otro en un canal público de Telegram (4 de agosto). Los dos salieron con su atribución al material original, recorriendo el camino entero: sondeo → archivo de los bytes → emisión → publicación.

★ De un vistazo

En cifras

12

cuentas en producción

5

flujos activos

3 + 3

redes de entrada y salida

1

archivo TOML describe todo

AES-256

GCM para cada credencial

AGPL-3.0

licencia del núcleo

★ Por dentro

Cómo está hecho

Un binario en Rust levanta tres cosas: el API (axum), el poller y el worker de emisión. En el medio, el archivo: bytes y metadatos en disco y en Postgres. La interfaz va aparte, partida en un núcleo de TypeScript sin ningún framework y envoltorios finos por encima — hoy Svelte.

poller Cada N horas le pregunta a cada fuente qué hay de nuevo, y baja lo que encuentra.
archivo Guarda los bytes y los metadatos. Es el centro: todo lo demás lo lee o lo escribe.
emisión Toma lo aprobado y lo publica, respetando el grifo de cada destino.
panel Donde una persona mira, aprueba, otorga permisos y frena.
cauce Exporta e importa la instalación entera como un archivo declarativo.

El servicio valida identidad; nunca la emite

No tiene usuarios: le pregunta al sitio que lo hospeda quién está del otro lado, y el anfitrión relee a la persona de su base en cada validación. Suspender a alguien tiene efecto inmediato, sin esperar a que expire nada. Si el servicio pudiera firmar una credencial, podría fabricar una identidad — y una identidad fabricada por quien la usa no prueba nada.

★ Libre y público

El código

Todo lo de esta página —el servicio en Rust, el panel, la CLI y la documentación— vive en un repositorio público, bajo AGPL-3.0: se puede usar, estudiar, modificar y desplegar, con la condición de publicar las modificaciones de quien lo ofrezca como servicio.

v0.1.0-rc.1

2026-08-15 · primera versión etiquetada

git clone https://gitlab.com/pineiden/reply2fb.git reply2social

Es un release candidate, y el sufijo no es modestia: Instagram —la fuente que da origen al proyecto— nunca corrió contra la API de Meta. Ese camino está verificado contra un servidor falso que corre dentro de los tests, y un servidor falso no puede desmentir lo que uno real diría. El changelog lista los siete límites de esa clase, uno por uno.

El repositorio se llama reply2fb y el módulo reply2social: nació espejando Instagram a una Página de Facebook y creció hasta ser multired. No se renombró para no romper los clones que ya existen.

★ Saber más

Documentación

Diez páginas con sus diagramas —renderizados en el build, así que un diagrama roto rompe la compilación en vez de aparecer en blanco.