Skip to content

灵桥 Linkora v0.6.0

Choose a tag to compare

@0x0021 0x0021 released this 05 Oct 10:12
· 73 commits to main since this release

修复「启动卡在步骤 4/8」——服务起不来的真凶

本地部署时日志停在「步骤 4/8: 初始化规则引擎… 完成」永不继续、Web 端口从不上线。根因是 embedding.offline=True(用本地缓存、不联网的常见配置)恰好命中「同步直载」分支,把主线程整个卡在读取模型权重上(实测 >50 秒,进程存活但 CPU 0.4%)。离线本该只决定"是否联网",与"是否阻塞启动"无关。现在改为后台加载:启动秒回,模型就绪情况照旧可在后台查询(约 10 秒),Web 不再被模型加载阻塞。

首页「决策追踪」不再停在旧消息

管理后台首页的决策追踪此前取的是最旧两条而非最新——后端按时间正序返回,前端组件却直接取前 N 条。现在排序下沉到组件内部统一处理,最新消息始终在最上方;「意图 & 路由」页同步受益。

关闭鉴权 + 无凭据时不再裸奔写接口

调试时关掉 web.auth_enabled 且未配置凭据,此前即使服务绑定了对外地址,所有写操作(改配置、删数据)与配置导出仍会完全无认证放行。现在这种情况直接拒绝(fail-closed 返回 503);仅本机 / 私网使用时维持原有放行行为,不影响本地免鉴权调试与内网反代部署。

管理后台口令从明文升级为 PBKDF2 哈希

config.yaml 里的 web.auth_password 此前存明文。项目本已内置 PBKDF2 支持但存量配置从未迁移,现提供迁移工具一键升级。登录行为完全不变(校验函数对明文与哈希双兼容),备份先行、明文全程不落盘不打印。

消除 82 处「静默吞噬错误的宽异常」并加门禁防回潮

项目内 640 处 except Exception 中,有 85 处既不记日志也不重新抛出——异常被彻底吞掉,排障时完全看不到线索(本次「启动卡死」被另一条噪音告警淹没就是实例)。现在这 85 处全部补上带完整堆栈的日志,行为不变;并新增 AST 门禁把宽异常总数锁定为「只减不增」,防止回潮。

说明:项目中大量宽异常是正确的防御性容错(配置解析失败即回退默认值、日志格式化失败绝不能崩),本版本刻意未做机械收窄——强行收窄反而会把可容错变成会崩。

性能:每次回复最多省 400 次数据库查询

「意图 & 路由」的少样本推荐原先对每条候选回复单独查一次"前一条用户消息",候选多时每次回复产生最多 400 次查询。现改为一次批量取回 + 二分定位,N+1 降为单次查询,返回值完全不变。

可靠性与数据库

  • 数据库索引自愈:2026-10-05 的生产事故(轮询器持续报 database is locked)真凶是某分库的 idx_conversations_updated 索引损坏(49 行 missing from index),导致每次写入退化为全表扫描重建索引、写锁长期被占。启动时自动检测并重建损坏索引(幂等、不动数据),上线后该错误归零。
  • 孤儿图片回收补 busy_timeout:撞写锁时立即失败会让孤儿图片静默漏回收,现改为等待而非立即失败。
  • 历史导入接口修复:/api/history/import 原先调用一个不存在的脚本(必然失败),现改为进程内执行,与其它导入路径同源。
  • 消息列表读路径不再写库:GET 请求原先会在关键路径内顺手回填图片路径(与业务写抢锁、阻塞响应),现改为请求返回后后台异步回填。

工程门禁

  • ruff 覆盖范围从 38% 扩到全量:此前只扫 src/,web/、tests/、scripts/、main.py 全在门外(web/routers/image.py 的真实崩溃就是这么漏的)。现已全部纳入且当前零违规。
  • CI 补并发控制与超时:连续推送不再叠加完整 CI 作业;任一 job 挂死不会永久占用 runner。
  • 依赖一致性门禁首次真正在 CI 生效:本次即拦下一次自动合并带来的 10 项版本漂移。

依赖与安全

  • 升级 urllib3 至 2.8.0,消除 3 条 Dependabot 告警(2 高危:分块解码无界内存耗尽、HTTPS 代理 TLS 配置被忽略;1 中危:分块解压死循环)。此前 requirements.lock 已是安全版本但 CI 实际消费的是 uv.lock 里的漏洞版本,两份锁文件现已对齐。
  • 清理 config.yaml.example 的出厂口令与失效文档,过期审计报告归档并标注状态。