Commit Graph

2 Commits

Author SHA1 Message Date
07d35297a6 fix(webui): 反代三处缺陷 —— 入口不显示、子域链接失效、前缀重定向逃逸
全部来自本机 systemd 实例的实测,不是推测。

1. 插件页「服务入口」永远显示"暂无"
   TABS.plugins.fetch 漏了 proxyServices,而 renderPlugins 第一行就调
   renderProxyServicesCard()(读 state.proxyServices)。于是该页签
   永远不请求 /api/v1/proxy/services —— journalctl 实测:用户正常使用
   期间零请求,只有我手工 curl 的那一条。
   判据 TestProxyServicesReachesPluginsTab 钉住三环(A 调用 B、B 读
   state、C fetch 含块名),已做变异验证(删掉该项立刻红)。
   不用静态调用图做通用依赖检查:实测它在 dashboard.js 上不可靠
   (中文注释引号破坏配平、分发器展开导致大量误报),已在注释里
   写明原因,避免后人重复踩。

2. 面板生成的子域链接 100% 进不了反代
   生成链接走 base_url 的主机名,路由匹配只认 base_domain。
   生产实例 base_url=homeagent.jianfgit.xyz、base_domain=localhost,
   于是链接落到门户 mux → 302 /login,而手拼 *.localhost 反而能进。
   新增 proxyBaseDomains 返回全部候选基域(配置值 → base_url 主机名
   → localhost),serveProxyHost 用它匹配。两者都认,不是二选一:
   *.localhost 是 RFC 6761 的零配置基座,不能丢。

3. 前缀模式下上游根绝对路径重定向逃出挂载点
   实测 NapCat:上游 GET / → 301 Location: /webui,浏览器跟随到
   https://<门户>/webui(已跑出 /napcat),门户 mux 接住 → 302 /login。
   httputil.ReverseProxy 不改写 Location,在 ModifyResponse 里补:
   只改以 / 开头且未带前缀的,避开 //host 与已经带前缀的(否则会出现
   /napcat/napcat/webui)。

顺带纠正:base_domain 保持原配置不动,改由代码兼容两种基域 ——
改配置会抢走别的 *.jianfgit.xyz 子域,且 *.jianfgit.xyz 是单层通配,
huawei-smarthome.homeagent.jianfgit.xyz 本来就证书不匹配(实测
verify error 62)。要外网可用子域形态,应把 base_domain 配成
jianfgit.xyz,那是运维决策,不在本次改动内。
2026-11-04 17:15:43 +08:00
81a0f5f598 feat(security): 插件按工具声明内容策略 + 目录名统一
## 一、插件声明层(用户裁定)

> 「敏感词策略也应该是插件声明啊,每个插件声明自己轮次以及自己工具的
>   敏感词策略」

SecurityProfile 新增两个字段:

  ToolSensitiveWords map[string][]string  // key=工具名模式(尾 *),value=词表
  DetectInjection    bool                 // 开启内核内置注入迹象识别

语义是**追加不覆盖**:整轮 SensitiveWords 仍然生效。
取宽不取窄的理由:当前处置是 B 档(标记+警示,不阻断),
多标一条只是多一句警示,漏标则是安全缺口。

## 二、修掉我自己造的「莲藕式分层」

前一版把 *security.Round 从 runInputTask 一路搬到工具链
(prepareInputTask(evt, round) → TaskFrame.SecRound →
executeToolCallOutcomeWithRound),并在 rtchild 里另补一条。

那是把**分层策略实现成跨层传参**:每多一条工具执行路径就要求调用方
多传一次句柄。profileActivator 的设计注释早就写明了正路:

> 工具调用发生在 LLM 决定之后,此时插件已不在调用栈上。
> 唯一可靠的传递方式是**内核在输入进来时记住**,在该轮的工具判定里使用。

改为 security 自取:

  Runtime.ScanContentForAgent(agentID, isChild, ins, text)
    → ForAgent(agentID, isChild)   // per-agent 视图,天然不串档
    → EffectiveProfile()           // session > longtime
    → 合并 全局词表 + 档位词表 + 工具词表 + DetectInjection

core 只递交**事实**(我是谁 / 哪个工具 / 什么文本),不认识 Round。
与 CheckToolForAgent 同一套身份推断,不引入第二个入口语义。
TaskFrame.SecRound / executeToolCallOutcomeWithRound 全部撤除。

## 三、目录名统一

third_party/homeagent-sdk → third_party/hologramagentsdk

module 与远端仓早已是 hologramagentsdk,只剩物理目录是遗留名。
同步改了 go.mod replace、构建/打包/部署脚本、5 处测试里的分段路径。
注意:这里改的是**主仓 vendored 的 SDK 源码路径**,example/ 由 SDK
独立仓自己跟踪,主仓不涉及。

## 判据

TestToolSensitiveWordsAppendOnlyForThatTool   词表只对目标工具生效 + 追加语义
TestToolSensitiveWordsUseAgentScope           security 按 agent scope 自取生效
(变异验证:删掉 ForAgent 查询 → 红)

## 验证

	go build ./...                 → 0
	go vet ./...                   → 0
	go test ./... -count=1 -race   → 62 ok / 0 FAIL / 0 DATA RACE
	gofmt -l internal/             → 干净
2026-11-03 09:51:11 +08:00