tinyrelayfile
tinyrelay/internal/policy/policy_test.go/

internal/policy/policy_test.go raw
1package policy
2
3import (
4 "encoding/json"
5 "strings"
6 "testing"
7
8 "github.com/FelineStateMachine/tinyrelay/internal/event"
9)
10
11func TestPatchOmittedAndEmptySections(t *testing.T) {
12 cur := Defaults("owner")
13 cur.Tags = []string{"one"}
14 cur.Features.Files = true
15 got, err := Patch(cur, map[string]json.RawMessage{
16 "tags": json.RawMessage(`[]`),
17 "features": json.RawMessage(`{"search":"off"}`),
18 })
19 if err != nil {
20 t.Fatal(err)
21 }
22 if len(got.Tags) != 0 || got.Features.Search != "off" || !got.Features.Files {
23 t.Fatalf("patch did not preserve or clear fields: %#v", got)
24 }
25}
26
27func TestJobsDefaultOnUntilSwitchedOff(t *testing.T) {
28 if !Defaults("owner").Features.Jobs {
29 t.Fatal("long tasks are off by default")
30 }
31 var stored Policy
32 if err := json.Unmarshal([]byte(`{"owner":"owner","writes":"open","reads":"open","features":{"search":"prose"}}`), &stored); err != nil {
33 t.Fatal(err)
34 }
35 if !stored.Features.Jobs {
36 t.Fatal("a stored policy without the field lost long tasks")
37 }
38 patched, err := Patch(Defaults("owner"), map[string]json.RawMessage{"features": json.RawMessage(`{"jobs":false}`)})
39 if err != nil {
40 t.Fatal(err)
41 }
42 if patched.Features.Jobs || patched.Features.Search != "prose" {
43 t.Fatalf("patch did not switch long tasks off: %#v", patched.Features)
44 }
45}
46
47func TestPrivateReadRequiresRecipient(t *testing.T) {
48 p := Defaults("owner")
49 p.Reads = "members"
50 e := event.Event{Kind: 1059, Tags: [][]string{{"p", "recipient"}}}
51 if CanRead(p, e, Access{Member: true, PubKeys: []string{"other"}}) {
52 t.Fatal("member without recipient identity can read private event")
53 }
54 if !CanRead(p, e, Access{Member: true, PubKeys: []string{"recipient"}}) {
55 t.Fatal("recipient cannot read private event")
56 }
57}
58
59func TestPolicyJSONHasNoHostedEconomy(t *testing.T) {
60 b, err := json.Marshal(Defaults(strings.Repeat("a", 64)))
61 if err != nil {
62 t.Fatal(err)
63 }
64 for _, forbidden := range []string{"lease", "fuel", "maxBlobMB", "eventsPerMinute", "reqsPerMinute"} {
65 if strings.Contains(string(b), forbidden) {
66 t.Fatalf("policy contains hosted field %q: %s", forbidden, b)
67 }
68 }
69}
70
71func TestGRASP08RequiresPrivateMembershipReads(t *testing.T) {
72 p := Defaults(strings.Repeat("a", 64))
73 p.Features.Grasp08 = true
74 p.Features.Grasp = true
75 if err := Validate(p); err == nil || !strings.Contains(err.Error(), "reads") {
76 t.Fatalf("GRASP-08 with open reads accepted: %v", err)
77 }
78 p.Reads = "members"
79 if err := Validate(p); err != nil {
80 t.Fatalf("valid private GRASP-08 policy rejected: %v", err)
81 }
82}
83
84func TestGRASP08RequiresBaseGRASP(t *testing.T) {
85 p := Defaults(strings.Repeat("a", 64))
86 p.Features.Grasp08 = true
87 p.Reads = "members"
88 p.Features.Grasp = false
89 if err := Validate(p); err == nil || !strings.Contains(err.Error(), "subfeatures") {
90 t.Fatalf("GRASP-08 without base GRASP accepted: %v", err)
91 }
92}
93
94func TestPrivateRepositoryRequiresGRASP08PrivateTenant(t *testing.T) {
95 e := event.Event{Kind: 30617, Tags: [][]string{{"private", "true"}}}
96 if CanRead(Policy{Reads: "open"}, e, Access{}) {
97 t.Fatal("private repository was readable on an open tenant")
98 }
99 p := Policy{Reads: "members"}
100 if !CanRead(p, event.Event{Kind: 1}, Access{Member: true}) {
101 t.Fatal("ordinary event became unreadable on a member tenant")
102 }
103 p.Features.Grasp08 = true
104 if !CanRead(p, e, Access{Member: true}) {
105 t.Fatal("private repository was unreadable on a GRASP-08 member tenant")
106 }
107}
108
109func TestGRASPHistoryExtensionsRequireGRASP02(t *testing.T) {
110 cases := []struct {
111 name string
112 set func(*Features)
113 }{
114 {name: "grasp03", set: func(f *Features) { f.Grasp03 = true }},
115 {name: "grasp05", set: func(f *Features) { f.Grasp05 = true }},
116 }
117 for _, tc := range cases {
118 t.Run(tc.name, func(t *testing.T) {
119 p := Defaults(strings.Repeat("a", 64))
120 p.Features.Grasp = true
121 tc.set(&p.Features)
122 if err := Validate(p); err == nil || !strings.Contains(err.Error(), "grasp02") {
123 t.Fatalf("accepted %s without GRASP-02: %v", tc.name, err)
124 }
125 p.Features.Grasp02 = true
126 if err := Validate(p); err != nil {
127 t.Fatalf("rejected %s with GRASP-02: %v", tc.name, err)
128 }
129 })
130 }
131}
132
133func TestValidatePrivatePeers(t *testing.T) {
134 p := Defaults(strings.Repeat("a", 64))
135 p.PrivatePeers = []string{"wss://peer.example/relay/"}
136 if err := Validate(p); err != nil {
137 t.Fatal(err)
138 }
139 p.PrivatePeers = []string{"https://peer.example/?token=bad"}
140 if err := Validate(p); err == nil {
141 t.Fatal("accepted private peer URL with query credentials")
142 }
143}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

  • https://012.run/npub1cq2s86qrtadf36eqq3epm38wmhdynrrcwxf84eldk3f94dkv7ttsrulrz5/tinyrelay.git

Refs