package grants import ( "slices" "strings" "git.novox.be/novox/mesh-sdk/go/catalogue" "git.novox.be/novox/mesh-sdk/go/seatdef" ) // **A module's sent store is read by the modules it is for** (design 47 G §59, §124): the grants part derives, from the // catalog graph and the seat definitions, never from a manifest field, a standing read of `_sent-objects` for the // callers the module's seat definition names for the verbs it serves, and for the consumers whose `consumes` declare its // events. The grant follows the catalog graph, so it is composed with each module's declaration at every pass. // verbCallersOf is, by seat and verb, the callers each verb of the definitions admits (a verb naming none takes its class's // default). func verbCallersOf(defs map[string]seatdef.Definition) map[string]map[string][]string { out := map[string]map[string][]string{} for _, d := range defs { for _, v := range d.Verbs { if out[d.Seat] == nil { out[d.Seat] = map[string][]string{} } out[d.Seat][v.Name] = v.EffectiveCallers() } } return out } // admits says whether a verb's callers name the module: `invokers` (every module whose manifest invokes the verb), the module // itself, or a seat it claims. func admits(callers []string, m catalogue.Manifest) bool { for _, c := range callers { switch { case c == seatdef.CallerInvokers, c == seatdef.CallerModulePrefix+m.Module: return true } if seat, ok := strings.CutPrefix(c, seatdef.CallerSeatPrefix); ok && slices.ContainsFunc(m.Claims, func(x catalogue.Claim) bool { return x.Name == seat }) { return true } } return false } // sentStoresRead are the bus names of the sent stores the module m reads: of each module whose event it consumes (the module's // own, or the seat a module claims), and of each module claiming a seat whose verb m invokes where the verb's callers admit m. // Never m's own store, which its binding grants it. func sentStoresRead(m catalogue.Manifest, all map[string]catalogue.Manifest, callers map[string]map[string][]string) []string { claimants := func(name string) []string { var out []string if _, ok := all[name]; ok { out = append(out, name) } for module, x := range all { if slices.ContainsFunc(x.Claims, func(c catalogue.Claim) bool { return c.Name == name }) { out = append(out, module) } } return out } var stores []string for _, c := range m.Consumes { name, _, ok := strings.Cut(strings.TrimPrefix(c, "seat:"), ".") if !ok || name == "*" { continue } for _, module := range claimants(name) { stores = append(stores, catalogue.SentObjectsName(module)) } } for _, in := range m.Invokes { seat, verb, ok := catalogue.SeatInvoke(in) if !ok || !admits(callers[seat][verb], m) { continue } for module, x := range all { if slices.ContainsFunc(x.Claims, func(c catalogue.Claim) bool { return c.Name == seat }) { stores = append(stores, catalogue.SentObjectsName(module)) } } } stores = slices.DeleteFunc(stores, func(s string) bool { return s == catalogue.SentObjectsName(m.Module) }) slices.Sort(stores) return slices.Compact(stores) }