package buscompose import ( "fmt" "git.novox.be/novox/mesh-sdk/go/delivery" ) // The compositions' buckets (novox/hq ADR 0539 clauses 2 and 4): one per node, `composed-`, holding the // compositions the ended controller made for that node, which only that node's node-engine reads. Nothing writes them // since the controller ended (ADR 0590); a node composes its own modules (ADR 0547 §2). // ComposedReads is what a node's node-engine publishes to follow its wants and compositions (ADR 0539 clauses 1, 2 and // 9): every key of its own composition bucket, and its own wants (`want..` and `want..node`) in the // assigner's bucket; nothing of another node's, nor the bucket of digests. func ComposedReads(node string) ([]string, error) { bucket, err := delivery.ComposedBucketFor(node) if err != nil { return nil, err } if !safeSubject.MatchString(node) { return nil, fmt.Errorf("%q cannot be part of a subject: a permission is a subject pattern, and this would widen it", node) } return append(readGrants(bucket, ""), readGrants(delivery.AssignerWantsBucket, "want."+node+".>")...), nil } // VerbsTheNodeAgentAsks are the seat verbs a node's node-engine calls of its own machine while it applies a want (ADR // 0539 clause 16, ADR 0429 §14): its backup holder backs a data module up before it moves, and says when it was. Asked // of its own machine only, `mesh.seat..tool..`. var VerbsTheNodeAgentAsks = []SeatVerb{{Seat: "node-backup", Verb: "now"}, {Seat: "node-backup", Verb: "backed-up"}} // NodeAgentAsks are the subjects of VerbsTheNodeAgentAsks for one node. func NodeAgentAsks(node string) ([]string, error) { if !safeSubject.MatchString(node) { return nil, fmt.Errorf("%q cannot be part of a subject: a permission is a subject pattern, and this would widen it", node) } var out []string for _, v := range VerbsTheNodeAgentAsks { out = append(out, "mesh.seat."+v.Seat+".tool."+v.Verb+"."+node) } return out, nil } // NodeAgentHears are the events a node's node-engine subscribes while it applies a want: the backup holder's word that a // backup is taken (`backed-up`), from whichever module holds node-backup on its machine (restic today). var NodeAgentHears = []string{"mesh.mod." + BackupHolderModule + ".event.backed-up"} // BackupHolderModule is the module that holds node-backup on every node, restic: the one whose word a node-engine hears. // A second holder of the seat is a change of this grant. const BackupHolderModule = "restic" // DeclarationsStream is the stream of each node's last declaration, `mesh.node..declare` (issue 107). Release 6 // sends none (ADR 0539 clauses 5 and 11): the stream is kept, with each node's consumer, only so a node away during the // switch finds its last declaration and with it the new node-engine; the controller deletes it once every node's have // names the new node-engine, and from then on neither asserts it nor any node's consumer on it; nor makes it again once // it is gone from the bus for any reason, since a stream made anew would hold no node's last declaration (issue 1945). const DeclarationsStream = "NODES" // RaiseAfterDeclarations is Raise once the declarations' stream is retired: the mesh's streams and consumers but the // declarations' stream, and no node's consumer of a declaration. func RaiseAfterDeclarations(r Raiser) error { for _, s := range MeshStreams() { if s.Name == DeclarationsStream { continue } if err := r.EnsureStream(s); err != nil { return fmt.Errorf("asserting stream %s: %w", s.Name, err) } } return AssertMeshConsumers(r) }