package stdio import ( "bytes" "encoding/json" "fmt" "slices" "strings" ) // Callers is a module's trusted list of who may call a verb of its (novox/hq ADR 0459 §2, ADR 0563 §8), as the mesh // writes a list setting into a file the module reads: `{"callers": [...]}`. An entry is a module's name (that module on // any machine), exactly ., or exactly person.. Each caller is the runtime's proof (CallerOf), never // an argument; nobody beyond the list is granted, a wildcard is no entry, and an unproven caller never matches. type Callers []string // ParseCallers reads a callers file: the list under `callers`, and nothing else. func ParseCallers(raw []byte) (Callers, error) { var f struct { Callers Callers `json:"callers"` } dec := json.NewDecoder(bytes.NewReader(raw)) dec.DisallowUnknownFields() if err := dec.Decode(&f); err != nil { return nil, fmt.Errorf("the callers setting is not a list of callers: %v", err) } return f.Callers, nil } // Allows says whether caller, as the runtime proved it, is one the list names. func (c Callers) Allows(caller string) bool { if caller == "" || caller == Unproven { return false } for _, entry := range c { if entry == "" || strings.ContainsAny(entry, "*> ") { continue } if entry == caller { return true } if !strings.Contains(entry, ".") { if _, module, ok := strings.Cut(caller, "."); ok && module == entry && !strings.HasPrefix(caller, "person.") { return true } } } return false } // VerbCallers is a holder's trusted list per verb (novox/hq ADR 0627 §2, design 51 *Who may call which verb*): for each // verb of the seats it holds, the callers that may call it, each entry read as Callers reads it. Two entries more stand // for a whole class: AnyCaller lets every proved caller call the verb (a read the mesh keeps open), AnyPerson every // operator's session the runtime proved as person.. It names no seat and no verb: the holder gives its verbs and // its defaults, and keeps any rule of its own seat (who may never be on a list) beside it. type VerbCallers map[string][]string // The entries of a VerbCallers list that stand for a class of callers. const ( AnyCaller = "*" AnyPerson = "operator" ) // ParseVerbCallers reads a holder's config value of verb to callers; an empty value is defaults. A verb not among verbs // is refused, so a list that names a verb the holder does not serve is said at once. func ParseVerbCallers(raw string, verbs []string, defaults VerbCallers) (VerbCallers, error) { if strings.TrimSpace(raw) == "" { return defaults, nil } var c VerbCallers if err := json.Unmarshal([]byte(raw), &c); err != nil { return nil, fmt.Errorf("callers is not a JSON object of verb to callers: %w", err) } for verb := range c { if !slices.Contains(verbs, verb) { return nil, fmt.Errorf("callers names the verb %q, which the holder does not serve", verb) } } return c, nil } // Allowed answers nil when caller, as the runtime proved it, may call verb; else the refusal naming both. An unproven // caller is never allowed, not even by AnyCaller. func (c VerbCallers) Allowed(verb, caller string) error { if caller == "" || caller == Unproven { return fmt.Errorf("%s: refused: the request carries no caller the tool runner proved", verb) } person := strings.HasPrefix(caller, "person.") for _, entry := range c[verb] { switch entry { case AnyCaller: return nil case AnyPerson: if person { return nil } default: if (Callers{entry}).Allows(caller) { return nil } } } return fmt.Errorf("%s: refused for %s: not on the holder's caller list for %s", verb, caller, verb) } // ModuleOf is the module of a proved module caller, which the runtime names .. func ModuleOf(proved string) string { if _, module, ok := strings.Cut(proved, "."); ok { return module } return proved } // ConfiguredVerbCallers is the holder's list as mesh-config resolved its config value key for this machine (Config): // a JSON object of verb to callers, or that object written as a string; an unset or empty value is defaults. A value // that cannot be read is an error, never the defaults, so a broken list is said, not widened. func ConfiguredVerbCallers(key string, verbs []string, defaults VerbCallers) (VerbCallers, error) { raw, err := Config(key) if err != nil { return nil, fmt.Errorf("the config value %s cannot be read: %w", key, err) } return parseConfiguredVerbCallers(raw, verbs, defaults) } func parseConfiguredVerbCallers(raw json.RawMessage, verbs []string, defaults VerbCallers) (VerbCallers, error) { var text string if err := json.Unmarshal(raw, &text); err == nil || len(bytes.TrimSpace(raw)) == 0 || string(bytes.TrimSpace(raw)) == "null" { return ParseVerbCallers(text, verbs, defaults) } return ParseVerbCallers(string(raw), verbs, defaults) }