RR-1: the reader refuses a callers entry that is no form of the format

An entry is operator, healers, persons, sessions, invokers, seat:<seat>, module:<module> or holder:<seat>@same-node;
a bare name or one of the earlier classes (holder, invokes, reviewers) is refused naming the entry.

Builds: design 47 G §336, §392, §409

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-11 10:41:35 +01:00
parent 078d3f53bf
commit 6b76c34ca3
2 changed files with 49 additions and 3 deletions
+43 -2
View File
@@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"strings"
)
// Callers says who may call a verb or send an accepted kind. It is read as text (the form every definition on main
@@ -53,13 +54,53 @@ func checkCallers(where string, c *Callers) Problems {
}
var ps Problems
for i, e := range c.List {
if e == "" {
ps = append(ps, Problem{fmt.Sprintf("%s[%d]", where, i), "is empty"})
if why := CallerEntryProblem(e); why != "" {
ps = append(ps, Problem{fmt.Sprintf("%s[%d]", where, i), why})
}
}
return ps
}
// The entries of a list of callers that are not a name (design 47 G §336).
const (
CallerOperator = "operator"
CallerHealers = "healers"
CallerPersons = "persons"
CallerSessions = "sessions"
CallerInvokers = "invokers"
)
// The prefixes of the entries that name a seat's holder or a module (design 47 G §392, §336).
const (
CallerSeatPrefix = "seat:"
CallerModulePrefix = "module:"
CallerHolderPrefix = "holder:"
CallerSameNode = "@same-node"
)
// CallerEntryProblem says why an entry of a list of callers is none of the forms of design 47 G §336, §392; empty
// when it is one: `operator`, `healers`, `persons`, `sessions`, `invokers`, `seat:<seat>`, `module:<module>` and
// `holder:<seat>@same-node`. A bare name is refused, since a name such as `mesh-grants` is both a seat and a module.
func CallerEntryProblem(e string) string {
switch e {
case CallerOperator, CallerHealers, CallerPersons, CallerSessions, CallerInvokers:
return ""
}
if n, ok := strings.CutPrefix(e, CallerSeatPrefix); ok && wordName.MatchString(n) {
return ""
}
if n, ok := strings.CutPrefix(e, CallerModulePrefix); ok && wordName.MatchString(n) {
return ""
}
if n, ok := strings.CutPrefix(e, CallerHolderPrefix); ok {
if seat, ok := strings.CutSuffix(n, CallerSameNode); ok && wordName.MatchString(seat) {
return ""
}
}
return fmt.Sprintf("%q is none of operator, healers, persons, sessions, invokers, seat:<seat>, module:<module> and "+
"holder:<seat>@same-node", e)
}
// The classes of a verb (design 47 G §391).
const (
ClassRead = "read"
+6 -1
View File
@@ -118,7 +118,12 @@ func TestADefinitionIsReadStrictlyNamingWhatIsWrong(t *testing.T) {
{"callers as text", strings.Replace(whole, `"name":"list",`, `"name":"list","callers":"a person",`, 1), ""},
{"callers as a list", strings.Replace(whole, `"name":"list",`, `"name":"list","callers":["operator","seat:mesh-grants","invokers"],"class":"read",`, 1), ""},
{"callers as neither", strings.Replace(whole, `"name":"list",`, `"name":"list","callers":7,`, 1), "callers is a text or a list"},
{"a list with an empty entry", strings.Replace(whole, `"name":"list",`, `"name":"list","callers":["operator",""],`, 1), "verbs[0].callers[1]: is empty"},
{"a list with an empty entry", strings.Replace(whole, `"name":"list",`, `"name":"list","callers":["operator",""],`, 1), "verbs[0].callers[1]"},
{"a bare name among callers", strings.Replace(whole, `"name":"list",`, `"name":"list","callers":["mesh-grants"],`, 1), `"mesh-grants" is none of operator`},
{"a class of the old branches", strings.Replace(whole, `"name":"list",`, `"name":"list","callers":["holder","invokes","reviewers"],`, 1), `"holder" is none of operator`},
{"every form among callers", strings.Replace(whole, `"name":"list",`,
`"name":"list","callers":["operator","healers","persons","sessions","invokers","seat:mesh-grants","module:mesh-grants","holder:node-backup@same-node"],`, 1), ""},
{"a holder not on the same node", strings.Replace(whole, `"name":"list",`, `"name":"list","callers":["holder:node-backup"],`, 1), "none of operator"},
{"a class that is none", strings.Replace(whole, `"name":"list",`, `"name":"list","class":"free",`, 1), `verbs[0].class: "free" is not a class (read, act, warrant)`},
{"an accepted kind's callers", strings.Replace(whole, `"events":`, `"accepts":[{"name":"step","body":{},"callers":["seat:mesh-pipeline-runner"]}],"events":`, 1), ""},
{"an event's callers", strings.Replace(whole, `"name":"created"`, `"name":"created","callers":["operator"]`, 1), "only an accepted kind carries callers"},