Cauce
Cauce es un archivo 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.
Sirve para cuatro cosas, en el orden en que importan: respaldo y desastre, alta masiva, versionar la configuración en git, y replicar a otra instalación.
Un solo formato, dos artefactos
El respaldo cifrado sale sólo por CLI, y el restore también entra sólo por CLI. Por HTTP los tokens salen vacíos, siempre, y no hay endpoint que los acepte. Ese corte es lo que deja al invariante «ningún endpoint de este servicio devuelve ni acepta texto cifrado» sin excepciones que recordar.
La cabecera no puede mentir. Si el archivo se declara ausentes y trae una
credencial, o se declara cifradas y no trae el bloque [cifrado], la
validación lo rechaza. No es un aviso: de esto depende que alguien archive
un manifiesto creyendo que tiene un respaldo.
Qué trae
Plan y aplicar
Como terraform plan y terraform apply, y el corte no es estético:
El plan no pide identidad; aplicar sí. La línea es «muta la base = firma». Mirar sólo lee, igual que validar, y pedirle identidad llevaría a saltearlo — justo el paso que evita aplicar a ciegas. Aplicar exige Administrar por el mismo validador que el panel: la CLI no tiene pase libre por correr en el servidor.
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á.
Es idempotente. Correrlo dos veces no duplica nada: el segundo plan dice «sin cambios» en todo. Sobre la instalación real, exportar y volver a planificar da 12 cuentas y 5 flujos sin cambios — que es la prueba de que el archivo describe lo que hay.
Restaurar: la otra mitad
cauce importar crea cuentas y flujos. Las credenciales las vuelca
cauce restaurar, y son dos comandos porque son dos permisos distintos sobre
dos cosas distintas.
En ese orden. restaurar no crea cuentas: si la cuenta no existe todavía,
lo dice y no escribe nada. Al revés no hay dónde escribir.
Si la clave no es la misma, se niega antes de tocar nada. El bloque
[cifrado] trae la huella de la clave con que se cifró; si no coincide con la
de esta instalación, sus blobs no se pueden abrir acá. Escribirlos igual dejaría
cuentas que parecen tener credencial —la salud diría que sí, el panel las
mostraría cargadas— y el fallo aparecería recién al publicar.
Y cada blob se abre antes de escribirlo: aunque la huella coincida, uno puede venir truncado.
Quedan en degradada, no en ok. La credencial está cargada y nadie la
ejercitó contra la red. Declarar ok sería afirmar que funciona sin haberlo
comprobado — el verde falso justo donde más caro sale, porque quien restaura se
va tranquilo.
Lo que el import NO hace
Un import es aditivo y nunca borra lo que el archivo no menciona. Y hay tres cosas que se declaran en el archivo y aun así no se aplican:
| El archivo dice | El import hace | Por qué |
|---|---|---|
consentimiento_vigente = "..." | Nada. Se avisa | Un permiso es una afirmación personal y fechada; un lote la degradaría a trámite |
activa = true | Lo crea pausado | Dos pollers sobre el mismo bot de Telegram se roban los updates |
auto_publica = true | Lo deja apagado | Que algo salga sin que nadie lo mire se decide mirando |
| una cuenta que ya está | No la renombra ni le borra config | El handle es lo que la gente lee en el panel; y un null borraría un grifo que alguien puso a mano |
Los tres se avisan, no se callan. Un import silencioso dejaría a alguien creyendo que restauró la instalación y que ya está emitiendo — y descubriría que no varios días después, cuando note que no salió nada.
La validación, antes de escribir nada
cauce validar corre entero sobre el archivo, sin tocar la base. Sirve
igual en una máquina que no tiene acceso a la instalación: por ejemplo, en la
revisión de un merge request.
Una clave de filtro desconocida es un ERROR, no un campo que se ignora.
Escribir tags en vez de tag daba antes un archivo válido cuyo flujo
publicaba todo: el motor ignoraba lo que no entendía, y una condición sin
criterios no filtra nada. El filtro más peligroso es el que parece estar y no
está.
Dos formas de escribir un criterio
El motor compara igual contra un valor suelto que contra una lista, y las condiciones que guarda el panel usan la forma corta. Las dos valen:
condicion = { tipo = "VIDEO" }condicion = { tipo = ["VIDEO", "CAROUSEL_ALBUM"] }Al exportar sale siempre como lista: una sola forma en el archivo, dos de escribirlo.
Esto no estaba, y el resultado era que el cauce no podía exportar la instalación real: el export se negaba —correctamente, antes que prometer menos filtro del que hay— y dejaba el archivo inservible justo en la instalación que tenía que respaldar.
Los criterios
Se cumplen a la vez. «Videos de Fulana sobre Palestina» quiere las tres cosas; con un O, el flujo prendería con muchísimo más de lo que su autora pidió.
| Criterio | Qué mira | Fail-closed |
|---|---|---|
tipo | Lo que declare la fuente | Un ítem sin tipo no pasa |
tag | Temas, sin #, normalizados | Un ítem sin tags no pasa: no sabemos de qué habla |
autor | Cuando la fuente distingue autor de cuenta | Un ítem sin autor no pasa |
desde_dias | Ventana temporal | Un ítem sin fecha no pasa |
desde_dias acota lo que se EMITE, no lo que se archiva. El histórico
completo sigue entrando al archivo; lo que esta ventana evita es que un backfill
de dos años se convierta en dos años de publicaciones.
Cuando una clave ya es de otro
Re-apuntar el flujo que existe mandaría lo que se publique después a otro destino, sin que nadie lo decidiera. Por eso es un error y no un ajuste silencioso: hay que cambiar la clave en el archivo.
La identidad de un flujo
Cada flujo tiene una clave: un slug estable, único en toda la instalación e
inmutable, sostenido en la base con UNIQUE, NOT NULL, un CHECK de
formato y un trigger.
No es nombre. El nombre se edita y se borra: una identidad renombrable
haría que cada renombre entrara como un flujo nuevo al importar, en silencio.
Una clave que ya existe apuntando a otro par de cuentas es un conflicto que
se informa, nunca un re-apuntado callado.