2d0c645ba2
技能正文/脚本/附件此前以节点本地磁盘(SKILLS_ROOT)为权威存储,DB 只存元数据。单机
compose 下 backend 与 backend_worker 恰好 bind-mount 同一个 /app/data 才让它工作;两者
一旦不在同一台宿主机,A 机上传的技能在 B 机 worker 上读不到,而失败是静默的——任务照跑,
只是技能不生效。
根因不在最近那批内置技能提交。F035 设计时就写明了这个约束(035 design.md:580),还留了
「演进为 MinIO 正文 + 本地物化」的出路,但三条后续动作(写进部署文档、启动自检、对象存储
化)一件都没落地——把架构问题降级成了一条没人执行的运维契约。294a0f35b 只是把开箱默认启用
的三个官方技能也接进这条链路,把受害面从「用户自建技能」放大到「所有租户默认就有的技能」。
改为对象存储内容寻址为唯一权威 + 节点按内容哈希本地物化:
- 键 linsight/skills/{tenant_id}/{name}/{content_hash}.zip。哈希算在文件映射上而非打包
字节上:zipfile 写入 time.localtime() 且顺序随 dict 迭代,拿归档字节当版本会让 seeder
每次启动都判定「变了」,重写所有租户所有技能,本地缓存目录每启动一次多一份。
- 哈希进键、而不是固定 {name}.zip:并发编辑时两次 PUT 落在两个对象上,DB 无论哪次 UPDATE
胜出都指向内容匹配的对象。固定键会出现对象留 B、行写 A 的永久分叉且无法自愈。副作用是
彻底不需要 HEAD/etag 探测(etag 在 multipart 下本就不是内容哈希,而上传上限正好 10MB)。
- 写路径不清理旧版本:A 写 hash1、B 写 hash2 时,A 的清理会删掉 B 刚发布且 DB 已指向的
对象——那等于把内容寻址刚消解的竞态请回来。只有 delete(整个技能没了)才按 prefix 全删,
孤儿对象留给 ops 回收。
- 物化是第二条写盘路径,重新 enforce MAX_UNPACKED_SIZE 与 _safe_rel_path:上传路径的两道
闸(在 _parse_upload 与旧 write_bundle 里)都不在这条路上,损坏或被篡改的对象本可以写满
磁盘或写出缓存目录外。
失败不再静默:区分「用户勾了但没加载成功」与「没勾」,前者推一条时间线提示(复用既有 step
通道,未新增 MessageEventType 枚举),三语齐。这正是本次改造的动机——换了存储却不动这里,
MinIO 抖动会以完全相同的方式复现同一个 bug。
顺带修掉:seeder 把所有 DB 异常都当并发竞争(收窄为 IntegrityError,否则连接失败、字段超长
也会被记成「另一副本赢了」);幂等改为比哈希且确认对象存在,保住原先逐字节比对附带的「对象
被误删则下次启动自愈」;skill_service._load_existing_bundle 是全仓唯一一处绕过 Store API 直
拼路径的逃逸;删掉 DORMANT 的 skill_middleware.py 与 built-in/ 死路径(对象存储下这一层语义
不存在,留着就是必然找不到文件的方法)。
存量迁移:ops 脚本为主,每台曾服务过 API 的机器都要跑一次;启动期只做极窄自愈——仅发布本机
确实持有、且字节数与 DB 记录一致的 bundle,其余按技能名报出来。多副本各自看到不同本地盘时,
让谁都能发布自己那份,胜出者就是随机的,那正是这次要消除的东西。回滚需先跑
restore_skills_to_local.py,否则新版本期间创建的技能在旧代码下静默失效。
约束本身上升为架构宪法 C8(禁止本地文件系统承载跨进程共享状态),并补齐 08-deployment.md 的
多节点章节——顺带修掉该文档两处已经写错的表述:它先前声称 SOP 迁移脚本「写对象存储」,实际
写的是本地盘,本次改完才成立。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
BiSheng 文档导航
找文档从这里开始。原则:规范看根目录、架构看
architecture/、功能文档看../features/。
规范(开发前必读)
| 文档 | 内容 |
|---|---|
constitution.md |
架构铁律 C1–C7(双 DB / 多租户 / 权限 / 分层 / 错误码 / 安全)——不可违反 |
SDD-Guide.md |
开发流程总纲:流程分级、★ 暂停点、偏差处理、测试分层、harness 现状 |
../AGENTS.md |
全局 agent 规则入口(各子项目规则按目录自动加载) |
架构(子系统深度)
architecture/ — 13 篇:总览 / 后端模块 / 工作流引擎 / RAG / Linsight / 双前端 / 数据模型 / 部署 / 开发指南 / 权限 ReBAC / 商业网关 / 多租户 / 游标分页 + 数据库表结构。子系统架构的唯一正文。
功能文档(SDD 产出)
../features/ — 按 v{X.Y.Z}/{NNN}-{name}/ 组织,每个功能含 spec.md / design.md / tasks.md(及按需 testcases.md,如 F025)。模板见 ../features/_templates/。
接口 · 测试 · 部署 · 科普
| 目录 | 内容 |
|---|---|
api/ |
接口文档(filelib 纯检索、知识空间/知识库接口) |
PRD/ |
现行迭代的产品 PRD 与技术方案(按 {版本} {主题} PRD/ 组织) |
observability/ |
BS_METRIC 指标日志契约(监控团队解析依据) |
私有化部署/ |
部署文档 |
blog/ |
设计科普(如"企业权限体系的前世今生") |