Files
dsh_ai1net_server/交付物/插件建库权限-B档落地-20260923.md
admin ce8e6ceed9 chore(工作区): 纳入版本控制基线(回收 411 MB 过程产物)
回收 411 MB(470 M → 58.8 M),全部经回收站,可恢复:
- 待清理/(146.2 M,含 relay 分片 128 M 与 42 项过程目录)
- tmp/(32.4 M,按接续棒命名的过程临时区)
- .workbuddy/tmp/(39.5 M)
- 4 份 workbuddy.db 冗余副本(101 M,09-23 事故的坏副本 / 抢救产物)
- tmp/im16/gw/centrifugo 二进制(63.9 M,可重下)+ 缓存残留

入库范围:常驻规则(CODEBUDDY.md / README.md / state.py)、在途接续入口与
接续包、docs/、交付物/、交接单/、归档/、scripts/、.codebuddy/、
.workbuddy/memory/;共 398 件,其中 >60 KB 的 26 件全为文档。

排除(.gitignore):tmp/、待清理/、运行态日志与缓存、*.db 与 DB 备份整目录、
打包二进制(*.tar.gz / *.tgz)、记忆修复前备份。
2026-09-24 07:51:03 +08:00

5.1 KiB
Raw Permalink Blame History

B 档落地 · 插件建库权限(角色级授权 CREATEDB)

拍板:2026-09-23 用户原话「B」⇒ 建库通路 = B 档(给 dshs 角色加 CREATEDB)。 状态:✅ 已在 47 落地并通过 11 条验收(2026-09-23 05:4x)。 机位:仅 47(PG 只在 Manager 上;106 无 PG)。 前置件:交付物/建库权限-D档被证伪与修正判定-20260923.md(本档为何取代 D 档)。


一 拍板内容与落地动作

ALTER ROLE dshs CREATEDB;          -- 唯一一句 DDL(幂等)

平台侧建库 = 用现有 dshs 连接、单语句执行:

CREATE DATABASE dshs_pl_<pluginId> OWNER dshs ENCODING 'UTF8' TEMPLATE template0;

🔴 必须单语句、不走事务 —— CREATE DATABASE 不能在事务块内(这是 D 档被证伪的同一条 PG 限制,B 档同样受约束,只是不再需要函数封装)。平台侧用 pg 的非事务执行路径(顶层 client.query('CREATE DATABASE …'),⛔ 不要包在 BEGIN/COMMIT 里)。


二 验收(11 条 · 实测读数)

# 断言 实测 判定
① dshs 可建库 建库成功 ✅
② 重名建库被拒(幂等靠错误码捕获) ERROR: database … already exists ✅
③ 新库属主 = dshs dshs_pl_bselftest/dshs ✅
④ 可连新库并建表 create table 成功 ✅
⑤ 新库内对象归 dshs 表数 = 1 ✅
⑥ 权限精确(须 f|t|f) false|true|false ✅
⑦ ⛔ 未拿到 CREATEROLE t(= 无该权) ✅
⑧ ⛔ 仍非超级用户 t(= 非超管) ✅
⑨ 库名白名单 PG 侧零拦截(建 evil_probe 成功) ⚠️ 见 §三
⑩ 内核表完好 13 ✅
⑪ 现有库未损 2(dshs + postgres) ✅
— 清理后残留 0 | 服务 dshs = active ✅

⑥ 是本档的核心断言:只多出 CREATEDB 一位,rolsuper / rolcreaterole 必须保持 false。


三 🔴 本档的已知代价(必须由平台代码兜住)

⑨ 揭示了 B 档的真实缺口:PG 侧没有"只允许建 dshs_pl_* 前缀库"的原生机制 ⇒ 白名单只能靠平台代码自觉。这正是 09-22 否掉 A 档的同一条理由,B 档原样继承。

因此平台侧必须强制三点(缺一即为该档的漏洞面):

  1. 库名单点生成 —— 库名只能来自 .dsh 声明的换算函数(包名去 scope、小写、-→_、前缀 dshs_pl_),⛔ 不接受外部传入的任意串。
  2. 建库前正则复校 —— 照抄 D 档那条:^dshs_pl_[a-z][a-z0-9_]{0,40}$,不匹配直接 400,⛔ 不把变量拼进 SQL 字符串(用标识符引用或参数化)。
  3. 每次建库落台账 + 审计 —— 写 plugin_datastores(库名 / 插件 ID / 建库时间 / 结果),使"平台到底建过哪些库"可对账;DROP 须 admin 二次确认(DB-03 §六-4)。

四 回滚

ALTER ROLE dshs NOCREATEDB;        -- 一句话回滚

影响面:已建好的 dshs_pl_* 库不受影响(属主是 dshs,平台照常建表读写)⇒ 只是新插件建不了库。回滚点 = 平台建库口返回 PG_CREATEDB_MISSING(503)。


五 ⚠️ 必须同步落的文档(回滚/重建时不能漏)

  1. dsh-server-docs/DEPLOY-本部署.md DB 初始化步骤追加:ALTER ROLE dshs CREATEDB;(标 🔴 用途 = 插件建库;⛔ 不得顺手给 CREATEROLE / SUPERUSER)。
  2. 交接单/插件投放与分库线-①…md —— §五 S4-2 建库 = admin 显式按钮;§十-D1 原文「上传钩子建库」须同步改。
  3. DB-03-插件数据面规范.md —— §三(谁建库)/ §四(何时建)/ §六(台账表 plugin_datastores)。

六 平台侧代码接口

// src/db/plugin-data/datastore.ts
export function pluginDbNameOf(pkgName: string): string          // 纯函数:包名 → dshs_pl_*
export function assertPluginDbName(dbName: string): void         // ^dshs_pl_[a-z][a-z0-9_]{0,40}$

export async function createPluginDatabase(client: PoolClient, dbName: string): Promise<'created' | 'exists'>
// 错误映射(供路由层用):
//   PG 42P04 duplicate_database  ⇒ 'exists'(幂等,非错误)
//   PG 42501 权限不足            ⇒ 503 PG_CREATEDB_MISSING(未授 CREATEDB / 已回滚)
//   名称不合白名单               ⇒ 400 invalid_plugin_db_name(平台侧复校,⛔ 不下发到 PG)

错误码变更:D 档的 PLUGIN_DB_HELPER_MISSING 随档位作废,恢复为 PG_CREATEDB_MISSING。


七 未做(具名原因)

项 原因
平台侧代码实现(§六) 属交接单 §五 S4 的代码面,按用户拍板的「A 档排期」= 等 IM 线整阶段收官后一次性跑完
§五 三份文档回写 本轮落点已定,但改交接单/DB-03 会与他线共享文件冲突;按 R9 拉长到同一批执行
drop_plugin_database ⛔ 不在本次拍板范围(DB-03 §六-4 将来一并走)