package catalogue import ( "slices" "strings" "testing" ) // A served verb is written as a bare name or in full, and both read into one type (novox/hq ADR 0132). func TestAServedVerbIsANameOrADefinition(t *testing.T) { m, err := decodeForTest([]byte(`{"module":"till","version":"1","tools":["price","refund"],` + `"seats":[{"name":"shop-till","serves":["price",{"name":"refund","description":"give it back",` + `"input":{"type":"object","properties":{"order":{"type":"string"}}}}]}],` + `"claims":[{"name":"shop-till","scope":"mesh"}]}`)) if err != nil { t.Fatal(err) } got := m.DefinesSeats[0].Serves if len(got) != 2 || got[0].Name != "price" || got[1].Name != "refund" || got[1].Description != "give it back" { t.Fatalf("verbs not read: %+v", got) } if got[1].Input["type"] != "object" { t.Fatalf("the schema did not travel with the verb: %+v", got[1].Input) } } // Holding a mesh seat that serves verbs requires serving them, and the refusal names the verbs. func TestHoldingAMeshSeatRequiresServingItsVerbs(t *testing.T) { // 774/S34/AC1: the seat mesh-enrolment is held by a module serving its six verbs, and a seventh is refused. enrolment, ok := SeatNamed(EnrolmentSeat) if !ok || enrolment.Scope != ScopeMesh || len(enrolment.Emits) != 5 { t.Fatalf("mesh-enrolment: in the set %v, %+v", ok, enrolment) } six := []string{"issue", "redeem", "confirm", "revoke", "tokens", "again"} // The tunnel key is given at issue (the operator, 2026-11-02 01:05). if issue := enrolment.Serves[0]; issue.Name != "issue" || !slices.Contains(issue.Input["required"].([]string), "overlay_key") { t.Errorf("issue requires %v", issue.Input["required"]) } holder := func(serves ...string) Manifest { return Manifest{Module: "mesh-enrolment", Tools: serves, Claims: []Claim{{Name: EnrolmentSeat, Scope: ScopeMesh, Serves: serves}}} } if err := CanHold(holder(six...), enrolment); err != nil { t.Errorf("the holder serving the six verbs was refused: %v", err) } if err := CanHold(holder(six[:5]...), enrolment); err == nil || !strings.Contains(err.Error(), "does not serve again") { t.Errorf("a holder missing again: %v", err) } if err := CanHold(holder(append(six, "mint")...), enrolment); err == nil || !strings.Contains(err.Error(), "mint") { t.Errorf("a holder saying it serves mint: %v", err) } was := Seats() t.Cleanup(func() { UseSeats(was) }) UseSeats([]Seat{{Name: "mesh-controller", Scope: ScopeMesh, Decision: "test", Serves: []Verb{{Name: "status"}, {Name: "push"}}}}) seat, _ := SeatNamed("mesh-controller") partial := Manifest{Module: "a-controller", Tools: []string{"status"}, Claims: []Claim{{Name: "mesh-controller", Scope: ScopeMesh}}} err := CanHold(partial, seat) if err == nil || !strings.Contains(err.Error(), "does not serve push") { t.Fatalf("a holder missing a verb was not refused by name: %v", err) } whole := Manifest{Module: "a-controller", Tools: []string{"status", "push"}, Claims: []Claim{{Name: "mesh-controller", Scope: ScopeMesh}}} if err := CanHold(whole, seat); err != nil { t.Fatalf("a holder serving every verb was refused: %v", err) } }