package apply import ( "fmt" "github.com/novox/mesh-host/internal/declaration" "github.com/novox/mesh-host/internal/store" ) // A node is adopted or converged, and a declaration says which it is for (novox/hq ADR 0100). // // **The two are not interchangeable, and the host knows which it is.** A converged declaration // carries the mesh's drop-by-default filter and retires the firewall the node was found with; on // an adopted node that closes the machine to everything the predecessor still serves — which is // what happened when an operator ran `reconcile` on an adopted control-node and it applied the // converged genesis bundle (novox/hq issue 104). The host reported "adopted" in every report and // compared nothing. Now it compares, at the point of application, whichever command delivered // the declaration. // // Only the mesh changes a node's mode, and it does so by sending a declaration: the flip arrives // over the link as the first converged declaration after adopted ones (`converge` on the // controller), and the way back as the first adopted one (`adopt`). So a declaration the link // delivers, signed and verified, is the mode's authority and is not checked against the record — // it becomes the record. Everything else — the carried bundle, a file, the kept declaration a // disconnected node re-applies — is held to the mode already recorded. // ModeOf says which mode a declaration is for. func ModeOf(d *declaration.Declaration) string { if d.Adoption != nil { return store.ModeAdopted } return store.ModeConverged } // CheckMode refuses a declaration whose mode is not the one this node has recorded. A node with // no recorded mode — a machine nothing has said a mode to yet — takes either. func CheckMode(known store.State, d *declaration.Declaration) error { if known.Mode == "" || known.Mode == ModeOf(d) { return nil } act := "`converge`" if ModeOf(d) == store.ModeAdopted { act = "`adopt`" } return fmt.Errorf("this node is %s; the declaration says %s — %s declaration is not applied "+ "to %s node; %s on the controller is the act that changes it, and it sends the "+ "declaration that does", known.Mode, ModeOf(d), article(ModeOf(d)), article(known.Mode), act) } func article(mode string) string { if mode == store.ModeAdopted { return "an adopted" } return "a converged" }