arborist/docs/diagrams/mesh-epoch-lifecycle.dot
russell@unturf.com c7275b5618
docs: mesh multiplayer protocol with dot diagrams
Adds docs/mesh.md and five graphviz diagrams covering the federation
layer: identity stack, epoch state machine, per-member secret envelope,
gossip wire contract, and operator decision tree. Pins the protocol
contract for the upcoming HTTP wire (mesh sync, mesh serve).

Makefile gets a 'docs' target with pattern rule so PNG renders are
incremental from .dot sources.
2026-04-28 12:54:36 -04:00

38 lines
1.7 KiB
Text

// aborist/mesh — epoch state machine.
//
// Every roster mutation bumps a counter. Old epochs persist forever
// (signatures stay verifiable). New gossip is encrypted under the
// post-rotation secret, so evicted members go opaque from epoch+1.
//
// Render: dot -Tpng docs/diagrams/mesh-epoch-lifecycle.dot -o /tmp/x.png
digraph mesh_epoch_lifecycle {
rankdir=LR;
bgcolor="white";
node [shape=box, style="rounded,filled", fontname="Helvetica"];
edge [fontname="Helvetica", fontsize=10];
none [label="no mesh state\n(meta.mesh.enabled = 0)", fillcolor="#eeeeee"];
e0 [label="epoch 0\nfounder = sole admin\nreason: 'genesis'", fillcolor="#fff7d6"];
e1 [label="epoch N\nroster + envelope\nsigned by actor", fillcolor="#d6ffd6"];
eN [label="epoch N+1\nfresh secret\nfresh envelope", fillcolor="#d6ffd6"];
historic [label="every prior epoch\nstays on disk\n(roster + signatures verifiable)", fillcolor="#ffffff", shape=note];
none -> e0 [label="aborist mesh init --group <name>"];
e0 -> e1 [label="add | kick | rotate"];
e1 -> eN [label="add | kick | rotate"];
eN -> eN [label="rotate (no roster change)"];
e1 -> historic [style=dashed, arrowhead=none, color="#888888"];
eN -> historic [style=dashed, arrowhead=none, color="#888888"];
subgraph cluster_ops {
label="Operator commands";
style="rounded,dashed";
color="#666666";
node [fillcolor="#e8f0ff", shape=note];
op_add [label="aborist mesh add\n--member-id bob ...\nadmin only"];
op_kick [label="aborist mesh kick\n--member-id bob ...\nadmin only"];
op_rotate [label="aborist mesh rotate\nany current member"];
}
}