Devices exchange ciphertext through a filesystem-shaped remote:
metadata/manifest # signed active generation + device list
metadata/devices/<id>.json
metadata/version
keys/generations/<id>/manifest
events/<device-id>/... # encrypted bundles
checkpoints/<id>/manifest
checkpoints/<id>/snapshot # gzip + encrypted compact history
acks/<device-id>.ackEngine.Sync pulls metadata (with rollback detection on metadata/manifest counters, namespaced per endpoint as remote:<id>),
imports generations, merges event bundles, pushes local events, writes acks,
and may checkpoint. published_seq is also per endpoint so a new mirror
receives this device’s history. Pulled bundle keys stay global.
After every enabled endpoint has been synced, the coordinator equalizes
objects (copy any layout key that exists on one remote and is missing on
another). A metadata/manifest with a lower counter never overwrites a
higher one. Partial failure continues: one cloud being down does not skip
the others. Callbacks run if any endpoint succeeded.
Writes use Transport.PutAtomic. Directory transport is tmp+rename. rclone
writes a temp object then moves when the backend supports it; otherwise
write-then-verify. On backends that allow duplicate names (Google Drive),
the move is followed by a sweep that deletes every other object with that
path so acks and device metadata replace instead of stacking.
repository.Probe inspects metadata/manifest and keys/generations/ so a stray file is not treated as a live repository.
Create (remnix setup) refuses Valid / Partial / UnsupportedVersion remotes.
Join (remnix device add) requires Valid and never calls InitializeRemote.
Garbage collection deletes superseding event objects after every required
device has acknowledged a checkpoint. Retired devices no longer block GC.
GC is retry-safe: if a storage or network error interrupts cleanup after some
objects were deleted, rerunning remnix gc recomputes the current safe set
and continues. Objects that were already removed are ignored. gc --dry-run uses the same eligibility logic and performs no deletions.
Pruning a device updates the signed metadata/manifest first (the logical
commit), then removes that device’s remote metadata, ack, and event objects.
If cleanup is interrupted, remnix device prune <device-id> resumes it.
Already-removed remote objects are ignored.
rsync/scp probe and setup wrap Begin/End so the live remote is inspected,
not an empty local stage.
