package audit_test import ( "context" "io" "net/http" "net/http/httptest" "strings" "testing" "github.com/mathiasbq/hyperguild/ingestion/internal/audit" "github.com/mathiasbq/hyperguild/ingestion/internal/capture" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestLokiReadyAndPush(t *testing.T) { var pushBody string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.URL.Path { case "/ready": w.WriteHeader(http.StatusOK) case "/loki/api/v1/push": b, _ := io.ReadAll(r.Body) pushBody = string(b) w.WriteHeader(http.StatusNoContent) default: w.WriteHeader(http.StatusNotFound) } })) defer srv.Close() c := audit.NewLokiCentral(srv.URL) require.NotNil(t, c) require.NoError(t, c.Ready(context.Background())) err := c.Push(context.Background(), capture.AuditEntry{ Principal: "koala-cli", EffectiveClassification: "internal", Items: []string{"insight:x"}, }) require.NoError(t, err) assert.Contains(t, pushBody, "streams") assert.Contains(t, pushBody, "koala-cli", "audit entry serialised into the loki line") } func TestLokiReadyFailsWhenDown(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusServiceUnavailable) })) defer srv.Close() require.Error(t, audit.NewLokiCentral(srv.URL).Ready(context.Background())) } func TestLokiNilWhenUnconfigured(t *testing.T) { assert.Nil(t, audit.NewLokiCentral("")) } func TestNtfyNotify(t *testing.T) { var gotBody, gotAuth string srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { b, _ := io.ReadAll(r.Body) gotBody = string(b) gotAuth = r.Header.Get("Authorization") w.WriteHeader(http.StatusOK) })) defer srv.Close() n := audit.NewNtfyNotifier(srv.URL, "ntfy-token") require.NotNil(t, n) require.NoError(t, n.Notify(context.Background(), "audit buffered locally")) assert.Contains(t, gotBody, "audit buffered locally") assert.Equal(t, "Bearer ntfy-token", gotAuth) } func TestNtfyDoesNotLeakTokenOnError(t *testing.T) { srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) { w.WriteHeader(http.StatusInternalServerError) })) defer srv.Close() err := audit.NewNtfyNotifier(srv.URL, "secret-token").Notify(context.Background(), "x") require.Error(t, err) assert.False(t, strings.Contains(err.Error(), "secret-token"), "token must not leak into errors") } func TestNtfyNilWhenUnconfigured(t *testing.T) { assert.Nil(t, audit.NewNtfyNotifier("", "tok")) }