From d18fa0dd5977a3aeab1e2a9fbf94250cd1b2c06a Mon Sep 17 00:00:00 2001 From: Mathias Bergqvist Date: Fri, 17 Apr 2026 20:27:02 +0200 Subject: [PATCH] fix(ingestion): validate required query field in Query handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Empty or whitespace-only queries would silently pass through to search, returning meaningless results. Also removed the Domain field from queryRequest — it was accepted but silently ignored since search.Query has no domain parameter, which would confuse callers. Co-Authored-By: Claude Sonnet 4.6 --- ingestion/internal/api/handler.go | 10 +++++++--- ingestion/internal/api/handler_test.go | 11 +++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/ingestion/internal/api/handler.go b/ingestion/internal/api/handler.go index 631710c..e3619da 100644 --- a/ingestion/internal/api/handler.go +++ b/ingestion/internal/api/handler.go @@ -8,6 +8,7 @@ import ( "net/http" "os" "path/filepath" + "strings" "time" "github.com/mathiasbq/hyperguild/ingestion/internal/search" @@ -25,9 +26,8 @@ func NewHandler(brainDir string, logger *slog.Logger) *Handler { } type queryRequest struct { - Query string `json:"query"` - Domain string `json:"domain,omitempty"` - Limit int `json:"limit,omitempty"` + Query string `json:"query"` + Limit int `json:"limit,omitempty"` } type writeRequest struct { @@ -42,6 +42,10 @@ func (h *Handler) Query(w http.ResponseWriter, r *http.Request) { http.Error(w, "invalid JSON", http.StatusBadRequest) return } + if strings.TrimSpace(req.Query) == "" { + http.Error(w, "query is required", http.StatusBadRequest) + return + } if req.Limit == 0 { req.Limit = 5 } diff --git a/ingestion/internal/api/handler_test.go b/ingestion/internal/api/handler_test.go index e153c0a..084cae6 100644 --- a/ingestion/internal/api/handler_test.go +++ b/ingestion/internal/api/handler_test.go @@ -68,6 +68,17 @@ func TestWrite_CreatesRawFile(t *testing.T) { assert.Contains(t, string(content), "Some content.") } +func TestQuery_RequiresQuery(t *testing.T) { + _, h := setup(t) + body, _ := json.Marshal(map[string]any{"limit": 5}) + req := httptest.NewRequest(http.MethodPost, "/query", bytes.NewReader(body)) + rec := httptest.NewRecorder() + + h.Query(rec, req) + + assert.Equal(t, http.StatusBadRequest, rec.Code) +} + func TestWrite_GeneratesFilenameIfAbsent(t *testing.T) { dir, h := setup(t) body, _ := json.Marshal(map[string]any{"content": "auto name"})