Files
mesh-tools/node-tools/internal/approval/marks_test.go
T
jschoubben 827628164a A-1 marks: the tool runner derives each served module's marks from the catalog half
The gate (node-tools/internal/approval) derives a module's marked tools and verbs, and the
subjects of its marked events and restricted streams, from its served entry (the build its
composed environment's fingerprint names) and the newest, unioned while they differ, and
the seat definitions' verb marks, which no holder unmarks. A bundle whose marks name a tool
it does not register is not loaded, its finding mark-unserved raised through the runner's
held writer and cleared when a bundle serves it. The first views now start whether or not
the console listens, since the gate reads the catalog half too.

Builds: design 46 7-approval-mark §5, §4 (at load), §3; design 34 every-event §33; lead answer A-154

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-12 05:05:13 +01:00

137 lines
7.0 KiB
Go

package approval
import (
"context"
"reflect"
"testing"
condseat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
"git.novox.be/novox/mesh-sdk/go/keys"
catalogseat "git.novox.be/novox/mesh-delivery/contracts/go/seats/meshcatalog"
"git.novox.be/novox/mesh-sdk/go/seatdef"
)
// fakeCatalog is a catalog half as a fixture: entries by fingerprint, the newest by module, the seat definitions.
type fakeCatalog struct {
ready error
revision string
byFp map[string]catalogseat.CatalogEntry
newest map[string]catalogseat.CatalogEntry
defs map[string]seatdef.Definition
}
func (c *fakeCatalog) Ready() error { return c.ready }
func (c *fakeCatalog) Revision() string { return c.revision }
func (c *fakeCatalog) Served(fp string) (catalogseat.CatalogEntry, bool, string) {
e, ok := c.byFp[fp]
return e, ok, "not-found"
}
func (c *fakeCatalog) Newest(m string) (catalogseat.CatalogEntry, bool) {
e, ok := c.newest[m]
return e, ok
}
func (c *fakeCatalog) Definitions() map[string]seatdef.Definition { return c.defs }
func entry(fp string, serves []string, manifest map[string]any) catalogseat.CatalogEntry {
return catalogseat.CatalogEntry{Module: "shell", Fp: fp, Serves: serves, Manifest: manifest}
}
// Design 46 7-approval-mark §5, §3, §4 and design 34 every-event §33: the marks a module's calls are gated by, derived from
// fixture catalog halves and served entries.
func TestTheMarks(t *testing.T) {
login := map[string]seatdef.Definition{"node-login-shell": {Seat: "node-login-shell",
Verbs: []seatdef.Verb{{Name: "execute", NeedsApproval: true}, {Name: "sessions"}}}}
v1 := entry("src2:1", []string{"node-login-shell.execute", "node-login-shell.sessions"},
map[string]any{"needs-approval": []any{"wipe"}})
v2 := entry("src2:2", []string{"node-login-shell.execute", "node-login-shell.sessions"},
map[string]any{"needs-approval": []any{"erase", "node-login-shell.sessions"}})
mail := catalogseat.CatalogEntry{Module: "mail", Fp: "src2:m", Manifest: map[string]any{
"needs-approval": []any{"mail.received"}, "emits": []any{"mail.received"},
"streams": []any{map[string]any{"name": "MAIL", "events": []any{"mail.**"}, "grant": map[string]any{"config": "readers", "events": "mail.{key}.**"}}}}}
for _, tc := range []struct {
name string
cat *fakeCatalog
module string
fp string
tools []string
verbs map[string]string
subjects []string
unread bool
}{
{name: "a seat's mark stands for every holder, and the holder's own adds up", cat: &fakeCatalog{revision: "7",
byFp: map[string]catalogseat.CatalogEntry{"src2:1": v1}, newest: map[string]catalogseat.CatalogEntry{"shell": v1}, defs: login},
module: "shell", fp: "src2:1", tools: []string{"wipe"}, verbs: map[string]string{"node-login-shell.execute": "seat node-login-shell"}},
{name: "a holder's needs-approval cannot unmark its seat's verb, and marks another", cat: &fakeCatalog{revision: "8",
byFp: map[string]catalogseat.CatalogEntry{"src2:2": v2}, newest: map[string]catalogseat.CatalogEntry{"shell": v2}, defs: login},
module: "shell", fp: "src2:2", tools: []string{"erase"}, verbs: map[string]string{"node-login-shell.execute": "seat node-login-shell",
"node-login-shell.sessions": "entry shell src2:2"}},
{name: "across a version change the union stands: a dropped mark is asked while the old bundle runs", cat: &fakeCatalog{revision: "9",
byFp: map[string]catalogseat.CatalogEntry{"src2:1": v1, "src2:2": v2}, newest: map[string]catalogseat.CatalogEntry{"shell": v2}, defs: login},
module: "shell", fp: "src2:1", tools: []string{"erase", "wipe"}, verbs: map[string]string{"node-login-shell.execute": "seat node-login-shell",
"node-login-shell.sessions": "entry shell src2:2"}},
{name: "a served entry that cannot be read leaves the newest marks, every marked call refused", cat: &fakeCatalog{revision: "9",
newest: map[string]catalogseat.CatalogEntry{"shell": v2}, defs: login},
module: "shell", fp: "src2:1", tools: []string{"erase"}, verbs: map[string]string{"node-login-shell.execute": "seat node-login-shell",
"node-login-shell.sessions": "entry shell src2:2"}, unread: true},
{name: "a bundle with no fingerprint has no served entry", cat: &fakeCatalog{revision: "9", defs: login},
module: "shell", unread: true},
{name: "a marked event and a stream with a grant give their subjects and each .>", cat: &fakeCatalog{revision: "3",
byFp: map[string]catalogseat.CatalogEntry{"src2:m": mail}, newest: map[string]catalogseat.CatalogEntry{"mail": mail}},
module: "mail", fp: "src2:m", subjects: []string{"mesh.mod.mail.event.mail.received", "mesh.mod.mail.event.mail.received.>",
"mesh.stream.mail.event.mail.>", "mesh.stream.mail.event.mail.received", "mesh.stream.mail.event.mail.received.>"}},
} {
t.Run(tc.name, func(t *testing.T) {
m := Derive(tc.cat, tc.module, tc.fp)
if got := keysOf(m.Tools); !reflect.DeepEqual(got, tc.tools) {
t.Errorf("tools %v, want %v", got, tc.tools)
}
if tc.verbs == nil {
tc.verbs = map[string]string{}
}
if !reflect.DeepEqual(m.Verbs, tc.verbs) {
t.Errorf("verbs %v, want %v", m.Verbs, tc.verbs)
}
if got := keysOf(m.Subjects); !reflect.DeepEqual(got, tc.subjects) {
t.Errorf("subjects %v, want %v", got, tc.subjects)
}
if (m.Unread != "") != tc.unread || m.Revision != tc.cat.revision {
t.Errorf("unread %q, revision %q", m.Unread, m.Revision)
}
})
}
// §4: a bundle whose marks name a tool it does not register is not loaded, its finding mark-unserved raised; a bundle that
// serves it clears it, and a catalog without the mark too.
t.Run("mark-unserved raised and cleared", func(t *testing.T) {
cat := &fakeCatalog{revision: "7", byFp: map[string]catalogseat.CatalogEntry{"src2:1": v1}, newest: map[string]catalogseat.CatalogEntry{"shell": v1}, defs: login}
w := &findings{}
g := New(Deps{Node: "n1", Runner: "node-tools", Catalog: cat, Findings: w})
if got := g.Unserved("shell", "src2:1", []string{"other"}); !reflect.DeepEqual(got, []string{"wipe"}) || w.raised[keys.EscapeName("n1.shell")] != KindMarkUnserved {
t.Fatalf("unserved %v, findings %v", got, w.raised)
}
if got := g.Unserved("shell", "src2:1", []string{"wipe"}); got != nil || w.raised[keys.EscapeName("n1.shell")] != "" {
t.Fatalf("a bundle serving the mark: unserved %v, findings %v", got, w.raised)
}
_ = g.Unserved("shell", "src2:1", nil)
cat.byFp["src2:1"], cat.newest["shell"] = entry("src2:1", nil, nil), entry("src2:1", nil, nil)
if got := g.Unserved("shell", "src2:1", nil); got != nil || w.raised[keys.EscapeName("n1.shell")] != "" {
t.Fatalf("a catalog without the mark: unserved %v, findings %v", got, w.raised)
}
})
}
// findings is the runner's held writer as a fixture: each finding raised now, by id.
type findings struct{ raised map[string]string }
func (f *findings) Write(_ context.Context, x condseat.Finding) error {
if f.raised == nil {
f.raised = map[string]string{}
}
f.raised[x.ID] = x.Kind
return nil
}
func (f *findings) Clear(_ context.Context, _, id, _, _ string) error {
delete(f.raised, id)
return nil
}