Names N2b: a part's holder function reads the seat-holders view it follows
HoldersIn is the one holder function a part gives seatlist.Part.Holders: the modules holding a seat on any node, from the seat-holders view as the part last heard it (a views follower's or a watched state's values), so a callers entry `seat:<seat>` is resolved with no call per checked call. Builds: design 47 G A-295, A-210 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
@@ -9,6 +9,8 @@ package seatlist
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -50,3 +52,36 @@ func HolderOf(call HolderCaller, seat string) (string, error) {
|
||||
}
|
||||
return "", fmt.Errorf("no module holds the seat %s on record", seat)
|
||||
}
|
||||
|
||||
// HoldersIn is a part's holder function (Part.Holders, design 47 G A-295): the modules holding a seat on any node, read from
|
||||
// values, the seat-holders view of the seat that places modules as the part last heard it (a views follower's or a watched
|
||||
// state's Values), so a callers entry `seat:<seat>` is resolved with no call per checked call. The view keys a seat held once
|
||||
// `<seat>` and a node seat `<seat>.<node>`; none while the view cannot be read or nobody holds the seat.
|
||||
func HoldersIn[V ~[]byte](values func() (map[string]V, error)) func(seat string) []string {
|
||||
return func(seat string) []string {
|
||||
keys, err := values()
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
var out []string
|
||||
for key, raw := range keys {
|
||||
if key != seat && !strings.HasPrefix(key, seat+".") {
|
||||
continue
|
||||
}
|
||||
var held struct {
|
||||
Holders []struct {
|
||||
Module string `json:"module"`
|
||||
} `json:"holders"`
|
||||
}
|
||||
if json.Unmarshal([]byte(raw), &held) != nil {
|
||||
continue
|
||||
}
|
||||
for _, h := range held.Holders {
|
||||
if h.Module != "" && !slices.Contains(out, h.Module) {
|
||||
out = append(out, h.Module)
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,10 +289,14 @@ func TestTheTwoToolsReadTheHeldListAndReadItAgainForTheirCallers(t *testing.T) {
|
||||
if err := RefusalWith("seat_list_again", bySeat, "ace.mesh-delivery-watchman", part.holdersOf); err == nil {
|
||||
t.Fatal("a seat entry allowed a module before the part was given its holders")
|
||||
}
|
||||
part.Holders(func(seat string) []string {
|
||||
return map[string][]string{"mesh-healers": {"mesh-delivery-watchman"}}[seat]
|
||||
})
|
||||
for caller, allowed := range map[string]bool{"ace.mesh-delivery-watchman": true, "ace.mesh-build-go": false, "person.jo": true} {
|
||||
// HoldersIn reads the seat-holders view as the part last heard it: a seat held once by `<seat>`, a node seat by
|
||||
// `<seat>.<node>`, and no other seat's key.
|
||||
view := map[string][]byte{"mesh-healers": []byte(`{"seat":"mesh-healers","holders":[{"module":"mesh-delivery-watchman","node":"g14"}]}`),
|
||||
"node-tool-runner.ace": []byte(`{"seat":"node-tool-runner","node":"ace","holders":[{"module":"node-tools","node":"ace"}]}`),
|
||||
"mesh-healers-x": []byte(`{"holders":[{"module":"mesh-build-go"}]}`)}
|
||||
part.Holders(HoldersIn(func() (map[string][]byte, error) { return view, nil }))
|
||||
bySeat = append(bySeat, "seat:node-tool-runner")
|
||||
for caller, allowed := range map[string]bool{"ace.mesh-delivery-watchman": true, "ace.mesh-build-go": false, "person.jo": true, "g14.node-tools": true} {
|
||||
if err := RefusalWith("seat_list_again", bySeat, caller, part.holdersOf); (err == nil) != allowed {
|
||||
t.Errorf("again by %s through the seat entry: %v, want allowed %v", caller, err, allowed)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user