// arborist/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="arborist mesh init --group \nthen mesh enable\n(creates epoch 0; founder = sole admin)", shape=box, style="rounded,filled", fillcolor="#d6ffd6"]; a_add [label="arborist mesh add\n--member-id \n--sign-pub \n--dh-pub \n[--role admin]", shape=box, style="rounded,filled", fillcolor="#d6ffd6"]; a_kick [label="arborist mesh kick\n--member-id \n--reason '...'", shape=box, style="rounded,filled", fillcolor="#d6ffd6"]; a_rotate [label="arborist 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]; }