config: keyproxy mpk refs, loop daemon knobs, redmine status map, gitea section

mpk: key refs resolve through the ukrrs/mopac-keyproxy hop ([keyproxy]
url + token_ref, POST /v1/resolve, short in-memory cache); env:/file:/
literal: refs keep working untouched, so the harness runs with or
without keyproxy up. [loop] gains poll_interval_secs + state_dir for the
self-host daemon; [redmine.status_map] (quoted TOML keys) drives status
transitions; [gitea] carries the optional REPORT-commit step, off by
default. All hosts live in harness.toml, none in code.

💘 Generated with Crush

Assisted-by: Crush:glm-5.2
This commit is contained in:
2026-08-28 22:05:41 -05:00
parent 86c39c8fc5
commit c869ac1b06
6 changed files with 596 additions and 9 deletions
+152
View File
@@ -0,0 +1,152 @@
package config
import (
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"strings"
"sync/atomic"
"testing"
)
// fakeKeyProxy mimics ukrrs/mopac-keyproxy POST /v1/resolve: bearer auth,
// {"ref":"mpk-<name>"} in, {"value":...} out.
type fakeKeyProxy struct {
t *testing.T
token string
resolve func(ref string) (string, int)
hits atomic.Int64
srv *httptest.Server
}
func newFakeKeyProxy(t *testing.T, token string) *fakeKeyProxy {
t.Helper()
f := &fakeKeyProxy{t: t, token: token}
f.resolve = func(ref string) (string, int) { return "value-for-" + ref, 200 }
f.srv = httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/v1/resolve" {
http.NotFound(w, r)
return
}
if got := r.Header.Get("Authorization"); got != "Bearer "+f.token {
http.Error(w, `{"error":"unauthorized"}`, http.StatusUnauthorized)
return
}
raw, _ := io.ReadAll(io.LimitReader(r.Body, 1<<20))
var body struct {
Ref string `json:"ref"`
}
if err := json.Unmarshal(raw, &body); err != nil || body.Ref == "" {
http.Error(w, `{"error":"bad_request"}`, http.StatusBadRequest)
return
}
f.hits.Add(1)
value, code := f.resolve(body.Ref)
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(code)
w.Write([]byte(`{"value":"` + value + `"}`))
}))
t.Cleanup(f.srv.Close)
return f
}
func TestKeyResolverMPK(t *testing.T) {
kp := newFakeKeyProxy(t, "kp-token")
cfg := Default()
cfg.KeyProxy.URL = kp.srv.URL
cfg.KeyProxy.TokenRef = "literal:kp-token"
r := NewKeyResolver(cfg)
// Auto-prefix: mpk:redmine -> ref "mpk-redmine" on the wire.
v, err := r.Resolve(context.Background(), "mpk:redmine")
if err != nil {
t.Fatalf("Resolve: %v", err)
}
if v != "value-for-mpk-redmine" {
t.Errorf("value = %q", v)
}
// Explicit full form resolves identically (cache hit, no new call).
v, err = r.Resolve(context.Background(), "mpk:mpk-redmine")
if err != nil || v != "value-for-mpk-redmine" {
t.Errorf("full form = %q err=%v", v, err)
}
if n := kp.hits.Load(); n != 1 {
t.Errorf("keyproxy hits = %d, want 1 (cache must absorb the repeat)", n)
}
// A different ref is a fresh call.
if _, err := r.Resolve(context.Background(), "mpk:litellm"); err != nil {
t.Fatalf("Resolve litellm: %v", err)
}
if n := kp.hits.Load(); n != 2 {
t.Errorf("keyproxy hits = %d, want 2", n)
}
}
func TestKeyResolverLocalRefsStillWork(t *testing.T) {
kp := newFakeKeyProxy(t, "kp-token")
cfg := Default()
cfg.KeyProxy.URL = kp.srv.URL
cfg.KeyProxy.TokenRef = "literal:kp-token"
r := NewKeyResolver(cfg)
t.Setenv("HARNESS_KP_TEST", "envval")
for ref, want := range map[string]string{
"env:HARNESS_KP_TEST": "envval",
"literal:abc": "abc",
} {
if v, err := r.Resolve(context.Background(), ref); err != nil || v != want {
t.Errorf("Resolve(%q) = %q err=%v, want %q", ref, v, err, want)
}
}
if n := kp.hits.Load(); n != 0 {
t.Errorf("local refs must not touch keyproxy, hits = %d", n)
}
}
func TestKeyResolverErrors(t *testing.T) {
kp := newFakeKeyProxy(t, "kp-token")
// No [keyproxy] url: clear error pointing at the config.
cfg := Default()
r := NewKeyResolver(cfg)
_, err := r.Resolve(context.Background(), "mpk:redmine")
if err == nil || !strings.Contains(err.Error(), "no [keyproxy] url") {
t.Errorf("no-url error = %v", err)
}
// Bad token: 401 surfaces, the presented token never does.
cfg = Default()
cfg.KeyProxy.URL = kp.srv.URL
cfg.KeyProxy.TokenRef = "literal:wrong-token"
r = NewKeyResolver(cfg)
_, err = r.Resolve(context.Background(), "mpk:redmine")
if err == nil || !strings.Contains(err.Error(), "401") {
t.Errorf("401 error = %v", err)
}
if strings.Contains(err.Error(), "wrong-token") {
t.Errorf("error leaks token: %v", err)
}
// Unknown ref: 404 with fixed body.
cfg = Default()
cfg.KeyProxy.URL = kp.srv.URL
cfg.KeyProxy.TokenRef = "literal:kp-token"
kp.resolve = func(ref string) (string, int) { return "", 404 }
r = NewKeyResolver(cfg)
_, err = r.Resolve(context.Background(), "mpk:nope")
if err == nil || !strings.Contains(err.Error(), "404") {
t.Errorf("404 error = %v", err)
}
// Hop down: transport error, not a hang or panic.
cfg = Default()
cfg.KeyProxy.URL = "http://127.0.0.1:1"
cfg.KeyProxy.TokenRef = "literal:kp-token"
r = NewKeyResolver(cfg)
_, err = r.Resolve(context.Background(), "mpk:redmine")
if err == nil {
t.Errorf("dead hop should error")
}
}