package link // The wire formats shared with the control plane, which defines them separately because this // binary requires nothing present and does not import it. A test on each side asserts the field // names, so a rename breaks both at once rather than on a real machine months later. // Routing keys a node may publish. Its broker account is scoped to this exchange and its own // queue, so it can say these things and nothing else. const ( KeyReport = "report" KeyAlive = "alive" ) // Alive is a node saying nothing except that it is there. // // novox/hq 09-the-node-lifecycle: *how long it has been disconnected is a fact the mesh must // hold, and nothing holds it today. Without it, a node running last month's assignments looks // exactly like one that is current.* // // Separate from a report because the two happen at completely different rates: a node is alive // constantly and applies something rarely, and reading one as the other would make a quiet node // look like a stale one. type Alive struct { Node string `json:"node"` } // Signed is a declaration and the signature over it. // // novox/hq ADR 0004: the transport is verified once at connect, and **each declaration is // verified by its signature, every time**. The two are different questions — a node connects to // the broker and takes instruction from the control plane behind it, and pinning only the first // would make the second transitive. // // The signature is over Declaration exactly as it arrived, bytes unchanged. Re-encoding before // verifying would mean checking a signature over something other than what was sent, and any // difference in key order or spacing would break it — so the raw message is what is signed and // what is checked. type Signed struct { Declaration []byte `json:"declaration"` Signature []byte `json:"signature"` } // Report is what a node says after applying, and it is a statement rather than a write. // // A node states; the context that owns the data writes (novox/hq ADR 0006). The difference is the // security boundary: something that can write cannot be prevented from writing anything, and // something that can only state has its blast radius bounded by what this struct can say. type Report struct { Node string `json:"node"` // Applied is what this machine now owns, by resource id. Applied []string `json:"applied,omitempty"` // Failed says what could not be applied, and why, in words for a person. Failed map[string]string `json:"failed,omitempty"` // Refused is set when the declaration was rejected whole rather than applied in part. Refused string `json:"refused,omitempty"` }