tinyrelayfile
tinyrelay/internal/daemon/private_repository_test.go/

internal/daemon/private_repository_test.go raw
1package daemon
2
3import (
4 "context"
5 "encoding/json"
6 "strings"
7 "testing"
8 "time"
9
10 "github.com/FelineStateMachine/tinyrelay/internal/configport"
11 "github.com/FelineStateMachine/tinyrelay/internal/event"
12 "github.com/FelineStateMachine/tinyrelay/internal/policy"
13 "github.com/FelineStateMachine/tinyrelay/internal/relay"
14 "github.com/FelineStateMachine/tinyrelay/internal/replication"
15 "github.com/FelineStateMachine/tinyrelay/internal/storage"
16)
17
18func TestPrivateRepositoryRejectedOnOpenTenantPublishAndImport(t *testing.T) {
19 _, tenant := testTenant(t)
20 p := tenant.Policy()
21 p.Features.Grasp = true
22 p.Reads = "open"
23 if err := tenant.applyPolicy(context.Background(), p); err != nil {
24 t.Fatal(err)
25 }
26 secret := strings.Repeat("4", 64)
27 owner, err := event.PublicKey(secret)
28 if err != nil {
29 t.Fatal(err)
30 }
31 e := event.Event{Kind: event.KIND_REPO, PubKey: owner, CreatedAt: 1, Tags: [][]string{{"d", "private"}, {"private", "true"}, {"clone", "https://relay.example/private.git"}}}
32 if err := event.Sign(&e, secret); err != nil {
33 t.Fatal(err)
34 }
35 if _, err := tenant.router.Publish(context.Background(), e, relay.Session{PubKeys: []string{owner}}); err == nil || !strings.Contains(err.Error(), "GRASP-08") {
36 t.Fatalf("open publish error = %v", err)
37 }
38 if err := tenant.ingest(context.Background(), e, replication.OriginImport); err == nil || !strings.Contains(err.Error(), "GRASP-08") {
39 t.Fatalf("open import error = %v", err)
40 }
41}
42
43func TestPrivateRepositoryPolicyCannotBeReopened(t *testing.T) {
44 owner, err := event.PublicKey(strings.Repeat("5", 63) + "1")
45 if err != nil {
46 t.Fatal(err)
47 }
48 _, tenant, _ := privatePeerTenant(t, "private-policy", owner)
49 e := event.Event{Kind: event.KIND_REPO, PubKey: owner, CreatedAt: 1, Tags: [][]string{{"d", "private"}, {"private", "true"}}}
50 if err := event.Sign(&e, strings.Repeat("5", 63)+"1"); err != nil {
51 t.Fatal(err)
52 }
53 if _, err := tenant.store.Save(context.Background(), e, storage.SaveOptions{Now: 1}); err != nil {
54 t.Fatal(err)
55 }
56 p := tenant.Policy()
57 p.Features.Grasp08 = false
58 p.Reads = "open"
59 if err := tenant.applyPolicy(context.Background(), p); err == nil {
60 t.Fatal("private policy transition was accepted")
61 }
62 patch := configport.Config{Format: configport.Format, Policy: map[string]json.RawMessage{
63 "features": json.RawMessage(`{"grasp08":false}`), "reads": json.RawMessage(`"open"`),
64 }}
65 if _, err := tenant.config.Apply(context.Background(), patch, false); err == nil {
66 t.Fatal("config import reopened a private tenant")
67 }
68 var stored policy.Policy
69 if err := tenant.store.GetSetting(context.Background(), "policy", &stored); err != nil {
70 t.Fatal(err)
71 }
72 if !tenant.PrivateServiceEnabled() || !stored.Features.Grasp08 || stored.Reads != "members" {
73 t.Fatal("rejected import changed the effective or durable private policy")
74 }
75}
76
77func TestLegacyPrivateRepositoryForcesBoundaryAfterRestart(t *testing.T) {
78 ctx := context.Background()
79 dir := t.TempDir()
80 app, err := New(ctx, Config{DataDir: dir, DefaultTenant: "main"})
81 if err != nil {
82 t.Fatal(err)
83 }
84 secret := strings.Repeat("6", 63) + "1"
85 owner, err := event.PublicKey(secret)
86 if err != nil {
87 t.Fatal(err)
88 }
89 meta, err := app.Create(ctx, CreateOptions{Name: "main", Owner: owner, Template: "default"})
90 if err != nil {
91 t.Fatal(err)
92 }
93 tenant, err := app.tenant(ctx, meta, "http://relay.test")
94 if err != nil {
95 t.Fatal(err)
96 }
97 now := time.Now().Unix()
98 items := []event.Event{
99 {Kind: event.KIND_REPO, PubKey: owner, CreatedAt: now, Tags: [][]string{{"d", "legacy"}, {"private", "true"}}},
100 {Kind: event.KIND_REPO_STATE, PubKey: owner, CreatedAt: now + 1, Tags: [][]string{{"d", "legacy"}}},
101 {Kind: 1621, PubKey: owner, CreatedAt: now + 2, Tags: [][]string{{"e", "legacy"}}},
102 }
103 for i := range items {
104 if err := event.Sign(&items[i], secret); err != nil {
105 t.Fatal(err)
106 }
107 if _, err := tenant.store.Save(ctx, items[i], storage.SaveOptions{Now: now}); err != nil {
108 t.Fatal(err)
109 }
110 }
111 if err := app.Close(ctx); err != nil {
112 t.Fatal(err)
113 }
114 app, err = New(ctx, Config{DataDir: dir, DefaultTenant: "main"})
115 if err != nil {
116 t.Fatal(err)
117 }
118 if err := app.Start(ctx, "http://relay.test"); err != nil {
119 t.Fatal(err)
120 }
121 t.Cleanup(func() { _ = app.Close(ctx) })
122 reloaded := app.tenants[meta.ID]
123 if reloaded == nil || !reloaded.PrivateServiceEnabled() || reloaded.Policy().Reads != "members" {
124 t.Fatal("legacy private data did not force members boundary")
125 }
126 if _, err := reloaded.Query(ctx, []event.Filter{{Kinds: []int{event.KIND_REPO, event.KIND_REPO_STATE, 1621}}}, relay.Session{}); err == nil {
127 t.Fatal("anonymous query reached legacy private metadata")
128 }
129 if _, err := reloaded.Count(ctx, []event.Filter{{Kinds: []int{event.KIND_REPO}}}, relay.Session{}); err == nil {
130 t.Fatal("anonymous count reached legacy private metadata")
131 }
132 var durable policy.Policy
133 if err := reloaded.store.GetSetting(ctx, "policy", &durable); err != nil {
134 t.Fatal(err)
135 }
136 if !durable.Features.Grasp08 || durable.Reads != "members" {
137 t.Fatal("legacy boundary must remain private after its announcement is removed")
138 }
139}

About

ownerc01503e8035f
visibilitypublic
headd730679639bf

Maintainers

  • c01503e8035f owner
  • ba1b5beed5b5 agent hermes

Clone

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

Refs