Skip to content
quarry Artifact [9ac11e97c0]
Login

Artifact [9ac11e97c0]

Artifact 9ac11e97c0ae29b02952b18e976db95634adb60fc8e004594242e00d7dda04a1:


package api

import (
	"context"
	"errors"
	"strings"
	"testing"
	"time"

	"craftdesign.group/quarry/internal/oltp"
	"craftdesign.group/quarry/internal/ops"
)

// memMirrors is a MirrorStore in memory, enough to drive posture.
type memMirrors map[string]Mirror

func (m memMirrors) Mirrors() ([]Mirror, error) {
	var out []Mirror
	for _, v := range m {
		out = append(out, v)
	}
	return out, nil
}
func (m memMirrors) MirrorFor(repo string) (Mirror, bool, error) { v, ok := m[repo]; return v, ok, nil }
func (m memMirrors) SetMirror(repo, url string, every int) error {
	m[repo] = Mirror{Repo: repo, URL: url, Every: every, Enabled: true}
	return nil
}
func (m memMirrors) DetachMirror(repo string) error {
	v := m[repo]
	v.Enabled, v.DetachedFrom = false, v.URL
	m[repo] = v
	return nil
}
func (m memMirrors) SetMirrorWrites(repo string, accept bool) error {
	v := m[repo]
	v.AcceptWrites = accept
	m[repo] = v
	return nil
}
func (m memMirrors) RecordMirrorRun(string, time.Duration, bool, error) (int, error) { return 0, nil }
func (m memMirrors) MirrorPulls(string, int) ([]MirrorPull, error)                   { return nil, nil }
func (m memMirrors) MirrorDiverged(string, string, time.Time) error                  { return nil }

func TestMirrorState(t *testing.T) {
	now := time.Date(2026, 8, 21, 12, 0, 0, 0, time.UTC)
	stamp := func(ago time.Duration) string { return now.Add(-ago).UTC().Format(time.RFC3339) }
	cases := []struct {
		name string
		m    Mirror
		want string
	}{
		{"fresh", Mirror{Enabled: true, Every: 3600, LastOK: stamp(10 * time.Minute)}, MirrorCurrent},
		{"edge", Mirror{Enabled: true, Every: 3600, LastOK: stamp(119 * time.Minute)}, MirrorCurrent},
		{"quiet too long", Mirror{Enabled: true, Every: 3600, LastOK: stamp(3 * time.Hour)}, MirrorLagging},
		{"never ran", Mirror{Enabled: true, Every: 3600}, MirrorLagging},
		{"failing", Mirror{Enabled: true, Every: 3600, LastOK: stamp(time.Minute), Failures: 1}, MirrorFailing},
		{"detached", Mirror{Enabled: false, DetachedFrom: "https://x/home"}, MirrorDetached},
	}
	for _, c := range cases {
		if got := mirrorState(c.m, now); got != c.want {
			t.Errorf("%s: got %s, want %s", c.name, got, c.want)
		}
	}
}

// A mirror refuses local writes until the operator allows them, and a
// detached store is native again. repo.get carries the posture.
func TestMirrorRefusesWrites(t *testing.T) {
	ix := wikiIndex(t)
	ms := memMirrors{}
	_ = ms.SetMirror("test", "https://upstream.example/home", 3600)
	r := ops.NewRegistry()
	if err := RegisterAll(r, Deps{Version: "v", Repos: testRepos(ix), Mirrors: ms}); err != nil {
		t.Fatal(err)
	}
	ctx := context.Background()
	newTicket := func() error {
		_, err := r.Invoke(ctx, "ticket.new", ticketNewIn{Repo: "test", Title: "t"})
		return err
	}
	err := newTicket()
	if !errors.Is(err, ops.ErrForbidden) || !strings.Contains(err.Error(), "upstream.example") {
		t.Fatalf("ticket on a mirror: want forbidden naming the upstream, got %v", err)
	}
	for _, op := range []struct {
		name string
		in   any
	}{
		{"wiki.save", wikiSaveIn{Repo: "test", Name: "p", Body: "b"}},
		{"forum.post", forumPostIn{Repo: "test", Title: "t", Body: "b"}},
		{"technote.add", technoteAddIn{Repo: "test", Body: "b"}},
	} {
		if _, err := r.Invoke(ctx, op.name, op.in); !errors.Is(err, ops.ErrForbidden) {
			t.Errorf("%s on a mirror: want forbidden, got %v", op.name, err)
		}
	}
	got, err := r.Invoke(ctx, "repo.get", repoGetIn{Repo: "test"})
	if err != nil {
		t.Fatal(err)
	}
	info := got.(repoInfo)
	if !info.Mirror.Tracking || info.Mirror.URL != "https://upstream.example/home" || info.Mirror.State != MirrorLagging {
		t.Fatalf("repo.get posture: %+v", info.Mirror)
	}

	if _, err := r.Invoke(ctx, "mirror.writes", mirrorWritesIn{Repo: "test", Accept: true}); err != nil {
		t.Fatal(err)
	}
	// (This harness has no store to write through, so the gate is
	// asserted directly once writes are allowed.)
	if ok, _ := (Deps{Mirrors: ms}).Writable("test"); !ok {
		t.Fatal("writes allowed, still refused")
	}

	if _, err := r.Invoke(ctx, "mirror.detach", mirrorDetachIn{Repo: "test"}); err != nil {
		t.Fatal(err)
	}
	got, _ = r.Invoke(ctx, "repo.get", repoGetIn{Repo: "test"})
	info = got.(repoInfo)
	if info.Mirror.Tracking || info.DetachedFrom != "https://upstream.example/home" {
		t.Fatalf("detached posture: %+v detachedFrom=%q", info.Mirror, info.DetachedFrom)
	}
	if ok, _ := (Deps{Mirrors: ms}).Writable("test"); !ok {
		t.Fatal("a detached store is native and writable")
	}
}

// The web's fleet page calls the mirror ops in process, where no router
// gate runs, so each op asks the letters itself (#318). A site admin with
// no role on the repository may pull it now, an operator act, but never
// reconfigure it, open it to writes or detach it.
func TestMirrorOpsAskTheLettersInProcess(t *testing.T) {
	ms := memMirrors{}
	_ = ms.SetMirror("test", "https://upstream.example/home", 3600)
	pulled := 0
	r := ops.NewRegistry()
	repos := NewRepos(map[string]*Repo{"test": {Index: wikiIndex(t),
		Mirror: func(string) (bool, error) { pulled++; return false, nil }}})
	if err := RegisterAll(r, Deps{Version: "v", Repos: repos, Mirrors: ms,
		Accounts: deedAccounts{admin: "root"},
		CapsFor: func(a, repo string) CapSet {
			if a == "ada" {
				return oltp.CapSet("a")
			}
			return oltp.CapSet("")
		},
	}); err != nil {
		t.Fatal(err)
	}
	for _, c := range []struct {
		op string
		in any
	}{
		{"mirror.set", mirrorSetIn{Repo: "test", URL: "https://elsewhere.example/x", Every: 3600}},
		{"mirror.writes", mirrorWritesIn{Repo: "test", Accept: true}},
		{"mirror.detach", mirrorDetachIn{Repo: "test"}},
	} {
		for _, who := range []string{"root", "grace"} {
			if _, err := r.Invoke(ops.WithUser(context.Background(), who), c.op, c.in); !errors.Is(err, ops.ErrForbidden) {
				t.Errorf("FAIL: %s ran %s on a repository they hold no `a` on: %v", who, c.op, err)
			}
		}
	}
	if m := ms["test"]; !m.Enabled || m.AcceptWrites || m.URL != "https://upstream.example/home" {
		t.Fatalf("FAIL: a refused op changed the mirror: %+v", m)
	}
	if _, err := r.Invoke(ops.WithUser(context.Background(), "ada"), "mirror.writes", mirrorWritesIn{Repo: "test", Accept: true}); err != nil {
		t.Errorf("FAIL: the repository's admin was refused: %v", err)
	}
	if _, err := r.Invoke(ops.WithUser(context.Background(), "root"), "mirror.run", mirrorRunIn{Repo: "test"}); err != nil || pulled != 1 {
		t.Errorf("FAIL: a site admin could not pull a mirror now: %v (pulled %d)", err, pulled)
	}
	if _, err := r.Invoke(ops.WithUser(context.Background(), "grace"), "mirror.run", mirrorRunIn{Repo: "test"}); !errors.Is(err, ops.ErrForbidden) {
		t.Errorf("FAIL: an account with no role pulled a mirror: %v", err)
	}
}