Skip to content

Cauce

Cauce —Spanish for watercourse, the channel a river runs through— is a TOML file describing where material may flow: which accounts exist and what goes from which to which. It publishes nothing — that is still the worker’s job, with its tap and its guards.

It is good for four things, in the order in which they matter: backup and disaster recovery, bulk sign-up, versioning the configuration in git, and replicating to another installation.

One format, two artefacts

HTTP / panel

CLI only

the installation

export

manifest

credenciales = ausentes

backup

credenciales = cifradas

can be committed

does NOT restore:

tokens must be reloaded

restores for real

+ a [cifrado] block

saying with which key

The encrypted backup only comes out through the CLI, and the restore only goes in through the CLI. Over HTTP the tokens always come out empty, and there is no endpoint that accepts them. That cut is what leaves the invariant “no endpoint of this service returns or accepts ciphertext” without exceptions to remember.

The header cannot lie. If the file declares itself ausentes and carries a credential, or declares itself cifradas and does not carry the [cifrado] block, validation rejects it. This is not a warning: whether somebody archives a manifest believing they have a backup depends on it.

What it carries

declares

declares

if it is a backup

source

destination

filters with

CAUCE

int

formato_version

1

text

credenciales

ausentes | cifradas

CUENTA

text

handle

PK

text

plataforma

text

rol

read write both

text

id_remoto

the feed URL, if RSS

text

instancia_url

int

max_por_hora

the tap

int

max_en_vuelo

int

poll_horas

text

via

navegador = public subscription

int

video_como_imagenes

text

consentimiento_vigente

INFORMATIVE only

text

credencial_cifrada

backup only

FLUJO

text

clave

PK

stable identity

text

origen

FK

text

destino

FK

text

nombre

mutable, does not identify

bool

activa

bool

auto_publica

CIFRADO

text

algoritmo

text

huella_clave

to know whether this installation can open it

CONDICION

text_array

tipo

VIDEO IMAGE CAROUSEL_ALBUM

text_array

tag

no #

text_array

autor

int

desde_dias

bounds what is EMITTED

Plan and apply

Like terraform plan and terraform apply, and the cut is not cosmetic:

yes

no

file.toml

cauce importar

only looks

+ what would be created

= what is already there

~ what would change

✗ the conflicts

convincing?

cauce importar --aplicar

writes

the file is corrected

applied

The plan does not ask for identity; applying does. The line is “mutating the database = signing”. Looking only reads, same as validating, and asking it for identity would lead people to skip it — precisely the step that avoids applying blind. Applying requires Administer through the same validator the panel uses: the CLI does not get a free pass for running on the server.

A single conflict stops everything. Applying “whatever can be applied” would leave the installation halfway between two descriptions, and nobody would know which one it is in.

It is idempotent. Running it twice duplicates nothing: the second plan says “no changes” across the board. Against the real installation, exporting and planning again gives 12 accounts and 5 flows with no changes — which is the proof that the file describes what is there.

Restoring: the other half

cauce importar creates accounts and flows. The credentials are poured in by cauce restaurar, and they are two commands because they are two different permissions over two different things.

backup.toml

cauce importar --aplicar

accounts and flows

cauce restaurar --aplicar

credentials

health: degraded

loaded, untested

In that order. restaurar does not create accounts: if the account does not exist yet, it says so and writes nothing. The other way round there is nowhere to write.

If the key is not the same, it refuses before touching anything. The [cifrado] block carries the fingerprint of the key it was encrypted with; if it does not match this installation’s, its blobs cannot be opened here. Writing them anyway would leave accounts that look like they have a credential —the health would say so, the panel would show them loaded— and the failure would only appear at publish time.

And every blob is opened before being written: even if the fingerprint matches, one of them may come in truncated.

They end up degradada, not ok. The credential is loaded and nobody has exercised it against the network. Declaring ok would assert that it works without having checked — the false green exactly where it costs most, because whoever restores walks away reassured.

What the import does NOT do

An import is additive and never deletes what the file does not mention. And there are three things declared in the file that are still not applied:

The file saysThe import doesWhy
consentimiento_vigente = "..."Nothing. It warnsA permission is a personal, dated assertion; doing it in bulk would degrade it to paperwork
activa = trueCreates it pausedTwo pollers on the same Telegram bot steal each other’s updates
auto_publica = trueLeaves it offSomething going out with nobody looking is decided by looking
an account that already existsDoes not rename it nor wipe its configThe handle is what people read in the panel; and a null would erase a tap somebody set by hand

All three warn, they do not stay quiet. A silent import would leave somebody believing they had restored the installation and that it was already emitting — and they would find out otherwise several days later, when they noticed nothing had gone out.

Validation, before writing anything

cauce validar runs in full over the file, without touching the database. It works just as well on a machine with no access to the installation: for instance, in the review of a merge request.

no

yes

yes

no

file.toml

is it TOML?

error, with line and column

is it a cauce?

the format version

the header does not lie

platforms and roles exist

the filter keys are known

the flows point at declared accounts

via is one that exists

were there errors?

cannot be applied

can be applied

+ the warnings above

An unknown filter key is an ERROR, not a field that gets ignored. Writing tags instead of tag used to give a valid file whose flow published everything: the engine ignored what it did not understand, and a condition with no criteria filters nothing. The most dangerous filter is the one that looks like it is there and is not.

Two ways of writing a criterion

The engine compares a single value the same way it compares a list, and the conditions the panel saves use the short form. Both are valid:

condicion = { tipo = "VIDEO" }
condicion = { tipo = ["VIDEO", "CAROUSEL_ALBUM"] }

On export it always comes out as a list: one form in the file, two ways of writing it.

This was missing, and the result was that cauce could not export the real installation: the export refused —correctly, rather than promising less filtering than there is— and left the file useless in exactly the installation it was meant to back up.

The criteria

They are met at the same time. “Videos by so-and-so about Palestine” wants all three things; with an OR, the flow would fire on far more than its author asked for.

CriterionWhat it looks atFail-closed
tipoWhatever the source declaresAn item with no type does not pass
tagTopics, without #, normalisedAn item with no tags does not pass: we do not know what it is about
autorWhen the source distinguishes author from accountAn item with no author does not pass
desde_diasTime windowAn item with no date does not pass

desde_dias bounds what is EMITTED, not what is archived. The full history still enters the archive; what this window prevents is a two-year backfill turning into two years of publications.

When a key already belongs to another

no

yes

yes

no

the file carries key K

does K already exist

in the database?

the flow is created

between the SAME

two accounts?

already exists: left alone

✗ CONFLICT

the whole plan refuses

Re-pointing the flow that already exists would send whatever is published afterwards to a different destination, without anyone deciding so. That is why it is an error and not a silent adjustment: the key has to be changed in the file.

A flow’s identity

Every flow has a clave: a stable slug, unique across the whole installation and immutable, held up in the database by UNIQUE, NOT NULL, a format CHECK and a trigger.

It is not nombre. The name is edited and deleted: a renameable identity would make every rename come in as a new flow on import, silently. A key that already exists pointing at a different pair of accounts is a conflict that gets reported, never a silent re-pointing.