clone

a self-hosted multitenant nostr relay with sites, file storage, git hosting, and inbox and outbox delivery

feat/ui-updates
tinyrelay / internal / daemon / mcp_grant_request_test.go
mcp_grant_request_test.go 2.8K
1package daemon23import (4 "context"5 "strings"6 "testing"7 "time"89 "github.com/FelineStateMachine/tinyrelay/internal/event"10 "github.com/FelineStateMachine/tinyrelay/internal/mcp"11)1213func TestMCPGrantRequestBuildsOperatorBoundRequest(t *testing.T) {14 _, tenant := testTenant(t)15 agent, _ := event.PublicKey(testAgentSecret)16 now := time.Now().Unix()17 if err := publishAs(t, tenant, agentGrantEvent(t, agent, now, now+3600, []string{"k", "1111"})); err != nil {18 t.Fatal(err)19 }20 changes := map[string]any{"kinds": []any{9}, "rooms": []any{"work"}}21 unsigned, err := tenant.mcpBuildGrantRequest(context.Background(), mcp.Call{Actor: agent, Arguments: map[string]any{"reason": "Need chat replies", "changes": changes}})22 if err != nil {23 t.Fatal(err)24 }25 if unsigned.Kind != 1111 || unsigned.Content != "Need chat replies" {26 t.Fatalf("unsigned request: %+v", unsigned)27 }28 if event.Tag(event.Event{Tags: unsigned.Tags}, "p") != tenant.Policy().Owner || event.Tag(event.Event{Tags: unsigned.Tags}, "request") != "grant" {29 t.Fatalf("request is not bound to operator: %v", unsigned.Tags)30 }31 grant := event.Tag(event.Event{Tags: unsigned.Tags}, "grant")32 if !strings.Contains(grant, `"base"`) || !strings.Contains(grant, `"kinds":[9]`) {33 t.Fatalf("grant change payload: %s", grant)34 }35}3637func TestMCPGrantRequestRejectsUnsupportedChanges(t *testing.T) {38 for _, raw := range []any{map[string]any{"unknown": "x"}, map[string]any{}} {39 if _, err := mcpGrantChanges(raw); err == nil {40 t.Errorf("accepted invalid changes: %#v", raw)41 }42 }43}4445func TestMCPGrantRequestRejectsMissingGrantAndLongReason(t *testing.T) {46 _, tenant := testTenant(t)47 agent, _ := event.PublicKey(testAgentSecret)48 call := mcp.Call{Actor: agent, Arguments: map[string]any{"reason": "need access", "changes": map[string]any{"kinds": []any{float64(9)}}}}49 if _, err := tenant.mcpBuildGrantRequest(context.Background(), call); err == nil {50 t.Fatal("agent without a grant accepted")51 }52 now := time.Now().Unix()53 if err := publishAs(t, tenant, agentGrantEvent(t, agent, now, now+3600, []string{"k", "1111"})); err != nil {54 t.Fatal(err)55 }56 call.Arguments["reason"] = strings.Repeat("x", 501)57 if _, err := tenant.mcpBuildGrantRequest(context.Background(), call); err == nil {58 t.Fatal("501-character reason accepted")59 }60}6162func TestMCPGrantRequestSchema(t *testing.T) {63 schema := mcpGrantRequestSchema()64 if err := mcp.Validate(schema, map[string]any{"event": map[string]any{}}); err != nil {65 t.Fatalf("signed follow-up should be schema-valid: %v", err)66 }67 valid := map[string]any{"reason": "Need room chat", "changes": map[string]any{"kinds": []any{float64(9)}}}68 if err := mcp.Validate(schema, valid); err != nil {69 t.Fatal(err)70 }71 if err := mcp.Validate(schema, map[string]any{"reason": "", "changes": map[string]any{"kinds": []any{float64(9)}}}); err == nil {72 t.Fatal("empty reason accepted")73 }74}