Why: Allow consumers to download an immutable module revision without nested source checkouts or local path replacements. Evidence: SELF package tests and the prior canonical-path rejection are recorded in the Dev dependency-workspace task card; remote consumption is replayed against the committed candidate. Impact: Change the module identity and its Go imports while preserving API behavior. Existing historical submodule revisions remain buildable. Refs: Versioned dependencies U1/U3; feature/dependency-workspace
70 lines
2.9 KiB
Go
70 lines
2.9 KiB
Go
package app
|
||
|
||
// EXT-13 红测(提案 2026-10-09-ext-g1-b1-b3 §1):进程内 Host.KnowledgeSearch
|
||
// 的检索面在适配器放行后吃到他人项目的共享知识;未放行保持本人两路、零泄露。
|
||
|
||
import (
|
||
"context"
|
||
"path/filepath"
|
||
"testing"
|
||
|
||
"git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/rag"
|
||
"git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/settings"
|
||
"git-ssh.u1680832.nyat.app/weichen/Agent-System-Backend.git/internal/store"
|
||
core "git-ssh.u1680832.nyat.app/weichen/Agent-System-Core.git"
|
||
)
|
||
|
||
// newExt13Host EXT-13 装配:真实 store + rag 管线 + authz 槽 + inprocHost(bob 视角)。
|
||
func newExt13Host(t *testing.T) (interface {
|
||
KnowledgeSearch(ctx context.Context, projectID core.ID, text string, topK int) ([]core.RetrievalHit, error)
|
||
}, *projectAuthz) {
|
||
t.Helper()
|
||
st, err := store.OpenSQLite(filepath.Join(t.TempDir(), "test.db"))
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
t.Cleanup(func() { st.Close() })
|
||
set := settings.NewService(st)
|
||
pipe := rag.NewPipeline(st, set, nil, nil)
|
||
authz := &projectAuthz{}
|
||
h := inprocHost{caps: hostcaps{st: st, pipe: pipe, set: set, authz: authz}, pluginID: "rdm", owner: "bob"}
|
||
// alice 已发布的项目知识(带 ProjectID;模拟发布状态机产物)。
|
||
if err := st.AddKnowledge(core.KnowledgeDoc{Owner: "alice", ProjectID: "p-1",
|
||
Source: "plugin:rdm", Ref: "ext13-1", Chunk: "EXT13共享独占令牌陈述"}); err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
return h, authz
|
||
}
|
||
|
||
func TestInprocHostKnowledgeSearchShared(t *testing.T) {
|
||
h, authz := newExt13Host(t)
|
||
ctx := context.Background()
|
||
q := core.RetrievalQuery{Text: "EXT13共享独占令牌", TopK: 5}
|
||
|
||
if hits, err := h.KnowledgeSearch(ctx, "", q.Text, q.TopK); err != nil || len(hits) != 0 {
|
||
t.Fatalf("before grant: hits=%d err=%v, want 0(未放行零泄露)", len(hits), err)
|
||
}
|
||
// 适配器放行 bob × p-1 → Host 检索面吃到 alice 的共享命中。
|
||
// (槽为首个注册者生效——切换授权改闭包内变量,不重注册。)
|
||
allowBob := true
|
||
authz.set("rdm", func(owner string, projectID core.ID) (bool, error) {
|
||
return allowBob && owner == "bob" && string(projectID) == "p-1", nil
|
||
})
|
||
hits, err := h.KnowledgeSearch(ctx, "", q.Text, q.TopK)
|
||
if err != nil {
|
||
t.Fatal(err)
|
||
}
|
||
if len(hits) == 0 {
|
||
t.Fatal("after grant: host search got 0 shared hits, want ≥1(EXT-13)")
|
||
}
|
||
// 指定他人 ProjectID 时同样经适配器(发布边界在下游状态机)。
|
||
if hits, err := h.KnowledgeSearch(ctx, "p-1", q.Text, q.TopK); err != nil || len(hits) == 0 {
|
||
t.Fatalf("scoped to shared project: hits=%d err=%v, want ≥1", len(hits), err)
|
||
}
|
||
// 撤销(同一注册内翻转授权)→ 共享命中即停、零泄露。
|
||
allowBob = false
|
||
if hits, err := h.KnowledgeSearch(ctx, "", q.Text, q.TopK); err != nil || len(hits) != 0 {
|
||
t.Fatalf("after revoke: hits=%d err=%v, want 0", len(hits), err)
|
||
}
|
||
}
|