Problem
Since 0.7.0 (#22) the engine handles membership changes correctly — but only clan users get them ergonomically. Non-clan deployments manage the peer set by hand, and every change is a multi-step, per-machine dance:
Adding a machine: exchange age recipients out of band, edit recipients on every existing machine, run ssync ticket on one machine, ssync join on the new one, restart daemons.
Removing a machine (docs/setup.md "Removing a machine"): edit recipients on every remaining machine, remove data_dir/namespace everywhere, re-pair every remaining machine with a fresh ssync ticket / ssync join, restart. For N machines that is N config edits plus N−1 re-pairs.
Clan mode has none of this because clan.vars owns the whole peer set: recipients, shared namespace secret (rotated via validation.peers), node-ids. The gap is purely UX/orchestration — the engine mechanism (recipient-fingerprint re-publish, drop_stale_replicas) is already in place.
Constraints
- Leaderless (DECISIONS §4), no server (§6) — no coordinator to hold the peer set.
- iroh-docs write capability is the namespace secret, so eviction always requires out-of-band redistribution of a new secret. Fully automatic in-band revocation is impossible by construction; the floor is "one artifact reaches each remaining machine, one restart".
Proposed direction (needs a call)
Promote shared-namespace mode to the primary manual mode and collapse membership into one distributable artifact:
ssync cluster init — generate a cluster file: shared namespace secret + recipient list (+ optional peer node-ids), same bytes on every machine.
ssync cluster add <recipient> [node-id] / ssync cluster rm <recipient> — rewrite the artifact; rm also rotates the namespace secret inside it.
- The user distributes the updated file however they already move secrets (scp, sops-nix, USB) and restarts the daemon. Everything else is automatic: the changed recipient set triggers the fingerprint re-publish, the changed secret opens the new namespace,
drop_stale_replicas abandons the old one.
That reduces any membership change to: run one command on one machine, copy one file, restart daemons. No ticket dance, no per-machine config edits.
Alternative (smaller, keeps ticket mode primary): a ssync revoke <recipient> helper that rewrites the local config, rotates the local namespace, prints the fresh ticket and the exact remaining steps. Cheaper, but stays O(N) manual actions per change.
Non-goals
- No relay/coordination service, no automatic secret transport — distribution stays the user's channel.
- No change to clan mode; ideally the cluster file is what the clan service generates, so both modes converge on one code path.
Problem
Since 0.7.0 (#22) the engine handles membership changes correctly — but only clan users get them ergonomically. Non-clan deployments manage the peer set by hand, and every change is a multi-step, per-machine dance:
Adding a machine: exchange age recipients out of band, edit
recipientson every existing machine, runssync ticketon one machine,ssync joinon the new one, restart daemons.Removing a machine (docs/setup.md "Removing a machine"): edit
recipientson every remaining machine, removedata_dir/namespaceeverywhere, re-pair every remaining machine with a freshssync ticket/ssync join, restart. For N machines that is N config edits plus N−1 re-pairs.Clan mode has none of this because clan.vars owns the whole peer set: recipients, shared namespace secret (rotated via
validation.peers), node-ids. The gap is purely UX/orchestration — the engine mechanism (recipient-fingerprint re-publish,drop_stale_replicas) is already in place.Constraints
Proposed direction (needs a call)
Promote shared-namespace mode to the primary manual mode and collapse membership into one distributable artifact:
ssync cluster init— generate a cluster file: shared namespace secret + recipient list (+ optional peer node-ids), same bytes on every machine.ssync cluster add <recipient> [node-id]/ssync cluster rm <recipient>— rewrite the artifact;rmalso rotates the namespace secret inside it.drop_stale_replicasabandons the old one.That reduces any membership change to: run one command on one machine, copy one file, restart daemons. No ticket dance, no per-machine config edits.
Alternative (smaller, keeps ticket mode primary): a
ssync revoke <recipient>helper that rewrites the local config, rotates the local namespace, prints the fresh ticket and the exact remaining steps. Cheaper, but stays O(N) manual actions per change.Non-goals