Files
dsh_ai1net_server/交付物/插件数据面-运行时取数口落地-20260925.md
admin 318430c9e9 chore(工作区): 插件投放与分库线收口入库(第 35 棒 + 22:44 拍板落盘)
范围 = 本线(插件投放与分库线)产物 + 记忆类,共 27 件:
- 接续入口_插件投放与分库线(1 件):§0 新增 22:44 拍板行;§2 第 36 棒范围改 5 步、条件步转无条件
- 交付物(22 件):MCN 数据面接入阶段一/阶段二系列(含 B 案落地与 shadow 读数)、
  P0 修通与移动端真机验收、pnpm-EPERM、两机 lib 差异、共享层台账语义、
  基础插件身份与回滚、插件接入验收、插件数据面取数口、移动端迁包与字号扩面、跨机错误消息
- 记忆(4 件):2026-09-24 / 2026-09-25 日志、MEMORY.md、本棒 automation 执行记录

⛔ 未含他线在途改动(只报告、不代提交):机制层 CODEBUDDY.md / state.py /
.codebuddy/rules/server-ops.md、接续入口_IM线、接续入口_StoryForge验收线、
其余 29 个 automation 目录、docs/规则与载体/、归档/、接续包_*。
2026-09-25 23:06:29 +08:00

7.0 KiB
Raw Permalink Blame History

插件数据面 · 运行时取数口落地(2026-09-25)

一句话:插件会话说的"平台面向插件的数据库接入面没建成、取数这条链路不通"属实; 本单把缺失的那一半(运行时取数)补齐 —— 库建好了但插件读不到写不进,现在通了。 归属线:插件投放与分库线(插件数据面取数口)|会话:aliyun-dsh-server-插件数据面 代码基线:D:\github\dsh_shenxian(生产口径 dshs)|⛔ 未 commit / 未 push / 未部署


一、缺口的真身(先定性,再动手)

层 本单前状态 证据
建库/管理面 ✅ 已建成(09-23) src/db/plugin-data/{schema,diff,datastore}.ts;47 真机建库 created 71 ms
运行时取数 🔴 零实现 ImDataPort 全仓 4 处命中(接口定义 + 引入 + 两个可选字段),无 implements/无实例化;new ImSdkHost() 只在 test/ 出现;全仓无一处传 data: ⇒ 插件调 insert 一律 not-registered
平台替代通路 🔴 无 datastore 系列路由全是 requireAdmin 管理动作,没有业务数据读写口

缺口成因是接缝两不管:IM 线 D 单原话「落成的是 ImDataPort 注入式端口(真库端口属建库面,本棒不越界)」 ⇒ 运行时实现被推给建库面,而建库面只做了管理面。两边都以为对方做。

二、交付物(5 新 + 2 改)

文件 作用
src/db/plugin-data/runtime.ts(新) 端口实现:SQL 生成(标识符一律引用)、归属强制注入、房间 ACL、游标分页、配额、逐次审计、失败具名(⛔ 不抛给插件)
src/db/plugin-data/registry.ts(新) 装配:声明现解(按 TTL 缓存,⛔ 不信记录字段)+ 库名三处一致性校验 + 每插件库连接池(max=2,照定稿 §五)+ 就绪判读
src/web/routes/plugin-data.ts(新) 实例可达的 HTTP 面:/api/im/plugin-data/status + /api/im/data/*(查/计/写/改/删)
sdk/im-plugin-client/index.mjs + package.json(新) 插件侧 SDK v1(REST 面):零依赖、可 vendoring、⛔ 不含平台实现与凭据
test/plugin-data-runtime.test.mjs(新 18 例) 端口判据回归(假执行器,⛔ 不连 PG,可机械复现)
test/im-plugin-client.test.mjs(新 6 例) SDK 契约(头注入 / 失败折形 / 未配置即拒)
package.json(改) 两组新测试挂进 test / verify 清单
src/web/server.ts(改) 注册 pluginDataRoutes(1 行 + 注释)

文档(同批落文):01-规范/08-插件开发与对接规范.md §3-4(重写 —— 插件会话照这节写)| 03-数据库/DB-03-插件数据面规范.md §五(落地状态 + id 语义 + 三条偏差)+ §十(待定项按实况更新)| 01-规范/09-IM插件SDK与扩展点契约.md §3-1、02-架构设计/数据-分库与权威存储架构.md §六(加落地指针)。

三、四条关键判据(本单的"不许含糊")

  1. id = 声明里的第一列(主键是 (归属列, 第一列) 的复合键,无代理 id 列)⇒ 第一列必须选稳定唯一业务键; 该列不可被 patch 改。这条此前没有任何文档写明,是本次从 createTableSql 反推后写进 DB-03 §五 的。
  2. 归属由内核写,插件覆盖不了:scope:user 给他人 user_id ⇒ bad-args;scope:room 必带 room_id 且过成员判定(未注入成员判定 ⇒ fail-closed,不是放行)。
  3. 库名只信平台:台账库名与声明换算不一致即拒(db-name-mismatch)⇒ 防"猜库名"与其后的一切。
  4. 失败具名:契约失败一律 200 + {ok:false,reason,detail}(与 ImDataPort 同形);4xx 只留给身份/就绪。

四、验收证据(可复现)

npm run build                     → rc=0(tsc 干净)
node --test test/plugin-data-runtime.test.mjs   → 18/18 过
node --test test/im-plugin-client.test.mjs      → 6/6 过
node scripts/check-layering.mjs   → ✅ 无新增违规

⚠️ 全量 npm test 现状:567 例中 7 例失败,全部是环境性 spawnSync <git|tar> EBUSY (本例只发生在调用 execFileSync 的子进程上;本单新增的 24 例零失败)。 受影响文件 = test/im-sdk.test.mjs(3 例)+ test/shared-layer-sync.test.mjs(4 例), 与本单改动无关(那两处代码路径本单未碰);在无该限制的环境下应可全绿。

五、权限影响评估(R5:新增对外面,故须出件)

  • 新增面=两个端点族:/api/im/data/*(业务数据读写)+ /api/im/plugin-data/status(只读判读)。
  • 鉴权=会话优先 + 实例凭据补位(与 IM 面同序、同一本 app.imInstanceTokens 登记簿; 头名与拒绝原因码取自 src/im/instance-token.ts,⛔ 不另写字面量)。
  • 可见面收窄三条:① 只有已建库(台账 state='ready')的插件能取数;② 归属列强制注入 ⇒ 越权得 0 行;③ 房间表复用内核成员表,非成员得 0 行。
  • 审计:逐次落 plugin_data_audit(谁 / 自称哪个插件 / 动作 / 表 / 影响行数 / 拒绝原因); ⛔ 不记行内容(不把插件数据抄进平台日志)。
  • 🔴 已知残余:同一用户的实例内,插件 A 可自称插件 B(越不出用户边界)⇒ 补法 = 每插件令牌; 本期以逐次审计兜底(可对账、可追责)。

六、未做(⛔ 不许看成"已闭环")

  1. 🔴 未部署到 47 / 106,未做真机验收 —— 代码与单测就绪 ≠ 生产可用。部署清单: scp 构建产物 → restart dshs → 真机自测四拒一空(写他人 user_id/room 表缺 room_id/ 缺主键列/带 created_at 应各拒;非成员读 room 表应得 0 行)+ 一次成功的 insert + find 回读。
  2. 跨节点形态仍不通:worker 上的实例 → Manager 侧数据面缺"实例→控制面"身份通道(DB-03 §六 自认) ⇒ 当前可用形态 = 同机 / 本机。
  3. 本期未提供:im.data.tx(同库多表事务)、聚合查询、软删 + 30 天保留、memberRooms 接线、 与 agent 同族的写入预算。
  4. 本单刻意不改 src/web/routes/im.ts(IM 线 D 单的验收判据 2 冻结了该文件 diff) ⇒ 鉴权口径在 plugin-data.ts 独立实现。⚠️ 长期成本:IM 线若改鉴权语义,本文件必须同步跟进; 将来要"一份实现两处用",须把鉴权提成 src/web/im-auth.ts 由两边 import(那要先解 D 单那条冻结判据)。

七、下一棒(建议,等排)

部署 + 真机验收(一条,做完即闭环):按上面 §六-1 清单在 47 落地并逐条取证; 若同时排"跨节点",则先做身份通道(属 IM 线 / 序47 的既有缺口,⛔ 不在本单范围)。