A seat's protocol lives in the store (migration 0047; seeded additively), a served verb carries its description and schema, holding a mesh seat requires serving its verbs, a node-scoped seat's tool carries the node, and the control plane serves status, nodes, node, modules, seats, builds, plan, assign, unassign, push, build and tools on its seat by running the same commands (novox/hq ADR 0132, ADR 0154, design 33). A grant of * reaches a role's tools; seat:<seat>.<verb> grants one.
94 lines
3.5 KiB
Go
94 lines
3.5 KiB
Go
package broker
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// A module that says it calls a tool may publish exactly that subject (novox/hq ADR 0152): the same
|
|
// grant a person gets, derived the same way, so one list answers "what may this ask" for everybody.
|
|
func TestAModuleMayAskOnlyTheToolsItInvokes(t *testing.T) {
|
|
perms, err := PermissionsFor(Principal{Kind: KindModule, Node: "desk", Module: "mesh-console",
|
|
Invokes: []string{"shop.price"}, PasswordHash: "x"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
has(t, perms.Publish, "mesh.mod.shop.tool.price")
|
|
hasNot(t, perms.Publish, "mesh.mod.shop.tool.refund")
|
|
hasNot(t, perms.Publish, "mesh.mod.*.tool.>")
|
|
}
|
|
|
|
// The console's grant: every tool, as one subject, and it reads as one.
|
|
func TestAModuleInvokingEverythingMayAskAnyTool(t *testing.T) {
|
|
perms, err := PermissionsFor(Principal{Kind: KindModule, Node: "desk", Module: "mesh-console",
|
|
Invokes: []string{"*"}, PasswordHash: "x"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
has(t, perms.Publish, "mesh.mod.*.tool.>")
|
|
}
|
|
|
|
// **A grant to call widens nothing else.** A module that invokes may not publish an event it did not
|
|
// declare, may not answer as another module, and subscribes nothing it did not consume — the
|
|
// difference between the console and a person is that the console is on a machine, not that it may
|
|
// do more.
|
|
func TestInvokingGrantsNothingButTheCall(t *testing.T) {
|
|
perms, err := PermissionsFor(Principal{Kind: KindModule, Node: "desk", Module: "mesh-console",
|
|
Invokes: []string{"*"}, PasswordHash: "x"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, p := range perms.Publish {
|
|
if strings.Contains(p, ".event.") {
|
|
t.Errorf("a module that only invokes may publish %q, an event it never declared", p)
|
|
}
|
|
// A role's tools are tools (ADR 0132); a role's work queue and events are not.
|
|
if strings.HasPrefix(p, "mesh.seat.") && !strings.Contains(p, ".tool.") {
|
|
t.Errorf("a module that only invokes may publish %q, a seat it neither holds nor uses", p)
|
|
}
|
|
}
|
|
for _, s := range perms.Subscribe {
|
|
if strings.Contains(s, ".tool.") && !strings.HasPrefix(s, "mesh.mod.mesh-console.") {
|
|
t.Errorf("a module that invokes may subscribe %q, another module's tools", s)
|
|
}
|
|
}
|
|
}
|
|
|
|
// A module that declares no invokes calls nothing, which is every module but the console.
|
|
func TestAModuleThatInvokesNothingCallsNothing(t *testing.T) {
|
|
perms, err := PermissionsFor(Principal{Kind: KindModule, Node: "one", Module: "shop",
|
|
Emits: []string{"order.placed"}, PasswordHash: "x"})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, p := range perms.Publish {
|
|
if strings.Contains(p, ".tool.") {
|
|
t.Errorf("a module with no invokes may publish %q", p)
|
|
}
|
|
}
|
|
}
|
|
|
|
// The malformed entry is refused for a module as it is for a person, and in the same words.
|
|
func TestAModulesToolGrantThatNamesNoToolIsRefused(t *testing.T) {
|
|
if _, err := PermissionsFor(Principal{Kind: KindModule, Node: "one", Module: "shop",
|
|
Invokes: []string{"telegram"}, PasswordHash: "x"}); err == nil {
|
|
t.Fatal("a grant naming a module but no tool was accepted")
|
|
}
|
|
}
|
|
|
|
// What a declaration says reaches the composed user, so a manifest's `invokes` is the grant.
|
|
func TestADeclaredInvokeReachesTheComposedUser(t *testing.T) {
|
|
users, err := Users(Records{
|
|
Nodes: []string{"desk"},
|
|
Assigned: map[string][]Declared{"desk": {{Module: "mesh-console", Invokes: []string{"*"}}}},
|
|
})
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
perms, err := PermissionsFor(users[len(users)-1])
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
has(t, perms.Publish, "mesh.mod.*.tool.>")
|
|
}
|