fix(channels): 渠道鉴权头三修 + 源名契约 + 夹具形状判据

P1-1 anthropic 基座补 build_headers(x-api-key + anthropic-version)
  根因:基座只有静态 anthropic-version、没有 build_headers ⇒ 内核兜底发
  Authorization: Bearer,而 Anthropic 协议要 x-api-key。
  ★ 证据冲突(计划 P1-1 原文一半有误):zcode 的
  /zcode-plan/anthropic/v1/messages 虽然**说 Anthropic 协议**,鉴权却是
  Bearer <zcode_jwt>(参考 zcode-transport.ts:121-125;全仓 grep x-api-key
  = 0 次命中)。故 zcode 必须**显式覆盖** build_headers 回到 Bearer,
  否则基座的正向修复会把它从"对"改成"错"。
  内核改动:internal/provider/provider.go —— 兜底 Bearer 让位给 x-api-key,
  避免同一请求带两套鉴权(部分 Anthropic 兼容上游对歧义鉴权直接 401)。

P1-2 channels-cline 的 build_headers 补 workos: 前缀
  根因:参考 cline.ts 发 `Bearer workos:<jwt>`,而池里存的是第二步 register
  换回的裸 token ⇒ 之前无 build_headers,内核兜底发裸 Bearer。
  幂等:已带前缀(含大小写变体)不重复拼。

P1-3 channels-gemini 只确认不改
  参考 gemini.ts:353-366 同样是 OAuth Bearer + 身份五头、刻意不发
  x-goog-api-key ⇒ 我们现状本来就对。加判据把这个结论钉住,防下轮照
  P1-1 的模子把它改坏。

P2 源名契约:仅 [A-Za-z0-9_-],禁 : 与 /
  根因:: 与 / 是限定名分隔符,出现在源名里会让 `源名:模型名` 有两种都
  自圆其说的切法,同一请求串在不同部署下可能路由到不同源,且**不报错**。
  校验加在写入口 core.normalizeSource(硬拒,API 400);启动时只告警,
  避免存量带 : 的源名让升级 brick 掉整个网关。
  解析入口 splitPinned 不做校验(解析不该拒绝已有数据)。

P3 夹具形状判据(本轮最重要的一条)
  根因:trae 的 Result 信封缺陷在扁平夹具下所有判据全绿,真实登录却报
  「缺少 Token」—— 夹具形状错 ⇒ 判据必然虚假通过。
  通用形状层:shapeFamilies 登记表,每族给 real/naive/fact/eval/assert,
  断言 fact(real) 且 !fact(naive) 且 assert(eval(real))。
  刻意**不比较 eval 输出形状**:trae 余额实现合法保留顶层兼容路径,
  拿输出比对会把合法兼容判成错误;能区分真假的是 fact(额度在哪一层)。
  另有仓库扫描:对特征明确的退化形状静态反查,需退化夹具时写 SHAPE-OK 豁免。

判据:11 个文件 / 30 用例。全部变异已验证会报红(9 处)。
This commit is contained in:
JianFeeeee
2026-10-18 00:38:49 +08:00
parent fc5326402f
commit 4174310421
18 changed files with 2194 additions and 36 deletions

View File

@ -0,0 +1,91 @@
package lua
import (
"testing"
)
// ★ P1-3(**只确认不改**):channels-gemini 的「静态身份五头 + 内核兜底 Bearer」
// 本来就是**对的**,不需要像 zcode 那样补 x-api-key。
//
// 这是本轮唯一一个"看起来同型、实际不是缺陷"的渠道,所以把它钉成判据,
// 免得下一轮有人照 P1-1 的模子给它也改一遍(那会把它弄坏)。
//
// 证据链(两条独立来源一致):
//
// ① 参考实现 vendor/channel-pack/src/gemini.ts:353-366 geminiHeaders()
// headers.set('Authorization', `Bearer ${credential.access_token}`)
// 再逐字注入 GEMINI_IDENTITY_HEADERS 五头
// 并**刻意不注入** x-goog-api-key(源注释:原版不带)
// ② 参考 src/gemini.ts:110-117 的 GEMINI_IDENTITY_HEADERS 与我们
// adapter.headers 的五头逐字相同(UA / x-client-name / x-client-version /
// x-machine-id / x-vscode-sessionid)
//
// 也就是说:gemini 走的是 **OAuth Bearer**(Cloud Code 凭据),不是
// Anthropic 那种 x-api-key,也不是 Cline 那种 workos: 前缀。它的鉴权
// 由内核兜底 `Authorization: Bearer <api_key>` 提供 —— 而 gemini 未声明
// credential_shape ⇒ api_key = 凭据里的 access_token ⇒ 兜底值正确。
//
// ⇒ **结论:不改。** 本判据把这个结论钉住:一旦有人给 channels-gemini 加上
//
// build_headers 发别的鉴权头(例如照 zcode 改成 x-api-key),这里会红。
func TestChannelsGeminiAuthIsBearerByDesign(t *testing.T) {
vm, _ := zcodeHarness(t)
// ① 适配器不该自己发鉴权头:静态头里**不得**出现 Authorization /
// x-api-key / x-goog-api-key。鉴权交给内核兜底 Bearer。
hdrs, err := vm.BuildHeaders("channels-gemini", map[string]interface{}{
"api_key": "GA-OAUTH-TOKEN",
"url": "https://cloudcode-pa.googleapis.com/v1internal:generateContent",
"method": "POST",
"body": `{}`,
})
if err != nil {
t.Fatalf("BuildHeaders: %v", err)
}
for _, forbidden := range []string{"Authorization", "x-api-key", "x-goog-api-key"} {
if v, has := hdrs[forbidden]; has {
t.Fatalf("★ channels-gemini 不该自己发 %s(实得 %q)—— "+
"Cloud Code 走 OAuth Bearer,由内核兜底发;"+
"自己发会让它与兜底冲突或改变鉴权方案(P1-3 结论是「不改」)",
forbidden, v)
}
}
// ② 身份五头必须还在(它们是准入条件,与鉴权无关)
for k, want := range map[string]string{
"User-Agent": "antigravity/4.3.0 (cmdc-pak)",
"x-client-name": "antigravity",
"x-client-version": "4.3.0",
"x-machine-id": "cmdc-pak",
"x-vscode-sessionid": "proxy",
} {
if got := hdrs[k]; got != want {
t.Fatalf("身份头 %s 应为 %q,实得 %q(参考 GEMINI_IDENTITY_HEADERS 逐字)", k, want, got)
}
}
t.Logf("✓ channels-gemini 只发身份五头、不自带鉴权(兜底 Bearer 即正确): %v", keysOf(hdrs))
}
// 配对判据:经**内核**装出来的头必须真的是 `Authorization: Bearer <token>`。
//
// 这条在 internal/provider 侧另有一条同型判据(build_headers_fallback_test.go),
// 这里从「适配器没抢鉴权」推到「兜底确实补上了」,把 P1-3 的结论补成闭环。
func TestChannelsGeminiKernelFallbackSendsBearer(t *testing.T) {
vm, _ := zcodeHarness(t)
// 适配器产出:不含任何鉴权头(见上一条)
hdrs, err := vm.BuildHeaders("channels-gemini", map[string]interface{}{
"api_key": "GA-OAUTH-TOKEN",
})
if err != nil {
t.Fatal(err)
}
if _, has := hdrs["Authorization"]; has {
t.Fatalf("适配器不该发 Authorization,实得 %v", hdrs)
}
// 于是内核兜底条件成立(Authorization 与 x-api-key 都为空)⇒ 会补 Bearer。
// 这里断言**条件成立**,而不是重复实现兜底逻辑(兜底本身由 provider 判据咬)。
if hdrs["x-api-key"] != "" {
t.Fatalf("x-api-key 必须为空(否则内核兜底不会补 Bearer),实得 %v", hdrs)
}
t.Log("✓ 适配器不装鉴权 ⇒ 内核兜底条件成立 ⇒ 发 Authorization: Bearer <access_token>")
}