Files
team-go/pkg/slack/agentrun_test.go
zeekay c6dc8ac2f7 Hanzo Team
The Go transactor and account service for Hanzo Team.

History starts here. The previous 107 commits carried the fork's origin in
their messages and their tree, and none of it described this code: the Go
under pkg/transactor is Hanzo's own work implementing a wire protocol, not
a port of anyone's implementation.

pkg/transactor/model.json remains, and remains attributed. It is a compiled
platform model this transactor loads through go:embed, governed by EPL-2.0
and named in NOTICE. Removing it is a replacement project -- a new compiler
and a move off the protocol -- not a deletion.
2026-08-30 17:07:38 -07:00

88 lines
2.9 KiB
Go

package slack
import (
"context"
"encoding/json"
"io"
"net/http"
"net/http/httptest"
"strings"
"testing"
)
// runAgent posts to {base}/v1/agents/{ref}/run with {"input":...} and the USER's
// bearer, and reads the RunResult `output`.
func TestRunAgent_RequestShape(t *testing.T) {
var gotPath, gotAuth, gotCT string
var gotBody map[string]string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
gotPath = r.URL.Path
gotAuth = r.Header.Get("Authorization")
gotCT = r.Header.Get("Content-Type")
raw, _ := io.ReadAll(r.Body)
_ = json.Unmarshal(raw, &gotBody)
_ = json.NewEncoder(w).Encode(map[string]any{
"id": "run_1", "status": "ok", "output": "the answer is 42", "model": "zen",
})
}))
defer srv.Close()
out, err := runAgent(context.Background(), srv.URL, "hanzo", "what is the answer", "at-user")
if err != nil {
t.Fatalf("run: %v", err)
}
if out != "the answer is 42" {
t.Fatalf("output parsed wrong: %q", out)
}
if gotPath != "/v1/agents/hanzo/run" {
t.Fatalf("path wrong: %s", gotPath)
}
if gotAuth != "Bearer at-user" {
t.Fatalf("must carry the USER bearer, got %q", gotAuth)
}
if !strings.HasPrefix(gotCT, "application/json") {
t.Fatalf("content-type: %s", gotCT)
}
if gotBody["input"] != "what is the answer" {
t.Fatalf("body input wrong: %+v", gotBody)
}
}
// team-go must NOT forge X-Org-Id / X-User-Id — the gateway mints them from the
// user bearer (HIP-0026). Sending them would be an untrusted client-supplied org.
func TestRunAgent_NoForgedIdentityHeaders(t *testing.T) {
var org, user string
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
org = r.Header.Get("X-Org-Id")
user = r.Header.Get("X-User-Id")
_ = json.NewEncoder(w).Encode(map[string]any{"status": "ok", "output": "ok"})
}))
defer srv.Close()
if _, err := runAgent(context.Background(), srv.URL, "hanzo", "x", "at"); err != nil {
t.Fatalf("run: %v", err)
}
if org != "" || user != "" {
t.Fatalf("must not forge identity headers, got org=%q user=%q", org, user)
}
}
// A run that executed but the model failed comes back 502 with status!=ok — that
// is surfaced as an error (never a fabricated success).
func TestRunAgent_ErrorRunSurfaced(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusBadGateway)
_ = json.NewEncoder(w).Encode(map[string]any{"status": "error", "error": "model timeout"})
}))
defer srv.Close()
if _, err := runAgent(context.Background(), srv.URL, "hanzo", "x", "at"); err == nil {
t.Fatal("error run must surface an error")
}
}
// A run is never attempted without a user bearer.
func TestRunAgent_RequiresBearer(t *testing.T) {
if _, err := runAgent(context.Background(), "http://unused", "hanzo", "in", ""); err == nil {
t.Fatal("missing bearer must error (never run unauthenticated)")
}
}