04 / resilience

Cut off,
is not amnesia

One full day without reaching the hub, and the local node keeps distilling on the staged data, in small batches. Five days without recovery, and it acts as its own hub. When the hub comes back, the two sides merge in a fixed order: push → send back → confirm → pull snapshot, with no step skipped. Only when the last step succeeds and the local copy is still there does the staging get deleted.

One day down / five days down pending.db dr/ hourly self-backup Never delete unconfirmed
01

Try pulling the cable

Cut the hub off, then advance time. State names, staging row counts and self-backup counts follow the real state machine; the numbers are illustrative and are not live readings.

edge recollect-node
primary hub
0 hours unreachable In sync
0h
24h · one day down
120h · five days down

Step one: cut the hub connection first

node status In sync
self_distillfalse
pending_turns0
staging_rows0
dr_backup_count0
replica/read-only · bytes untouched
auto_unlocktrue
00
In sync connected
In sync; failed syncs do not enter staging.
01 · 24h
Distilling locally offline_distilling
Distils in small batches on the local staging area; the read-only copy is not touched byte for byte.
02 · 120h
Detached, still distilling detached_distilling
The next state comes only after a self-backup succeeds; unconfirmed backups are never deleted.
03
Acting as hub detached_promoted
Acts as its own hub; old backups may only be cleaned up after the merge back is confirmed.
04
Rejoined rejoined
Staging may only be deleted after all four steps finish.
02

Merging back has one order only

Push rows written locally (push), then send back the rows accumulated while offline (rows), and pull a new snapshot (pull) only after the hub confirms. If a step fails, the next one does not run and the local copy is not deleted; the next round sends the same batch again, the hub recognises it and does not write duplicates. Session reads work the same way: when the hub is unreachable, fall back to the local copy and mark the receipt source=local + degraded, never passing local results off as the hub's.

step 01
push
Push what was written locally to the hub; stop on failure.
step 02
rows
Send back the rows accumulated offline; the next step runs only after the hub answers 200.
step 03
Confirm
The same batch sent twice counts once; nothing is written twice.
step 04
pull
Pull the new snapshot; staging is deleted only if that succeeds and the local copy is still there.
401 / 403 / 409 Not the same as being offline. 401/403 means no permission or a rejection, 409 means the two versions disagree; treating them as offline triggers local distillation by mistake.
1 day / 5 days Both gates count consecutive unreachability, not the number of failed attempts.
0 bytes While offline the read-only copy stays untouched; local distillation writes only to pending.db and dr/.
03

A backup does one thing: catch up

A backup catches up entry by entry along the replication sequence. Behind, it catches up; missing entries, it reports "unavailable + gap" rather than passing off stale content. Only after catching up and passing verification may it take over.

hub backup · how to read the numbersThree parts
ItemValueNotes
hub backupraw transcript · memory · manifestAll three written together, keeping the last 7 sets; the manifest carries version and progress
hub restoreThree stepsWithout --confirm checks only; on restore, extraction progress is rolled back to the position in the manifest
dr/HourlyStarts only after detaching from the hub (five days down); current copy + staging + raw transcript + state
Unconfirmed self-backupNever deletedCleaned up only after merging back into the original hub and confirming
Private key in backupsNo plaintexthub key export archived encrypted on its own; doctor reports the fingerprint only