Compare commits

...
10 Commits
22 changed files with 1622 additions and 44 deletions
+2
View File
@@ -30,3 +30,5 @@ CLAUDE.md
*.log *.log
tmp/ tmp/
work/ work/
.worktrees/
.superpowers/
+1 -1
View File
@@ -29,7 +29,7 @@
<!-- gitnexus:start --> <!-- gitnexus:start -->
# GitNexus — Code Intelligence # GitNexus — Code Intelligence
This project is indexed by GitNexus as **a-share-analysis** (2015 symbols, 2692 relationships, 50 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. This project is indexed by GitNexus as **a-share-analysis** (2186 symbols, 2864 relationships, 50 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely.
> If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first. > If any GitNexus tool warns the index is stale, run `npx gitnexus analyze` in terminal first.
+99 -35
View File
@@ -2,19 +2,19 @@
## 1. 用途与适用边界 ## 1. 用途与适用边界
本手册用于 Mac 本地开发期间,按需访问家中 Windows 上仅监听回环地址的 TDX HTTP 接口。链路只用于真实字段核验和只读冒烟,不是生产采集、数据上报或公网部署方案。 本手册用于 Mac 本地开发期间,访问家中 Windows 上仅监听回环地址的 TDX HTTP 接口。TDX 是市场概览的正式行情来源;SSH 隧道负责把家庭局域网和外部 Tailscale 两种开发位置统一成同一个 Mac 回环入口。该链路不是生产采集、数据上报或公网部署方案。
```text ```text
Mac 本地程序 Mac 本地程序 / TDX Bridge
-> 127.0.0.1:17710 -> 127.0.0.1:17710
-> SSH 本地端口转发 -> SSH 本地端口转发
-> Tailscale 私有网络 -> 家庭局域网或 Tailscale 私有网络
-> Windows OpenSSH -> 同一台 Windows OpenSSH
-> Windows 127.0.0.1:17709 -> Windows 127.0.0.1:17709
-> TDX -> TDX
``` ```
日常开发默认使用仓库内固定样本。只有需要验证 TDX 真实协议和字段时才启动本隧道;Windows 离线不得阻塞普通开发、测试或构建。 两个场景只切换 SSH 目标别名,TDX Bridge 和上层业务始终访问 `http://127.0.0.1:17710/`。离线样本只允许作为显式开发和自动化测试回退,并必须标记为离线数据;不得伪装为实时 TDX。Windows 离线不得阻塞普通测试或构建。
## 2. 安全边界 ## 2. 安全边界
@@ -157,20 +157,34 @@ Restart-Service sshd
管理员和非管理员两种方式只选与实际账户匹配的一种。若修改了 `C:\ProgramData\ssh\sshd_config`,先执行 `sshd -t` 校验,再重启服务。 管理员和非管理员两种方式只选与实际账户匹配的一种。若修改了 `C:\ProgramData\ssh\sshd_config`,先执行 `sshd -t` 校验,再重启服务。
## 6. 配置 Mac SSH 别名 ## 6. 配置 Mac SSH 双场景别名
编辑 Mac 的 `~/.ssh/config`,加入: 家庭局域网和外部 Tailscale 连接同一台 Windows、同一个账户和同一个 `sshd`,复用同一把项目专用密钥,不创建第二把 SSH 密钥。编辑 Mac 的 `~/.ssh/config`,加入:
```sshconfig ```sshconfig
Host tdx-windows Host tdx-windows-lan tdx-windows-tailnet
HostName <WINDOWS_TAILSCALE_HOST>
User <WINDOWS_SSH_USER> User <WINDOWS_SSH_USER>
IdentityFile ~/.ssh/tdx_windows IdentityFile ~/.ssh/tdx_windows
IdentitiesOnly yes IdentitiesOnly yes
UseKeychain yes
AddKeysToAgent yes
ServerAliveInterval 30 ServerAliveInterval 30
ServerAliveCountMax 3 ServerAliveCountMax 3
ExitOnForwardFailure yes ExitOnForwardFailure yes
LocalForward 127.0.0.1:17710 127.0.0.1:17709 LocalForward 127.0.0.1:17710 127.0.0.1:17709
Host tdx-windows-lan
HostName <WINDOWS_LAN_HOST>
Host tdx-windows-tailnet
HostName <WINDOWS_TAILSCALE_HOST>
```
真实局域网地址、Tailscale 地址和用户名只保存在本机 SSH 配置,不写入仓库。开发代理需要核对当前配置时使用:
```bash
ssh -G tdx-windows-lan | awk '/^(hostname|user|identityfile|localforward) / {print}'
ssh -G tdx-windows-tailnet | awk '/^(hostname|user|identityfile|localforward) / {print}'
``` ```
然后修正权限: 然后修正权限:
@@ -191,37 +205,70 @@ ssh-keygen -lf "$env:ProgramData\ssh\ssh_host_ed25519_key.pub"
再在 Mac 连接,并确认首次连接提示的 Ed25519 指纹与 Windows 输出一致: 再在 Mac 连接,并确认首次连接提示的 Ed25519 指纹与 Windows 输出一致:
```bash ```bash
ssh -v tdx-windows ssh -v tdx-windows-tailnet
``` ```
预期可以直接登录,或只要求输入私钥口令。若仍要求 Windows 账户密码,重点检查公钥文件位置、ACL、登录账户是否属于 Administrators,以及 SSH 调试输出中实际使用的密钥。 预期可以直接登录,或只要求输入私钥口令。若仍要求 Windows 账户密码,重点检查公钥文件位置、ACL、登录账户是否属于 Administrators,以及 SSH 调试输出中实际使用的密钥。
## 7. 启动和停止隧道 ## 7. 两种场景的选择、启动和停止
### 7.1 前台运行 ### 7.1 选择规则
适合首次验证,按 `Ctrl+C` 停止: | 当前场景 | 使用别名 | 前置条件 |
|---|---|---|
| Mac 与 Windows 位于已配置的家庭局域网 | `tdx-windows-lan` | Windows 在线、TDX 已登录、家庭 LAN 的 SSH 22 可达 |
| Mac 在外部网络,或家庭 LAN SSH 不可达 | `tdx-windows-tailnet` | Mac 与 Windows 的 Tailscale 均在线,Tailnet ping 成功 |
两种隧道不能同时启动,因为都会独占 Mac `127.0.0.1:17710`。在家庭网络内优先使用 LAN;若 LAN 前置检查失败,不修改 TDX 监听地址,改用 Tailscale。
### 7.2 家庭局域网模式
前置检查:
```bash ```bash
ssh -N tdx-windows ssh -o BatchMode=yes -o ClearAllForwardings=yes -T tdx-windows-lan exit
``` ```
### 7.2 后台运行 仓库文档不保存真实地址,家庭路径直接通过 SSH 别名验证。首次连接必须核对局域网地址与已信任的 Tailscale 地址返回相同 Windows 主机密钥指纹。
使用独立控制套接字启动,便于精确停止本项目隧道: 后台启动和检查:
```bash ```bash
ssh -fN -M -S ~/.ssh/tdx-windows-control tdx-windows ssh -fN -M -S ~/.ssh/tdx-windows-lan-control tdx-windows-lan
ssh -S ~/.ssh/tdx-windows-control -O check tdx-windows ssh -S ~/.ssh/tdx-windows-lan-control -O check tdx-windows-lan
``` ```
停止后台隧道: 停止:
```bash ```bash
ssh -S ~/.ssh/tdx-windows-control -O exit tdx-windows ssh -S ~/.ssh/tdx-windows-lan-control -O exit tdx-windows-lan
``` ```
如果控制套接字残留但进程已不存在,先确认 `17710` 没有监听,再删除该单个套接字文件。不要用宽泛的 `pkill ssh`,以免终止其他 SSH 会话。 Windows 的家庭 SSH 防火墙规则应使用项目专用名称 `A-Share-TDX-SSH-LAN`,只允许家庭子网访问 TCP 22。系统原有的全范围 OpenSSH 入站规则保持禁用,不为 TDX 开放 `17709`。
### 7.3 外部 Tailscale 模式
前置检查:
```bash
tailscale up
tailscale ping <WINDOWS_TAILSCALE_HOST>
```
后台启动和检查:
```bash
ssh -fN -M -S ~/.ssh/tdx-windows-tailnet-control tdx-windows-tailnet
ssh -S ~/.ssh/tdx-windows-tailnet-control -O check tdx-windows-tailnet
```
停止:
```bash
ssh -S ~/.ssh/tdx-windows-tailnet-control -O exit tdx-windows-tailnet
```
如果控制套接字残留但进程已不存在,先确认 `17710` 没有监听,再删除对应场景的单个控制套接字。不要用宽泛的 `pkill ssh`,以免终止其他 SSH 会话。
## 8. 验证 TDX 链路 ## 8. 验证 TDX 链路
@@ -266,11 +313,11 @@ curl --fail-with-body --silent --show-error \
1. 确认 Windows 保持开机、联网,Tailscale 和 `sshd` 在线,TDX 已启动并登录。 1. 确认 Windows 保持开机、联网,Tailscale 和 `sshd` 在线,TDX 已启动并登录。
2. Mac 切换到外部网络后重新连接 Tailscale。 2. Mac 切换到外部网络后重新连接 Tailscale。
3. 执行 `tailscale ping <WINDOWS_TAILSCALE_HOST>`。 3. 执行 `tailscale ping <WINDOWS_TAILSCALE_HOST>`。
4. 执行 `ssh -N tdx-windows` 并保持终端运行。 4. 执行 `ssh -N tdx-windows-tailnet` 并保持终端运行。
5. 依次执行 `nc` 和只读 `curl` 冒烟。 5. 依次执行 `nc` 和只读 `curl` 冒烟。
6. 停止隧道,确认 `127.0.0.1:17710` 不再监听。 6. 停止隧道,确认 `127.0.0.1:17710` 不再监听。
如果外网演练失败,日常开发继续使用固定样本。不要临时开放公网 SSH、RDP 或 TDX 端口。 如果外网演练失败,开发和自动化测试可显式切换到离线样本,并明确标记数据来源。不要临时开放公网 SSH、RDP 或 TDX 端口。
## 10. Windows 无人值守准备 ## 10. Windows 无人值守准备
@@ -320,7 +367,7 @@ New-NetFirewallRule `
- Windows 执行 `Get-Service sshd` 和 `Get-NetTCPConnection -LocalPort 22 -State Listen`。 - Windows 执行 `Get-Service sshd` 和 `Get-NetTCPConnection -LocalPort 22 -State Listen`。
- 检查 Windows 防火墙和 Tailscale 访问规则。 - 检查 Windows 防火墙和 Tailscale 访问规则。
- Mac 执行 `ssh -vvv tdx-windows`,确认目标是 Tailscale 地址而非家庭公网地址。 - Mac 执行 `ssh -vvv tdx-windows-tailnet`,确认目标是 Tailscale 地址而非家庭公网地址。
### SSH 仍要求 Windows 密码 ### SSH 仍要求 Windows 密码
@@ -343,35 +390,52 @@ New-NetFirewallRule `
### 外出后 Windows 不在线 ### 外出后 Windows 不在线
- 无法远程唤醒或恢复交互式 TDX 登录时,切回固定样本继续开发。 - 无法远程唤醒或恢复交互式 TDX 登录时,显式切回离线样本继续开发,并保持非实时标记。
- 不通过新增公网暴露、共享密码或关闭防火墙绕过问题。 - 不通过新增公网暴露、共享密码或关闭防火墙绕过问题。
- 待公网部署需求明确后,另立功能实现生产级采集器、心跳、补传和远程运维。 - 待公网部署需求明确后,另立功能实现生产级采集器、心跳、补传和远程运维。
## 13. 日常操作速查 ## 13. 日常操作速查
开始真实 TDX 联调: ### 13.1 在家开发
```bash ```bash
tailscale ping <WINDOWS_TAILSCALE_HOST> ssh -o BatchMode=yes -o ClearAllForwardings=yes -T tdx-windows-lan exit
ssh -fN -M -S ~/.ssh/tdx-windows-control tdx-windows ssh -fN -M -S ~/.ssh/tdx-windows-lan-control tdx-windows-lan
ssh -S ~/.ssh/tdx-windows-control -O check tdx-windows ssh -S ~/.ssh/tdx-windows-lan-control -O check tdx-windows-lan
nc -vz 127.0.0.1 17710 nc -vz 127.0.0.1 17710
``` ```
结束联调: 结束家庭局域网联调:
```bash ```bash
ssh -S ~/.ssh/tdx-windows-control -O exit tdx-windows ssh -S ~/.ssh/tdx-windows-lan-control -O exit tdx-windows-lan
lsof -nP -iTCP:17710 -sTCP:LISTEN lsof -nP -iTCP:17710 -sTCP:LISTEN
``` ```
最后一条命令无输出表示本地转发已经停止。 ### 13.2 在外开发
```bash
tailscale up
tailscale ping <WINDOWS_TAILSCALE_HOST>
ssh -fN -M -S ~/.ssh/tdx-windows-tailnet-control tdx-windows-tailnet
ssh -S ~/.ssh/tdx-windows-tailnet-control -O check tdx-windows-tailnet
nc -vz 127.0.0.1 17710
```
结束外部联调:
```bash
ssh -S ~/.ssh/tdx-windows-tailnet-control -O exit tdx-windows-tailnet
lsof -nP -iTCP:17710 -sTCP:LISTEN
```
最后一条命令无输出表示本地转发已经停止。切换场景时必须先停止当前隧道,再启动另一场景;不得通过更换 TDX Bridge 地址绕过端口冲突。
## 14. 后续 Provider 接入约束 ## 14. 后续 Provider 接入约束
- 平台配置只能引用 Mac 回环地址 `127.0.0.1:17710`,不得保存家庭网络地址。 - 平台配置只能引用 Mac 回环地址 `127.0.0.1:17710`,不得保存家庭网络或 Tailscale 地址。
- 真实 TDX Provider 必须显式启用;默认仍为确定性的固定样本 Provider。 - TDX 是正式行情来源;离线样本只作为显式开发和测试回退,必须展示来源与陈旧状态,生产环境禁止启用。
- Provider 必须限制请求超时、响应体大小、股票数量和并发,并输出来源、采集时间、交易日期、协议版本、追踪 ID 和陈旧状态。 - Provider 必须限制请求超时、响应体大小、股票数量和并发,并输出来源、采集时间、交易日期、协议版本、追踪 ID 和陈旧状态。
- TDX 原始字段仅在 Adapter 内转换,上层市场概览、规则分析和 AI 分析只依赖版本化内部契约。 - TDX 原始字段仅在 Adapter 内转换,上层市场概览、规则分析和 AI 分析只依赖版本化内部契约。
- 隧道中断必须返回明确的不可用或陈旧状态,不能把固定样本伪装成实时行情。 - 隧道中断必须返回明确的不可用或陈旧状态,不能把离线样本伪装成实时行情。
- Windows 采集器、公网接收 API、多目标推送、补传队列和无人值守运维继续延期,实施时单独立项并重新进行安全、性能和合规评估。 - Windows 采集器、公网接收 API、多目标推送、补传队列和无人值守运维继续延期,实施时单独立项并重新进行安全、性能和合规评估。
@@ -0,0 +1,31 @@
# GitNexus 开发前基线
- 功能编号:FEAT-MO-001
- 记录时间:2026年08月18日 00:26:46 CST
- 分支:main
- 基线提交:`c0a6f5560584`
- 创建方式:用户授权跳过 `v0.0.9` Schema 备份后,按 `governance:start` 输出结构手工留痕
## 工作区
```text
(干净)
```
## GitNexus 状态
```text
Repository: /Users/citrons/Documents/Codex/2026-08-12/wo-x/a-share-analysis
Indexed: 8/17/2026, 6:03:13 PM
Indexed commit: c0a6f55
Current commit: c0a6f55
Status: up-to-date
```
## Schema 门禁例外
失败证据、用户决定、禁止伪造边界和残余风险见 `../schema-baseline-waiver.md`。本记录不表示 `governance:start` 自动门禁通过。
## 后续人工分析
首页设计确认后,在修改任何函数、类或方法前继续执行 GitNexus query、context 和 upstream impact,并将直接、间接、跨模块消费者及高风险处置补充到 `impact-plan.md`。
@@ -0,0 +1,36 @@
# GitNexus 开发前影响计划
- 功能编号:FEAT-MO-001
- 基线提交:`c0a6f5560584`
- 当前阶段:TDX 开发连接设计与首页方案确认
- 当前总体风险:LOW(仅本机 SSH 配置和操作文档);首页业务代码风险待设计确认后按符号补充
## 直接与间接影响
### TDX 双路径开发连接
- 正式行情来源确定为 TDX;家庭局域网和外部 Tailscale 只改变 Mac 到同一 Windows `sshd` 的网络路径。
- TDX Bridge 的稳定入口固定为 Mac 回环地址 `127.0.0.1:17710`,市场概览、规则分析、AI 分析和未来 HTTP 契约不得依赖家庭地址、Tailscale 地址或 TDX 原始字段。
- 当前仓库没有 TDX Provider 或市场概览运行时符号,本阶段只更新操作文档;GitNexus 未识别可执行调用链影响。
- 首页业务设计确认后,必须对 `App.vue`、`createAppRouter`、后端模块装配、HTTP DTO 和新增市场概览符号分别执行 upstream impact。HIGH 或 CRITICAL 结果先告知用户再修改。
## 跨模块同步修改
- HTTP/OpenAPI:当前连接文档不修改;首页正式接入时需要版本化市场概览 DTO 与 OpenAPI 契约。
- Web API 与 adapter:当前不修改;未来页面只能经 `web/src/api/<业务域>/index.ts`、Axios 封装和 ViewModel 消费数据。
- 消息契约、Redis、MySQL、Scheduler、Worker:当前不启用。正式采集链路仍按独立功能立项,不能由 API 请求临时抓取全市场数据。
- 配置部署:真实地址、用户名、密钥和控制套接字只保留在开发机,不进入仓库、环境模板或前端构建物。
- 测试:两种 SSH 路径均需验证到同一 Mac 回环端点;离线样本只作显式开发回退,不得标记为实时 TDX。
- 文档:同步更新 Tailscale/SSH 开发手册,明确家庭局域网与外部 Tailscale 的选择、启动、停止、切换和验证方法。
## 安全、性能与回退
- Windows 的 TDX 继续只监听 `127.0.0.1:17709`,禁止改为局域网或公网监听。
- 家庭 SSH 入站规则只允许家庭子网访问 TCP 22;系统原有全范围 OpenSSH 规则保持禁用。
- 两条 SSH 路径复用同一项目专用 Ed25519 密钥;局域网主机密钥必须与已验证的 Tailscale 主机密钥指纹一致。
- 家庭 LAN 与当前 Tailscale 直连延迟均足以满足开发期分钟级行情;首页不得承诺秒级刷新。
- 回退时停止对应 SSH 控制连接、删除本机 TDX 别名,并删除 Windows 项目专用防火墙规则;不得删除通用 SSH 密钥、Tailscale 账户或 TDX 数据。
## Schema 例外风险
`v0.0.9` Schema 基线缺失会阻断严格自动治理门禁,风险见 `../schema-baseline-waiver.md`。本功能不借该例外修改数据库结构、读取生产数据库或声称发布门禁通过。
@@ -0,0 +1,23 @@
# v0.0.9 Schema 基线一次性例外
- 功能编号:FEAT-MO-001
- 日期:2026-08-18
- 适用范围:仅 FEAT-MO-001 开发启动
## 事实记录
按常规流程执行 `npm run schema:baseline` 时,本机因不存在 MySQL 5.7.x 的 `mysql` 与 `mysqldump` 客户端,在执行 `mysql --version` 前以 `spawnSync mysql ENOENT` 失败。失败发生在客户端前置检查阶段,未连接开发数据库,也未生成基线目录或半成品。
用户确认本次继续跳过数据库备份。该决定只适用于从已发布版本 `v0.0.9` 启动 FEAT-MO-001,不继承 GOV-011 对 `v0.0.8` 的一次性例外,也不建立通用跳过能力。
## 处理决定
- 不伪造 `not_applicable`、`captured_empty`、空 SQL、客户端版本、服务端版本或校验摘要。
- 不修改 Schema 工具或 `governance:start` 增加跳过参数。
- 手工保存与 `governance:start` 同等结构的 GitNexus 开发前基线和影响计划。
- FEAT-MO-001 不得因此连接、探测或读取生产数据库。
- 后续功能需要 Schema 基线时,仍必须提供可验证的 MySQL 5.7.x 客户端,或再次获得用户针对该版本的明确授权。
## 风险与接受
缺少 `v0.0.9` Schema 基线意味着仓库不能证明该发布版本对应的开发库结构,也会使依赖严格 Schema 证据的自动治理门禁无法通过。用户接受本次追溯风险;该例外不表示数据库门禁、发布门禁或未来数据库变更已经通过。
@@ -49,6 +49,8 @@
| `54499f0` | `fix(GOV-011): 放宽 MySQL 服务端为完整 5.7 系列` | 已推送 Gitea | | `54499f0` | `fix(GOV-011): 放宽 MySQL 服务端为完整 5.7 系列` | 已推送 Gitea |
| `dc8da80` | `fix(GOV-011): 支持 MySQL 5.7 系列健康检查` | 已推送 Gitea | | `dc8da80` | `fix(GOV-011): 支持 MySQL 5.7 系列健康检查` | 已推送 Gitea |
| `cce77aa` | `docs(GOV-011): 统一运行时系列版本口径` | 已推送 Gitea | | `cce77aa` | `docs(GOV-011): 统一运行时系列版本口径` | 已推送 Gitea |
| `7478a96` | `docs(GOV-011): 完成系列版本验证与审查` | 已推送 Gitea |
| `88e2fdf` | `chore(GOV-011): 发布 v0.0.9 系列版本约束` | 已推送 Gitea,`v0.0.9` 指向该提交 |
## 验证证据 ## 验证证据
@@ -57,3 +59,4 @@
- lint、格式、类型检查、OpenAPI 契约、Web/Server 构建、Playwright 4/4 和源码发布验证通过。 - lint、格式、类型检查、OpenAPI 契约、Web/Server 构建、Playwright 4/4 和源码发布验证通过。
- GitNexus 相对 v0.0.8 检测为 23 个文件、70 个符号、11 条受影响流程、HIGH;运行流仅落在既定 Schema 与健康检查边界,详见 `gitnexus/`。 - GitNexus 相对 v0.0.8 检测为 23 个文件、70 个符号、11 条受影响流程、HIGH;运行流仅落在既定 Schema 与健康检查边界,详见 `gitnexus/`。
- 依赖审计为 0 已知漏洞,Redis 返回 `PONG`;两张视觉截图无溢出或控制台错误。 - 依赖审计为 0 已知漏洞,Redis 返回 `PONG`;两张视觉截图无溢出或控制台错误。
- Gitea `refs/heads/main` 与发布提交 `88e2fdffc8c71dd682405c148a81953a8dcee9d6` 一致;带注释标签对象为 `4d1553b68587a6218416bf0279494d720bb37161`,解引用后指向同一发布提交。
@@ -1,16 +1,16 @@
# GitNexus 开发后基线 # GitNexus 开发后基线
- 索引提交:`cce77aa` - 索引提交:`88e2fdf`
- 索引时间:2026-08-17 17:43(Asia/Shanghai) - 索引时间:2026-08-17 17:58(Asia/Shanghai)
- 状态:up-to-date - 状态:up-to-date
- 节点:2015 - 节点:2090
- 关系:2692 - 关系:2767
- 集群:49 - 集群:49
- 执行流:50 - 执行流:50
## 工作区状态 ## 工作区状态
实现提交均已推送 `origin/main`。索引刷新后仅有 GitNexus 自动更新的 `AGENTS.md` 计数、GOV-011 最终证据和视觉截图等待后续文档提交。 实现、验证和发布提交均已推送 `origin/main`,`v0.0.9` 已精确推送并指向 `88e2fdf`。本次索引刷新只自动更新 `AGENTS.md` 计数,随后与发布引用一起进入追溯提交。
## 运行边界 ## 运行边界
@@ -1,7 +1,7 @@
# GitNexus 前后对比 # GitNexus 前后对比
- before:1894 个符号、2569 条关系、50 条流程(GOV-011 启动记录) - before:1894 个符号、2569 条关系、50 条流程(GOV-011 启动记录)
- after:2015 个节点、2692 条关系、50 条流程(`cce77aa`) - after:2090 个节点、2767 条关系、50 条流程(`88e2fdf`)
- 相对 v0.0.8 detect-changes:23 个文件、70 个符号、11 条受影响流程、HIGH - 相对 v0.0.8 detect-changes:23 个文件、70 个符号、11 条受影响流程、HIGH
## 差异解释 ## 差异解释
@@ -58,6 +58,14 @@
## GitNexus 证据 ## GitNexus 证据
- after:2015 节点、2692 关系、49 集群、50 流程,索引 `cce77aa` 为 up-to-date。 - 发布后 after:2090 节点、2767 关系、49 集群、50 流程,索引 `88e2fdf` 为 up-to-date。
- compare:23 文件、70 符号、11 流程、HIGH;运行影响仅在既有 Schema 与 API 健康路径。 - compare:23 文件、70 符号、11 流程、HIGH;运行影响仅在既有 Schema 与 API 健康路径。
- `AGENTS.md` 的 GitNexus 计数由 `analyze` 自动从 2004/2681 更新为 2015/2692。 - `AGENTS.md` 的 GitNexus 计数在实现和发布两次 `analyze` 中由 2004/2681 更新为 2015/2692,再更新为 2090/2767。
## 发布引用
- 发布提交:`88e2fdffc8c71dd682405c148a81953a8dcee9d6`。
- Gitea `refs/heads/main`:发布时与上述提交一致。
- 带注释标签对象:`4d1553b68587a6218416bf0279494d720bb37161`。
- Gitea `refs/tags/v0.0.9^{}`:`88e2fdffc8c71dd682405c148a81953a8dcee9d6`。
- 标签只精确推送一次,未使用批量标签推送、强推或移动标签。
@@ -3,6 +3,8 @@
- 发布版本:v0.0.9 - 发布版本:v0.0.9
- 状态:已发布 - 状态:已发布
- 发布日期:2026-08-17 - 发布日期:2026-08-17
- 发布提交:`88e2fdffc8c71dd682405c148a81953a8dcee9d6`
- 标签:`v0.0.9`(带注释标签,解引用后指向发布提交)
## 调整 ## 调整
@@ -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 历史基线验证必须永久保留。
@@ -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。
@@ -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、生产边界被放宽或自动门禁未恢复时立即停止发布并回退。
File diff suppressed because it is too large Load Diff
@@ -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
@@ -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 前提交,已发布的历史基线保持不变。
@@ -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` 验证,禁止访问生产环境。
@@ -0,0 +1,21 @@
# 回退方案
## 代码回退
若纯 Node 导出器出现历史兼容、结构完整性或安全问题,回退 GOV-012 代码提交,恢复原 MySQL CLI 实现。不得删除或改写任何已发布的历史基线。
## format v3 处理
GOV-012 未发布前生成的 v3 测试产物可以删除并重新生成;一旦随正式版本发布,验证器必须永久保留 v3 只读兼容。回退不能把 v3 清单伪装为 v2。
## 数据库边界
本功能不修改数据库结构和数据,因此不执行数据库回滚。回退只涉及治理工具、依赖锁文件、文档和未发布的测试产物。
## 触发条件
- 导出结果缺少任一受支持对象。
- 相同 Schema 无法稳定生成相同校验值。
- 历史 v1/v2 基线验证回归。
- 工具读取业务数据、泄露凭据或可能连接生产环境。
- `schema:verify` 或 `governance:start` 不能形成闭环。
@@ -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` 基线,再验证自动门禁恢复。
@@ -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;通过失败关闭、摘要复核和人工重跑控制。
+1
View File
@@ -48,5 +48,6 @@
- [GOV-009:应用工程脚手架基线](features/GOV-009-application-scaffold-baseline/manifest.yaml) - [GOV-009:应用工程脚手架基线](features/GOV-009-application-scaffold-baseline/manifest.yaml)
- [GOV-010:开发质量与前后端架构规范](features/GOV-010-development-quality-architecture/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-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)
功能档案是需求、设计、代码、测试、版本和回退之间的唯一正式关联入口。 功能档案是需求、设计、代码、测试、版本和回退之间的唯一正式关联入口。