The controller ended by its unassignment (ADR 0590): its user, its lease's cut and reads, the operator's hand path to its compositions and its writers' rows go; an enrolling node enrols through mesh-enrolment alone; the desk's prompt stays the vault's alone (DeskOnly). The golden lists are now this composer's own, taken first from the controller's with its user removed. The bus module's tools may remove the controller's leftovers by name, consumers, CONTROL, ASSIGNMENTS, its 17 buckets and each node's declaration files' bucket, under the word controller-leftovers (clause 6). The provisioner client reads placement in place of the assignments mirror. Issue 1126 B3a, B5. Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
78 lines
3.1 KiB
Go
78 lines
3.1 KiB
Go
package buscompose
|
|
|
|
import (
|
|
"slices"
|
|
"sort"
|
|
"strings"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/announce"
|
|
)
|
|
|
|
// Who may read a module's state is what the module announced (novox/hq ADR 0495 clauses 2 and 3, ADR 0513 §3; issue
|
|
// 1790). A module says on the bus which states it keeps and which others may read (announce.Subject); the controller
|
|
// keeps the last word of each (announce.KeptBucket) and grants a reader's `reads: <owner>.<name>` only when the owner
|
|
// announced that state readable. An owner that has announced nothing yet is read as before, from the reader's `reads`
|
|
// (the transition, until every module announces), and is named as not yet announced.
|
|
|
|
// StatesAnnouncedBucket is the controller's bucket of the last announcement of each module (announce.KeptBucket).
|
|
const StatesAnnouncedBucket = announce.KeptBucket
|
|
|
|
// ReadsAnnouncedBy splits one reader module's `reads` (`<owner>.<name>`) by what each owner announced: granted when the
|
|
// owner announced the state readable (by this reader, where it named its readers: announce.State.Readers), when the
|
|
// composer names the reader among the state's readers (NamedReaders, ADR 0547 clause 9), or when the owner announced
|
|
// nothing yet (the transition); refused otherwise, and a read named for other modules is refused. There is no judgement
|
|
// without the reader (issue 774): one made without it refused every named reader, and Users judges again for the
|
|
// reader whatever split it is given (withAnnouncedReads). An empty reader is judged by the readable mark alone.
|
|
func ReadsAnnouncedBy(reader string, reads []string, announced map[string]announce.States) (granted, refused []string) {
|
|
for _, r := range reads {
|
|
owner, name, ok := strings.Cut(r, ".")
|
|
s, said := announced[owner]
|
|
switch {
|
|
case reader != "" && !ReaderMay(reader, r):
|
|
refused = append(refused, r)
|
|
case reader != "" && namedReader(reader, r):
|
|
// A state the composer names its readers for is theirs whatever its owner announced.
|
|
granted = append(granted, r)
|
|
case reader != "" && ok && said && s.Keeps(name):
|
|
if s.ReadableBy(name, reader) {
|
|
granted = append(granted, r)
|
|
} else {
|
|
refused = append(refused, r)
|
|
}
|
|
case !ok || !said || s.Readable(name):
|
|
granted = append(granted, r)
|
|
default:
|
|
refused = append(refused, r)
|
|
}
|
|
}
|
|
return granted, refused
|
|
}
|
|
|
|
// NotAnnounced are the owners some module reads the state of and that have announced nothing yet, sorted: read from the
|
|
// readers' `reads` as before, until they announce.
|
|
func NotAnnounced(r Records) []string {
|
|
seen := map[string]bool{}
|
|
var out []string
|
|
for _, ds := range r.Assigned {
|
|
for _, d := range ds {
|
|
for _, read := range append(append([]string(nil), d.Reads...), d.ReadsRefused...) {
|
|
owner, _, ok := strings.Cut(read, ".")
|
|
if !ok || seen[owner] {
|
|
continue
|
|
}
|
|
if _, said := r.Announced[owner]; !said {
|
|
seen[owner] = true
|
|
out = append(out, owner)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
sort.Strings(out)
|
|
return out
|
|
}
|
|
|
|
// namedReader says the composer names module among the readers of read (NamedReaders).
|
|
func namedReader(module, read string) bool {
|
|
return slices.Contains(NamedReaders[strings.TrimSpace(read)], module)
|
|
}
|