1 Commits

Author SHA1 Message Date
a0ab9ddda5 feat(lua): 插件适配器管理桥接(R4-a)—— 安装/改写/删除,支撑 token 轮换
用户需求:插件可安装、运行时修改适配器以支持复杂认证与 token 轮换;
适配器本身不需要持续运行(它是无状态请求级弹性池)。

  插件(长期运行)─定期/事件─> install/update/remove_adapter
                                      │
                                      ▼
                      内核重建该适配器的池(新池先发布,旧池后回收)
                                      │
                                      ▼
                          后续请求自然使用新逻辑

三条安全规则(与 R6 同源):
1. 路径安全:ValidateAdapterName(无穿越/绝对路径/空白)
2. 不得影子内置:插件不能注册与内置同名适配器(运维仍可自行覆盖)
3. 归属可查:owner 表记录每个适配器由谁安装,于是"插件只能改自己装的"
   是可判定的,而非靠约定。没有归属信息时,插件 A 能劫持插件 B 的认证逻辑
   而无法被察觉。

修掉两个开发中暴露的真实缺陷:
1. 池替换窗口:LoadAdapterSource 原先在 v.mu 内先 shutdown 旧池再装新池,
   窗口期内请求拿到 "pool closed"。改为**新池先发布、旧池后回收**。
2. 并发轮换仍失败:多个 goroutine 同时轮换时,单次重试会连续落在刚被下个
   轮换关闭的池上。acquireAcrossSwap 改为按**墙钟**(2s 上限)+1ms 退避
   重试新池 —— 轮换是运维的意图,落在微秒窗口里的请求不该因此失败。
   上限保证适配器真消失时仍会及时报错而非空转。
3. 声明名 vs 注册键:脚本可声明与注册键不同的 name(插件按自己控制的键注册,
   但适配器声明源真正引用的名字)。归属表同时记两个键,删除时一并清理;
   EffectiveAdapterName 在声明名下也能查到池。

测试:11 个(安装/轮换/影子内置/跨插件窃取/碰运维适配器/路径穿越/删除/
归属列举/并发 8×20 压力/语法错误安装即拒/声明名上报)。

注:internal/gateway 的变异测试 harness 拒绝在脏工作区运行(设计如此),
故本提交后它才可运行。
2026-10-11 10:03:43 +08:00