The grants part grants a seat verb only to a module that names it in invokes (GR8), so a call missing from a manifest is refused live. Listed every module's seat-verb calls in code (constant clients, seatlist.HolderOf, operatorask, buildrun's drops and puts) against its invokes: the teller asks who holds operator-channel (operatorask.Bucket) and the checker drops asks of the image build seat. Every asker of a build seat names the queues it asks as seat:<seat>.accept.<queue> (A-231): the runner check and delivery, the assigner check, the builder delivery, the checker check and recheck; the indexer had its entry. The validator judges that form through mesh-sdk's catalogue.QueueInvoke against the kinds the seat accepts. mesh-grants: a consumed seat view whose seat has no holder on record grants nothing instead of refusing the whole module (TestGrants); TestCallersAndWhyRefused and TestSentStoresRead take §610's class defaults. Builds: design 47 G §544, §601, §610, §616, A-231, A-179 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
60 lines
2.2 KiB
Go
60 lines
2.2 KiB
Go
package grants
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/seatdef"
|
|
)
|
|
|
|
type defsGate struct{ defs map[string]seatdef.Definition }
|
|
|
|
func (defsGate) MayAct(...string) bool { return true }
|
|
func (g defsGate) Definitions() map[string]seatdef.Definition { return g.defs }
|
|
|
|
type canCall struct {
|
|
allowed bool
|
|
asked map[string]any
|
|
}
|
|
|
|
func (c *canCall) Call(key string, body any) (json.RawMessage, error) {
|
|
c.asked = body.(map[string]any)
|
|
return json.Marshal(map[string]any{"allowed": c.allowed})
|
|
}
|
|
|
|
// grants_callers and grants_why_refused read the definitions' callers (design 47 G §83): every verb takes its class's
|
|
// default (§610: no verb names its callers; an act's are the operator, sessions and invokers, a read's invokers, persons
|
|
// and sessions), and a refused account is told the call subject it lacks and the callers the definition admits.
|
|
func TestCallersAndWhyRefused(t *testing.T) {
|
|
defs := map[string]seatdef.Definition{"mesh-wants": {Seat: "mesh-wants", Scope: "mesh", Verbs: []seatdef.Verb{
|
|
{Name: "upgrade", Class: seatdef.ClassAct},
|
|
{Name: "entry", Class: seatdef.ClassRead},
|
|
}}}
|
|
lines := CallerLines(defs, "mesh-wants", "")
|
|
if len(lines) != 2 || lines[0].Verb != "entry" || lines[0].Named || lines[1].Named ||
|
|
strings.Join(lines[0].Callers, ",") != "invokers,persons,sessions" ||
|
|
strings.Join(lines[1].Callers, ",") != "operator,sessions,invokers" {
|
|
t.Fatalf("lines: %+v", lines)
|
|
}
|
|
can := &canCall{}
|
|
p := &Part{SeatList: defsGate{defs}, Call: can}
|
|
got, err := p.WhyRefused("one.shop", "mesh-wants.upgrade", "")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
out := got.(map[string]any)
|
|
if out["lacks"] != "mesh.seat.mesh-wants.call.upgrade.one~shop" || can.asked["subject"] != out["lacks"] ||
|
|
!strings.Contains(out["says"].(string), "operator, sessions, invokers") {
|
|
t.Errorf("a refused caller: %+v", out)
|
|
}
|
|
can.allowed = true
|
|
got, _ = p.WhyRefused("one.shop", "mesh-wants.upgrade", "")
|
|
if _, lacks := got.(map[string]any)["lacks"]; lacks {
|
|
t.Errorf("an allowed caller lacks a grant: %+v", got)
|
|
}
|
|
if _, err := p.WhyRefused("one.shop", "mesh-wants.nothing", ""); err == nil {
|
|
t.Error("a verb no definition names was explained")
|
|
}
|
|
}
|