Step 4 of a module's permissions granted every user of a seat every verb the seat serves, so a kept-artifact call was composed for any module using a build seat. The compiled Seat now carries each verb's effective callers (seatdef EffectiveCallers, the class defaults), filled where the askers of its queues are, and a user is granted a verb's call subject only where those callers name it: invokers that invoke it, its module, or a seat it holds. A seat whose definitions are unread grants its users no verb. Builds: design 47 G §610, §336, §271 (test 60), A-165, A-179 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
47 lines
2.7 KiB
Go
47 lines
2.7 KiB
Go
package grants
|
|
|
|
import (
|
|
"slices"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/catalogue"
|
|
"git.novox.be/novox/mesh-sdk/go/seatdef"
|
|
|
|
"mesh-grants/internal/buscompose"
|
|
)
|
|
|
|
// The sent stores a module reads follow the catalog graph (design 47 G §59, §124): the consumers of a module's events and the
|
|
// callers a seat's verb admits, and no other module.
|
|
func TestSentStoresRead(t *testing.T) {
|
|
holder := catalogue.Manifest{Module: "shop", Claims: []catalogue.Claim{{Name: "orders-seat"}}}
|
|
all := map[string]catalogue.Manifest{"shop": holder, "bank": {Module: "bank"}, "plain": {Module: "plain"}}
|
|
callers := map[string]map[string][]string{"orders-seat": {
|
|
"place": {"seat:billing", "module:plain"}, "list": seatdef.DefaultCallers(seatdef.ClassRead), "wipe": seatdef.DefaultCallers(seatdef.ClassAct)}}
|
|
for _, c := range []struct {
|
|
name string
|
|
m catalogue.Manifest
|
|
want []string
|
|
}{
|
|
{"consumes a module's event", catalogue.Manifest{Module: "bank", Consumes: []string{"shop.sold"}}, []string{"shop_sent-objects"}},
|
|
{"consumes a seat's event", catalogue.Manifest{Module: "bank", Consumes: []string{"orders-seat.sold"}}, []string{"shop_sent-objects"}},
|
|
{"invokes a verb that names its seat", catalogue.Manifest{Module: "bank", Claims: []catalogue.Claim{{Name: "billing"}},
|
|
Invokes: []string{"seat:orders-seat.place"}}, []string{"shop_sent-objects"}},
|
|
{"invokes a verb that names it", catalogue.Manifest{Module: "plain", Invokes: []string{"seat:orders-seat.place"}}, []string{"shop_sent-objects"}},
|
|
{"invokes a read, its callers include invokers", catalogue.Manifest{Module: "bank", Invokes: []string{"seat:orders-seat.list"}}, []string{"shop_sent-objects"}},
|
|
{"invokes an act no one names it for", catalogue.Manifest{Module: "bank", Invokes: []string{"seat:orders-seat.wipe"}}, nil},
|
|
{"invokes a verb that names others", catalogue.Manifest{Module: "bank", Invokes: []string{"seat:orders-seat.place"}}, nil},
|
|
{"declares neither", catalogue.Manifest{Module: "bank"}, nil},
|
|
{"its own store is its binding's", holder, nil},
|
|
} {
|
|
if got := sentStoresRead(c.m, all, callers); !slices.Equal(got, c.want) {
|
|
t.Errorf("%s: %v, want %v", c.name, got, c.want)
|
|
}
|
|
} // The same callers reach each seat a declaration holds, uses or watches, from which its users' call subjects are
|
|
// composed (design 47 G A-179).
|
|
d := buscompose.Declared{Module: "bank", Uses: []buscompose.Seat{{Name: "orders-seat"}}, Holds: []buscompose.Seat{{Name: "billing"}}}
|
|
withVerbCallers(callers, &d)
|
|
if !slices.Equal(d.Uses[0].VerbCallers["place"], callers["orders-seat"]["place"]) || d.Holds[0].VerbCallers != nil {
|
|
t.Errorf("a used seat's verbs carry %v, a held seat no definition names %v", d.Uses[0].VerbCallers, d.Holds[0].VerbCallers)
|
|
}
|
|
}
|