ci / vet-and-test (pull_request) Successful in 37s
Why: EXT-8 closure needs the vector channel shared (not just fulltext), the /host/v1 knowledge face honoring the authorizer, and citation-ref-to-artifact consistency pinned as an acceptance test. Evidence: TestRetrieveSharedVectorChannel (hash embedder: authorized shared vector hit retrievable, denied yields zero), TestSharedSearchFace (hostapi switches to SharedSearch when wired), TestSharedCitationRefDownloadable (shared hit -> Ref -> artifact content download for the authorized member); go test ./... 32/32 packages ok. Impact: store.SearchKnowledgeVectorsShared; rag.Pipeline.RetrieveShared (own + shared fulltext + shared vector, RRF-merged); server searchKnowledge prefers RetrieveShared when the retriever implements it; hostapi Server.SharedSearch wired in the composition root through the same authorizer slot. Default behavior unchanged. Refs: EXT-8 proposal acceptance; slices 1-2.
50 lines
1.6 KiB
Go
50 lines
1.6 KiB
Go
package hostapi
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
|
|
core "agent-system-core"
|
|
)
|
|
|
|
// EXT-8 余项:hostapi 检索面——SharedSearch 可用时整体切换(本人+适配器放行的
|
|
// 共享追加);不可用时维持现状(仅本人回调)。
|
|
func TestSharedSearchFace(t *testing.T) {
|
|
own := []core.RetrievalHit{{Doc: core.KnowledgeDoc{Owner: "bob", Chunk: "本人命中"}}}
|
|
sharedHit := core.RetrievalHit{Doc: core.KnowledgeDoc{Owner: "alice", ProjectID: "prj-s", Chunk: "共享命中"}}
|
|
|
|
srv := &Server{Token: "t", Search: func(ctx context.Context, owner, text string) ([]core.RetrievalHit, error) {
|
|
return own, nil
|
|
}}
|
|
run := func() int {
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/host/v1/knowledge/search?q=x", nil)
|
|
req.Header.Set("Authorization", "Bearer "+srv.Token)
|
|
srv.Handler().ServeHTTP(rec, req)
|
|
return rec.Code
|
|
}
|
|
if code := run(); code != http.StatusOK {
|
|
t.Fatalf("plain search: %d", code)
|
|
}
|
|
|
|
srv.SharedSearch = func(ctx context.Context, owner, text string) ([]core.RetrievalHit, error) {
|
|
return append(own, sharedHit), nil
|
|
}
|
|
rec := httptest.NewRecorder()
|
|
req := httptest.NewRequest(http.MethodGet, "/host/v1/knowledge/search?q=x", nil)
|
|
req.Header.Set("Authorization", "Bearer "+srv.Token)
|
|
srv.Handler().ServeHTTP(rec, req)
|
|
if rec.Code != http.StatusOK {
|
|
t.Fatalf("shared search: %d %s", rec.Code, rec.Body.String())
|
|
}
|
|
var hits []core.RetrievalHit
|
|
if err := jsonUnmarshal(rec.Body.Bytes(), &hits); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if len(hits) != 2 || hits[1].Doc.Owner != "alice" {
|
|
t.Fatalf("hits = %+v, want 本人+共享", hits)
|
|
}
|
|
}
|