package httpapi import ( "context" "knowledge-governance/internal/dobotaiops" "knowledge-governance/internal/qaopsquality" "net/http" "net/http/httptest" "strings" "testing" "time" ) type masterFixtureReader struct { calls int tenant string } func (f *masterFixtureReader) ListRecords(context.Context, dobotaiops.RecordQuery) (dobotaiops.RecordPage, error) { panic("master must never fall back to replaceable mirror/source reads") } func (f *masterFixtureReader) GetRecord(context.Context, string, string) (dobotaiops.Record, error) { panic("master must never fetch the production source") } func (f *masterFixtureReader) Available(context.Context) error { return nil } func (f *masterFixtureReader) Safety() dobotaiops.SourceSafety { return dobotaiops.SourceSafety{} } func (f *masterFixtureReader) MasterQualityStore() *qaopsquality.Store { return nil } func (f *masterFixtureReader) ListMasterRecords(_ context.Context, q dobotaiops.RecordQuery) (dobotaiops.RecordPage, error) { f.calls++ f.tenant = q.Window.TenantKey return dobotaiops.RecordPage{Items: []dobotaiops.Record{}, Columns: []string{"question"}, AsOf: time.Date(2026, 10, 19, 0, 0, 0, 0, time.UTC), LocalRevision: 3}, nil } func (f *masterFixtureReader) GetMasterRecord(_ context.Context, tenant, id string) (dobotaiops.Record, error) { f.calls++ f.tenant = tenant return dobotaiops.Record{ID: id, Question: "fixture master"}, nil } func (f *masterFixtureReader) ReadMasterQualityScope(context.Context, dobotaiops.RecordQuery) (dobotaiops.QualityScope, error) { return dobotaiops.QualityScope{}, nil } func TestQAMasterUsesFixedTenantAndNeverSourceFallback(t *testing.T) { auth := newFakeAuthStore() auth.sessions["fixture-master-admin"] = "usr-boss" reader := &masterFixtureReader{} h, e := NewHandler(Config{Store: &fakeJobStore{}, Auth: &AuthConfig{Store: auth}, QAOps: reader, QAOpsTenantKey: "fixed-master-tenant", Now: func() time.Time { return time.Date(2026, 10, 19, 0, 0, 0, 0, time.UTC) }}) if e != nil { t.Fatal(e) } base := "/api/v1/qa-ops/master/records" for _, c := range []struct { path string cookie bool status int }{{base + "?start=2026-10-05T00:00:00Z&end=2026-10-12T00:00:00Z", true, 200}, {base + "/fixture-id", true, 200}, {base + "?tenant=other", true, 400}, {base, false, 401}} { r := httptest.NewRequest(http.MethodGet, c.path, nil) if c.cookie { r.AddCookie(&http.Cookie{Name: sessionCookieName, Value: "fixture-master-admin"}) } w := httptest.NewRecorder() h.ServeHTTP(w, r) if w.Code != c.status { t.Fatalf("master route %s: got %d, wanted %d", c.path, w.Code, c.status) } if w.Header().Get("Cache-Control") != "no-store" { t.Fatal("master employee data was cacheable") } } if reader.calls != 2 || reader.tenant != "fixed-master-tenant" { t.Fatal("master fixed-tenant read path missing") } r := httptest.NewRequest(http.MethodPost, base+"/fixture-id/reviews", strings.NewReader(`{}`)) r.AddCookie(&http.Cookie{Name: sessionCookieName, Value: "fixture-master-admin"}) w := httptest.NewRecorder() h.ServeHTTP(w, r) if w.Code != 403 { t.Fatal("master review lacked explicit same-origin intent gate", w.Code) } }