# 开发数据库 Schema 基线与版本门禁设计规格 - 功能编号:GOV-007 - 规格版本:0.1 - 状态:approved_for_review - 日期:2026-08-13 ## 背景与目标 数据库正式启用后,每个新应用版本开始开发前都需要一份可审计的结构起点。只保存迁移脚本不能证明开发数据库在版本开始时的真实结构,也无法发现手工改表造成的漂移。 本功能建立强制门禁:开始开发下一个语义化版本前,从开发环境数据库导出当前已发布版本的完整 Schema,规范化、校验并纳入 Git。开发流程和脚本禁止连接、读取或探测生产数据库。 ## 版本与命名 基线按“被备份的当前已发布版本”命名,而不是即将开发的版本。例如开始开发 `v0.0.6` 前,封存 `v0.0.5` 状态: ```text database/schema-baselines/v0.0.5/ ├── schema.sql ├── manifest.yaml └── checksum.sha256 ``` 每个应用版本开始前都生成一次。即使 Schema 未变化,也生成新版本目录,以相同内容校验值证明没有结构漂移。 ## 唯一允许的数据来源 - 只允许读取开发环境数据库。 - 加载开发专用本地配置,要求 `APP_ENV=development`。 - 数据库名固定为 `a_share_analysis_dev`;名称不匹配立即终止。 - 启用真实导出时主机必须为 `127.0.0.1`、`localhost` 或 `::1`;远程开发库必须先通过运维建立本地 SSH 隧道,脚本不接受任意远程目标。 - 禁止通过命令参数覆盖环境类型、数据库名或传入任意 env 文件路径。 - 禁止连接、读取、探测或导出生产数据库;生产备份属于独立运维流程,不进入开发门禁。 - 推荐使用只拥有开发库结构读取和例程查看权限的专用账号,不授予生产访问能力。 即使主机名看似本地,脚本也必须验证环境和数据库名;不能只依赖地址白名单判断安全。 ## 导出范围 使用 MySQL 5.7 客户端 `mysqldump`,仅导出结构,不包含任何表数据。基线必须完整包含: - 数据库表、列、主键、索引、外键与表选项。 - 视图。 - 触发器。 - 存储过程和函数。 - Event Scheduler 事件。 导出命令必须使用 `--no-data --routines --triggers --events`,并使用符合 MySQL 5.7 的选项。执行元数据查询的 `mysql` 客户端和执行导出的 `mysqldump` 客户端必须分别验证为 5.7.x。账号凭据通过开发 env 或受控客户端配置提供,禁止出现在命令参数、日志或清单中。 ## 规范化 原始 `mysqldump` 输出经过确定性规范化后才能进入 Git: - 删除导出时间、完成时间、客户端路径等不稳定注释。 - 删除或规范化环境绑定的 `DEFINER`,避免恢复时绑定个人账号。 - 删除由数据增长产生的 `AUTO_INCREMENT=<当前值>`,保留列的自增属性。 - 统一换行符与文件末尾换行。 - 禁止把主机、端口、账号、密码或客户端配置路径写入 SQL。 - 不改变表、视图、触发器、例程和事件的业务定义。 规范化工具必须通过固定输入/输出测试证明不会误删业务 SQL。 ## 校验与清单 `manifest.yaml` 至少记录: - `application_version`:被备份的已发布版本。 - `git_commit`:该版本标签最终指向的提交。 - `source_environment: development`。 - `database_name: a_share_analysis_dev`。 - MySQL 客户端和服务端精确版本。 - `charset: utf8mb4`。 - `collation: utf8mb4_general_ci`。 - 生成时间与生成工具版本。 - 是否包含表、视图、触发器、例程和事件。 - 规范化 SQL 的 SHA-256。 `checksum.sha256` 使用标准格式记录 `schema.sql` 校验值。流程必须重新计算并验证清单、校验文件和实际 SQL 三者一致。 ## 强制阻断条件 出现以下任一情况,不允许进入下一版本开发: - 当前已发布版本没有 Schema 基线,且数据库已启用。 - `APP_ENV` 不是 `development`。 - 数据库名不是 `a_share_analysis_dev`。 - 检测到生产配置文件、生产环境标识或禁止的连接目标。 - MySQL 客户端或服务端不是 5.7.x。 - 字符集或排序规则不是 `utf8mb4` / `utf8mb4_general_ci`。 - 导出缺少视图、触发器、存储过程/函数或事件的范围声明。 - SQL 包含 `DEFINER`、不稳定导出注释、当前 AUTO_INCREMENT 值或疑似凭据。 - 校验值不一致、目标版本目录已存在且内容不同,或 Git 工作区存在无法解释的 Schema 改动。 禁止覆盖既有版本基线。需要修正时新增带原因的治理记录和修复提交,不静默重写已发布事实。`schema:verify` 是本地内容校验;`governance:start` 还要求基线文件已被 Git 跟踪、工作区无改动、当前分支已推送以及远程发布标签仍指向清单提交。 ## 首次启用与未启用状态 当前 MySQL 尚未启用,因此在开发新版本前允许记录结构备份“不适用”,但必须能证明功能开关为关闭,且不得创建伪造的空 `schema.sql` 冒充数据库基线。 首次启用 MySQL 的版本必须: 1. 通过迁移创建开发库初始结构。 2. 在 MySQL 5.7 开发环境验证字符集与排序规则。 3. 发布时建立首份真实 Schema 基线。 4. 后续每个版本开始前严格执行本门禁。 ## 开发流程位置 下一版本开发前顺序为: 1. 确认当前已发布版本和标签提交。 2. 判断 MySQL 功能开关;未启用则保存可验证的不适用记录。 3. 已启用时从开发数据库导出、规范化并校验完整 Schema。 4. 将当前发布版本基线作为独立中文提交推送 Gitea。 5. 确认工作区干净和远程同步成功。 6. 再创建下一版本 PRD、设计与功能档案,执行 GitNexus 开发前分析。 数据库迁移必须从上一基线在 MySQL 5.7 开发环境正向执行验证。禁止直接修改共享开发表代替迁移脚本。 ## 安全边界 - Schema 基线只含结构,不含业务数据、账号数据或生产数据。 - 导出脚本不得回显秘密,也不得接受密码命令行参数。 - 开发工具和代理无权使用生产 env 或生产数据库验证功能。 - 基线提交前扫描疑似凭据、生产主机、`DEFINER` 和数据 INSERT。 - Schema 基线进入 Git 后视为公开给仓库使用者,任何敏感对象名称或注释都应在数据库设计阶段避免。 ## 实施范围 GOV-007 将实现数据库目录规范、开发 env 模板扩展、确定性 SQL 规范化工具、导出/校验脚本、自动化测试、开发流程门禁和完整追溯档案。由于当前 MySQL 未启用,本功能只验证阻断逻辑、规范化固定样本和“不适用”路径,不连接任何数据库。 ## 验收标准 - 开发流程明确每个应用版本开始前建立上一已发布版本的开发库 Schema 基线。 - 脚本只接受 `development` 和固定开发库名,无法通过普通参数切换到生产配置。 - 导出范围包含表、视图、触发器、存储过程/函数和事件且不含数据。 - 规范化稳定移除时间注释、`DEFINER` 和当前 AUTO_INCREMENT 值,但保留业务 SQL。 - 清单和 SHA-256 格式可自动校验。 - MySQL 5.7、`utf8mb4`、`utf8mb4_general_ci` 不符合时阻断。 - 当前未启用 MySQL 时使用可验证“不适用”记录,不伪造空 Schema。 - 自动化测试、治理门禁、GitNexus 和双 Review 通过。 - 中文提交和对应版本标签精确推送 Gitea。