fix9b2-5: the readable check judges a read in the seat form against the modules claiming the seat

Builds: design 47 G A-128, A-116
This commit is contained in:
2026-11-12 01:31:48 +01:00
parent 7b16e195ee
commit 4cd0b42d80
3 changed files with 54 additions and 24 deletions
+1 -1
View File
@@ -11,4 +11,4 @@ replace git.novox.be/novox/mesh-catalog/modules/disk-load/diskreadings => ../../
replace git.novox.be/novox/mesh-catalog/modules/restic/backupgood => ../../modules/restic/backupgood
require git.novox.be/novox/mesh-sdk/go v0.0.0-00010101000000-000000000000 // indirect
require git.novox.be/novox/mesh-sdk/go v0.0.0-00010101000000-000000000000
+44 -23
View File
@@ -31,6 +31,7 @@ import (
"git.novox.be/novox/mesh-catalog/modules/disk-load/diskreadings"
"git.novox.be/novox/mesh-catalog/modules/restic/backupgood"
"git.novox.be/novox/mesh-sdk/go/catalogue"
)
// Known are the constants of the owners' published packages an announcement may name a state by, by the selector the
@@ -53,6 +54,7 @@ func Findings(root string) ([]string, error) {
}
dirs := map[string]string{}
reads := map[string][]string{}
holders := map[string][]string{} // seat -> the modules of the catalogue that claim it
for _, path := range manifests {
raw, err := os.ReadFile(path)
if err != nil {
@@ -61,11 +63,17 @@ func Findings(root string) ([]string, error) {
var m struct {
Module string `json:"module"`
Reads []json.RawMessage `json:"reads"`
Claims []struct {
Name string `json:"name"`
} `json:"claims"`
}
if err := json.Unmarshal(raw, &m); err != nil {
return nil, fmt.Errorf("%s: %w", path, err)
}
dirs[m.Module] = filepath.Dir(path)
for _, c := range m.Claims {
holders[c.Name] = append(holders[c.Name], m.Module)
}
for _, r := range m.Reads {
var s string
if json.Unmarshal(r, &s) == nil {
@@ -77,32 +85,45 @@ func Findings(root string) ([]string, error) {
owners := map[string]Announced{}
for reader, rs := range reads {
for _, r := range rs {
owner, state, ok := strings.Cut(r, ".")
dir, inCatalogue := dirs[owner]
if !ok || !inCatalogue || owner == reader {
continue
}
a, seen := owners[owner]
if !seen {
var problems []string
a, problems, err = AnnouncedBy(dir)
// A read in the seat form `seat:<seat>.<state>` (design 47 G A-116, A-128) is of the holder of the seat, found where it
// is read: each module of the catalogue claiming the seat is judged for the state, as a read of it by name is.
var targets []string
state := ""
if seat, local, isSeat, err := catalogue.SeatRead(r); isSeat {
if err != nil {
return nil, err
continue // the manifest validator names a malformed seat read
}
owners[owner] = a
for _, p := range problems {
out = append(out, owner+": "+p)
targets, state = holders[seat], local
} else if owner, local, ok := strings.Cut(r, "."); ok {
targets, state = []string{owner}, local
}
for _, owner := range targets {
dir, inCatalogue := dirs[owner]
if !inCatalogue || owner == reader {
continue
}
a, seen := owners[owner]
if !seen {
var problems []string
a, problems, err = AnnouncedBy(dir)
if err != nil {
return nil, err
}
owners[owner] = a
for _, p := range problems {
out = append(out, owner+": "+p)
}
}
if a == nil {
continue // announces nothing from code: read as before
}
readable, keeps := a[state]
switch {
case !keeps:
out = append(out, fmt.Sprintf("%s reads %s.%s, which %s's code does not announce: the read is refused on the mesh", reader, owner, state, owner))
case !readable:
out = append(out, fmt.Sprintf("%s reads %s.%s, which %s's code announces not readable: the read is refused on the mesh; announce it readable", reader, owner, state, owner))
}
}
if a == nil {
continue // announces nothing from code: read as before
}
readable, keeps := a[state]
switch {
case !keeps:
out = append(out, fmt.Sprintf("%s reads %s.%s, which %s's code does not announce: the read is refused on the mesh", reader, owner, state, owner))
case !readable:
out = append(out, fmt.Sprintf("%s reads %s.%s, which %s's code announces not readable: the read is refused on the mesh; announce it readable", reader, owner, state, owner))
}
}
}
+9
View File
@@ -50,6 +50,15 @@ func TestFindings(t *testing.T) {
"modules/r/module.json": `{"module":"r","reads":["o.bound"]}`,
"modules/o/module.json": `{"module":"o"}`,
"modules/o/index.ts": `await keeps([{ name: "bound", readable: true }]);`}, ""},
{"seat form, the holder's state not readable", map[string]string{
"modules/r/module.json": `{"module":"r","reads":["seat:the-seat.s"]}`,
"modules/o/module.json": `{"module":"o","claims":[{"name":"the-seat","scope":"mesh"}]}`,
"modules/o/cmd/o/main.go": goOwner + "var _ = announce.State{Name: \"s\"}\n"},
"r reads o.s, which o's code announces not readable"},
{"seat form, the holder's state readable, and a seat no module of the catalogue holds", map[string]string{
"modules/r/module.json": `{"module":"r","reads":["seat:the-seat.s","seat:elsewhere.s"]}`,
"modules/o/module.json": `{"module":"o","claims":[{"name":"the-seat","scope":"mesh"}]}`,
"modules/o/cmd/o/main.go": goOwner + "var _ = announce.State{Name: \"s\", Readable: true}\n"}, ""},
{"an owner that announces nothing, and one outside the catalogue", map[string]string{
"modules/r/module.json": `{"module":"r","reads":["o.s","mesh-controller.lease"]}`,
"modules/o/module.json": `{"module":"o"}`,