package httpapi import ( "context" "knowledge-governance/internal/qaopsorg" "net/http" "net/http/httptest" "strings" "testing" ) type orgSpy struct { calls int actor string err error } func (s *orgSpy) GetView(context.Context) (qaopsorg.State, error) { s.calls++ return qaopsorg.State{State: "empty"}, s.err } func (s *orgSpy) PreviewRules(context.Context, qaopsorg.SaveRequest) (qaopsorg.State, error) { s.calls++ return qaopsorg.State{}, s.err } func (s *orgSpy) SaveRules(_ context.Context, _ qaopsorg.SaveRequest, actor string) (qaopsorg.State, error) { s.calls++ s.actor = actor return qaopsorg.State{}, s.err } func TestQAOrganizationGuardsIdentityIntentAndErrors(t *testing.T) { spy := &orgSpy{} auth := newFakeAuthStore() auth.sessions["org-admin"] = "usr-boss" auth.sessions["org-viewer"] = "usr-eye" handler, err := NewHandler(Config{Store: &fakeJobStore{}, QAOrg: spy, Auth: &AuthConfig{Store: auth}}) if err != nil { t.Fatal(err) } base := "/api/v1/qa-ops/organization" for _, tc := range []struct { method, path, token, action, origin, body string status int }{ {"GET", base, "", "", "", "", 401}, {"GET", base, "org-viewer", "", "", "", 403}, {"GET", base, "org-admin", "", "", "", 200}, {"GET", base + "?tenant=another", "org-admin", "", "", "", 400}, {"PUT", base + "/regions", "org-admin", "", "", "{}", 403}, {"PUT", base + "/regions", "org-admin", "qa-organization", "https://untrusted.invalid", "{}", 403}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{"updated_by":"forged"}`, 400}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{} {}`, 400}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{}`, 400}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{"directory_id":"d","base_revision":"","rules":null}`, 400}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{"directory_id":"d","rules":[]}`, 400}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{"directory_id":"d","base_revision":"","regions":null,"rules":[]}`, 400}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{"directory_id":"d","base_revision":"","regions":[null],"rules":[]}`, 400}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{"directory_id":"d","base_revision":"","regions":[{"id":"edu","name":null}],"rules":[]}`, 400}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{"directory_id":"d","base_revision":"","rules":[],"rules":[]}`, 400}, {"PUT", base + "/regions", "org-admin", "qa-organization", "", `{"directory_id":"d","base_revision":"","rules":[]}`, 200}, {"POST", base + "/preview", "org-admin", "qa-organization", "", `{"directory_id":"d","base_revision":"","rules":[]}`, 200}, } { req := httptest.NewRequest(tc.method, tc.path, strings.NewReader(tc.body)) if tc.token != "" { req.AddCookie(&http.Cookie{Name: sessionCookieName, Value: tc.token}) } req.Header.Set("X-Governance-Action", tc.action) req.Header.Set("Origin", tc.origin) res := httptest.NewRecorder() handler.ServeHTTP(res, req) if res.Code != tc.status { t.Fatalf("%s %s got %d want %d: %s", tc.method, tc.path, res.Code, tc.status, res.Body.String()) } } if spy.calls != 3 || spy.actor == "" || spy.actor == "forged" { t.Fatalf("invalid requests reached store or actor not stamped: %+v", spy) } spy.err = qaopsorg.ErrConflict req := httptest.NewRequest("PUT", base+"/regions", strings.NewReader(`{"directory_id":"d","base_revision":"","rules":[]}`)) req.AddCookie(&http.Cookie{Name: sessionCookieName, Value: "org-admin"}) req.Header.Set("X-Governance-Action", "qa-organization") res := httptest.NewRecorder() handler.ServeHTTP(res, req) if res.Code != 409 { t.Fatal("stale configuration not reported as conflict") } }