数据库变更规范闸门 —— 在多 AI 编码平台(Qoder / Claude Code / Codex)环境下,强制约束所有数据库变更操作遵守统一规范。
AI 编码助手在执行数据库操作时,容易出现以下问题:
- 方言混用:PostgreSQL 项目中写出 MySQL 语法,反之亦然
- 违规外键:在 DDL 中使用
FOREIGN KEY/REFERENCES,而项目约定关联关系由应用层维护 - 越权操作:修改工作流引擎(
act_*)、定时任务(qrtz_*)等受保护的框架核心表 - 遗漏归档:执行完 SQL 后没有归档脚本,导致变更历史丢失
- 关键字冲突:字段名/表名使用数据库保留关键字(如
order、group、key)
db-guard 通过 hook 闸门 + 规范流程 的双重机制,在 AI 助手写出 SQL 的瞬间拦截违规,并在流程末端强制归档与回报。
AI 助手写 SQL
│
▼
┌─────────────────────────────────┐
│ PreToolUse Hook(pre 模式) │
│ ── 方言混用?外键?受保护表? ── │
│ 违规 → 阻断并说明原因 │
│ 通过 → 放行执行 │
└─────────────────────────────────┘
│
▼
执行 SQL & 归档到 db/branches/
│
▼
┌─────────────────────────────────┐
│ Stop Hook(stop 模式) │
│ ── 归档完成?回报块输出? ────── │
│ 缺失 → 阻断,要求补齐 │
│ 齐全 → 放行(最多阻断 2 次) │
└─────────────────────────────────┘
| 平台 | PreToolUse 拦截方式 | Stop 事件 | 退出码 |
|---|---|---|---|
| Qoder | stderr 输出原因 | 有 | exit 2 |
| Claude Code | stdout JSON permissionDecision |
有(decision: block) |
exit 0 |
| Codex | stdout JSON permissionDecision |
无(仅清理 flag) | exit 0 |
在 db-guard 源码仓库执行一次:
npm install -g .进入目标项目根目录:
cd your-project
db-guard init # 交互式选择平台 + 配置
db-guard init --tools qoder # 仅安装 Qoder 平台
db-guard init --tools qoder --prefix ops_ --db postgresql # 全非交互安装后会在目标项目中创建:
.db-guard/
├── db_guard.mjs ← hook 闸门脚本
├── skills/db-guard/ ← 规范文档与参考文件
└── tmp/ ← 会话临时文件(已 gitignore)
并为所选平台写入 hook 配置(.qoder/settings.json / .claude/settings.json / .codex/hooks.json)。
db-guard uninstall所有数据库变更必须走完以下流程,由 db-guard/SKILL.md 定义:
| 步骤 | 内容 |
|---|---|
| 0 | 探测方言 — 读 application-local.yaml 的 JDBC URL,不猜 |
| 1 | 生成 SQL — 套用对应方言的建表模板 |
| 2 | 设计自检 — 无外键、无保留关键字、框架字段齐全 |
| 3 | 表前缀权限判定 — 禁止层直接拒绝,需确认层进入步骤 4 |
| 4 | 人工确认 — 展示完整 SQL,等待用户明确同意(仅 infra_* / system_*) |
| 5 | 执行 — 通过 MCP 写工具执行 |
| 6 | 归档 — 写入 db/branches/{branch}/history/,按类型追加到 DDL/DML 汇总文件 |
| 7 | 序列同步 — PostgreSQL 下手动指定 id 的 INSERT 必须追加 setval |
| 8 | 回报块 — 输出 [DB-CHANGE] 固定格式,未输出视为未完成 |
- 无外键 — 关联关系在应用层维护,DDL 中严禁
FOREIGN KEY/REFERENCES - 无保留关键字 — 字段名/表名不得使用 MySQL / PostgreSQL 保留关键字
- 方言不混用 — PostgreSQL 项目中不得出现 MySQL 语法,反之亦然
- DDL/DML 分离 — 两种 SQL 严禁混写在同一归档文件中
- 序列同步 — PG 下手动指定
id的 INSERT 必须追加setval('表名_seq', MAX(id))
| 层级 | 表前缀 | 行为 |
|---|---|---|
| 禁止层 | act_*、flw_*、bpm_*、qrtz_*、yudao_demo* |
即使用户要求也拒绝 |
| 需确认层 | infra_*、system_* |
展示 SQL 并等待用户明确同意 |
| 业务层 | 项目业务前缀(默认 ops_) |
可直接执行,仍需归档 |
db-guard/
├── hook.mjs ← 跨平台 hook 闸门(核心)
├── bin/db-guard.mjs ← CLI 安装工具(npm bin 入口)
├── fixtures.sh ← 回归测试(临时 git 仓库,不接触真实项目)
├── settings.json ← 本仓库的 Qoder hook 配置
├── db-guard/
│ ├── SKILL.md ← 8 步强制流程规范
│ └── references/
│ ├── design-conventions.md ← 双方言建表模板与字段约定
│ ├── protected-tables.md ← 表前缀权限分流规则
│ ├── archive-layout.md ← 归档目录结构与文件模板
│ └── reserved-keywords.md ← MySQL 8.4 + PostgreSQL 18 保留关键字
├── AGENTS.md ← Codex 平台指南
├── CLAUDE.md ← Claude Code 平台指南
└── package.json
bash fixtures.sh hook.mjs在临时 git 仓库中运行,覆盖三平台的输出格式差异与 Stop 阶段校验逻辑。运行后要求 fail=0。
- fail-open — 闸门自身任何异常都放行,绝不因工具 bug 卡死 AI 会话
- 最多阻断 2 次 — Stop 阶段防止与 Agent 形成死循环
- 幂等安装 — 重复执行
db-guard init安全,不产生副作用
MIT