From c6059354034ae34f550016b9d020b790e455ba37 Mon Sep 17 00:00:00 2001 From: Citrons <909229731@qq.com> Date: Tue, 18 Aug 2026 00:46:03 +0800 Subject: [PATCH] =?UTF-8?q?docs(GOV-012):=20=E7=A1=AE=E8=AE=A4=E7=BA=AF=20?= =?UTF-8?q?Node=20Schema=20=E5=AF=BC=E5=87=BA=E5=99=A8=E8=AE=BE=E8=AE=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../GOV-012-node-schema-exporter/design.md | 57 ++++++++++++++++ .../gitnexus/before.md | 28 ++++++++ .../gitnexus/impact-plan.md | 36 ++++++++++ .../manifest.yaml | 12 ++++ .../GOV-012-node-schema-exporter/prd.md | 68 +++++++++++++++++++ .../requirements.md | 34 ++++++++++ .../GOV-012-node-schema-exporter/rollback.md | 21 ++++++ .../schema-baseline-waiver.md | 20 ++++++ .../GOV-012-node-schema-exporter/test-plan.md | 32 +++++++++ docs/index.md | 1 + 10 files changed, 309 insertions(+) create mode 100644 docs/features/GOV-012-node-schema-exporter/design.md create mode 100644 docs/features/GOV-012-node-schema-exporter/gitnexus/before.md create mode 100644 docs/features/GOV-012-node-schema-exporter/gitnexus/impact-plan.md create mode 100644 docs/features/GOV-012-node-schema-exporter/manifest.yaml create mode 100644 docs/features/GOV-012-node-schema-exporter/prd.md create mode 100644 docs/features/GOV-012-node-schema-exporter/requirements.md create mode 100644 docs/features/GOV-012-node-schema-exporter/rollback.md create mode 100644 docs/features/GOV-012-node-schema-exporter/schema-baseline-waiver.md create mode 100644 docs/features/GOV-012-node-schema-exporter/test-plan.md diff --git a/docs/features/GOV-012-node-schema-exporter/design.md b/docs/features/GOV-012-node-schema-exporter/design.md new file mode 100644 index 0000000..566b012 --- /dev/null +++ b/docs/features/GOV-012-node-schema-exporter/design.md @@ -0,0 +1,57 @@ +# 纯 Node.js 开发库 Schema 导出器设计 + +## 1. 架构 + +保留 `tools/database/schema-baseline.mjs` 作为治理入口,继续负责固定配置、发布版本、产物构建、历史验证、原子持久化和远程发布核对。新增 `tools/database/mysql2-schema-exporter.mjs`,集中负责连接、元数据读取、`SHOW CREATE`、依赖排序和确定性 SQL 渲染,不把一次业务流程拆成过多小文件。 + +```text +development 配置 + -> schema-baseline 安全边界 + -> mysql2-schema-exporter + -> MySQL 5.7 元数据与 SHOW CREATE + -> 确定性 schema.sql + -> manifest.yaml + checksum.sha256 + -> 原子版本目录 +``` + +根工作区直接声明 `mysql2`,使治理工具拥有明确依赖。`runBaselineGeneration` 和 CLI 入口改为异步,外部 npm 命令保持不变。 + +## 2. format v3 与历史兼容 + +format v3 使用独立字段记录 Node 导出器名称、导出器版本、数据库驱动名称、驱动版本和 MySQL 服务端版本,不复用 v1/v2 的 `mysql_client_version` 或 `mysqldump_client_version` 含义。 + +验证器按 `format_version` 分支:v1/v2 保留现有字段和校验规则;v3 校验新字段。既有目录不得自动升级、格式化或重写。`captured`、`captured_empty` 和 `not_applicable` 状态继续保留。 + +## 3. 对象导出与顺序 + +导出器先从 `information_schema` 获取固定库的对象清单和依赖,再对每个对象执行参数受控的 `SHOW CREATE`: + +1. 基础表按名称排序,保留列、索引、外键、表选项和注释。 +2. 存储过程与函数按类型和名称排序。 +3. 视图依据库内依赖拓扑排序;循环或未知依赖失败。 +4. 触发器按所属表、时机、事件和执行顺序排序。 +5. Event Scheduler 事件按名称排序。 + +例程、触发器和事件使用稳定 `DELIMITER`。标识符只能来自元数据,并统一转义反引号。导出结果删除 `DEFINER`、当前 `AUTO_INCREMENT` 值、时间、主机、用户名和客户端噪声;同一结构必须产生逐字节一致结果。 + +## 4. 完整性与安全 + +导出前后分别计算对象摘要,包含对象类型、名称、依赖和定义可观察版本;摘要不一致表示并发 DDL,命令失败。任何对象无法 `SHOW CREATE`、结果为空或类型未知时禁止跳过。 + +连接只允许固定 development 边界,禁用多语句,使用单连接、超时和对象数量限制。工具只查询元数据和 `SHOW CREATE`,不查询业务表、不锁表、不执行 DDL/DML。密码只存在于内存配置,并在所有路径通过 `finally` 关闭连接。 + +现有 SQL 安全扫描继续拒绝顶层数据操作、连接串、疑似凭据和残留 `DEFINER`;对象体内部合法 DML 通过分隔符解析保留。 + +## 5. 性能与异常恢复 + +Schema 备份不在在线请求路径。使用单连接和有限并发,目标中小型开发库 30 秒内完成;连接、查询、总时长、对象数量或响应大小超过保护值时失败。 + +产物先写入版本父目录中的临时目录,经过 SQL 扫描、对象计数、manifest 和 SHA-256 一致性校验后原子重命名。失败时删除临时目录,既有版本目录禁止覆盖。 + +## 6. 实施迁移 + +GOV-012 因缺少 `v0.0.9` 基线使用用户授权的一次性人工启动记录。实现通过后立即运行新导出器生成并推送 `v0.0.9` 基线,再重新执行自动 `governance:start`,证明后续开发不再依赖本机 MySQL CLI。 + +## 7. 依赖评估 + +选择已有技术栈中的 `mysql2`,避免引入不透明的第三方 dump 包。替代方案包括安装 MySQL 5.7 客户端或远程执行 `mysqldump`,前者在现代 macOS 上难以维护,后者增加 SSH、凭据和远程工具版本风险。退出时可替换 exporter 端口实现,但 format v3 历史基线验证必须永久保留。 diff --git a/docs/features/GOV-012-node-schema-exporter/gitnexus/before.md b/docs/features/GOV-012-node-schema-exporter/gitnexus/before.md new file mode 100644 index 0000000..94145e7 --- /dev/null +++ b/docs/features/GOV-012-node-schema-exporter/gitnexus/before.md @@ -0,0 +1,28 @@ +# GitNexus 开发前基线 + +- 功能编号:GOV-012 +- 记录时间:2026年08月18日 CST +- 分支:main +- 基线提交:`3555b7c2224e` +- 创建方式:用户授权跳过 `v0.0.9` Schema 备份后手工留痕 + +## 工作区 + +```text +(干净) +``` + +## GitNexus 状态 + +```text +Indexed commit: 3555b7c +Current commit: 3555b7c +Status: up-to-date +Nodes: 2,112 +Edges: 2,790 +Flows: 50 +``` + +## 工具限制 + +重新索引后 GitNexus MCP 连接返回 `Transport closed`。该限制不得解释为无影响;影响计划使用现有图谱历史、静态调用点和测试引用形成保守结论,并要求修改代码前重新尝试 MCP upstream impact。 diff --git a/docs/features/GOV-012-node-schema-exporter/gitnexus/impact-plan.md b/docs/features/GOV-012-node-schema-exporter/gitnexus/impact-plan.md new file mode 100644 index 0000000..3347805 --- /dev/null +++ b/docs/features/GOV-012-node-schema-exporter/gitnexus/impact-plan.md @@ -0,0 +1,36 @@ +# GitNexus 开发前影响计划 + +- 功能编号:GOV-012 +- 基线提交:`3555b7c2224e` +- 总体风险:HIGH(版本治理和全部后续开发入口) + +## 直接与间接影响 + +### `runBaselineGeneration` + +- 直接被 Schema CLI 入口和多组单元测试调用;从同步子进程改为异步数据库连接会影响生成命令、测试注入和错误传播。 +- 间接影响 `schema:baseline` 产物以及后续 `schema:verify`、`assertCurrentReleasedBaselinePublished` 和 `governance:start` 的可用性。 +- 控制:保留外部命令,使用可注入假连接先测试,真实开发库只在专项验证中读取。 + +### `assertMysql57Metadata` 与历史验证 + +- 同时服务 captured、captured_empty 和历史目录验证。直接修改现有字段语义会破坏 v1/v2 发布证据。 +- 控制:保留 v1/v2 原验证分支,新增 v3 元数据验证函数或明确格式分支,不原地复用旧客户端字段。 + +### SQL 规范化、对象计数和安全扫描 + +- 新导出器输出不再完全等同 mysqldump 文本,可能影响 `normalizeSchemaSql`、`splitSqlStatements`、对象计数和敏感语句扫描。 +- 控制:用六类对象固定夹具覆盖格式、分隔符、对象体 DML、`DEFINER`、自增值和确定性输出。 + +## 跨模块同步修改 + +- HTTP/OpenAPI、Web API、消息契约、Redis、API、Scheduler、Worker:无运行时影响。 +- 数据库:只读开发库 Schema,不修改迁移、表或数据;生产数据库禁止访问。 +- 依赖:根工作区新增 `mysql2` 直接依赖并更新锁文件,需审计安全、许可证和维护边界。 +- 治理:Schema format 升级、开发流程、代码规范、GOV-007 现行说明和测试必须同步;历史档案保持原文。 +- 测试:Schema 测试是主要影响面,治理测试和完整验证用于确认后续开发入口未回归。 +- 文档:新增 GOV-012 PRD、设计、测试、回退和开发总结,记录 v0.0.9 基线补建结果。 + +## 高风险处置 + +这是全部版本开发的关键路径,风险至少为 HIGH。修改任何相关函数前必须重新执行 GitNexus upstream impact;若 MCP 仍不可用,使用静态调用关系、现有 50 条流程和全量回归交叉验证。历史基线失败、数据语句进入 SQL、生产边界被放宽或自动门禁未恢复时立即停止发布并回退。 diff --git a/docs/features/GOV-012-node-schema-exporter/manifest.yaml b/docs/features/GOV-012-node-schema-exporter/manifest.yaml new file mode 100644 index 0000000..5d43fc3 --- /dev/null +++ b/docs/features/GOV-012-node-schema-exporter/manifest.yaml @@ -0,0 +1,12 @@ +id: GOV-012 +name: 纯 Node.js 开发库 Schema 导出器 +slug: node-schema-exporter +status: approved +owner: project +created_at: 2026-08-18 +requirements: requirements.md +prd: prd.md +design: design.md +implementation_plan: implementation-plan.md +traceability_note: 设计已确认;实施计划需在用户复核书面规格后创建 +release: unreleased diff --git a/docs/features/GOV-012-node-schema-exporter/prd.md b/docs/features/GOV-012-node-schema-exporter/prd.md new file mode 100644 index 0000000..5262f38 --- /dev/null +++ b/docs/features/GOV-012-node-schema-exporter/prd.md @@ -0,0 +1,68 @@ +# 纯 Node.js 开发库 Schema 导出器 PRD + +- 功能编号:GOV-012 +- PRD 版本:0.1 +- 状态:approved +- 日期:2026-08-18 + +## 背景与问题 + +当前 `schema:baseline` 依赖本机 MySQL 5.7.x 的 `mysql` 和 `mysqldump` 可执行文件。开发机无法安装这些客户端时,命令在连接数据库前以 `spawnSync mysql ENOENT` 失败,导致上一发布版本无法形成 Schema 基线,后续 `governance:start` 和版本开发流程持续阻断。 + +项目已经采用 Node.js 22.x、pnpm 和 `mysql2`,不应要求开发机额外安装 MySQL Server,也不应通过 Docker、远程 shell 或非版本化人工导出绕过治理门禁。 + +## 产品目标 + +- 使用纯 Node.js 和 `mysql2` 从固定开发库导出完整、确定性、可验证的 Schema。 +- 保持 `npm run schema:baseline`、`npm run schema:verify` 和 `governance:start` 的外部用法不变。 +- 保留历史 format v1/v2 基线的只读兼容,不重写既有发布证据。 +- 在实现完成后生成并推送 `v0.0.9` 基线,恢复自动版本开发流程。 + +## 范围 + +- 导出表、索引、外键、视图、触发器、存储过程、函数和 Event Scheduler 事件。 +- 新增 format v3 清单,记录 Node 导出器、`mysql2` 驱动和 MySQL 5.7.x 服务端信息。 +- 使用开发环境白名单、对象摘要前后校验、SQL 安全扫描、原子写入和 SHA-256 校验。 +- 为导出、验证、历史兼容、错误恢复和真实空开发库补充测试。 + +## 非目标 + +- 不备份任何表数据。 +- 不连接、探测或读取生产数据库。 +- 不安装 MySQL Server、MySQL CLI、Docker 或远程导出服务。 +- 不修改业务数据库结构、迁移、实体或应用查询。 +- 不把 TypeORM 实体定义当作现有数据库真实结构的替代品。 + +## 用户流程 + +1. 开发者在开发下一版本前运行 `npm run schema:baseline`。 +2. 工具固定读取 development 配置并验证目标库边界。 +3. Node 导出器连接开发库、读取完整对象定义并生成版本目录。 +4. 开发者运行 `npm run schema:verify`,提交并推送该目录。 +5. `governance:start` 核对基线、远程分支和发布标签后允许下一功能开发。 + +## 成功指标 + +- 未安装 `mysql` 和 `mysqldump` 的开发机能够完成真实 Schema 基线生成。 +- 相同结构重复导出产生逐字节一致的 SQL 和 SHA-256。 +- format v1/v2 历史基线继续通过原有验证。 +- 空开发库生成 `captured_empty`,非空开发库生成完整 `schema.sql`。 +- 失败时不留下目标版本目录或半成品。 + +## 验收标准 + +- Given 本机不存在 MySQL CLI,When 执行 `schema:baseline`,Then 工具通过 `mysql2` 连接固定开发库且不调用外部数据库命令。 +- Given 数据库包含所有受支持对象,When 导出完成,Then SQL 包含完整对象定义且不包含数据、凭据和 `DEFINER`。 +- Given 历史 format v1/v2 基线,When 执行 `schema:verify`,Then 继续按原规则通过或失败,文件不被重写。 +- Given 导出期间对象摘要变化,When 执行完成前复核,Then 命令失败并清理临时目录。 +- Given `v0.0.9` 基线已提交推送,When 执行 `governance:start`,Then 不再因本机缺少 MySQL CLI 被阻断。 + +## 风险 + +- `SHOW CREATE` 权限不足会阻断完整导出,必须明确报错,不能跳过对象。 +- 视图依赖和例程分隔符处理错误会降低恢复能力,必须用固定夹具和恢复顺序测试覆盖。 +- 本功能位于版本治理关键路径,任何历史兼容回归都可能阻断全部后续开发。 + +## 发布与回退 + +GOV-012 作为独立治理版本发布。若新导出器不能生成确定性完整结构、历史基线验证回归或 `governance:start` 无法恢复,则不得发布;代码回退到 GOV-012 前提交,已发布的历史基线保持不变。 diff --git a/docs/features/GOV-012-node-schema-exporter/requirements.md b/docs/features/GOV-012-node-schema-exporter/requirements.md new file mode 100644 index 0000000..996cbf4 --- /dev/null +++ b/docs/features/GOV-012-node-schema-exporter/requirements.md @@ -0,0 +1,34 @@ +# 工程需求 + +## 功能需求 + +- `schema:baseline` 不得调用本机 `mysql`、`mysqldump` 或其他外部数据库客户端。 +- 根工作区直接声明并使用固定版本的 `mysql2`,不得从 Server 私有依赖路径加载。 +- 工具只允许 development、`a_share_analysis_dev`、固定开发主机白名单、MySQL 5.7.x、`utf8mb4` 和 `utf8mb4_general_ci`。 +- 使用 `SHOW CREATE` 导出基础表、视图、触发器、存储过程、函数和事件;索引与外键随表定义保存。 +- 视图按库内依赖拓扑排序;循环依赖、未知依赖或对象丢失必须失败。 +- format v3 清单记录导出器和驱动信息;format v1/v2 继续只读验证。 +- 空库仍生成 `captured_empty`,MySQL 未启用仍生成 `not_applicable`,两者不得创建伪造 SQL。 +- 版本目录继续使用临时目录、完整校验后原子重命名,既有目录只允许逐字节幂等复用。 + +## 安全需求 + +- 禁止查询业务表数据,禁止 DDL、DML、多语句、锁表和生产探测。 +- 密码只能从被 Git 忽略的 development 配置读取,不进入异常、日志、清单、SQL 或命令参数。 +- 顶层数据语句、连接串、疑似凭据、残留 `DEFINER` 和环境主机信息必须被拒绝。 +- 对象名只能来自已验证的元数据,并使用 MySQL 标识符转义。 +- 连接必须在所有成功和失败路径关闭。 + +## 性能与稳定性需求 + +- 使用单连接和有限并发,设置连接超时、查询超时、对象数量和响应大小保护。 +- 中小型开发库目标在 30 秒内完成;超时不得保存部分基线。 +- 导出前后读取对象摘要,两次不一致时失败,避免并发 DDL 形成混合快照。 +- 相同输入必须生成确定性顺序、换行、清单和校验值。 + +## 兼容与测试需求 + +- 外部命令名称和参数保持不变。 +- 现有 format v1/v2 夹具、状态和错误边界继续通过。 +- 新增假连接单元测试,不以真实数据库作为普通测试门禁。 +- 实施完成后只对固定开发库执行一次真实 `captured_empty` 或 `captured` 验证,禁止访问生产环境。 diff --git a/docs/features/GOV-012-node-schema-exporter/rollback.md b/docs/features/GOV-012-node-schema-exporter/rollback.md new file mode 100644 index 0000000..4823b38 --- /dev/null +++ b/docs/features/GOV-012-node-schema-exporter/rollback.md @@ -0,0 +1,21 @@ +# 回退方案 + +## 代码回退 + +若纯 Node 导出器出现历史兼容、结构完整性或安全问题,回退 GOV-012 代码提交,恢复原 MySQL CLI 实现。不得删除或改写任何已发布的历史基线。 + +## format v3 处理 + +GOV-012 未发布前生成的 v3 测试产物可以删除并重新生成;一旦随正式版本发布,验证器必须永久保留 v3 只读兼容。回退不能把 v3 清单伪装为 v2。 + +## 数据库边界 + +本功能不修改数据库结构和数据,因此不执行数据库回滚。回退只涉及治理工具、依赖锁文件、文档和未发布的测试产物。 + +## 触发条件 + +- 导出结果缺少任一受支持对象。 +- 相同 Schema 无法稳定生成相同校验值。 +- 历史 v1/v2 基线验证回归。 +- 工具读取业务数据、泄露凭据或可能连接生产环境。 +- `schema:verify` 或 `governance:start` 不能形成闭环。 diff --git a/docs/features/GOV-012-node-schema-exporter/schema-baseline-waiver.md b/docs/features/GOV-012-node-schema-exporter/schema-baseline-waiver.md new file mode 100644 index 0000000..b5f0fec --- /dev/null +++ b/docs/features/GOV-012-node-schema-exporter/schema-baseline-waiver.md @@ -0,0 +1,20 @@ +# v0.0.9 Schema 基线启动例外 + +- 功能编号:GOV-012 +- 日期:2026-08-18 +- 适用范围:仅 GOV-012 开发启动 + +## 原因 + +本机不存在 MySQL 5.7.x `mysql` 与 `mysqldump` 客户端,现有工具在连接数据库前以 `spawnSync mysql ENOENT` 失败。GOV-012 的目标正是移除该本机依赖,因此无法先用旧工具生成 `v0.0.9` 基线再开发修复。 + +## 用户决定 + +用户明确授权本次跳过数据库备份。该授权只用于 GOV-012 启动,不建立通用跳过选项,也不继承到 GOV-012 之后的其他功能。 + +## 限制与补偿 + +- 不伪造空库、SQL、客户端版本或校验摘要。 +- 不连接或探测生产数据库。 +- 使用手工 GitNexus before/impact 记录替代自动 `governance:start` 的启动证据。 +- 新导出器通过后必须优先生成、验证、单独提交并推送 `v0.0.9` 基线,再验证自动门禁恢复。 diff --git a/docs/features/GOV-012-node-schema-exporter/test-plan.md b/docs/features/GOV-012-node-schema-exporter/test-plan.md new file mode 100644 index 0000000..e251735 --- /dev/null +++ b/docs/features/GOV-012-node-schema-exporter/test-plan.md @@ -0,0 +1,32 @@ +# 测试计划 + +## 单元与契约测试 + +- 旧实现下先证明无 MySQL CLI 时失败,再使纯 Node 路径转绿。 +- 假连接覆盖表、视图依赖、触发器、过程、函数、事件和空库。 +- 覆盖 MySQL 5.7.x 成功以及 5.6、8.x、MariaDB、字符集和排序规则失败。 +- 覆盖视图拓扑排序、循环依赖、未知对象、权限不足、空 `SHOW CREATE` 和对象摘要漂移。 +- 覆盖标识符转义、`DEFINER` 清除、当前自增值清除和稳定分隔符。 +- 覆盖顶层数据操作、凭据、连接串和生产标识拒绝;对象体内合法 DML 保留。 +- 覆盖连接成功、查询失败、渲染失败和持久化失败时的连接关闭与临时目录清理。 +- 覆盖相同输入逐字节确定性和 SQL/manifest/checksum 篡改检测。 + +## 历史兼容 + +- 全部 format v1/v2 历史夹具继续验证。 +- format v3 的 `captured`、`captured_empty` 和 `not_applicable` 分支通过。 +- 旧字段不被新格式复用,历史目录不发生内容变化。 +- `governance:start` 继续验证基线已跟踪、已推送、当前分支和远程标签一致。 + +## 真实开发库验证 + +- 只读取 `deploy/env/development/api.env.local` 和固定开发库。 +- 记录服务端版本、字符规则、对象数量、耗时和最终状态,不记录密码、地址或 SQL 正文到聊天和 QA 摘要。 +- 当前为空时生成 `captured_empty`;发现实际对象时生成完整 `captured`,不得按预期强制为空。 +- 运行 `schema:verify`、治理测试、格式、lint、类型检查和完整仓库验证。 + +## 安全与性能 + +- 证明没有子进程数据库客户端调用、业务表数据查询、生产配置读取或多语句执行。 +- 固定夹具验证对象数量、响应大小、查询和总时长保护。 +- 残余风险包括真实库权限差异和并发 DDL;通过失败关闭、摘要复核和人工重跑控制。 diff --git a/docs/index.md b/docs/index.md index c9baeaa..7772197 100644 --- a/docs/index.md +++ b/docs/index.md @@ -48,5 +48,6 @@ - [GOV-009:应用工程脚手架基线](features/GOV-009-application-scaffold-baseline/manifest.yaml) - [GOV-010:开发质量与前后端架构规范](features/GOV-010-development-quality-architecture/manifest.yaml) - [GOV-011:Node 与 MySQL 系列版本约束(v0.0.9)](features/GOV-011-runtime-version-series/manifest.yaml) +- [GOV-012:纯 Node.js 开发库 Schema 导出器](features/GOV-012-node-schema-exporter/manifest.yaml) 功能档案是需求、设计、代码、测试、版本和回退之间的唯一正式关联入口。