From 7ba9a81feb6c8969222502afce7f10fd53dd1e31 Mon Sep 17 00:00:00 2001 From: Alan Buscaglia Date: Wed, 27 May 2026 17:04:59 +0200 Subject: [PATCH] fix(store): handle global scope in normalizeScope normalizeScope had no case for "global", silently coercing it to "project". Add "global" alongside "personal" in the switch so mem_save/mem_update/HTTP API callers can create and upsert global observations correctly. Closes #122 --- internal/store/store.go | 8 +++++--- internal/store/store_test.go | 26 ++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/internal/store/store.go b/internal/store/store.go index 362c6061..007ba319 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -5807,10 +5807,12 @@ func truncate(s string, max int) string { func normalizeScope(scope string) string { v := strings.TrimSpace(strings.ToLower(scope)) - if v == "personal" { - return "personal" + switch v { + case "personal", "global": + return v + default: + return "project" } - return "project" } // NormalizeProject applies canonical project name normalization: diff --git a/internal/store/store_test.go b/internal/store/store_test.go index ad84de32..d328cc92 100644 --- a/internal/store/store_test.go +++ b/internal/store/store_test.go @@ -7715,3 +7715,29 @@ func TestGetDeferred_NotFound(t *testing.T) { t.Errorf("expected error to contain 'not found'; got %q", err.Error()) } } + +func TestNormalizeScopeHandlesGlobal(t *testing.T) { + tests := []struct { + input string + want string + }{ + {"global", "global"}, + {"Global", "global"}, + {"GLOBAL", "global"}, + {" global ", "global"}, + {"personal", "personal"}, + {"Personal", "personal"}, + {"project", "project"}, + {"Project", "project"}, + {"", "project"}, + {"unknown", "project"}, + } + for _, tc := range tests { + t.Run(tc.input, func(t *testing.T) { + got := normalizeScope(tc.input) + if got != tc.want { + t.Errorf("normalizeScope(%q) = %q, want %q", tc.input, got, tc.want) + } + }) + } +}