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.
50 lines
2.7 KiB
Text
50 lines
2.7 KiB
Text
// aborist/mesh — group operator decision tree.
|
|
//
|
|
// When a group steward (admin) faces a roster question, this diagram
|
|
// shows which CLI verb solves it and what guarantee comes out the
|
|
// other side.
|
|
//
|
|
// Render: dot -Tpng docs/diagrams/mesh-group-decisions.dot -o /tmp/x.png
|
|
|
|
digraph mesh_group_decisions {
|
|
rankdir=TB;
|
|
bgcolor="white";
|
|
node [fontname="Helvetica"];
|
|
edge [fontname="Helvetica", fontsize=10];
|
|
|
|
start [label="group steward has a question", shape=ellipse, style="filled", fillcolor="#eeeeee"];
|
|
|
|
q_first [label="is mesh\ninitialized\nyet?", shape=diamond, style="filled", fillcolor="#fff7d6"];
|
|
q_role [label="is the question\nabout people\nor secrets?", shape=diamond, style="filled", fillcolor="#fff7d6"];
|
|
q_who [label="add, remove,\nor refresh?", shape=diamond, style="filled", fillcolor="#fff7d6"];
|
|
q_admin [label="are you\nadmin in\ncurrent epoch?", shape=diamond, style="filled", fillcolor="#fff7d6"];
|
|
|
|
a_init [label="aborist mesh init --group <name>\nthen mesh enable\n(creates epoch 0; founder = sole admin)", shape=box, style="rounded,filled", fillcolor="#d6ffd6"];
|
|
a_add [label="aborist mesh add\n--member-id <id>\n--sign-pub <hex>\n--dh-pub <hex>\n[--role admin]", shape=box, style="rounded,filled", fillcolor="#d6ffd6"];
|
|
a_kick [label="aborist mesh kick\n--member-id <id>\n--reason '...'", shape=box, style="rounded,filled", fillcolor="#d6ffd6"];
|
|
a_rotate [label="aborist mesh rotate\n--reason '...'\n(any current member)", shape=box, style="rounded,filled", fillcolor="#d6ffd6"];
|
|
|
|
g_admin [label="permission denied\n(only admins of the\ncurrent epoch may add or kick)", shape=box, style="rounded,filled", fillcolor="#ffe0e0"];
|
|
|
|
g_add [label="new member can decrypt\nepoch+1 forward;\ncannot reach prior epochs", shape=note, style="filled", fillcolor="#ffffff"];
|
|
g_kick [label="kicked member's prior\nsignatures stay valid forever;\nopaque to gossip from epoch+1 on", shape=note, style="filled", fillcolor="#ffffff"];
|
|
g_rot [label="fresh secret on the same roster;\nuse on suspected secret leak\nor scheduled hygiene", shape=note, style="filled", fillcolor="#ffffff"];
|
|
|
|
start -> q_first;
|
|
q_first -> a_init [label="no"];
|
|
q_first -> q_role [label="yes"];
|
|
|
|
q_role -> q_who [label="people"];
|
|
q_role -> a_rotate [label="just rotate the secret"];
|
|
|
|
q_who -> q_admin [label="add or kick"];
|
|
q_who -> a_rotate [label="refresh secret only"];
|
|
|
|
q_admin -> a_add [label="yes (admin) -> add"];
|
|
q_admin -> a_kick [label="yes (admin) -> kick"];
|
|
q_admin -> g_admin [label="no"];
|
|
|
|
a_add -> g_add [arrowhead=none, style=dotted];
|
|
a_kick -> g_kick [arrowhead=none, style=dotted];
|
|
a_rotate -> g_rot [arrowhead=none, style=dotted];
|
|
}
|