Module assigner client: the operations of a proposal's change and the states of an open proposal, for its holder and for the enrolment that builds add-node (B7f finding 4; ADR 0634 §4; issue 1966)

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 15:43:25 +01:00
parent 5f8b8edd20
commit bb2140c236
2 changed files with 53 additions and 0 deletions
@@ -0,0 +1,39 @@
package meshmoduleassignerclient
// The operations a proposal's change names (novox/hq ADR 0567 §2), the words of a change's `op`. The seat's contract
// carries the field; its callers (the enrolment builds OpAddNode and OpRemoveNode) and its holder share the words here.
const (
// OpPlace places a module on a node, with its host ports and bindings.
OpPlace = "place"
// OpTakeOff takes a module off a node.
OpTakeOff = "take-off"
// OpPin pins the provider of a provision on a node; OpUnpin removes a pin.
OpPin = "pin"
OpUnpin = "unpin"
// OpHold says a module placed on the node holds a seat; OpUnhold, that it holds it no more.
OpHold = "hold"
OpUnhold = "unhold"
// OpDecide sets a decided field of the node (NodeDecided by its JSON name), its address among them.
OpDecide = "decide"
// OpConfig sets a module's config placement or values on the node.
OpConfig = "config"
// OpSeed is the node's whole placement: the take-over (adopt, §7), never given by a caller.
OpSeed = "seed"
// OpAddNode adds a joining node with its decided fields and the public halves of its keys, on the warrant of the
// enrolment that issued its token (novox/hq ADR 0587 §7): the enroller's alone, the proposal's one change.
OpAddNode = "add-node"
// OpRemoveNode takes a joining node off placement again when its enrolment ends unconfirmed, revoked or expired: the
// enroller's alone, on the same warrant, the proposal's one change, of a node with no module and no holding.
OpRemoveNode = "remove-node"
)
// The states of an open proposal (the field `state` of the state `proposals`).
const (
// ProposalAnswering: its candidates are written and the nodes it must hear from have not all answered.
ProposalAnswering = "answering"
// ProposalFailed: its verdict failed; it stays open, for its proposer to read and withdraw, or for a node's later
// answer to judge it again.
ProposalFailed = "failed"
// ProposalAsked: its verdict passed and the operator is asked to approve it.
ProposalAsked = "asked"
)
@@ -0,0 +1,14 @@
package meshmoduleassignerclient
import "testing"
// The words are the wire's: a holder and a caller that spell one differently refuse each other's proposals.
func TestOpsAndProposalStatesAreTheWire(t *testing.T) {
for got, want := range map[string]string{OpPlace: "place", OpTakeOff: "take-off", OpPin: "pin", OpUnpin: "unpin", OpHold: "hold",
OpUnhold: "unhold", OpDecide: "decide", OpConfig: "config", OpSeed: "seed", OpAddNode: "add-node", OpRemoveNode: "remove-node",
ProposalAnswering: "answering", ProposalFailed: "failed", ProposalAsked: "asked"} {
if got != want {
t.Errorf("%q, want %q", got, want)
}
}
}