Compare commits

..
13 Commits
67 changed files with 2079 additions and 75 deletions
+1 -1
View File
@@ -29,7 +29,7 @@
<!-- gitnexus:start -->
# GitNexus — Code Intelligence
This project is indexed by GitNexus as **a-share-analysis** (1847 symbols, 2522 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** (2015 symbols, 2692 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.
+12
View File
@@ -4,11 +4,23 @@
## Unreleased
## 0.0.9 - 2026-08-17
- Node.js 运行时约束明确为完整 22.x,不绑定 minor 或 patch。
- MySQL 客户端、mysqldump、服务端和健康检查统一接受完整 5.7.x,不设置最低补丁版本。
- MySQL 健康详情改为展示服务端实际三段版本,字符集、排序规则、库名和东八区时区继续严格校验。
- 系统架构、开发规范、本地开发和 Ubuntu 源码部署手册统一采用系列版本口径,历史版本证据保持原样。
- 用户确认开发库为空并授权 GOV-011 一次性跳过 v0.0.8 Schema 基线;仓库未伪造基线或增加通用绕过开关。
## 0.0.8 - 2026-08-17
- 新增安全、性能、GitNexus 跨模块影响和独立开发总结的可执行治理门禁。
- 约定后端业务模块内按需分层,以及前端 Axios 统一封装、API 分域和 OpenAPI 类型契约。
- 项目生产交付统一为 Ubuntu 源码部署,移除 Dockerfile、Compose、镜像校验和容器测试入口。
- 本地 Redis、MySQL 5.7.42 与 RocketMQ 5.x 均作为外部服务,项目不再提供自动启动或容器兜底。
- 新增源码发布门禁,校验 Web/Server 构建产物与 systemd、Nginx 配置一致性。
- 完成 Vue 3 Web、NestJS API/Scheduler/Worker、OpenAPI 单向契约和最小权限配置的工程基线确认。
- 补充 Tailscale 访问 Windows TDX 的开发操作文档和采集 PoC 前置档案;本版本不实现常驻采集程序。
## 0.0.7 - 2026-08-13
+1 -1
View File
@@ -1 +1 @@
0.0.7
0.0.9
+2 -2
View File
@@ -60,10 +60,10 @@ OpenAPI 负责描述本项目 HTTP 契约,Axios 负责浏览器实际请求。
## 4. 数据库技术基线
- 数据库服务端固定使用 MySQL 5.7.42;开发、测试和生产环境禁止使用其他补丁版本或 MySQL 8.x 代替兼容性验证。
- 数据库服务端统一使用 MySQL 5.7.x;开发、测试和生产环境禁止使用 MySQL 5.6.x、8.x、MariaDB 或其他数据库代替兼容性验证,但不锁定 5.7 系列内的补丁版本。
- 数据库与表默认字符集固定为 `utf8mb4`,排序规则固定为 `utf8mb4_general_ci`。
- 数据库初始化、表结构、连接会话、ORM 配置和迁移脚本必须显式声明或验证该字符集与排序规则,不能依赖服务器默认值。
- 正式启用持久化前,必须在真实 MySQL 5.7 环境验证服务端版本、Schema/表排序规则、迁移和关键查询。
- 正式启用持久化前,必须在真实 MySQL 5.7.x 环境验证服务端版本、Schema/表排序规则、迁移和关键查询。
- 第一阶段市场概览只定义 MySQL Repository 接口并使用内存实现,不启动数据库、不建立生产连接;后续启用时不得改变前端 API 和核心分析契约。
## 5. 当前实施顺序
+2 -2
View File
@@ -1,6 +1,6 @@
# 本地开发环境
本地开发由开发机提供 Node.js 22.x、pnpm 10.25.0 和已开机自启的 Redis `127.0.0.1:6379`。Web、API、Scheduler 与 Worker 全部从源码启动;MySQL 5.7.42 和 RocketMQ 5.x 也是外部服务,项目脚本不负责安装、启动、停止或删除任何基础设施。
本地开发由开发机提供 Node.js 22.x、pnpm 10.25.0 和已开机自启的 Redis `127.0.0.1:6379`。Web、API、Scheduler 与 Worker 全部从源码启动;MySQL 5.7.x 和 RocketMQ 5.x 也是外部服务,项目脚本不负责安装、启动、停止或删除任何基础设施。
## 首次准备
@@ -16,7 +16,7 @@ Redis 必须返回 `PONG`。如果不可达,应先修复开发机外部服务
把 `deploy/env/development/*.env.example` 复制为同目录的 `*.env.local`。四份 local 文件被 Git 忽略:Web 只能含 `VITE_` 公开变量;API、Scheduler、Worker 按最小权限分别读取自己的配置,不共享一份全能 env。
固定开发 MySQL 只允许 `a_share_analysis_dev`,主机必须是回环地址或代码内白名单 `112.192.20.11`,服务端固定为 MySQL 5.7.42,字符集为 `utf8mb4`、排序规则为 `utf8mb4_general_ci`、会话时区为 `+08:00`。Schema 工具和开发检查禁止连接、探测或读取生产库。
固定开发 MySQL 只允许 `a_share_analysis_dev`,主机必须是回环地址或代码内白名单 `112.192.20.11`,服务端必须属于 MySQL 5.7.x 且不限制系列内补丁版本,字符集为 `utf8mb4`、排序规则为 `utf8mb4_general_ci`、会话时区为 `+08:00`。Schema 工具和开发检查禁止连接、探测或读取生产库。
## 启动顺序
@@ -0,0 +1,377 @@
# Tailscale + SSH 隧道访问 TDX 开发手册
## 1. 用途与适用边界
本手册用于 Mac 本地开发期间,按需访问家中 Windows 上仅监听回环地址的 TDX HTTP 接口。链路只用于真实字段核验和只读冒烟,不是生产采集、数据上报或公网部署方案。
```text
Mac 本地程序
-> 127.0.0.1:17710
-> SSH 本地端口转发
-> Tailscale 私有网络
-> Windows OpenSSH
-> Windows 127.0.0.1:17709
-> TDX
```
日常开发默认使用仓库内固定样本。只有需要验证 TDX 真实协议和字段时才启动本隧道;Windows 离线不得阻塞普通开发、测试或构建。
## 2. 安全边界
- 不在路由器上开放或转发 SSH、RDP、`17709`、`17710` 等端口。
- TDX 继续只监听 Windows `127.0.0.1:17709`,不得改为 `0.0.0.0`。
- SSH 使用独立 Ed25519 密钥,不在脚本、仓库、文档或远程 URL 中保存密码和私钥。
- Mac 转发端口只绑定 `127.0.0.1:17710`,不得绑定局域网或所有网卡。
- 真实返回只用于只读验证。日志和测试报告必须脱敏,不保存家庭网络信息、登录信息或无关原始载荷。
- 开发隧道不连接生产数据库、不承担生产采集,也不证明数据源具备商业展示或再分发授权。
文档中的值均为占位符:
- `<WINDOWS_TAILSCALE_HOST>`:Windows 的 Tailscale MagicDNS 名称或 Tailscale IP。
- `<WINDOWS_SSH_USER>`:用于 SSH 登录的 Windows 用户。
- `<MAC_TAILSCALE_IP>`:Mac 的 Tailscale IP,仅在收紧防火墙来源时使用。
## 3. 首次建立 Tailscale 网络
### 3.1 Mac
1. 从 Tailscale 官方渠道安装客户端。
2. 登录项目使用的同一个 Tailnet。
3. 确认菜单栏中的 Tailscale 状态为已连接。
4. 在终端检查本机和节点列表:
```bash
tailscale ip -4
tailscale status
```
### 3.2 Windows
1. 从 Tailscale 官方渠道安装客户端。
2. 登录与 Mac 相同的 Tailnet。
3. 确认 Windows 节点在 Tailscale 管理后台和 Mac 的 `tailscale status` 中均为在线。
4. 在 Windows PowerShell 中检查地址和状态:
```powershell
tailscale ip -4
tailscale status
```
### 3.3 私网连通验证
在 Mac 执行:
```bash
tailscale ping <WINDOWS_TAILSCALE_HOST>
```
只有 Tailscale ping 成功后再排查 SSH。不要用公网 IP 替换占位符,也不要为排障临时开放路由器端口。
## 4. 配置 Windows OpenSSH Server
以下命令在 Windows 管理员 PowerShell 中执行。
### 4.1 安装并启动服务
```powershell
Get-WindowsCapability -Online | Where-Object Name -Like 'OpenSSH.Server*'
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start-Service sshd
Set-Service -Name sshd -StartupType Automatic
Get-Service sshd
```
如果 OpenSSH Server 已安装,`Add-WindowsCapability` 可以跳过。`Get-Service sshd` 应显示服务正在运行且启动类型为自动。
检查端口监听:
```powershell
Get-NetTCPConnection -LocalPort 22 -State Listen
```
### 4.2 确认防火墙规则
OpenSSH 安装通常会创建入站规则。先检查,不要重复创建同名规则:
```powershell
Get-NetFirewallRule -Name 'OpenSSH-Server-In-TCP' -ErrorAction SilentlyContinue
```
首次联调可以保留系统创建的 SSH 规则;链路确认后按第 11 节限制为 Tailscale 来源。不得新增公网端口映射。
## 5. 配置 SSH 密钥登录
### 5.1 在 Mac 生成项目专用密钥
```bash
ssh-keygen -t ed25519 -a 100 -f ~/.ssh/tdx_windows -C "tdx-windows-development"
chmod 600 ~/.ssh/tdx_windows
chmod 644 ~/.ssh/tdx_windows.pub
pbcopy < ~/.ssh/tdx_windows.pub
```
私钥 `~/.ssh/tdx_windows` 只保留在 Mac,不发送给 Windows,也不提交仓库。建议为私钥设置口令,并由 macOS 钥匙串或 `ssh-agent` 管理。
### 5.2 Windows 管理员账户
Windows OpenSSH 默认从 `C:\ProgramData\ssh\administrators_authorized_keys` 读取管理员公钥。必须先创建文件,再设置 ACL;否则 `icacls` 会报“系统找不到指定的文件”。
在管理员 PowerShell 中执行,按提示粘贴刚复制的单行公钥:
```powershell
$authorizedKeys = "$env:ProgramData\ssh\administrators_authorized_keys"
New-Item -ItemType Directory -Force -Path (Split-Path $authorizedKeys)
if (-not (Test-Path $authorizedKeys)) {
New-Item -ItemType File -Path $authorizedKeys
}
$publicKey = Read-Host '粘贴 Mac 的单行 SSH 公钥'
if (-not (Get-Content $authorizedKeys | Where-Object { $_ -eq $publicKey })) {
Add-Content -Path $authorizedKeys -Value $publicKey -Encoding ascii
}
icacls $authorizedKeys /inheritance:r
icacls $authorizedKeys /grant "*S-1-5-18:F" "*S-1-5-32-544:F"
Restart-Service sshd
```
`S-1-5-18` 是 SYSTEM,`S-1-5-32-544` 是本地 Administrators 组。使用 SID 可以避免中文 Windows 的组名本地化问题。
### 5.3 Windows 非管理员账户
非管理员账户使用用户目录下的 `authorized_keys`。在该登录用户自己的 PowerShell 中执行:
```powershell
$sshDirectory = "$env:USERPROFILE\.ssh"
$authorizedKeys = "$sshDirectory\authorized_keys"
New-Item -ItemType Directory -Force -Path $sshDirectory
if (-not (Test-Path $authorizedKeys)) {
New-Item -ItemType File -Path $authorizedKeys
}
$publicKey = Read-Host '粘贴 Mac 的单行 SSH 公钥'
if (-not (Get-Content $authorizedKeys | Where-Object { $_ -eq $publicKey })) {
Add-Content -Path $authorizedKeys -Value $publicKey -Encoding ascii
}
icacls $authorizedKeys /inheritance:r
icacls $authorizedKeys /grant "$($env:USERNAME):F"
Restart-Service sshd
```
管理员和非管理员两种方式只选与实际账户匹配的一种。若修改了 `C:\ProgramData\ssh\sshd_config`,先执行 `sshd -t` 校验,再重启服务。
## 6. 配置 Mac SSH 别名
编辑 Mac 的 `~/.ssh/config`,加入:
```sshconfig
Host tdx-windows
HostName <WINDOWS_TAILSCALE_HOST>
User <WINDOWS_SSH_USER>
IdentityFile ~/.ssh/tdx_windows
IdentitiesOnly yes
ServerAliveInterval 30
ServerAliveCountMax 3
ExitOnForwardFailure yes
LocalForward 127.0.0.1:17710 127.0.0.1:17709
```
然后修正权限:
```bash
chmod 700 ~/.ssh
chmod 600 ~/.ssh/config ~/.ssh/tdx_windows
```
首次连接先验证密钥登录:
先在 Windows 管理员 PowerShell 查看主机公钥指纹:
```powershell
ssh-keygen -lf "$env:ProgramData\ssh\ssh_host_ed25519_key.pub"
```
再在 Mac 连接,并确认首次连接提示的 Ed25519 指纹与 Windows 输出一致:
```bash
ssh -v tdx-windows
```
预期可以直接登录,或只要求输入私钥口令。若仍要求 Windows 账户密码,重点检查公钥文件位置、ACL、登录账户是否属于 Administrators,以及 SSH 调试输出中实际使用的密钥。
## 7. 启动和停止隧道
### 7.1 前台运行
适合首次验证,按 `Ctrl+C` 停止:
```bash
ssh -N tdx-windows
```
### 7.2 后台运行
使用独立控制套接字启动,便于精确停止本项目隧道:
```bash
ssh -fN -M -S ~/.ssh/tdx-windows-control tdx-windows
ssh -S ~/.ssh/tdx-windows-control -O check tdx-windows
```
停止后台隧道:
```bash
ssh -S ~/.ssh/tdx-windows-control -O exit tdx-windows
```
如果控制套接字残留但进程已不存在,先确认 `17710` 没有监听,再删除该单个套接字文件。不要用宽泛的 `pkill ssh`,以免终止其他 SSH 会话。
## 8. 验证 TDX 链路
### 8.1 Windows 本机验证
先确认 TDX 客户端已启动、已登录,接口监听 `127.0.0.1:17709`:
```powershell
Get-NetTCPConnection -LocalAddress 127.0.0.1 -LocalPort 17709 -State Listen
```
端口没有监听时,应先恢复 TDX 客户端;SSH 和 Tailscale 无法替代 TDX 服务本身。
### 8.2 Mac 端口验证
隧道启动后在 Mac 执行:
```bash
nc -vz 127.0.0.1 17710
lsof -nP -iTCP:17710 -sTCP:LISTEN
```
`17710` 的监听进程应为本次 SSH 隧道,不应是其他应用。
### 8.3 只读 HTTP 冒烟
```bash
curl --fail-with-body --silent --show-error \
--connect-timeout 3 \
--max-time 10 \
-H 'Content-Type: application/json' \
-X POST 'http://127.0.0.1:17710/' \
--data '{"id":1,"method":"get_market_data","params":{"stock_list":["600519.SH"],"count":5,"dividend_type":"none","period":"1d"}}'
```
链路验收条件:HTTP 返回成功,且 TDX 业务响应中的错误码表示成功。只验证少量公开行情,不调用交易、账户、自选、写入或大批量接口。
## 9. 外网场景验证
在真正离开家庭网络前,使用 Mac 手机热点或其他外部网络完成一次演练:
1. 确认 Windows 保持开机、联网,Tailscale 和 `sshd` 在线,TDX 已启动并登录。
2. Mac 切换到外部网络后重新连接 Tailscale。
3. 执行 `tailscale ping <WINDOWS_TAILSCALE_HOST>`。
4. 执行 `ssh -N tdx-windows` 并保持终端运行。
5. 依次执行 `nc` 和只读 `curl` 冒烟。
6. 停止隧道,确认 `127.0.0.1:17710` 不再监听。
如果外网演练失败,日常开发继续使用固定样本。不要临时开放公网 SSH、RDP 或 TDX 端口。
## 10. Windows 无人值守准备
当前链路是开发辅助,不承诺生产级 7x24 可用性。为了减少外出后无法联调的概率,可在 Windows 上做以下准备:
- 将虚拟机配置为宿主机启动后自动启动,并确认异常关机后的恢复策略。
- 保持 Tailscale 与 `sshd` 服务自动启动,重启后通过另一台 Tailnet 设备验证在线状态。
- 接通电源时禁用自动睡眠:
```powershell
powercfg /change standby-timeout-ac 0
```
- 明确 TDX 是否需要交互式桌面登录、验证码或人工确认。需要人工登录时,不得把它描述为无人值守服务。
- 安排 Windows 更新和虚拟机重启窗口;更新后重新验证 Tailscale、SSH、TDX 监听和只读请求。
- 不为自动启动把 Windows 密码、TDX 凭据或 SSH 私钥写入仓库和普通脚本。
## 11. 收紧访问范围
链路验证通过后,在 Tailscale 管理后台将访问规则限制为指定开发身份或 Mac 到 Windows SSH 端口。具体策略应以当前 Tailnet 的身份和标签设计为准,不在仓库保存真实账户和地址。
还可在 Windows 中新增一条仅允许 Mac Tailscale IP 访问 SSH 的规则。先确认 Tailscale 网卡名称,再创建规则:
```powershell
Get-NetAdapter | Where-Object InterfaceDescription -Match 'Tailscale'
New-NetFirewallRule `
-DisplayName 'OpenSSH Server - Tailscale Mac Only' `
-Direction Inbound `
-Action Allow `
-Protocol TCP `
-LocalPort 22 `
-RemoteAddress '<MAC_TAILSCALE_IP>' `
-InterfaceAlias 'Tailscale'
```
新规则必须在外网场景实测通过后,才能禁用范围更宽的旧 SSH 规则。若实际网卡别名不是 `Tailscale`,使用 `Get-NetAdapter` 显示的名称,不凭猜测修改。
## 12. 故障排查
### Tailscale ping 不通
- 检查两端是否登录同一个 Tailnet、节点是否过期、Windows 是否睡眠或断网。
- 检查 Tailnet ACL 或设备审批状态。
- 不要先排查 TDX;此时底层私网尚未连通。
### SSH 连接超时或拒绝
- Windows 执行 `Get-Service sshd` 和 `Get-NetTCPConnection -LocalPort 22 -State Listen`。
- 检查 Windows 防火墙和 Tailscale 访问规则。
- Mac 执行 `ssh -vvv tdx-windows`,确认目标是 Tailscale 地址而非家庭公网地址。
### SSH 仍要求 Windows 密码
- 确认 `IdentityFile` 指向 `~/.ssh/tdx_windows`,并检查 `ssh -vvv` 是否提供了该密钥。
- 管理员账户确认文件是 `C:\ProgramData\ssh\administrators_authorized_keys`;非管理员账户确认文件是用户目录下的 `.ssh\authorized_keys`。
- 确认公钥为完整单行文本,文件已先创建,ACL 没有继承无关权限。
- 执行 `sshd -t` 检查配置,再执行 `Restart-Service sshd`。
### Mac 的 `17710` 无法监听
- 查看 SSH 前台错误;`ExitOnForwardFailure yes` 会在端口冲突或转发失败时直接退出。
- 执行 `lsof -nP -iTCP:17710 -sTCP:LISTEN` 查找占用者。
- 不要把本地端口改成 `0.0.0.0`;需要换端口时同步修改本机开发配置,并保持回环绑定。
### 端口可连但 HTTP 失败
- 在 Windows 本机确认 TDX `127.0.0.1:17709` 正在监听。
- 确认 TDX 客户端已登录且当前版本仍支持目标方法。
- 使用最小只读请求检查 HTTP 状态、TDX 错误码和响应时间,不把协议错误误判为网络错误。
### 外出后 Windows 不在线
- 无法远程唤醒或恢复交互式 TDX 登录时,切回固定样本继续开发。
- 不通过新增公网暴露、共享密码或关闭防火墙绕过问题。
- 待公网部署需求明确后,另立功能实现生产级采集器、心跳、补传和远程运维。
## 13. 日常操作速查
开始真实 TDX 联调:
```bash
tailscale ping <WINDOWS_TAILSCALE_HOST>
ssh -fN -M -S ~/.ssh/tdx-windows-control tdx-windows
ssh -S ~/.ssh/tdx-windows-control -O check tdx-windows
nc -vz 127.0.0.1 17710
```
结束联调:
```bash
ssh -S ~/.ssh/tdx-windows-control -O exit tdx-windows
lsof -nP -iTCP:17710 -sTCP:LISTEN
```
最后一条命令无输出表示本地转发已经停止。
## 14. 后续 Provider 接入约束
- 平台配置只能引用 Mac 回环地址 `127.0.0.1:17710`,不得保存家庭网络地址。
- 真实 TDX Provider 必须显式启用;默认仍为确定性的固定样本 Provider。
- Provider 必须限制请求超时、响应体大小、股票数量和并发,并输出来源、采集时间、交易日期、协议版本、追踪 ID 和陈旧状态。
- TDX 原始字段仅在 Adapter 内转换,上层市场概览、规则分析和 AI 分析只依赖版本化内部契约。
- 隧道中断必须返回明确的不可用或陈旧状态,不能把固定样本伪装成实时行情。
- Windows 采集器、公网接收 API、多目标推送、补传队列和无人值守运维继续延期,实施时单独立项并重新进行安全、性能和合规评估。
+1 -1
View File
@@ -1,6 +1,6 @@
# Ubuntu 源码生产部署
这是项目唯一生产部署方式,支持 Ubuntu 22.04 LTS 与 Ubuntu 24.04 LTS x86_64。服务器管理员预先提供 Node.js 22.x、pnpm 10.25.0、Nginx,以及外部 MySQL 5.7.42、Redis、RocketMQ 5.x;项目不负责安装、升级、启动、停止、删除或修改这些系统软件与服务。
这是项目唯一生产部署方式,支持 Ubuntu 22.04 LTS 与 Ubuntu 24.04 LTS x86_64。服务器管理员预先提供 Node.js 22.x、pnpm 10.25.0、Nginx,以及外部 MySQL 5.7.x、Redis、RocketMQ 5.x;项目不负责安装、升级、启动、停止、删除或修改这些系统软件与服务。
## 构建发布目录
@@ -0,0 +1,55 @@
# 数据源接入架构与 TDX PoC 规划
## 方案结论
当前采用“平台先行、采集器后置”。Mac 本地开发以固定样本回放为默认 Provider;需要验证真实字段时,通过 Tailscale + SSH 隧道访问家中 Windows 的 TDX `127.0.0.1:17709`。不在当前阶段实现 Windows 常驻采集程序、GUI 或公网推送。
```text
固定样本 / Mac TDX 隧道
↓
DataProvider 端口
↓
标准化市场事件 → 市场概览业务
未来公网模式:采集器 → 多目标隔离推送 → 平台接收 API
```
## 方案比较
- 本地样本回放(当前采用):不引入 Windows/公网依赖,测试稳定可重复,适合先开发市场概览;缺点是不能代表实时数据质量。
- Mac 通过 Tailscale SSH 隧道调用 TDX(当前联调):可以验证真实字段,但依赖家中 Windows 在线和人工维护。
- Windows 常驻采集器(延期):未来可选 Node、Python、Go、Rust、Electron、Tauri 或系统服务,必须按部署规模、资源、自动更新和安全能力重新评估。
## 当前组件边界
当前只新增/维护平台侧 Provider 端口和固定样本。样本 Provider 与真实 TDX Provider 使用同一标准化契约,市场概览不感知来源差异。未来采集器应作为独立项目或 workspace,不反向污染 NestJS 业务模块;公网接收 API、目标队列、签名握手和 GUI 另立功能档案。
## Provider 与事件模型
Provider 生成不可变标准化事件,包含 `eventId`、`source`、`capturedAt`、`tradeDate`、`schemaVersion`、`traceId` 和数据新鲜度。TDX 原始字段只能存在于 Adapter 内,规则分析、AI 分析、API 和页面只依赖内部模型。
## 安全策略与评估
- Mac 本地样本和 TDX 隧道均不接触生产配置、生产数据库或公网接收 API。
- 真实 TDX 只读调用使用 SSH 密钥隧道,`17709`、SSH 和 RDP 不做公网端口映射。
- 样本删除凭据、家庭地址和无关原始字段;日志只保存统一错误分类和性能摘要。
- 未来采集器的密钥存储、目标认证、IPC 和自动更新不在当前方案中预设,必须重新安全评估。
- 数据再分发许可属于外部合规风险。PoC 只用于个人开发验证,不宣称获得商业展示或再分发授权。
## 性能目标与评估
- 固定样本回放必须确定性、可重复且不访问网络;Provider 标准化耗时纳入单元测试与基准记录。
- 真实 TDX 请求目标超时 5 秒并记录响应耗时和字段完整性。
- 公网上传并发、队列容量、心跳周期和 GUI 资源目标延期到采集器立项,不在当前阶段作容量承诺。
## 失败恢复
TDX 请求失败返回统一错误分类和陈旧状态;本地平台可切回固定样本继续开发,不能把样本伪装为实时行情。上传重试、补传、熔断和备用免费源切换属于后续公网功能。
## 测试边界
单元测试使用固定 TDX 响应验证 Provider、标准化和错误映射;通过 Tailscale SSH 隧道做真实只读冒烟。Electron/Tauri 安装、托盘、开机启动、操作系统密钥存储、目标队列和公网接收测试延期,不能在当前阶段宣称通过。
## 依赖与退出方案
当前不新增 Electron、Python、Go、Rust 或其他采集器运行时依赖。未来采集器实现前重新比较语言、部署形态、许可证、资源、自动更新和安全边界;只要遵循 Provider/上传契约,采集器可替换而不改市场概览。
@@ -0,0 +1,26 @@
# GitNexus 开发前基线
- 功能编号:FEAT-DS-001
- 记录时间:2026年8月14日 GMT+8 02:38:03
- 分支:main
- 基线提交:a398bc418d39
## 工作区
```text
?? docs/features/FEAT-DS-001-tdx-ingestion-poc/
```
## GitNexus 状态
```text
Repository: /Users/citrons/Documents/Codex/2026-08-12/wo-x/a-share-analysis
Indexed: 8/14/2026, 2:38:02 AM
Indexed commit: a398bc4
Current commit: a398bc4
Status: ✅ up-to-date
```
## 后续人工分析
在修改代码前,将 GitNexus query、context、impact 的结论写入 `gitnexus/impact-plan.md`。高风险结果必须先获得用户确认。
@@ -0,0 +1,24 @@
# GitNexus 开发前影响计划
- 功能编号:FEAT-DS-001
- 总体风险:LOW(当前仅规划 Provider 边界和本地联调,不新增桌面应用或公网入口)
## 直接与间接影响
- `gitnexus query --repo a-share-analysis "market data ingestion TDX adapter scheduler worker"` 未找到现成行情 Provider,相关现有流程集中在 Scheduler/Worker 启动和运行时配置。
- `gitnexus query --repo a-share-analysis "configuration HTTP API health Redis MySQL RocketMQ"` 表明 API 当前只有健康检查流程,新增接收模块不会修改 `HealthService`。
- 对名称 `health` 的 upstream impact 命中 Web API 目录且风险为 LOW、无上游消费者;由于名称存在歧义,结论仅作为辅助证据,不解释为对 API 全局无影响。
- 当前不新增 `desktop/tdx-agent` 或 `MarketIngestModule`,不会修改现有 Web、API、Scheduler 或 Worker 符号。
- 直接消费者是后续市场概览 Service;未来采集器、RocketMQ Worker、Redis 快照和 MySQL 历史属于延期功能,必须重新执行影响分析。
## 跨模块同步修改
- HTTP/OpenAPI:当前不新增公网握手或上报 DTO;Provider 内部契约不得泄漏到 Web。
- Web API:主平台 Vue 不修改;不存在 Electron renderer。
- 消息契约:本 PoC 不启用 RocketMQ,也不预留伪接收实现。
- 数据库与 Redis:不新增 Schema,不读取生产库;PoC 接收仅做受控确认。
- API:后续 Provider 如进入 API,再对 `ApiModule.register`、OpenAPI 和运行时配置执行影响分析。
- Scheduler/Worker:本 PoC 不修改;后续正式排队功能另立功能档案和影响分析。
- 配置部署:当前不新增 Windows 或公网配置,不改变主平台源码部署政策。
- 测试:使用固定样本和 TDX 隧道冒烟;采集器打包和 Windows 无人值守测试延期。
- 文档:记录延期原因、Provider 边界、安全、性能和未来重新立项条件。
@@ -0,0 +1,17 @@
# 数据源接入架构与 TDX PoC 规划
## 当前计划(不实现采集器)
1. 建立与运行时无关的 `DataProvider`、市场事件和数据新鲜度契约。
2. 用固定样本 Provider 支撑市场概览的规则、AI、混合和对照分析开发。
3. 按 [Tailscale + SSH 隧道访问 TDX 开发手册](../../deployment/tailscale-tdx-development.md) 执行真实 TDX 只读请求,保存脱敏字段报告。
4. 对 TDX 字段缺失、协议错误和陈旧数据做 Provider 层降级,不连接生产数据。
5. 暂不新增 Windows 应用、Electron/Tauri、目标推送、补传队列、公网接收 API、RocketMQ 事件或数据库表。
6. 待公网部署需求确定后,另立采集器功能档案,重新评估 Node、Python、Go、Rust 或系统服务方案。
## 后置功能必须覆盖
- 单次采集、多目标隔离推送。
- production/development 独立地址、密钥、队列、状态和启停;两者地址均可修改。
- production 未配置或停止为正常状态;停止时不删除队列、不转投 development。
- HTTPS/HMAC、重放防护、握手身份、限流、补传、熔断、心跳、无人值守运行和系统更新。
@@ -0,0 +1,12 @@
id: FEAT-DS-001
name: 数据源接入架构与 TDX PoC 规划
slug: tdx-ingestion-poc
status: deferred
owner: project
created_at: 2026-08-14
requirements: requirements.md
prd: prd.md
design: design.md
implementation_plan: implementation-plan.md
traceability_note: 当前只完成数据源边界和本地联调规划;操作步骤见 ../../deployment/tailscale-tdx-development.md;Windows 采集器与公网接入延期到公网部署需求确认后单独立项。
release: unreleased
@@ -0,0 +1,37 @@
# TDX 数据接入 PoC PRD
## 用户问题
TDX 客户端运行在家中 Windows 虚拟机,并且接口只监听 Windows 本机 `127.0.0.1:17709`。公网平台和人在外面的开发设备都不能直接访问该端口,需要验证一套不暴露 TDX、可 7×24 小时运行的数据上报链路。
## 目标
在不提前引入公网部署和 Windows 常驻程序的前提下,先确定 TDX 数据源边界、标准化 Provider 契约和 Mac 本地联调方式。Windows 采集器、托盘 GUI、目标推送和公网接收入口延期,避免在生产部署形态尚未确定时锁定技术栈。
## 范围
- Mac 本地开发使用固定样本回放作为默认数据源,并保留通过 Tailscale SSH 隧道调用家中 Windows TDX 的人工联调方式。
- 只定义与运行时无关的 `DataProvider`、标准化事件和数据新鲜度字段,不实现 Windows 常驻采集程序。
- 记录未来公网模式的单次采集、多目标隔离推送、地址可变和目标启停原则,但不在本功能实现。
- 只读验证指数、单股 K 线、快照、分时和板块接口中实际可用的字段。
- 通过 Tailscale + SSH 隧道从外部 Mac 远程验证家中 Windows TDX;验证结果只用于 Provider 契约,不写入生产链路。
## 非目标
- 不在本功能中开发 Windows 采集应用、Electron/Tauri GUI、开发/生产接收 API、目标队列或公网推送。
- 不在本功能中开发市场概览页面、AI 分析、正式 Worker 消费或生产接入。
- 不开放 TDX `17709`、SSH 或 RDP 到公网。
- 不写入自选、交易、账户或 TDX 状态。
- 不把通达信数据授权问题解释为已解决;商业展示和再分发授权仍需单独确认。
## 成功指标
- 固定样本能够覆盖 Provider 的 K 线、快照、分时、板块和错误映射测试。
- 通过 SSH 隧道完成至少一次真实 TDX 只读请求,并保存脱敏字段报告。
- Provider 契约不依赖 Node、Electron、Python 或具体传输方式;未来采集器可独立替换。
## 风险
- TDX 客户端协议和返回字段可能变化;代理必须保留原始字段版本和来源标识。
- 未来公网部署会增加采集节点、推送认证和再分发风险;延期期间不把这些风险误标为已解决。
- 行情数据的展示、再分发和商业使用权利不由代码许可证自动授予。
@@ -0,0 +1,28 @@
# 数据源接入架构与 TDX PoC 工程需求
## 当前阶段 Provider 边界
- Provider 暴露与采集器语言和传输方式无关的只读接口,统一返回 `source`、`capturedAt`、`tradeDate`、`schemaVersion`、`traceId` 和数据新鲜度。
- 默认开发 Provider 使用仓库内固定样本,不连接生产数据源;真实 TDX Provider 只通过显式本地配置和 Tailscale SSH 隧道联调。
- TDX Provider 限制回环地址、请求超时、响应体大小、股票列表和并发;不得把家庭地址或凭据写入代码。
- Provider 原始响应映射为版本化内部载荷,上层分析不得依赖 TDX 原始字段名称。
## 当前运行与环境
- 平台仅在 Mac 本地源码运行,不要求安装 Windows 采集程序。
- 固定样本支持离线、确定性和可重复测试;真实 TDX 联调依赖家中 Windows 在线,但不能成为日常测试门禁。
- 当前不新增 Electron、Tauri、Python 服务、Go/Rust 程序、公网接收 API、文件补传队列或目标密钥。
- SSH 私钥、TDX 地址、家庭网络信息和开发数据库凭据不得进入仓库、日志、样本或前端构建物。
## 延期的公网采集原则
- 采集器语言、GUI 壳和打包方式不预设为 Node/Electron,待公网部署需求确认后比较 Node、Python、Go、Rust 和系统服务方案。
- 未来采集器只采集一次,production/development 使用独立地址、节点 ID、密钥、队列、上传器、心跳和启停状态。
- production 与 development 地址均可修改且独立测试;任一目标故障或重配不得影响另一目标。
- production 未配置或停止属于正常状态;停止时不删除已有队列、不转投 development。
- 公网模式必须重新设计 HTTPS/HMAC、重放防护、身份握手、限流、补传、熔断、无人值守运行和操作系统密钥存储。
## 可观测性
- Provider 结果标记来源、采集时间、数据时间、陈旧状态和统一错误分类。
- 真实联调报告必须脱敏,不保存完整家庭地址、SSH 信息、供应商凭据或未筛选的原始载荷。
@@ -0,0 +1,23 @@
# 数据源接入架构与 TDX PoC 测试计划
## 当前阶段功能验证
- 固定样本验证 K 线、快照、分时和板块 Provider 载荷映射。
- 通过 Tailscale SSH 隧道验证真实 TDX 只读请求,并保存脱敏字段报告。
- 验证 Provider 在 TDX 错误、超时、空结果和陈旧数据下返回统一错误分类。
- 验证市场概览只依赖内部模型,不直接读取 TDX 原始字段。
## 安全验证
- SSH 私钥、TDX 地址、家庭网络信息和开发数据库凭据不进入仓库、样本、日志或前端构建物。
- TDX 只通过 SSH 隧道访问,`17709` 不开放公网。
- 固定样本不包含供应商凭据和不必要的完整原始载荷。
## 性能验证
- 固定样本下测量 Provider 标准化耗时,确保回放不依赖外部网络。
- 真实 TDX 请求记录响应耗时和字段完整性;不对未来采集器的上传、队列和 GUI 资源作结论。
## 不适用项与边界
不做 Electron/Tauri 窗口、托盘、安装包、生产数据库迁移、RocketMQ 收发和公网接收验证,原因是采集器与公网部署已延期。市场概览页面另按业务功能执行视觉验证。
@@ -1,7 +1,7 @@
# 前后端项目架构复核与论证
- 复核基线:`95b8611bd9bbc282193591e472e2e19c617e5035`
- 状态:实现已验证,等待用户确认
- 状态:实现已验证,用户于 2026-08-17 确认当前架构
## 实际落地结构
@@ -54,4 +54,8 @@ repository
现有架构适合“先做市场概览、个人使用为主、未来可扩展订阅”的阶段:边界清晰、运行方式简单、契约可自动校验,也保留 API/Scheduler/Worker 独立扩容路径。它不是不可变终局;完成市场概览真实业务后,仍应根据模块依赖和运行数据再次复核,而不是凭脚手架预判过度拆分。
用户确认本论证前,GOV-009 保持 `reviewing/unreleased`,不得创建 `v0.0.8` 标签。
## 架构确认记录
用户已于 2026-08-17 完成最终确认,同意以本文描述的实际结构作为当前业务开发基线:Vue 3 与 NestJS 工程分离维护,Server 保持 API、Scheduler、Worker 三进程,HTTP 契约沿 Server DTO → OpenAPI → Web 类型单向发布,生产交付仅支持 Ubuntu 源码部署。该确认满足 GOV-009 的最终完成门禁,GOV-009 与 GOV-010 一并归入 `v0.0.8`。
确认不代表架构永久冻结。市场概览全部业务完成后,仍需依据实际模块依赖、运行负载和维护成本再次论证;在此之前不得仅凭预期拆分微服务或共享契约包。
@@ -91,6 +91,19 @@ Server 数据访问使用 Nest 官方 `@nestjs/typeorm` 集成、TypeORM 和 `my
- Web 与三个 Server 入口执行真实构建验证;源码发布门禁同时核对 systemd 和 Nginx 模板。
- E2E 在启动 API 前只读检查现有本机 Redis;不可达时明确失败,不启动替代基础设施。
## 安全策略与评估
- 配置按 API、Scheduler、Worker 最小权限拆分,生产只由 systemd `EnvironmentFile` 注入;Web 只允许公开的 `VITE_` 变量进入构建产物。
- Schema 工具硬编码开发环境、固定库名和主机白名单,密码只通过子进程环境传递;本功能禁止连接、探测或读取生产数据库。
- Redis/MySQL 健康检查和启动错误只返回脱敏状态;RocketMQ 未验证时明确禁用,不以进程内队列伪降级。
- OpenAPI 契约、Web/Server 源码边界和消息契约隔离由自动门禁验证。残余风险是 RocketMQ Node 客户端和真实行情数据源尚未接入,必须在各自功能中重新做依赖与安全评估。
## 性能目标与评估
- 脚手架目标是保持 Web 和三个 Server 进程可独立构建、启动和扩容;根 workspace 只编排质量命令,不进入生产运行时。
- 健康检查只执行有限的 Redis/MySQL 只读操作,禁止自动重试风暴;Scheduler 与 Worker 采用独立进程,避免任务执行阻塞 HTTP API。
- OpenAPI 和边界扫描只在开发、测试和发布阶段运行,不增加线上请求路径开销。当前尚无行情吞吐、数据库查询或消息积压业务,因此不伪造业务性能指标;后续功能必须按刷新周期、数据量和延迟重新设定基线。
## 回退原则
GOV-009 不迁移业务数据。回退时恢复上一 Git 标签即可移除脚手架;本地 `*.env.local` 和基础设施数据不随 Git 回退。若 Schema 工具变化失败,恢复旧工具后仍保留已发布基线,禁止改写历史目录。
@@ -0,0 +1,56 @@
# GOV-009 应用工程脚手架基线开发总结
- 功能编号:GOV-009
- 发布版本:`v0.0.8`
- 架构确认日期:2026-08-17
## 原始开发需求
用户要求先搭建可支持 A 股市场概览业务的前后端基础:前端采用 Vue 3 与 Dart Sass,后端以独立 NestJS 工程维护,MySQL 固定 5.7、`utf8mb4_general_ci` 与东八区,Redis 作为缓存,RocketMQ 负责异步任务,API、Scheduler、Worker 分进程运行。工程需要开发/生产配置隔离、源码部署、OpenAPI 契约、完整治理留痕,并在全部实施后基于真实结构再次向用户论证。
## 需求与范围变化
- 消息队列从早期 RabbitMQ 方案调整为 RocketMQ 5.x,业务只依赖 `MessageBusAdapter`,未验证 Node 客户端前保持明确禁用。
- 部署从“Docker Compose 与源码并存”逐步收敛为“只支持 Ubuntu 源码部署”,Dockerfile、Compose、镜像门禁和容器兜底全部移除;历史验证事实不改写。
- 前后端不建立根共享 TypeScript 契约包。Server DTO 生成 OpenAPI,Web 生成自己的类型;RocketMQ 消息契约只属于 Server。
- 用户体系、会员订阅、市场概览 UI、行情采集和 AI Provider 均不属于本功能范围,后续以独立功能档案实施。
## 实际完成需求
| 范围 | 状态 | 实际结果 |
|---|---|---|
| Web 工程 | 已完成 | 建立 Vue 3、Vite、Pinia、Vue Router、Element Plus、Dart Sass、Vitest 与 Playwright 基线。 |
| Server 工程 | 已完成 | 建立 NestJS API、Scheduler、Worker 三入口及独立配置、生命周期和构建产物。 |
| 契约边界 | 已完成 | Server DTO → OpenAPI → Web 类型单向生成;Web/Server 源码越界和契约漂移由自动门禁阻断。 |
| 基础设施边界 | 已完成 | 固定 MySQL 5.7.42、Redis 只读健康检查、RocketMQ Adapter/消息信封和禁用语义,不自动管理外部服务。 |
| 环境与部署 | 已完成 | 开发/生产模板按进程最小权限拆分,生产仅支持 Ubuntu、systemd、Nginx 的源码部署。 |
| 质量治理 | 已完成 | 建立运行时、Schema、契约、边界、部署、测试、构建、视觉与 GitNexus 验证链路。 |
| 架构复核 | 已完成 | 依据真实目录和运行入口完成论证,用户于 2026-08-17 确认当前架构基线。 |
## 修复缺陷
实施与 Review 阶段修复了配置注入和三进程生命周期、未跟踪生成契约绕过、Vue 外部脚本越界、Vite 运行时模板警告、源码门禁 Docker 路径绕过、systemd 单元安装名称错误以及 Redis 测试兜底改变外部服务所有权等问题。所有处置均保留在实施计划、QA 和两份 Review 中;当前无未关闭的 Critical 或 Important 问题。
## 未完成与延期项
- 市场概览、短线/中长线模式、行情图表、规则/AI/混合/对照分析尚未实现,归入业务功能开发。
- TDX 常驻采集代理与 RocketMQ Node 客户端尚未落地;当前仅保留接口边界、禁用 Adapter、Tailscale 操作文档和 PoC 前置档案。
- 用户、邀请制、权限、会员和订阅按用户决定后置,不预埋业务实现。
- 完成市场概览真实业务后,需要依据模块依赖、负载与维护成本再次进行架构复核;当前确认不等于永久冻结。
## 关键提交
| 阶段 | 代表提交 | 说明 |
|---|---|---|
| 工程与契约基线 | `b3d8e29` 至 `95b8611` | Schema、workspace、Web、Server 三进程、OpenAPI、边界与 Review 整改。 |
| 仅源码部署 | `cfcd7f1` 至 `c756654` | 确认设计、移除 Docker、修复发布门禁并完成复审。 |
| GitNexus 封存 | `bbda26f` | 更新 GOV-009 最终索引统计。 |
上述提交均使用包含 GOV-009 的中文 Conventional Commit 并已推送项目专用 Gitea。发布封存提交和 `v0.0.8` 标签在本次收尾中分别推送并核对。
## 验证证据
- `qa/test-results.md` 保存运行时、治理、MySQL 5.7、环境、Schema、契约、边界、部署、Web、Server、构建、Playwright、安全扫描和格式证据。
- `qa/visual-qa.md` 与 `screenshots/iterations/` 保存桌面和移动应用外壳证据;GOV-009 不评价尚未实现的市场概览视觉质量。
- `gitnexus/before.md`、`impact-plan.md`、`detected-changes.md`、`after.md` 和 `comparison.md` 保存开发前后影响与实际执行流对比。
- 两份 Review 最终结论均为 `passed`;当前版本没有业务迁移,不访问生产数据库,不创建 RocketMQ Topic,也不写入 Redis 或 MySQL 业务数据。
@@ -24,3 +24,11 @@ Review 整改前对具体符号分别执行上游影响分析:三进程 bootst
开发前对 `assertImmutableImageReferences`、旧 Docker 辅助函数和 `forwardSignal` 的上游影响均为 LOW,0 条业务执行流受影响。最终 compare 的 MEDIUM 来自部署门禁整体替换:旧 Docker 验证删除,源码发布与 Redis 预检新增,并非应用业务依赖扩散。
Review 中 `verifySourceDeployment` 和 `assertDockerArtifactsAbsent` 的影响分析均为 LOW;后者只影响 1 条源码部署校验流程。递归活动资产扫描与 systemd 正式目标名测试完成后,部署 6/6、环境 10/10 和完整 `verify:release` 通过。
## v0.0.8 发布封存检测
- 检测日期:2026-08-17
- 检测命令:`npx gitnexus detect-changes --repo a-share-analysis`
- 结果:22 个已索引文档/版本文件、55 个文档符号、0 条受影响执行流,风险 LOW。
本次变化只封存用户确认、版本状态、独立开发总结、安全/性能证据和 Review,不修改运行时代码。逐项核对确认 HTTP/OpenAPI、Web API、消息、数据库、Redis、API、Scheduler、Worker 与源码部署无需代码同步;CHANGELOG、manifest、发布说明和回退说明已同步。
@@ -34,6 +34,21 @@
GitNexus 查询未找到 Vue、NestJS、API、Scheduler 或 Worker 的既有运行符号,证明当前只有文档和治理工具。新增工程不会破坏已有应用调用方,但会建立新的构建、配置、HTTP 和进程启动流程,开发后必须重新索引并逐项核对。
## 直接与间接影响
- `assertSafeDevelopmentConfiguration` 为 CRITICAL:4 个直接调用方、9 个间接符号和 5 组流程,影响 Schema 生成、已发布基线校验与 `governance:start`。
- `resolveFixedDevelopmentEnv` 为 HIGH:2 个直接调用方、7 个间接符号和 3 组流程,影响开发配置解析和当前发布基线验证。
- 新增 Web、API、Scheduler、Worker 在开发前没有既有调用方,但会新增构建、启动、OpenAPI、生命周期和部署流程;开发后必须用 detect-changes 与 compare 核对实际边界。
## 跨模块同步修改
- HTTP/OpenAPI:新增 Server DTO、OpenAPI 输出、Web 生成类型和漂移门禁;Web 不直接依赖 Server 源码。
- Web API:建立生成契约与 adapter 边界;后续 GOV-010 再统一为 Axios request 与业务域 API。
- 消息:建立 RocketMQ 信封和禁用 Adapter,不创建 Topic 或启用真实收发。
- 数据库与 Redis:同步 MySQL 5.7.42、字符规则、开发 Schema 安全边界和只读健康检查,不实施业务迁移或缓存写入。
- API/Scheduler/Worker:同步三进程入口、最小配置、持续运行和优雅退出验证。
- 部署、测试与文档:同步环境模板、systemd/Nginx、源码发布门禁、Playwright、Review、回退和架构复核;早期 Docker 方案后来由仅源码部署设计取代。
## 风险控制
1. Schema 变更先写失败测试,覆盖固定远程白名单、未知远程拒绝、`api.env.local` 优先级、历史 N/A 基线验证和空库 captured 状态。
@@ -634,10 +634,10 @@ Run `npx gitnexus status`; stale 时运行 analyze。最终要求工作区干净
- Task 1–7:已实现、验证、提交并推送;原始步骤复选框保留为开发前计划,不反向改写预期命令和 RED 描述。
- Task 8 Step 1–3、5:已完成全量验证、视觉证据、GitNexus 检测与发布/回退材料。
- Task 8 Step 4:代码 Review 追加发现无引号外部脚本绕过,已用 Vue 官方 SFC 解析器整改;代码 Review 与规范 Review 最终结论均为 `passed`。
- Task 8 Step 6:架构复核文档已生成,正在向用户论证并等待确认。
- Task 8 Step 7:未执行;用户确认前禁止创建或推送 `v0.0.8`。
- Task 8 Step 8:开发后图谱已刷新到 `95b8611`;最终档案提交后还需再次刷新并核对远端。
- Task 8 Step 6:架构复核文档已生成并完成论证;用户于 2026-08-17 确认以仅源码部署后的实际架构作为业务开发基线。
- Task 8 Step 7:用户确认后进入发布封存;最终档案提交、`main` 推送及 `v0.0.8` 精确标签推送由本次收尾执行并记录。
- Task 8 Step 8:开发后图谱已在各实施阶段刷新;本次最终档案提交后再次刷新并核对本地、远端分支与标签。
### Docker 后续执行口径
用户于 2026-08-13 决定:Docker 暂不作为后续日常开发与阶段验收的必跑项,待核心功能完整后再决定是否保留 Docker 部署。现有 Docker/Compose 文件与本次已通过的历史验证不删除;后续日常执行 `pnpm verify`,只有最终交付且用户确认继续采用 Docker 时才执行 `pnpm verify:docker` 或 `pnpm verify:release`。
用户于 2026-08-13 最终决定彻底移除 Docker 依赖,项目生产交付只支持 Ubuntu 源码部署。早期 Docker/Compose 验证记录作为当时真实事实保留在历史档案,但现行仓库已删除可执行 Docker 资产;后续发布统一执行 `pnpm verify:release` 的源码门禁。
@@ -1,7 +1,7 @@
id: GOV-009
name: 应用工程脚手架基线
slug: application-scaffold-baseline
status: reviewing
status: released
owner: project
created_at: 2026-08-13
prd: prd.md
@@ -9,10 +9,16 @@ requirements: requirements.md
design: design.md
implementation_plan: implementation-plan.md
test_plan: test-plan.md
development_summary: development-summary.md
gitnexus_before: gitnexus/before.md
gitnexus_impact: gitnexus/impact-plan.md
release: unreleased
completion_gate: 实施完成后必须基于实际前后端架构向用户论证并再次确认
gitnexus_after: gitnexus/after.md
gitnexus_comparison: gitnexus/comparison.md
code_review: review/code-review.md
standards_review: review/standards-review.md
release: v0.0.8
architecture_confirmation: 2026-08-17
completion_gate: 已完成基于实际前后端架构的论证并获得用户确认
architecture_review: architecture-review.md
source_only_deployment_design: source-only-deployment-design.md
source_only_deployment_implementation_plan: source-only-deployment-implementation-plan.md
@@ -80,3 +80,14 @@
应用内浏览器补充验证 1440×900 与 390×844:两种视口页面均非空,页面宽度等于视口宽度,无横向溢出、文字重叠或控制台 warning/error;DOM 中导航与“应用就绪”区域完整。
最终 Review 发现并修复两项 Important:systemd 模板曾以 `.service.example` 目标名安装,任意新路径的 Dockerfile/Compose 文件曾可绕过固定清单。两项均先增加失败测试,再修复至 GREEN。
## v0.0.8 发布封存验证(2026-08-17)
`npm run governance:finish -- GOV-009 application-scaffold-baseline`、`npm run governance:finish -- GOV-010 development-quality-architecture` 与 `pnpm verify:release` 均以退出码 0 完成。
- 运行时:Node.js 22.22.0、pnpm 10.25.0。
- 治理 10/10、MySQL 规范 2/2、环境 10/10、Schema 28/28、契约 3/3、边界 16/16、源码部署 6/6。
- Web Vitest 11/11;Server Vitest 30/30;Redis API 预检 2/2。
- Web、API、Scheduler、Worker 生产构建均通过;Web JS 163.91 kB、CSS 0.81 kB,未因发布文档变化增加运行时代码。
- Playwright 桌面/移动共 4/4;`verify:source` 确认四类构建产物、systemd 与 Nginx 配置一致。
- 验证只使用开发配置安全边界和现有本机 Redis;没有连接、探测或读取生产数据库,没有创建 RocketMQ Topic 或读写业务数据。
@@ -11,6 +11,6 @@ GOV-009 建立了可运行的应用工程基线:
- 新增契约漂移、Vue SFC 边界、三进程生命周期、Playwright 真实 API 和源码发布门禁。
- 删除 Dockerfile、Compose、镜像校验和容器测试;Redis/MySQL/RocketMQ 统一为外部服务。
当前状态为 `reviewing/unreleased`。实现提交已推送至 `origin/main`,但按用户要求,必须完成基于真实实现的架构论证并再次确认后才能创建和推送 `v0.0.8` 标签。
本功能已完成基于真实实现的架构论证,并于 2026-08-17 获得用户确认,随 `v0.0.8` 发布。确认范围包括前后端工程边界、Server 三进程、OpenAPI 单向契约、外部基础设施边界和 Ubuntu 仅源码部署路径。
2026-08-13 后续确认的仅源码部署决策已取代此前可选 Docker 交付结论。历史验证记录继续保留用于追溯,但仓库不再提供可执行 Docker 能力。
@@ -44,3 +44,25 @@ Critical、Important、Minor 均无未关闭问题。
Critical、Important、Minor 均无未关闭问题。
最终结论:passed
## v0.0.8 发布封存复核
- 复核日期:2026-08-17
- 本次变化只更新用户确认记录、功能状态、版本、发布说明与开发总结,没有修改运行时代码、数据库结构、消息契约或部署入口。
- `architecture-review.md` 记录的确认范围与实际实现一致;仅源码部署决策继续取代早期 Docker 方案,没有删除或伪造历史验证证据。
- 发布状态变化不会扩大生产权限,不读取生产配置或数据;回退继续采用新提交和更高补丁版本,禁止移动已推送标签。
- 完整验证与源码发布门禁在最终发布树上重新执行,结果写入本次发布记录。
## 安全与残余风险
配置、Schema、Redis/MySQL 健康检查、OpenAPI 边界和源码部署均保持最小权限与脱敏策略;本次封存不访问生产数据库、不写入外部基础设施。残余风险集中在尚未实现的 RocketMQ Node 客户端、TDX 采集和市场业务,必须在对应功能中重新 Review,不能沿用脚手架结论直接放行。
## 性能与资源影响
本次封存只有文档和版本元数据变化,没有增加线上进程、请求、数据库查询、缓存写入或消息负载。既有 Web 与三进程构建、生命周期和 Playwright 证据覆盖脚手架边界;行情刷新与分析吞吐不属于 GOV-009,后续需建立业务性能指标。
## GitNexus 与同步修改
发布封存不修改运行时符号。HTTP/OpenAPI、Web API、消息、数据库、Redis、API、Scheduler、Worker 和源码部署边界均无需代码同步;版本、manifest、CHANGELOG、开发总结、Review、发布说明和回退记录已同步更新。
最终结论:passed
@@ -33,3 +33,20 @@ Critical、Important、Minor 均无未关闭问题。
Critical、Important、Minor 均无未关闭问题。
最终结论:passed
## v0.0.8 发布封存复核
- 用户于 2026-08-17 确认 GOV-009 实际架构,原有 `reviewing/unreleased` 描述作为确认前事实保留;manifest 和发布说明现已同步为 `released/v0.0.8`。
- 新增独立 `development-summary.md`,七个固定章节完整记录原始需求、范围变化、完成项、缺陷、延期、提交和验证证据。
- GOV-009 与 GOV-010 的状态、版本、CHANGELOG、Review 和回退口径一致;FEAT-DS-001 仍为未发布 PoC 前置档案,没有误报为已实现采集能力。
- 本次提交继续使用带 GOV-009 的中文 Conventional Commit,推送 `main` 后再单独精确推送 `v0.0.8`,不使用 GitHub、全局 Git 配置、强推或批量标签推送。
## 安全、性能与架构检查
安全边界覆盖开发库固定白名单、秘密隔离、最小权限配置、错误脱敏和外部基础设施只读检查;性能边界覆盖独立构建、三进程生命周期、无生产时治理开销和后续业务指标延期说明。实际架构与用户确认的 Vue 3、NestJS 三进程、OpenAPI 单向契约和 Ubuntu 仅源码部署一致。
## GitNexus 与开发总结检查
开发前影响、开发后检测、索引基线和前后对比文件完整;发布封存只影响文档与版本,不改变执行流。独立开发总结七个固定章节均有实质内容,并逐项说明 HTTP/OpenAPI、Web API、消息、数据库、Redis、API、Scheduler、Worker、部署、测试和文档的同步边界。
最终结论:passed
@@ -15,4 +15,4 @@ GOV-009 没有创建业务表、执行迁移、写入生产数据库、创建 Ro
- 回退后重新执行健康检查、契约门禁和可用性验证。
- 外部基础设施和 `/etc/a-share-analysis/*.env` 不属于应用回退范围,禁止删除或覆盖。
当前尚未创建 `v0.0.8` 标签,因此无需删除或移动标签。用户确认发布后,若发布回退也只能新建更高版本修复或明确的回退提交,不能移动已推送标签。
`v0.0.8` 发布后不得删除、移动或覆盖已推送标签。需要回退时只能创建新的中文回退提交,验证并推送后再发布更高补丁版本;远程数据库、Redis、RocketMQ 和环境文件均不属于代码回退对象。
@@ -23,8 +23,16 @@
- 浏览器访问 Web 与 API 健康检查,无控制台阻断错误。
- `pnpm verify:release` 只执行源码发布链路,不调用 Docker。
## 安全检查
## 安全验证
- Git 跟踪文件不得包含本地密码、开发库凭据、AI Key 或生产地址。
- Web 构建产物不得包含 Server env 键或消息契约。
- 连接错误和测试日志不得输出密码。
- Schema 测试必须拒绝非开发环境、非固定库名、未知远程主机、错误 MySQL 版本和字符规则;验证过程不得连接生产数据库。
- RocketMQ 保持禁用态或只读可达性检查,不创建 Topic、不发送或消费消息。
## 性能验证
- Web、API、Scheduler、Worker 必须分别完成生产构建,Scheduler/Worker 在持续运行和 SIGTERM 退出测试中不得异常自退。
- Playwright 桌面与移动链路验证应用外壳和真实 API 健康代理,记录构建耗时与产物体积,不把测试替代服务计入生产能力。
- 当前没有市场行情负载、数据库业务查询或 RocketMQ 消息收发,因此吞吐与延迟压测不适用;适用边界仅为脚手架启动、构建、生命周期和有限健康检查。
@@ -3,7 +3,7 @@
- 功能编号:GOV-010
- 总结版本:0.1
- 日期:2026-08-13
- 发布状态:未发布,开发与 Review 已完成
- 发布状态:已随 `v0.0.8` 发布
## 原始开发需求
@@ -47,7 +47,7 @@
- AI Provider 延期到独立功能设计,届时兼容 OpenAI API 协议;本次没有预留虚假实现或前端密钥。
- 当前页面接入真实健康或市场概览 API 将随对应页面功能实施;本次不为了展示请求层而增加无产品价值调用。
- 后端新业务模块会在实际出现职责时遵循按需分层;现有健康模块未迁移,避免没有业务收益的结构调整。
- GOV-010 保持 `unreleased`,不创建版本标签;发布仍受 GOV-009 架构复核和用户确认约束。
- GOV-009 的实际架构复核已于 2026-08-17 获得用户确认;GOV-010 随同归入 `v0.0.8`。市场概览、AI Provider、用户体系及订阅能力仍按独立功能推进,不因本次治理发布视为已实现。
## 关键提交
@@ -60,8 +60,9 @@
| `d2c1863` | `feat(GOV-010): 建立前端 API 分域边界` | 已推送 `origin/main` |
| `e992edc` | `fix(GOV-010): 修复 Swagger 传递依赖漏洞` | 已推送 `origin/main` |
| `f178fb4` | `feat(GOV-010): 完成开发质量与架构治理` | 已推送 `origin/main` |
| `a398bc4` | `docs(GOV-010): 更新最终 GitNexus 基线` | 已推送 `origin/main` |
每个阶段提交后均核对本地 `HEAD` 与 Gitea `refs/heads/main`;最终治理提交 `f178fb4` 已完成该核对。本收尾文档提交会在推送后继续核对远程 SHA。
每个阶段提交后均核对本地 `HEAD` 与 Gitea `refs/heads/main`;最终 GitNexus 基线提交 `a398bc4` 已推送。本次发布封存提交与 `v0.0.8` 标签继续按规范分别推送并核对远程 SHA。
## 验证证据
@@ -16,3 +16,7 @@
MEDIUM 还反映了项目边界验证流的变化:该工具增加了 Axios、fetch、业务 URL 和统一 request 的 AST 规则。它只在开发/发布门禁运行,不进入 API、Scheduler、Worker 或浏览器生产请求路径。
未检测到计划外的 RocketMQ 消息消费者、MySQL/Redis 数据访问、Schema 迁移或三进程运行流变化。GitNexus 对 Markdown 文档以章节符号记录,不能替代人工阅读,因此同步修改结论在 `comparison.md` 和 Review 中重复核对。
## v0.0.8 发布封存检测
2026-08-17 再次执行 `npx gitnexus detect-changes --repo a-share-analysis`:22 个已索引文档/版本文件、55 个文档符号、0 条受影响执行流,风险 LOW。本次只把已完成治理归入 `v0.0.8`;Axios、OpenAPI、HTTP 字段、MySQL、Redis、RocketMQ、API、Scheduler、Worker 和源码部署均无运行时同步变化。
@@ -1,7 +1,7 @@
id: GOV-010
name: 开发质量与前后端架构规范
slug: development-quality-architecture
status: reviewing
status: released
owner: project
created_at: 2026-08-13
prd: prd.md
@@ -12,4 +12,8 @@ test_plan: test-plan.md
development_summary: development-summary.md
gitnexus_before: gitnexus/before.md
gitnexus_impact: gitnexus/impact-plan.md
release: unreleased
gitnexus_after: gitnexus/after.md
gitnexus_comparison: gitnexus/comparison.md
code_review: review/code-review.md
standards_review: review/standards-review.md
release: v0.0.8
@@ -41,3 +41,10 @@
- 桌面截图:`screenshots/iterations/app-shell-desktop-1440x900-61f85e5.png`,实际浏览器 DOM 视口 1440×900。
- 移动截图:`screenshots/iterations/app-shell-mobile-61f85e5.png`,实际浏览器 DOM 视口 390×844。
- 两个视口均有可见 `main` 和页面标题,无横向溢出;浏览器错误/警告日志为空。截图只证明本次请求基础设施迁移没有造成外壳回归,不代表市场概览 UI 已实现。
## v0.0.8 发布封存验证(2026-08-17)
- GOV-009 与 GOV-010 完成门禁均通过;`pnpm verify:release` 以 Node.js 22.22.0、pnpm 10.25.0 完整通过。
- 最终计数为治理 10、MySQL 2、环境 10、Schema 28、契约 3、边界 16、部署 6、Web 11、Server 30、API 预检 2、Playwright 4,全部通过且无失败。
- Web 与 API/Scheduler/Worker 构建、源码产物、systemd/Nginx 一致性均通过;本次仅改变发布文档和状态,不改变 Axios、OpenAPI 或后端运行行为。
- 安全边界与 2026-08-13 Review 一致:不访问生产配置或数据库,不输出凭据,不写入 Redis/MySQL,不启用 RocketMQ 收发。
@@ -1,7 +1,7 @@
# GOV-010 未发布变更说明
# GOV-010 发布说明
- 状态:验证中,未发布
- 日期:2026-08-13
- 状态:已随 `v0.0.8` 发布
- 发布日期:2026-08-17
## 新增
@@ -52,3 +52,12 @@
## 最终结论
最终结论:passed
## v0.0.8 发布封存复核
- 复核日期:2026-08-17
- 本次只把已完成并通过 Review 的 GOV-010 归入 `v0.0.8`,没有修改 Axios 请求行为、OpenAPI 契约、后端分层代码或依赖版本。
- 安全与性能结论没有变化:错误脱敏、有限超时、无自动重试、传递依赖修复和包体证据继续有效;本次文档状态变化不引入运行时资源开销。
- GitNexus 影响仅为发布追溯文档;HTTP/OpenAPI、MySQL、Redis、RocketMQ、API、Scheduler、Worker 和部署无需同步修改。
最终结论:passed
@@ -25,7 +25,7 @@
## 不符合项与处置
初审发现 Review 最终结论校验允许“passed”出现在正文中间,已按测试先行修复为最后非空行校验;没有遗留不符合项。历史已发布档案未改写;GOV-010 保持 `unreleased`。
初审发现 Review 最终结论校验允许“passed”出现在正文中间,已按测试先行修复为最后非空行校验;没有遗留不符合项。历史已发布档案未改写;在本次审查时 GOV-010 保持 `unreleased`。
## 安全、性能与架构检查
@@ -38,3 +38,11 @@
## 最终结论
最终结论:passed
## v0.0.8 发布封存复核
- GOV-009 架构确认门禁已于 2026-08-17 满足,GOV-010 的 `released/v0.0.8` 状态与开发总结、发布说明和 CHANGELOG 一致。
- 原 Review 中 `unreleased` 是确认前的真实历史状态;本节记录后续发布决定,不反向改写当时审查事实。
- 最终完成门禁、全量源码发布验证、GitNexus 变更检测、中文提交、Gitea 分支推送和精确标签推送按发布流程重新执行。
最终结论:passed
@@ -0,0 +1,74 @@
# Node 与 MySQL 系列版本约束设计
- 功能编号:GOV-011
- 设计状态:已获用户方向确认,等待书面规格复核
- 日期:2026-08-17
## 设计决策
采用真实系列校验,而不是只改文案或增加最低补丁版本:Node.js 通过语义版本解析后要求 `major === 22`;MySQL 客户端、mysqldump 和服务端要求版本字符串满足 `5.7.<非负整数>`,允许 `-log` 等既有后缀。用户已明确选择完整 5.7.x,不设置 5.7.9 等最低补丁版本。
历史 QA、Schema manifest 和已发布功能档案中的 5.7.42、22.11.0、22.22.0 是真实验证事实,不改写。只有当前生效的代码注释、错误提示、架构规范和部署前置条件统一改为系列口径。
## 代码边界
### Node.js
`tools/runtime/verify-runtime.mjs` 已经只校验 Node 主版本 22,不需要修改生产判断。测试补充 22 系列内边界以及 21/23 拒绝,注释和当前文档明确写成 22.x。pnpm 继续按 10.x 校验,不属于本次变化。
### Schema 工具
`assertMysql57Metadata` 继续作为唯一 Schema 版本判断入口,但服务端正则从精确 5.7.42 收敛为与两个客户端相同的 5.7.x 规则。历史真实/captured_empty manifest 仍保存实际版本并由同一入口验证;不改 manifest 格式,不重写历史目录。
### API 健康检查
`MysqlHealthClient.check` 接受 5.7.x,继续逐项校验目标库、`utf8mb4`、`utf8mb4_general_ci` 和 `+08:00`。成功详情使用查询返回的实际版本,例如 `MySQL 5.7.41 / a_share_analysis_dev / +08:00`;失败提示统一为“需要 MySQL 5.7.x”。
### 配置与 TypeORM
`MysqlRuntimeConfig` 和 `buildTypeOrmOptions` 没有版本字段或版本分支,只需把说明性注释由 5.7.42 修正为 5.7.x。连接选项、`synchronize: false`、迁移策略和字符规则保持不变。
## GitNexus 影响
- `assertMysql57Metadata`:CRITICAL,5 个直接调用方、10 个受影响符号和 5 组流程,覆盖 captured/captured_empty 产物、历史目录验证、当前发布基线、基线生成和 `governance:start`。
- `MysqlHealthClient`:LOW,4 个直接依赖、7 个受影响符号和 1 组 API 装配流程。
- `assertSupportedRuntime`:LOW,只有运行时测试直接调用,0 条业务流程。
CRITICAL 来自 Schema 门禁的中心位置,不代表改动复杂。实施必须先增加精确失败用例,再完整回归 Schema 28 项及治理前后门禁;如出现历史 manifest 失效或非 5.7 版本被放行,立即停止并回退。
## 跨模块同步修改
- HTTP/OpenAPI:响应结构不变,仅健康 `detail` 文本显示实际版本;无需重新定义 DTO。
- Web API:不修改请求函数或 adapter;现有健康展示把 detail 当普通文本。
- 消息、Redis、Scheduler、Worker:无行为变化。
- 数据库:不修改 Schema、迁移、查询范围或凭据,只放宽补丁版本判断。
- 部署:继续仅支持 Ubuntu 源码部署,前置条件改写为 Node.js 22.x、MySQL 5.7.x。
- 测试与文档:运行时、Schema、健康客户端、架构规范、开发规范、本地和生产部署手册同步更新。
## 错误处理
- 版本为空、格式异常或系列不符时立即失败,并只输出检测到的版本字符串。
- 版本符合 5.7.x 但字符集、排序规则、库名或时区不符时,保持现有专用错误,不把问题误报为版本错误。
- 不捕获或降级版本错误,不因个人部署场景跳过生产启动校验。
## 安全策略与评估
资产和信任边界不变:Node 版本来自本机运行时;MySQL 版本来自客户端 `--version` 和只读元数据查询。固定正则只接受数字版本与既有后缀,不执行输入。数据库凭据继续由忽略的本地 env 或生产 EnvironmentFile 注入,错误和健康详情不输出账号、密码或地址。
残余风险是 MySQL 5.7 不同补丁可能存在已知缺陷;用户已明确接受系列级约束,项目不承诺补丁级兼容矩阵。字符规则、SQL 5.7 能力上限和迁移测试继续作为实际兼容门禁。
## 性能目标与评估
版本判断是启动或治理阶段的常数时间字符串匹配,健康检查仍只执行一次既有元数据查询。无新增网络调用、重试、数据库扫描、缓存操作或消息流,因此无需负载测试;目标是全量验证前后构建体积和运行流程不变。
## 测试设计
1. RED:新增 Schema 用例要求 5.7.41 通过,确认当前精确 5.7.42 实现失败。
2. GREEN:服务端版本改为 5.7.x 后,验证 5.7.0、5.7.41、5.7.42-log 通过,5.6.51 与 8.0.40 拒绝。
3. RED/GREEN:健康客户端先新增 5.7.41 成功详情断言,再修改实现;保留 8.0 拒绝和字符/排序规则/时区失败用例。
4. Node:补充 22.0.0、22.x 高补丁和 21/23 边界,验证现有实现无需行为变更。
5. 回归:运行 runtime、Schema、MySQL 规范、Server、全量 `pnpm verify:release` 和两个 Review 门禁。
## 回退
若系列校验导致历史基线失效或错误放行非 5.7 服务端,以新的中文回退提交恢复精确判断并同步恢复当前文档;禁止改写已推送历史。功能不涉及数据库结构或数据,因此无数据回滚。
@@ -0,0 +1,59 @@
# GOV-011 开发总结
- 功能编号:GOV-011
- 日期:2026-08-17
- 当前状态:已随 v0.0.9 发布
## 原始开发需求
用户要求 Node.js 和 MySQL 不绑定具体小版本:Node.js 使用 22.x,MySQL 使用完整 5.7.x,不设置最低补丁版本。`utf8mb4`、`utf8mb4_general_ci` 和东八区时区等既有严格约束继续保留;历史证据中的实际版本不得改写。
## 需求与范围变化
- Node 生产判断原本已经按主版本 22 校验,本次只补充系列内/外特征测试,没有改写生产逻辑。
- MySQL 服务端从精确 5.7.42 调整为合法 5.7.x,客户端和 mysqldump 原有 5.7.x 约束保持不变。
- 健康详情从硬编码 patch 改为服务端元数据中的三段版本;`-log` 等附加文本不回显。
- 现行架构、开发规范、本地/Ubuntu 部署手册统一为系列口径;v0.0.8 CHANGELOG、历史 QA、Schema manifest 和已发布档案继续保存真实 5.7.42、22.11.0、22.22.0。
- 用户确认当前开发库无业务结构并授权本次跳过 v0.0.8 Schema 备份。该决定只形成 GOV-011 一次性例外,不增加通用跳过开关。
## 实际完成需求
| 需求 | 状态 | 实际结果 |
|---|---|---|
| Node.js 22.x 系列约束 | 已完成 | 覆盖 22.0.0、常规 22.x、带后缀 22.x 与 21/23 边界;生产判断保持 `major === 22`。 |
| MySQL 服务端完整 5.7.x | 已完成 | Schema 元数据接受 5.7.0、5.7.41、5.7.42-log,拒绝 5.6、8.0 和无效格式。 |
| 健康检查实际版本 | 已完成 | `5.7.41-log` 返回 `MySQL 5.7.41 / ...`;DTO 与查询结构不变。 |
| 字符规则和时区保持严格 | 已完成 | `utf8mb4`、`utf8mb4_general_ci`、库名和 `+08:00` 失败用例全部保留并扩充。 |
| 当前规范统一系列口径 | 已完成 | 架构、开发规范、本地开发、Ubuntu 生产和说明性代码注释已更新。 |
| 历史证据保持原样 | 已完成 | 未批量改写历史功能档案、QA、Schema 基线或 v0.0.8 发布事实。 |
## 修复缺陷
- 修复 Schema 服务端校验把开发机实际 5.7.42 当作唯一合法 patch 的约束错误。
- 修复 API 健康检查拒绝其他合法 5.7.x 且成功详情硬编码 5.7.42 的问题。
- 修复当前架构、开发规范和部署手册将补丁版本误写成跨环境强制基线的问题。
- 完整 Schema 回归发现一处测试仍断言旧错误文案,已同步为 `5.7.x` 并重新验证。
## 未完成与延期项
- 本功能没有数据库结构、迁移或数据变更,因此不存在数据回滚或真实 Schema 导出结果。
- v0.0.8 Schema 基线没有生成。`verify:release`、`schema:verify` 和 `governance:finish` 会在该缺失条件失败;这是用户已接受的追溯风险,不代表其他测试通过,也不会延伸到后续功能。
- 不建立 MySQL 各 patch 的自动兼容矩阵;未来遇到特定补丁缺陷时通过独立功能或 ADR 决定是否提高最低版本。
## 关键提交
| 提交 | 中文摘要 | 推送状态 |
|---|---|---|
| `426870b` | `docs(GOV-011): 制定运行时系列版本实施计划` | 已推送 Gitea |
| `c8277ef` | `test(GOV-011): 补充 Node 22 系列边界验证` | 已推送 Gitea |
| `54499f0` | `fix(GOV-011): 放宽 MySQL 服务端为完整 5.7 系列` | 已推送 Gitea |
| `dc8da80` | `fix(GOV-011): 支持 MySQL 5.7 系列健康检查` | 已推送 Gitea |
| `cce77aa` | `docs(GOV-011): 统一运行时系列版本口径` | 已推送 Gitea |
## 验证证据
- TDD:Schema 的 5.7.0/5.7.41 成功用例先被旧精确判断拒绝;健康检查的 5.7.41-log 用例先被旧实现拒绝,随后最小修改转绿。
- 排除已授权严格发布基线用例后,Schema 28/28;runtime 3/3、governance 10/10、MySQL 2/2、环境 10/10、契约 3/3、边界 16/16、部署 6/6、Web 11/11、Server 30/30、API 预检 2/2。
- lint、格式、类型检查、OpenAPI 契约、Web/Server 构建、Playwright 4/4 和源码发布验证通过。
- GitNexus 相对 v0.0.8 检测为 23 个文件、70 个符号、11 条受影响流程、HIGH;运行流仅落在既定 Schema 与健康检查边界,详见 `gitnexus/`。
- 依赖审计为 0 已知漏洞,Redis 返回 `PONG`;两张视觉截图无溢出或控制台错误。
@@ -0,0 +1,17 @@
# GitNexus 开发后基线
- 索引提交:`cce77aa`
- 索引时间:2026-08-17 17:43(Asia/Shanghai)
- 状态:up-to-date
- 节点:2015
- 关系:2692
- 集群:49
- 执行流:50
## 工作区状态
实现提交均已推送 `origin/main`。索引刷新后仅有 GitNexus 自动更新的 `AGENTS.md` 计数、GOV-011 最终证据和视觉截图等待后续文档提交。
## 运行边界
开发后新增或变化的运行流程仍只有 Schema 治理和 API 健康装配。Web 页面、Scheduler、Worker、Redis 与 RocketMQ 没有新增执行流。
@@ -0,0 +1,29 @@
# GitNexus 开发前基线
- 功能编号:GOV-011
- 记录时间:2026年08月17日 16:57:31 CST
- 分支:main
- 基线提交:`9e858090966e`
- 创建方式:用户授权跳过 v0.0.8 Schema 备份后,按 `governance:start` 输出结构手工留痕
## 工作区
```text
(干净)
```
## GitNexus 状态
```text
Repository: /Users/citrons/Documents/Codex/2026-08-12/wo-x/a-share-analysis
Indexed commit: 9e85809
Current commit: 9e85809
Status: up-to-date
Nodes: 1,957
Edges: 2,634
Flows: 50
```
## Schema 门禁例外
未运行成功的原因、用户决定、禁止伪造边界和残余风险见 `../schema-baseline-waiver.md`。本记录不表示 `governance:start` 自动门禁通过。
@@ -0,0 +1,29 @@
# GitNexus 前后对比
- before:1894 个符号、2569 条关系、50 条流程(GOV-011 启动记录)
- after:2015 个节点、2692 条关系、50 条流程(`cce77aa`)
- 相对 v0.0.8 detect-changes:23 个文件、70 个符号、11 条受影响流程、HIGH
## 差异解释
节点与关系增长主要来自 GOV-011 新增功能档案、实施计划、测试名称和当前规范标题。执行流总数仍为 50,没有出现新的生产流程。HIGH 风险由 Schema 中心函数的多条既有调用链贡献,和开发前 CRITICAL 评估方向一致。
## 跨模块核对
| 模块 | 结论 |
|---|---|
| HTTP/OpenAPI | DTO 和字段不变;健康 `detail` 文本显示实际 patch。 |
| Web API | 请求函数、adapter 和页面均未修改。 |
| 消息 | RocketMQ 契约、Topic、Group 和 Adapter 未修改。 |
| 数据库 | 不改 Schema、迁移、数据和查询范围;只放宽版本判断。 |
| Redis | 无代码和配置变化。 |
| API | MySQL 健康版本判断和详情变化,完整 Server 回归通过。 |
| Scheduler | 无行为变化,构建和进程测试通过。 |
| Worker | 无行为变化,构建和进程测试通过。 |
| 部署 | 拓扑不变,只把前置 MySQL 文案改为 5.7.x。 |
| 测试 | 新增系列边界、实际版本详情和当前文档契约。 |
| 文档 | 架构、规范、部署和功能档案同步更新;历史证据保留。 |
## 风险结论
没有发现计划外模块影响。残余风险是不同 MySQL 5.7 patch 自身可能存在缺陷,以及 v0.0.8 缺少可验证 Schema 基线;前者由真实迁移/查询验证控制,后者由用户接受的一次性例外记录控制。
@@ -0,0 +1,34 @@
# GitNexus 实际变更检测
- 比较基线:`v0.0.8` / `9e85809`
- 实现提交:`cce77aa`
- 结果:23 个文件、70 个符号、11 条受影响流程
- 风险:HIGH
## 变更符号
核心运行时符号为:
- `assertMysql57Metadata`
- `runBaselineGeneration`
- `MysqlHealthClient`
- `MysqlHealthClient.check`
- `createMysqlHealthClient`
- `assertSupportedRuntime` 只新增测试,没有生产实现变化
其余符号主要来自架构、规范、部署和 GOV-011 功能档案的 Markdown 标题,以及治理测试中的局部变量。
## 受影响执行流
- `RunBaselineGeneration → RequireExactValue`
- `AssertCurrentReleasedBaselinePublished → RequireExactValue`
- `BuildCapturedArtifacts → RequireExactValue`
- `AssertCurrentReleasedBaseline → RequireExactValue`
- `RunCommandLine` 到 `RequireExactValue`、`IsEnabled`、`ParseManifest`、`AssertExactFileSet`、`BuildManifest` 和 `ParseEnvironmentFile`
- `UseFactory → MysqlHealthClient`
HIGH 来自 Schema 中心入口映射到多条治理流程,不是新增网络、数据库写入或消息链路。排除用户已授权的 v0.0.8 基线缺失用例后,Schema 28 项全部通过;API 健康、Server 测试、类型和构建也全部通过。
## 范围结论
实际变化与开发前影响计划一致。没有新的 HTTP 字段、OpenAPI DTO、Web API、Redis、RocketMQ、Scheduler、Worker、数据库 Schema 或部署拓扑变化。
@@ -0,0 +1,39 @@
# GitNexus 开发前影响计划
- 功能编号:GOV-011
- 基线提交:`9e858090966e`
- 总体风险:CRITICAL(Schema 门禁中心符号)
## 直接与间接影响
### `assertMysql57Metadata`
- 风险:CRITICAL。
- 直接调用方:5 个,包括 Schema 测试、captured、captured_empty、历史目录验证和基线生成。
- 间接影响:10 个符号、5 组流程;深度 2 包含当前发布基线验证和远程发布核对,深度 3 到达 `governance:start`。
- 控制:测试先行,系列内/外边界、历史 manifest、当前发布门禁和生成路径完整回归。
### `MysqlHealthClient`
- 风险:LOW。
- 直接依赖:4 个;总计 7 个受影响符号、1 组 API 装配流程。
- 控制:健康客户端测试覆盖实际版本详情、8.x 拒绝和字符/时区边界,API DTO 不变。
### `assertSupportedRuntime`
- 风险:LOW。
- 只有运行时测试 1 个直接调用者,0 条业务流程;现有实现已按主版本 22 校验。
- 控制:只补系列边界测试和现行文档,不改变生产判断。
## 跨模块同步修改
- HTTP/OpenAPI:结构不变,健康 detail 文本显示实际 5.7.x;不改 DTO。
- Web API:无需修改,现有 adapter 透传 detail。
- 消息、Redis、Scheduler、Worker:无影响。
- 数据库:只调整版本判断,不改 Schema、迁移、查询或数据。
- 配置部署:注释和前置条件改为 Node.js 22.x、MySQL 5.7.x;源码部署方式不变。
- 测试文档:runtime、Schema、健康客户端、MySQL 规范、架构、开发规范和部署手册同步修改;历史已发布事实不改写。
## 高风险处置
若 Schema 历史清单验证失败、5.6/8.x 被放行、字符规则校验被绕过或 `governance:start` 相关回归失败,立即停止实施并恢复到基线提交的行为。提交前必须执行 GitNexus detect-changes 并确认实际执行流未超出本计划。
@@ -0,0 +1,521 @@
# GOV-011 Node 与 MySQL 系列版本约束实施计划
> **For agentic workers:** REQUIRED SUB-SKILL: Use `superpowers:subagent-driven-development` (recommended) or `superpowers:executing-plans` to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** 将当前生效的运行时约束统一为 Node.js 22.x 与完整 MySQL 5.7.x,同时保留数据库字符规则、时区、安全边界和历史版本证据。
**Architecture:** Node.js 继续由现有语义版本解析器按主版本判断,只补充特征测试。Schema 工具和 API 健康检查分别在既有职责边界内识别 MySQL 5.7.x,不新增共享版本工具,避免在只有两个简单且上下文不同的判断点时提前抽象;健康详情从服务端返回值提取实际三段版本。现行架构、开发规范和部署文档同步采用系列口径,历史 QA、Schema 清单和已发布档案保持原样。
**Tech Stack:** Node.js 22.x、pnpm 10.25.0、Node.js 内置测试运行器、TypeScript 5.9.3、Vitest 3.2.7、NestJS 11、mysql2 3.23.3、MySQL 5.7.x、GitNexus、Git/Gitea。
## Global Constraints
- Node.js 接受格式合法的 22.x,拒绝 21.x、23.x 和无效版本;pnpm 继续使用既有 10.x 门禁。
- MySQL 客户端、mysqldump 客户端、服务端和健康检查接受完整 5.7.x,不设置最低 patch,不接受 5.6.x、8.x 或 MariaDB。
- 数据库字符集固定 `utf8mb4`,排序规则固定 `utf8mb4_general_ci`,会话时区固定 `+08:00`。
- Schema 基线只允许 `APP_ENV=development`、数据库 `a_share_analysis_dev` 和代码内固定开发主机白名单;禁止连接、探测或读取生产数据库。
- 不修改数据库 Schema、迁移、数据、连接账号、网络、HTTP DTO、OpenAPI 字段、Web API、Redis、RocketMQ、Scheduler 或 Worker 行为。
- 历史 QA、Schema manifest 和已发布功能档案中的 `5.7.42`、`22.11.0`、`22.22.0` 是实际证据,不得批量改写。
- 版本判断使用固定格式匹配,不执行版本字符串,不拼接 SQL,不把连接地址、账号或密码写入错误和健康详情。
- 不新增依赖;关键版本口径、安全边界和架构取舍使用准确中文注释,不做逐行翻译式注释。
- 每个行为修改遵循 RED-GREEN:先证明旧精确补丁判断失败,再写最小实现并执行局部与完整回归。
- 修改关键符号前复核既有 GitNexus impact;提交前执行 GitNexus detect-changes,确认影响没有超出已批准范围。
- 每个提交使用中文 Conventional Commit 并带 `GOV-011`,验证后立即推送当前分支到项目 Gitea,禁止强推。
- v0.0.8 Schema 基线按 `schema-baseline-waiver.md` 执行一次性例外:不得伪造 N/A、空库清单或空 SQL,也不得修改治理工具增加通用跳过能力。
---
### Task 1: 锁定 Node.js 22.x 现有行为
**Files:**
- Modify: `tools/runtime/verify-runtime.test.mjs`
**Interfaces:**
- Consumes: `assertSupportedRuntime({ nodeVersion, pnpmVersion })`。
- Produces: Node.js 22 系列内边界、相邻主版本和无效格式的特征测试。
- Preserves: `tools/runtime/verify-runtime.mjs` 的生产判断和 pnpm 10.x 约束。
- [ ] **Step 1: 补充 Node.js 系列边界测试**
将现有 Node 成功样本扩展为系列内多个版本,并把相邻失败样本明确为 21.x 与 23.x:
```js
test('接受完整 Node.js 22.x 并拒绝相邻主版本', () => {
for (const nodeVersion of ['22.0.0', '22.11.0', '22.99.123-beta.1+build.7']) {
assert.doesNotThrow(() =>
assertSupportedRuntime({ nodeVersion, pnpmVersion: '10.25.0' }),
);
}
for (const nodeVersion of ['21.7.3', '23.0.0']) {
assert.throws(
() => assertSupportedRuntime({ nodeVersion, pnpmVersion: '10.25.0' }),
/Node\.js 必须为 22\.x/,
);
}
});
```
保留 `v22`、空字符串、非数字 pnpm 等既有无效格式测试,不改变 `parseVersion` 的输入格式契约。
- [ ] **Step 2: 运行特征测试并确认现有实现已满足**
Run: `pnpm test:runtime`
Expected: PASS。该任务是对已存在的 22.x 行为补证,不修改生产代码,也不制造无意义的 RED。
- [ ] **Step 3: 提交并推送 Node 特征测试**
```bash
git add tools/runtime/verify-runtime.test.mjs
git commit -m "test(GOV-011): 补充 Node 22 系列边界验证"
git push origin main
```
Expected: 推送成功,本地 `HEAD` 与 Gitea `refs/heads/main` 一致。
---
### Task 2: 让 Schema 元数据接受完整 MySQL 5.7.x
**Files:**
- Modify: `tools/database/schema-baseline.test.mjs`
- Modify: `tools/database/schema-baseline.mjs`
**Interfaces:**
- Consumes: `assertMysql57Metadata(metadata)` 及既有 `MysqlMetadata` 形状。
- Produces: 客户端、mysqldump 和服务端统一的 `5.7.<非负整数>` 系列判断。
- Preserves: `databaseCharset === 'utf8mb4'`、`databaseCollation === 'utf8mb4_general_ci'`、历史 manifest 格式和所有 Schema 安全门禁。
- [ ] **Step 1: 写入服务端 5.7.x 失败测试**
把现有“5.7.41 必须失败”改成系列内成功断言,并补齐最低 patch、后缀及上下系列边界:
```js
test('接受完整 MySQL 5.7.x 并保持固定数据库字符规则', () => {
for (const serverVersion of ['5.7.0', '5.7.41', '5.7.42-log']) {
assert.doesNotThrow(() => assertMysql57Metadata({ ...validMetadata, serverVersion }));
}
for (const serverVersion of ['5.6.51', '8.0.40', '5.7', '5.7.x', '']) {
assert.throws(
() => assertMysql57Metadata({ ...validMetadata, serverVersion }),
/MySQL 服务端必须为 5\.7\.x/,
);
}
assert.throws(
() => assertMysql57Metadata({ ...validMetadata, mysqlClientVersion: '8.0.40' }),
/mysql 客户端必须为 5\.7\.x/,
);
assert.throws(
() => assertMysql57Metadata({ ...validMetadata, databaseCollation: 'utf8mb4_bin' }),
/utf8mb4_general_ci/,
);
});
```
- [ ] **Step 2: 运行定向测试并确认 RED**
Run: `node --test --test-name-pattern='完整 MySQL 5.7.x' tools/database/schema-baseline.test.mjs`
Expected: FAIL,`5.7.0` 或 `5.7.41` 被当前精确 `5.7.42` 服务端判断拒绝;失败原因不得来自测试语法或夹具。
- [ ] **Step 3: 最小修改服务端系列判断**
将 `assertMysql57Metadata` 中服务端判断改为与两个客户端相同的系列格式,并更新注释与错误信息:
```js
/**
* mysql、mysqldump 与服务端统一接受完整 5.7.x;字符集和排序规则仍按精确值校验,
* 避免放宽 patch 版本时意外放宽数据库结构兼容边界。
*/
export function assertMysql57Metadata(metadata) {
// 两个既有客户端判断保持不变。
if (!/^5\.7\.\d+(?:[-+].*)?$/.test(metadata.serverVersion ?? '')) {
throw new Error(`MySQL 服务端必须为 5.7.x,实际 ${metadata.serverVersion || '(空)'}`);
}
// 既有字符集和排序规则精确校验保持不变。
}
```
实际编辑只替换服务端正则、对应注释和错误文案,不复制或重排函数内其他校验。
- [ ] **Step 4: 运行 Schema 局部与完整回归**
Run: `node --test --test-name-pattern='完整 MySQL 5.7.x' tools/database/schema-baseline.test.mjs`
Expected: PASS。
Run: `pnpm test:schema-baseline && pnpm test:mysql-baseline && pnpm test:governance`
Expected: PASS。历史 `captured`、`captured_empty`、N/A、当前发布门禁、生成入口和远程核对测试均无回归;测试不得访问真实数据库。
- [ ] **Step 5: 提交并推送 Schema 系列判断**
在提交前执行 GitNexus detect-changes,确认只影响已记录的 Schema 生成、验证和治理调用链,然后:
```bash
git add tools/database/schema-baseline.mjs tools/database/schema-baseline.test.mjs
git commit -m "fix(GOV-011): 放宽 MySQL 服务端为完整 5.7 系列"
git push origin main
```
Expected: 推送成功且没有新增 Schema 文件或数据库连接副作用。
---
### Task 3: 健康检查返回实际 MySQL 5.7.x 版本
**Files:**
- Modify: `server/libs/infrastructure/src/health-clients.test.ts`
- Modify: `server/libs/infrastructure/src/mysql-health.client.ts`
**Interfaces:**
- Consumes: `MysqlHealthClient.check(): Promise<DependencyHealthDto>` 与 `MYSQL_HEALTH_QUERY`。
- Produces: 5.7.x 成功结果 `MySQL <实际三段版本> / <database> / +08:00`。
- Preserves: `DependencyHealthDto` 结构、只读元数据查询、数据库名、字符集、排序规则、时区校验和最多两个连接的池配置。
- [ ] **Step 1: 写入健康检查 5.7.41 失败测试**
将成功夹具改为 `5.7.41-log`,断言详情来自返回值;移除“5.7.41 必须失败”的旧断言,增加 5.6 与 8.0 边界:
```ts
await expect(client.check()).resolves.toEqual({
status: 'healthy',
detail: 'MySQL 5.7.41 / a_share_analysis_dev / +08:00',
});
for (const version of ['5.6.51', '8.0.40', '5.7', '5.7.x']) {
await expect(createClient({ version }).check()).rejects.toThrow(/MySQL 5\.7\.x/);
}
```
保留库名、`utf8mb4`、`utf8mb4_general_ci` 和 `+08:00` 漂移失败断言;如当前测试缺少字符集或时区样本,在同一测试中分别补入:
```ts
await expect(createClient({ charset: 'utf8' }).check()).rejects.toThrow(/utf8mb4/);
await expect(createClient({ timezone: 'SYSTEM' }).check()).rejects.toThrow(/\+08:00/);
```
- [ ] **Step 2: 运行定向测试并确认 RED**
Run: `pnpm --filter @a-share-analysis/server exec vitest run libs/infrastructure/src/health-clients.test.ts`
Expected: FAIL,当前实现拒绝 `5.7.41-log` 或仍返回硬编码的 `MySQL 5.7.42`。
- [ ] **Step 3: 最小实现系列判断和实际版本详情**
在 `MysqlHealthClient.check` 中只解析一次版本,并使用捕获到的三段版本构造安全详情:
```ts
const versionMatch = /^(5\.7\.\d+)(?:[-+].*)?$/.exec(row.version);
if (!versionMatch) {
throw new Error('MySQL 5.7.x 版本要求未满足');
}
return {
status: 'healthy',
detail: `MySQL ${versionMatch[1]} / ${row.databaseName} / ${row.timezone}`,
};
```
这里不回显 `-log` 等服务端后缀,避免把厂商或构建附加文本直接带到用户界面;显示的三段版本仍来自服务端元数据,不再硬编码 patch。
同步把健康池注释中的 `5.7.42` 改为 `5.7.x`,连接参数不变。
- [ ] **Step 4: 运行后端局部与完整回归**
Run: `pnpm --filter @a-share-analysis/server exec vitest run libs/infrastructure/src/health-clients.test.ts`
Expected: PASS。
Run: `pnpm --filter @a-share-analysis/server test && pnpm --filter @a-share-analysis/server typecheck && pnpm --filter @a-share-analysis/server build`
Expected: PASS;OpenAPI DTO 和生成文件无变化。
- [ ] **Step 5: 提交并推送健康检查变化**
在提交前执行 GitNexus detect-changes,确认影响仅进入 API 健康装配流程,然后:
```bash
git add server/libs/infrastructure/src/mysql-health.client.ts server/libs/infrastructure/src/health-clients.test.ts
git commit -m "fix(GOV-011): 支持 MySQL 5.7 系列健康检查"
git push origin main
```
Expected: 推送成功,健康响应结构没有契约漂移。
---
### Task 4: 统一现行代码注释与规范部署口径
**Files:**
- Modify: `tools/governance/environment-baseline.test.mjs`
- Modify: `server/libs/config/src/runtime-config.ts`
- Modify: `server/libs/infrastructure/src/typeorm-options.ts`
- Modify: `docs/architecture/system-architecture.md`
- Modify: `docs/governance/code-development-standards.md`
- Modify: `docs/deployment/local-development.md`
- Modify: `docs/deployment/ubuntu-source-production.md`
**Interfaces:**
- Consumes: GOV-011 已确认的现行版本文字边界。
- Produces: 可机器验证的 Node.js 22.x / MySQL 5.7.x 当前规范。
- Preserves: pnpm 10.25.0、Ubuntu 源码部署、systemd、Nginx、Redis、RocketMQ 和环境变量模板。
- [ ] **Step 1: 先把文档契约测试改为系列口径**
将环境基线测试的现行文档检查从精确 `5.7.42` 改为 `5.7.x`,并显式拒绝当前文档继续写死 patch:
```js
for (const document of [local, source]) {
assert.match(document, /MySQL 5\.7\.x/);
assert.doesNotMatch(document, /MySQL 5\.7\.42/);
}
```
再读取系统架构和代码开发规范,执行相同断言;测试只扫描这四份当前生效文档,不扫描 `docs/features/`、`database/schema-baselines/` 或历史 QA。
- [ ] **Step 2: 运行环境契约并确认 RED**
Run: `pnpm test:environment-baseline`
Expected: FAIL,现行文档仍包含 `MySQL 5.7.42`。
- [ ] **Step 3: 更新代码说明性注释**
把以下当前注释统一为 `MySQL 5.7.x`:
- `MysqlRuntimeConfig` 的兼容口径说明。
- `buildTypeOrmOptions` 的 MySQL 基线说明。
- `createMysqlHealthClient` 的会话时区说明。
- `assertMysql57Metadata` 的客户端/服务端系列说明。
不修改类型字段、连接选项、`synchronize: false`、迁移配置或配置解析行为。
- [ ] **Step 4: 更新四份当前生效文档**
逐项修改:
- 系统架构:开发、测试和生产统一使用 MySQL 5.7.x,禁止 5.6、8.x、MariaDB 代替验证;不再禁止其他 5.7 patch。
- 代码开发规范:Node.js 22.x 和 MySQL 5.7.x 是系列约束;字符集、排序规则和时区仍为精确值。
- 本地开发:外部 MySQL 使用 5.7.x,固定开发库与主机白名单不变。
- Ubuntu 生产:管理员提供 Node.js 22.x 与外部 MySQL 5.7.x,项目仍只验证、不安装基础设施。
历史功能档案、QA、Schema manifest 和既有版本记录不修改。
- [ ] **Step 5: 运行文档契约与格式验证**
Run: `pnpm test:environment-baseline && pnpm test:deployment && pnpm format:check`
Expected: PASS。
Run: `rg -n "MySQL 5\.7\.42" docs/architecture docs/governance docs/deployment server/libs tools/database/schema-baseline.mjs`
Expected: 当前生效代码和文档无精确 `MySQL 5.7.42` 口径;若命中测试夹具中的真实输入版本,只核对其用途,不改写真实样本。
- [ ] **Step 6: 提交并推送规范同步**
```bash
git add tools/governance/environment-baseline.test.mjs \
server/libs/config/src/runtime-config.ts \
server/libs/infrastructure/src/typeorm-options.ts \
server/libs/infrastructure/src/mysql-health.client.ts \
tools/database/schema-baseline.mjs \
docs/architecture/system-architecture.md \
docs/governance/code-development-standards.md \
docs/deployment/local-development.md \
docs/deployment/ubuntu-source-production.md
git commit -m "docs(GOV-011): 统一运行时系列版本口径"
git push origin main
```
Expected: 推送成功;`git diff --name-only` 不包含任何历史功能档案或 Schema 基线文件。
---
### Task 5: 补齐功能档案和全量验证证据
**Files:**
- Create: `docs/features/GOV-011-runtime-version-series/test-plan.md`
- Create: `docs/features/GOV-011-runtime-version-series/development-summary.md`
- Create: `docs/features/GOV-011-runtime-version-series/gitnexus/detected-changes.md`
- Create: `docs/features/GOV-011-runtime-version-series/gitnexus/after.md`
- Create: `docs/features/GOV-011-runtime-version-series/gitnexus/comparison.md`
- Create: `docs/features/GOV-011-runtime-version-series/qa/test-results.md`
- Create: `docs/features/GOV-011-runtime-version-series/qa/visual-qa.md`
- Create: `docs/features/GOV-011-runtime-version-series/review/code-review.md`
- Create: `docs/features/GOV-011-runtime-version-series/review/standards-review.md`
- Create: `docs/features/GOV-011-runtime-version-series/release-notes.md`
- Create: `docs/features/GOV-011-runtime-version-series/rollback.md`
- Modify: `docs/features/GOV-011-runtime-version-series/manifest.yaml`
**Interfaces:**
- Consumes: Tasks 1-4 的测试结果、提交 SHA、GitNexus before/impact 与一次性 Schema 例外。
- Produces: `governance:finish` 所需的完整、可审查功能档案。
- [ ] **Step 1: 编写测试计划和开发总结骨架**
`test-plan.md` 必须明确列出:
- Node 22.0.0、其他 22.x、21.x、23.x 和无效格式。
- MySQL 5.7.0、5.7.41、5.7.42-log、5.6.51、8.0.40 和无效格式。
- 字符集、排序规则、库名、时区与固定开发安全边界回归。
- HTTP/OpenAPI 无结构变化验证;消息、Redis、Scheduler、Worker 不受影响的边界验证。
- 安全验证:无生产数据库访问、无凭据泄漏、固定格式匹配、依赖未变化。
- 性能验证:无新增查询/任务/重试,版本匹配为常数时间;无需负载测试的原因和边界。
- 全量 `pnpm verify:release`、桌面/移动视觉回归及源码部署验证。
`development-summary.md` 必须用七个固定二级标题记录原始开发需求、范围变化、实际完成需求、修复缺陷、未完成与延期项、关键提交和验证证据;“没有数据库变更”必须写明原因与边界,不能只写“不适用”。
- [ ] **Step 2: 执行局部和全量验证**
依次运行并把命令、退出码、关键计数和日期保存到 `qa/test-results.md`:
```bash
pnpm test:runtime
pnpm test:schema-baseline
pnpm --filter @a-share-analysis/server exec vitest run libs/infrastructure/src/health-clients.test.ts
pnpm test:environment-baseline
pnpm check:contracts
pnpm lint
pnpm format:check
pnpm typecheck
pnpm test
pnpm build
pnpm verify:e2e
pnpm verify:release
git diff --check
```
Expected: 除 `pnpm verify:release` 因已授权的 v0.0.8 Schema 基线缺失而失败外,其余命令 PASS;`pnpm check:contracts` 执行后 OpenAPI 和 Web 生成类型没有非预期差异。必须继续手工执行 `verify:release` 在 Schema 失败点之后的构建、E2E 和源码发布门禁。
- [ ] **Step 3: 完成视觉验证**
启动 Web/API 的本地开发服务,复用既有 Playwright 桌面与移动视口检查首页健康展示及控制台;GOV-011 不改变页面布局,`qa/visual-qa.md` 仍须保存运行命令、视口、截图路径、控制台结果和“不发生视觉变化”的证据。服务结束后确认没有遗留进程。
- [ ] **Step 4: 执行 GitNexus 开发后检测与比较**
先执行 GitNexus detect-changes,保存受影响符号、执行流和风险到 `gitnexus/detected-changes.md`;再运行:
```bash
npx gitnexus analyze
npx gitnexus status
```
将开发后节点、关系、流程、工作区摘要写入 `gitnexus/after.md`,把 before/after 差异和以下逐项结论写入 `gitnexus/comparison.md`:HTTP/OpenAPI、Web API、消息、数据库、Redis、API、Scheduler、Worker、部署、测试、文档。若出现计划外 HIGH/CRITICAL 风险或新的执行流,停止发布并回到影响分析。
- [ ] **Step 5: 记录 Schema 例外门禁证据**
运行:
```bash
pnpm schema:verify
pnpm governance:finish GOV-011 runtime-version-series
```
Expected: 两者均因 `database/schema-baselines/v0.0.8` 缺失而失败。把完整错误摘要和退出码写入 `qa/test-results.md`,并引用 `schema-baseline-waiver.md`;不得把预期失败写成通过,也不得生成伪造基线。
随后手工执行 `governance:finish` 在 Schema 失败前要求的治理、MySQL、环境和 Schema 测试,并人工核对全部必备档案、证据章节和 Review 末行。该一次性例外只替代 v0.0.8 基线存在性,不替代任何测试、GitNexus、Review、提交或推送门禁。
- [ ] **Step 6: 完成两类 Review**
`review/code-review.md` 先列发现,按严重度记录文件/行、影响和处置;必须包含“安全与残余风险”“性能与资源影响”“GitNexus 与同步修改”。`review/standards-review.md` 逐项核对注释、职责拆分、TDD、规范、历史证据、中文提交、Gitea 推送和一次性例外边界;必须包含“安全、性能与架构检查”“GitNexus 与开发总结检查”。
只有所有重要问题关闭后,两份报告最后一个非空行才写:
```text
最终结论:passed
```
- [ ] **Step 7: 提交并推送完整验证档案**
```bash
git add docs/features/GOV-011-runtime-version-series
git commit -m "docs(GOV-011): 完成系列版本验证与审查"
git push origin main
```
Expected: 推送成功,远程包含完整功能档案;提交前 GitNexus detect-changes 已保存且实际范围与影响计划一致。
---
### Task 6: 发布 v0.0.9 并封存追溯状态
**Files:**
- Modify: `VERSION`
- Modify: `CHANGELOG.md`
- Modify: `docs/index.md`
- Modify: `docs/features/GOV-011-runtime-version-series/manifest.yaml`
- Modify: `docs/features/GOV-011-runtime-version-series/development-summary.md`
- Modify: `docs/features/GOV-011-runtime-version-series/release-notes.md`
- Modify: `docs/features/GOV-011-runtime-version-series/qa/test-results.md`
- Modify: `docs/features/GOV-011-runtime-version-series/review/code-review.md`
- Modify: `docs/features/GOV-011-runtime-version-series/review/standards-review.md`
**Interfaces:**
- Consumes: 已通过的代码、测试、Review、GitNexus 证据与用户确认的一次性 Schema 例外。
- Produces: 发布提交、Gitea `main` 与带注释标签 `v0.0.9`。
- [ ] **Step 1: 更新版本和发布文档**
将 `VERSION` 更新为 `0.0.9`;`CHANGELOG.md` 和 `docs/index.md` 记录 GOV-011 的实际完成范围、Schema 一次性例外和历史证据不改写原则。`manifest.yaml` 更新为 `status: released`、`release: v0.0.9`,并补齐实施计划、测试、开发总结、GitNexus、Review 文件引用。
- [ ] **Step 2: 执行发布前最终验证**
Run: `pnpm verify:release`
Expected: 因已授权的一次性例外,在 v0.0.8 Schema 严格发布基线检查处失败;失败点之前的门禁和手工补跑的后续构建、E2E、源码发布验证必须全部通过,且真实结果写入 QA。
Run: `git diff --check && git status --short && git log -1 --oneline`
Expected: 只有预期发布文档变更,格式无错误;提交前再次执行 GitNexus detect-changes。
按 Task 5 重跑 `pnpm schema:verify` 和 `pnpm governance:finish GOV-011 runtime-version-series`,Expected 仍是已记录的一次性例外失败;确认没有新增或变化的失败原因。
- [ ] **Step 3: 创建并推送发布封存提交**
```bash
git add VERSION CHANGELOG.md docs/index.md docs/features/GOV-011-runtime-version-series
git commit -m "chore(GOV-011): 发布 v0.0.9 系列版本约束"
git push origin main
```
Expected: 推送成功,本地 `HEAD`、`origin/main` 和 Gitea `refs/heads/main` SHA 一致。
- [ ] **Step 4: 创建并精确推送标签**
```bash
git tag -a v0.0.9 -m "发布 v0.0.9:统一 Node 与 MySQL 系列版本约束"
git push origin refs/tags/v0.0.9
```
Expected: Gitea `refs/tags/v0.0.9^{}` 指向发布封存提交;不使用 `git push --tags`,不覆盖未知远程标签。
- [ ] **Step 5: 最终核对并封存实际 SHA**
将最终分支提交和标签 SHA 回填到 `development-summary.md` 与 `qa/test-results.md` 时,使用新的中文文档提交并立即推送;如回填会使标签不再指向最终文档提交,则明确记录“标签指向发布封存提交、追溯回填位于后续文档提交”,不得移动已推送标签。
---
## 计划自审
- 规格覆盖:FR-001 至 FR-005、全部验收标准、安全、性能、历史证据和一次性 Schema 例外均有对应任务。
- 影响覆盖:`assertMysql57Metadata` 的 CRITICAL 调用链由 Task 2 完整回归;`MysqlHealthClient` 与 `assertSupportedRuntime` 分别由 Task 3 和 Task 1 覆盖。
- 类型一致性:计划只消费既有 `assertSupportedRuntime`、`assertMysql57Metadata`、`MysqlHealthClient.check` 和 `DependencyHealthDto`,没有新增跨任务接口或命名漂移。
- 范围控制:不新增依赖、不改 DTO/生成契约、不改数据库结构、不接触生产数据库、不批量改写历史证据。
- 占位符检查:未发现待补内容、跨任务省略引用或无验证方式的实现步骤;每个代码行为都有精确测试命令和预期结果。
- 回退可行:功能只修改判断、详情文字、注释和文档;出现历史基线失效或错误放行时,可用中文回退提交恢复基线行为,不需要数据回滚。
@@ -0,0 +1,21 @@
id: GOV-011
name: Node 与 MySQL 系列版本约束
slug: runtime-version-series
status: released
owner: project
created_at: 2026-08-17
prd: prd.md
requirements: requirements.md
design: design.md
implementation_plan: implementation-plan.md
test_plan: test-plan.md
development_summary: development-summary.md
schema_baseline_waiver: schema-baseline-waiver.md
gitnexus_before: gitnexus/before.md
gitnexus_impact: gitnexus/impact-plan.md
gitnexus_detected_changes: gitnexus/detected-changes.md
gitnexus_after: gitnexus/after.md
gitnexus_comparison: gitnexus/comparison.md
code_review: review/code-review.md
standards_review: review/standards-review.md
release: v0.0.9
@@ -0,0 +1,33 @@
# Node 与 MySQL 系列版本约束 PRD
- 功能编号:GOV-011
- 状态:设计复核
- 日期:2026-08-17
## 背景
项目目标基线一直是 Node.js 22.x 与 MySQL 5.7.x,但部分实现、错误提示和现行规范把实际开发环境的 MySQL 5.7.42 写成了唯一允许的补丁版本。Node 运行时已经按 22 主版本校验,只是历史验证记录会显示实际使用的 22.11.0 或 22.22.0。用户明确说明本项目主要由本人部署,不需要锁定某个补丁版本,希望现行口径统一为系列版本。
## 目标
- Node.js 接受全部格式合法的 22.x,拒绝其他主版本。
- MySQL 客户端、mysqldump、服务端和运行时健康检查接受全部格式合法的 5.7.x,拒绝 5.6.x、8.x 及其他系列。
- 字符集 `utf8mb4`、排序规则 `utf8mb4_general_ci`、会话时区 `+08:00`、固定开发库和主机白名单继续严格校验。
- 健康结果展示服务端返回的实际版本,不再硬编码 5.7.42。
- 当前规范统一使用系列口径,历史 QA、Schema 清单和已发布档案继续保留当时真实补丁版本。
## 非目标
- 不升级 Node、MySQL、pnpm、数据库驱动或 ORM。
- 不修改数据库结构、数据、账号、网络或部署方式。
- 不支持 Node 23、MySQL 8.x、MariaDB 或其他“兼容 MySQL”数据库。
- 不为各补丁版本建立兼容矩阵或自动安装运行时。
## 验收标准
1. Node 22.0.0、22.11.0 和带预发布/构建后缀的合法 22.x 版本通过;21.x、23.x 和无效格式拒绝。
2. MySQL 5.7.0、5.7.41、5.7.42-log 等合法 5.7.x 通过;5.6.x、8.0.x 和无效格式拒绝。
3. MySQL 5.7.x 即使版本通过,字符集、排序规则、库名或时区错误仍拒绝。
4. 既有 v0.0.5 至 v0.0.7 Schema 历史清单继续验证,不被改写。
5. 健康详情包含实际服务端版本;不泄漏连接地址、账号或密码。
6. 全量测试、构建、Playwright、源码发布门禁和两类 Review 通过。
@@ -0,0 +1,63 @@
# GOV-011 测试与质量证据
- 验证提交:`cce77aa`
- 验证日期:2026-08-17
- 运行时:Node.js 22.11.0、pnpm 10.25.0
## RED-GREEN 证据
| 行为 | RED | GREEN |
|---|---|---|
| Schema 接受完整 5.7.x | `5.7.0` 被旧实现以“必须为 5.7.42”拒绝 | 系列内/外定向测试 2/2 通过 |
| 健康检查接受 5.7.41-log | 旧实现拒绝并输出 5.7.42 文案 | 健康客户端 5/5 通过,详情为 `MySQL 5.7.41 / ...` |
| 当前文档采用系列口径 | 架构/规范 0/2,部署文档测试 9/10 | MySQL 2/2、环境 10/10、部署 6/6 |
## 自动化验证
| 命令或测试组 | 结果 | 关键证据 |
|---|---|---|
| `pnpm check:runtime` | passed | Node.js 22.11.0、pnpm 10.25.0 |
| `pnpm check:contracts` | passed | OpenAPI 与 Web 生成类型无漂移,项目边界通过 |
| `pnpm lint` | passed | Web/Server ESLint 无错误 |
| `pnpm format:check` | passed | 全仓 Prettier 通过 |
| `pnpm typecheck` | passed | Web、Vite 和 Server TypeScript 通过 |
| runtime | 3/3 | 22.x 系列与相邻主版本 |
| governance | 10/10 | 功能档案和 Review 门禁 |
| MySQL 规范 | 2/2 | 当前架构/规范使用 5.7.x |
| 环境 | 10/10 | 部署手册使用 5.7.x,其他环境边界保持 |
| Schema(跳过严格发布基线) | 28/28 | 生成、验证、历史 manifest 和字符规则回归 |
| contracts | 3/3 | 生成契约跟踪与漂移阻断 |
| boundaries | 16/16 | 前后端与 HTTP 边界 |
| deployment | 6/6 | 唯一 Ubuntu 源码发布边界 |
| Web | 11/11 | 请求、adapter 与外壳 |
| Server | 30/30 | API、配置、基础设施和进程 |
| API 预检 | 2/2 | Redis 可达/不可达分支 |
| `pnpm build` | passed | Web、API、Scheduler、Worker 构建成功 |
| `pnpm verify:e2e` | 4/4 | Chromium 桌面/移动页面和健康 API |
| `pnpm verify:source` | passed | 构建产物、systemd、Nginx 一致 |
## 一次性例外失败证据
`pnpm verify:release` 退出码非 0。它依次通过 runtime、契约、lint、格式、类型以及 Schema 之前的测试,随后在 Schema 第 28 个严格发布基线用例失败;实际错误为缺少 `database/schema-baselines/v0.0.8`。Schema 总计 29 项,其中 28 项通过、1 项为该已知失败。
`pnpm schema:verify` 在直接目录校验处失败;`pnpm governance:finish GOV-011 runtime-version-series` 在其前置 `test:schema-baseline` 的严格发布基线用例处失败。两者根因都是同一个 v0.0.8 目录缺失条件。原因、用户授权和禁止伪造边界见 `schema-baseline-waiver.md`;其余等价门禁已逐项执行并保存上表证据。
## 安全证据
- `pnpm audit --prod --registry=https://registry.npmjs.org/`:`No known vulnerabilities found`。
- `redis-cli -h 127.0.0.1 -p 6379 ping`:`PONG`,只验证本机开发 Redis。
- 构建产物扫描只命中 `MYSQL_PASSWORD`、`AI_API_KEY` 等配置键和必填错误文案,没有真实值、连接串或 Authorization 头。
- 本次没有新增依赖、SQL、命令执行、数据库写入、生产连接或外部网络请求。
- 健康详情只返回三段版本、库名和时区,不返回原始后缀、地址、账号或密码。
## 性能证据
- Web JS:163908 字节;CSS:805 字节,与 v0.0.8 记录一致。
- 健康检查仍为一次元数据查询,连接池上限 2;无重试、扫描、缓存或消息增量。
- Schema 与 runtime 判断只在启动/治理阶段执行常数时间正则匹配,不进入行情请求热路径。
## GitNexus 证据
- after:2015 节点、2692 关系、49 集群、50 流程,索引 `cce77aa` 为 up-to-date。
- compare:23 文件、70 符号、11 流程、HIGH;运行影响仅在既有 Schema 与 API 健康路径。
- `AGENTS.md` 的 GitNexus 计数由 `analyze` 自动从 2004/2681 更新为 2015/2692。
@@ -0,0 +1,21 @@
# GOV-011 视觉回归记录
- 页面:应用工程基础外壳
- 变更类型:后端版本判断、测试、注释和文档;无页面样式或交互修改
- 结论:无可观察视觉回归
## 桌面
- Chromium 视口:1440×900
- 截图:[app-shell-desktop-1440x900-cce77aa.png](/Users/citrons/Documents/Codex/2026-08-12/wo-x/a-share-analysis/docs/features/GOV-011-runtime-version-series/screenshots/iterations/app-shell-desktop-1440x900-cce77aa.png)
- 检查:`main` 可见,标题正常,无横向溢出,控制台 warning/error 为空。
## 移动
- Chromium 视口:390×844
- 截图:[app-shell-mobile-390x844-cce77aa.png](/Users/citrons/Documents/Codex/2026-08-12/wo-x/a-share-analysis/docs/features/GOV-011-runtime-version-series/screenshots/iterations/app-shell-mobile-390x844-cce77aa.png)
- 检查:标题与主内容正常换行和留白,无横向溢出、遮挡或裁切,控制台 warning/error 为空。
## 自动化证据
`pnpm verify:e2e` 在 desktop-chromium 与 mobile-chromium 共执行 4 项,全部通过;覆盖页面可见性、横向溢出、运行时错误和同源 `/api/v1/health` 契约。截图生成后测试 API 与 Vite 服务均通过 SIGINT 关闭,端口 3000/5173 无遗留监听。
@@ -0,0 +1,22 @@
# GOV-011 发布说明
- 发布版本:v0.0.9
- 状态:已发布
- 发布日期:2026-08-17
## 调整
- Node.js 运行时约束明确为完整 22.x,不绑定 minor 或 patch。
- MySQL 客户端、mysqldump、服务端和 API 健康检查统一接受完整 5.7.x,不设置最低 patch。
- MySQL 健康详情显示服务端实际三段版本,不再硬编码 5.7.42。
- 系统架构、代码开发规范、本地开发和 Ubuntu 源码部署手册统一使用系列版本口径。
## 保持不变
- `utf8mb4`、`utf8mb4_general_ci`、`+08:00`、固定开发库和主机白名单继续严格校验。
- HTTP/OpenAPI 响应结构、Web API、Redis、RocketMQ、Scheduler、Worker、数据库 Schema 和源码部署拓扑不变。
- 历史 QA、Schema 清单、CHANGELOG 历史版本和已发布功能档案继续记录当时真实 patch。
## 已知例外
v0.0.8 没有开发库 Schema 基线。用户确认开发库为空并授权 GOV-011 一次性跳过;仓库没有伪造基线或增加通用绕过开关。该例外导致 `verify:release`、`schema:verify` 和 `governance:finish` 在同一基线存在性检查失败,其他门禁已逐项执行并留证。
@@ -0,0 +1,22 @@
# Node 与 MySQL 系列版本约束需求
## 功能需求
- FR-001:运行时门禁必须以主版本 22 判断 Node.js,不绑定 minor 或 patch。
- FR-002:Schema 生成与验证必须以 major/minor 5.7 判断 mysql 客户端、mysqldump 客户端和 MySQL 服务端,不绑定 patch。
- FR-003:API MySQL 健康检查必须接受任意 5.7.x,并在成功详情中显示实际版本。
- FR-004:MySQL 5.7.x 系列校验不得放宽数据库名、字符集、排序规则、时区或开发环境安全边界。
- FR-005:现行架构、开发规范和部署手册必须使用 Node.js 22.x、MySQL 5.7.x;历史证据中的实际版本不批量改写。
## 质量需求
- 必须测试系列内至少两个不同补丁版本和系列外上下边界。
- 必须遵循 RED → GREEN:先让 5.7.41 被精确 5.7.42 校验拒绝,再实施系列校验。
- `assertMysql57Metadata` 的 GitNexus 风险为 CRITICAL,必须完整回归 Schema 生成、历史验证、当前发布基线和治理启动相关测试。
- 不新增依赖,不增加生产请求、数据库查询或后台任务。
## 安全与性能
- 版本字符串只做固定格式匹配,不执行命令、不拼接 SQL。
- 数据库访问仍限于既有只读元数据查询;本功能不连接生产数据库。
- 运行时只增加常数时间字符串判断,不产生可测量的吞吐或内存影响。
@@ -0,0 +1,52 @@
# GOV-011 代码 Review
- reviewer_type:self
- reviewer:当前实现代理结构化自审
- 基线:`v0.0.8` / `9e85809`
- 审查实现:`cce77aa`
- 日期:2026-08-17
## 审查范围
审查 Node 特征测试、Schema 元数据校验、MySQL 健康客户端、治理测试、现行架构/规范/部署文档、GitNexus 影响和一次性 Schema 例外。重点检查版本格式、错误边界、历史清单兼容、健康信息泄漏和门禁真实性。
## 发现
### 已关闭问题
| 严重程度 | 位置 | 问题 | 处置 |
|---|---|---|---|
| Important | `tools/database/schema-baseline.test.mjs` 历史清单篡改测试 | 完整回归仍断言旧的“服务端必须为 5.7.42”文案,导致生产实现转为系列口径后测试失败。 | 更新为 `5.7.x` 断言;排除已授权发布基线用例后 Schema 28/28。 |
| Minor | `implementation-plan.md` 全量门禁预期 | 原计划把 `verify:release` 写为 PASS,但该命令包含必然触发一次性 Schema 例外的测试。 | 修正文档为真实失败并要求手工执行其余等价门禁。 |
### 未发现问题
未发现未关闭的 Critical、Important 或阻塞性 Minor。服务端正则只接受 `5.7.<数字>` 与 `-`/`+` 后缀;5.6、8.0、无 patch 和文字 patch 均拒绝。字符集、排序规则、库名、时区和生产数据库边界没有放宽。
## 测试缺口
没有针对每个 MySQL 5.7 patch 建立真实数据库兼容矩阵;这是用户明确接受的系列版本策略。本次使用纯函数、固定元数据和现有集成测试验证判断边界,不证明第三方数据库每个 patch 都没有厂商缺陷。首次真实迁移和查询仍必须在目标 5.7.x 环境验证。
## 安全与残余风险
- 版本字符串不执行、不进入 SQL;健康详情不回显原始后缀、地址、账号或密码。
- Schema 入口仍固定 development、开发库和主机白名单;本次未连接生产数据库。
- 残余风险一是不同 5.7 patch 的已知缺陷,二是 v0.0.8 缺少可验证 Schema 基线。前者由真实部署验证控制,后者由用户授权的一次性例外承担。
## 性能与资源影响
- 只增加常数时间正则捕获,没有新增查询、网络、重试、缓存、任务或依赖。
- 健康查询次数和连接池上限不变;Web 构建体积与 v0.0.8 一致。
- 不进入行情采集、分析、Redis、RocketMQ 或图表热路径,无需负载测试。
## GitNexus 与同步修改
开发前 `assertMysql57Metadata` 为 CRITICAL,5 个直接调用方、10 个受影响符号、5 组流程;`MysqlHealthClient` 为 LOW。开发后相对 v0.0.8 为 HIGH、23 文件、70 符号、11 流程,运行影响均属于计划中的 Schema 与 API 健康路径。HTTP/OpenAPI、Web API、消息、数据库 Schema、Redis、Scheduler、Worker 和部署拓扑没有计划外修改。
## v0.0.9 发布封存复核
- 发布只增加版本、CHANGELOG、索引和功能状态,不修改运行时判断、健康查询或数据库边界。
- 一次性 Schema 例外、HIGH GitNexus 风险和手工等价门禁证据均保留,没有改写为全量门禁通过。
- 发布标签必须指向通过上述 Review 的封存提交,并与 Gitea 远程引用核对。
最终结论:passed
@@ -0,0 +1,39 @@
# GOV-011 开发规范符合性 Review
- reviewer_type:self
- reviewer:当前实现代理结构化自审
- 审查提交:`cce77aa`
- 日期:2026-08-17
## 检查结果
- [x] PRD、需求、设计、实施计划、测试计划、开发总结、QA、GitNexus、Review、发布与回退资料齐全。
- [x] 修改关键符号前执行 GitNexus 上游影响分析,提交前执行 detect-changes。
- [x] HIGH/CRITICAL 风险已向用户说明,并以完整 Schema 与健康回归控制。
- [x] 行为修改遵循 RED-GREEN,测试失败原因来自旧实现而非语法或夹具。
- [x] 关键版本口径和安全边界使用准确中文注释,没有逐行复述。
- [x] 未新增依赖、预测性抽象、空分层或过度文件拆分。
- [x] 没有修改前端 Axios/API 分域、后端业务模块分层或 OpenAPI DTO。
- [x] 所有阶段提交使用中文 Conventional Commit 和 GOV-011,并立即推送 Gitea。
- [x] 没有使用 GitHub、强推、生产数据库或真实凭据。
- [x] 历史 QA、Schema 清单和已发布档案保持原样。
## 不符合项与处置
完成门禁无法通过 v0.0.8 Schema 基线存在性校验。该项不是静默忽略:用户在开发前明确确认当前开发库为空并要求本次跳过,仓库保存 `schema-baseline-waiver.md`,实际失败命令和风险写入 QA。没有修改治理工具,也没有伪造 `not_applicable`、`captured_empty` 或空 SQL。除此之外未发现未处置的不符合项。
## 安全、性能与架构检查
安全边界保持固定开发环境、库名、主机白名单、字符集、排序规则和时区;健康输出已脱敏,依赖审计 0 漏洞。性能只增加常数时间字符串匹配,查询、连接池、构建体积和执行流数量没有增加。架构仍为 Vue 3 Web 与 NestJS API/Scheduler/Worker 独立项目、Ubuntu 源码部署和外部 MySQL/Redis/RocketMQ。
## GitNexus 与开发总结检查
before、impact-plan、detected-changes、after、comparison 互相对应;最终索引为 2015 节点、2692 关系、50 流程。开发总结包含七个固定章节,明确原始需求、范围变化、实际完成、缺陷、延期、提交和验证证据;HIGH 风险与一次性 Schema 例外均有具体边界,不以空占位通过门禁。
## v0.0.9 发布封存复核
- VERSION、CHANGELOG、文档索引、manifest、开发总结和发布说明的 v0.0.9 状态必须一致。
- 发布提交和标签分别精确推送;禁止强推、批量推送标签或移动已发布标签。
- 历史 v0.0.8 的 5.7.42 事实不因当前系列口径反向改写。
最终结论:passed
@@ -0,0 +1,24 @@
# GOV-011 回退说明
GOV-011 不修改数据库结构、迁移或数据,不写 Redis,不操作 RocketMQ,也不修改生产配置。回退只涉及版本判断、健康详情、测试、注释和当前规范文档。
## 触发条件
- 合法 MySQL 5.7.x 被错误拒绝,或 5.6/8.x 被错误放行。
- 历史 captured/captured_empty manifest 无法验证。
- 健康接口泄漏原始版本后缀或返回错误 patch。
- 系列判断导致 Schema 生成、治理启动或 API 启动出现无法修复的回归。
## 回退步骤
1. 使用新的中文 Conventional Commit 恢复 `assertMysql57Metadata` 和 `MysqlHealthClient` 到上一已验证行为;禁止重写 Gitea 历史、强推或移动已发布标签。
2. 同步恢复对应测试、代码注释和当前架构/部署文档,避免实现与规范不一致。
3. 不改写已经发布的 GOV-011 档案;通过后续回退记录说明原因、范围和提交。
4. 因无数据库结构或数据变化,不执行数据库回滚。
## 回退验证
- 重新执行 runtime、Schema、MySQL 规范、环境、Server 健康、类型和构建测试。
- 执行 OpenAPI 契约、Playwright 双视口和源码发布验证。
- 运行 GitNexus impact、detect-changes 与 analyze,记录回退实际流程影响。
- v0.0.8 Schema 一次性例外仍只作为历史事实存在,不因代码回退生成伪造基线。
@@ -0,0 +1,22 @@
# v0.0.8 Schema 基线一次性例外
- 功能编号:GOV-011
- 日期:2026-08-17
- 适用范围:仅 GOV-011 开发启动
## 事实记录
按常规流程执行 `pnpm schema:baseline` 时,本机因不存在 MySQL 5.7 `mysql`/`mysqldump` 客户端而在执行 `mysql --version` 前失败,未连接数据库、未生成目录或半成品;随后 `schema:verify` 因 `database/schema-baselines/v0.0.8` 不存在而按设计阻断。
用户确认当前开发库没有业务结构,并明确要求本次先跳过备份。GOV-011 只调整 Node/MySQL 版本系列判断,不创建表、迁移或数据,不读取生产数据库。
## 处理决定
- 不伪造 `not_applicable`、`captured_empty`、空 SQL、版本信息或校验摘要。
- 不修改 `governance:start` 或 Schema 工具增加通用跳过开关。
- 手工保存与 `governance:start` 同等的 GitNexus before/impact 文档,并在 GOV-011 Review 中核对本例外。
- 本例外不自动适用于后续功能;下一次需要 Schema 基线时仍应提供可验证的 MySQL 5.7.x 客户端或由用户再次明确决定。
## 风险
缺少 v0.0.8 Schema 基线意味着无法用仓库证据证明当时开发库为空。该风险由用户接受;GOV-011 不修改数据库,不能借本例外执行任何 Schema 或数据写入。
Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

@@ -0,0 +1,58 @@
# GOV-011 测试计划
- 功能编号:GOV-011
- 验证环境:Node.js 22.11.0、pnpm 10.25.0、macOS 开发机
- 数据库边界:不连接、探测或读取生产数据库;本次不执行真实 Schema 导出
## 1. Node.js 系列验证
- 接受 `22.0.0`、`22.11.0` 和带预发布/构建后缀的合法 22.x。
- 拒绝 21.x、23.x、空字符串、`v22` 和其他无法解析格式。
- pnpm 继续只接受 10.x,不因 Node 约束调整而放宽。
## 2. Schema 元数据验证
- 接受 MySQL 服务端 `5.7.0`、`5.7.41`、`5.7.42-log`。
- 拒绝 `5.6.51`、`8.0.40`、`5.7`、`5.7.x` 和空字符串。
- mysql 与 mysqldump 客户端继续要求合法 5.7.x。
- 服务端版本通过后,字符集仍必须为 `utf8mb4`,排序规则仍必须为 `utf8mb4_general_ci`。
- 回归 captured、captured_empty、not_applicable、历史 manifest、生成入口和发布门禁调用链。
- 因用户授权的 v0.0.8 基线一次性例外,严格发布基线用例预期只在目录缺失处失败;使用 `--test-skip-pattern='严格发布门禁'` 验证其余 28 项全部通过。
## 3. API 健康检查验证
- `5.7.41-log` 返回 `MySQL 5.7.41 / <数据库> / +08:00`,证明 patch 来自服务端元数据而非硬编码。
- 拒绝 5.6.x、8.x 和无效版本格式。
- 拒绝错误库名、`utf8`、`utf8mb4_0900_ai_ci` 和 `SYSTEM` 时区。
- 保持固定只读元数据查询、健康 DTO 结构和生产库名按当前配置校验。
- 执行 Server 全量测试、类型检查和 API/Scheduler/Worker 三进程构建。
## 4. 规范与部署验证
- 当前系统架构、代码开发规范、本地开发和 Ubuntu 源码部署文档必须写明 `MySQL 5.7.x`。
- 上述四份当前文档不得再出现 `MySQL 5.7.42`;历史 QA、Schema 清单、CHANGELOG 历史版本和已发布功能档案不参与该否定扫描。
- Node.js 22.x、pnpm 10.25.0、Ubuntu 源码部署、systemd、Nginx、Redis 和 RocketMQ 约束保持不变。
## 安全验证
- 版本字符串仅进入固定正则,不执行命令、不拼接 SQL。
- MySQL 健康错误不回显服务端原始附加文本、连接地址、账号或密码。
- Schema 测试使用固定夹具和依赖注入,不连接真实数据库;本功能不执行 `schema:baseline`。
- `pnpm audit --prod --registry=https://registry.npmjs.org/` 必须为 0 已知漏洞。
- 扫描 Web/Server 构建产物中的凭据模式;配置键名允许存在,真实值、连接串和授权头不得存在。
- `git diff --check`、GitNexus detect-changes 和 Review 核对没有生产数据、真实 `.env` 或凭据进入提交。
## 性能验证
- 版本解析为启动/治理阶段常数时间正则匹配,不增加数据库查询、网络调用、重试、缓存或消息操作。
- 健康检查继续只执行一次既有元数据查询,连接池上限仍为 2。
- Web 页面和依赖未变化,生产 JS/CSS 体积应与 v0.0.8 基线一致。
- 本功能不改变行情计算、数据库扫描、Redis 热点、RocketMQ 吞吐、Worker 并发或图表渲染,因此不执行负载测试;后续触及这些路径的业务功能必须重新设定性能目标。
## 7. 全量与视觉验证
- 执行 runtime、governance、MySQL、环境、Schema、契约、边界、部署、Web 和 Server 测试。
- 执行 OpenAPI 重新生成、lint、格式、类型检查、Web/Server 构建和源码发布验证。
- Playwright 在 Chromium 1440×900 与 390×844 下验证页面、同源健康 API、横向溢出和控制台。
- 保存桌面/移动截图并人工检查无重叠、裁切或空白渲染回归。
- 真实执行 `pnpm verify:release`、`pnpm schema:verify` 和 `pnpm governance:finish GOV-011 runtime-version-series`;三者因同一个已授权 v0.0.8 基线缺失条件失败,必须保存失败证据并手工执行其余等价门禁。
+10 -10
View File
@@ -8,7 +8,7 @@
- 前端:Vue 3、Vite、TypeScript、Dart Sass、Naive UI;浏览器 HTTP 请求统一使用 Axios,接口类型由 OpenAPI 生成。
- 后端:NestJS、TypeScript。
- 数据库:MySQL 5.7.42,字符集 `utf8mb4`,排序规则 `utf8mb4_general_ci`;缓存:Redis;消息队列:RocketMQ 5.x。
- 数据库:MySQL 5.7.x,字符集 `utf8mb4`,排序规则 `utf8mb4_general_ci`;缓存:Redis;消息队列:RocketMQ 5.x。
- 图表:Lightweight Charts负责K线和分时,ECharts负责热力图、分布和资金趋势。
- AI:由服务端调用兼容 OpenAI 格式的付费 API,密钥不得下发浏览器。
@@ -127,24 +127,24 @@ count += 1;
- 业务代码只依赖项目定义的 `MessageBusAdapter` 和版本化事件契约,禁止直接依赖 RocketMQ SDK 类型;客户端、NameServer 或 Proxy 接入方式由基础设施适配层决定。
- 免费数据源通过 Adapter 统一为内部模型,上层不得依赖供应商原始字段。
## 11. MySQL 5.7 兼容规范
## 11. MySQL 5.7.x 兼容规范
- 开发、测试和生产环境统一使用 MySQL 5.7.42,禁止使用其他 5.7 补丁、`latest`、MySQL 8.x 或其他数据库代替兼容性验证。
- 开发、测试和生产环境统一使用 MySQL 5.7.x,不设置最低补丁版本;禁止使用 `latest`、MySQL 5.6.x、8.x、MariaDB 或其他数据库代替兼容性验证。
- 创建数据库必须显式声明 `DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci`;建表与迁移脚本必须显式保持 `DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci`。
- ORM 和数据库驱动必须声明 `utf8mb4`,连接建立后验证会话、数据库和表的排序规则为 `utf8mb4_general_ci`,不得依赖服务器默认值。
- 文本列默认继承表级规则。列级改变字符集或排序规则必须由具体功能设计解释,并通过 ADR 审批。
- 禁止使用 MySQL 8.x 专属或在 5.7 行为不同的公用表表达式、递归 CTE、窗口函数、函数索引、不可见索引、`utf8mb4_0900_*` 排序规则和 JSON 增强能力。
- 不得依赖 `CHECK` 约束在 MySQL 8.x 的强制执行语义;MySQL 5.7 下的业务约束必须由边界校验、普通索引或可测试的写入逻辑保证。
- 不得依赖 `CHECK` 约束在 MySQL 8.x 的强制执行语义;MySQL 5.7.x 下的业务约束必须由边界校验、普通索引或可测试的写入逻辑保证。
- `utf8mb4_general_ci` 不区分大小写。证券代码、外部事件 ID、幂等键等身份字段必须规范化输入,或显式采用经设计批准的二进制比较与唯一键,不能误把默认比较当成大小写敏感。
- 索引长度按 MySQL 5.7 和 `utf8mb4` 最多四字节字符预算;超长标识使用受控长度、前缀索引或稳定摘要时,必须说明唯一性和碰撞处理。
- JSON 字段只能使用 MySQL 5.7 已支持并经过真实环境验证的能力,查询和索引不得建立在 8.x 特性上。
- 每份迁移脚本必须能够从上一版本基线在 MySQL 5.7 正向执行;禁止用直接修改共享数据库表代替迁移脚本。
- 索引长度按 MySQL 5.7.x 和 `utf8mb4` 最多四字节字符预算;超长标识使用受控长度、前缀索引或稳定摘要时,必须说明唯一性和碰撞处理。
- JSON 字段只能使用 MySQL 5.7.x 已支持并经过真实环境验证的能力,查询和索引不得建立在 8.x 特性上。
- 每份迁移脚本必须能够从上一版本基线在 MySQL 5.7.x 正向执行;禁止用直接修改共享数据库表代替迁移脚本。
- 代码 Review 必须检查服务端版本、字符集、排序规则、SQL/迁移兼容性、索引长度和字符串比较语义;任一不符合项按 Important 处理并阻断发布。
### Schema 基线规范
- 每个新应用版本开发前必须封存上一已发布版本的开发库 Schema;只能读取 `APP_ENV=development`、`a_share_analysis_dev` 和 MySQL 5.7,主机仅允许回环地址或固定开发白名单 `112.192.20.11`,禁止连接、探测或读取生产数据库。配置优先读取 Git 忽略的 `deploy/env/development/api.env.local`。
- 导出使用 MySQL 5.7 `mysqldump` 的 `--no-data --routines --triggers --events`,完整保留表、索引、外键、视图、触发器、存储过程、函数和事件,不得包含任何表数据。
- 每个新应用版本开发前必须封存上一已发布版本的开发库 Schema;只能读取 `APP_ENV=development`、`a_share_analysis_dev` 和 MySQL 5.7.x,主机仅允许回环地址或固定开发白名单 `112.192.20.11`,禁止连接、探测或读取生产数据库。配置优先读取 Git 忽略的 `deploy/env/development/api.env.local`。
- 导出使用 MySQL 5.7.x `mysqldump` 的 `--no-data --routines --triggers --events`,完整保留表、索引、外键、视图、触发器、存储过程、函数和事件,不得包含任何表数据。
- 规范化必须确定性删除导出时间、环境 `DEFINER` 和表选项中的当前 `AUTO_INCREMENT=<值>`,同时保留列定义的 `AUTO_INCREMENT` 属性和业务 SQL。
- 账号密码只能通过受控子进程环境传递,不得进入参数、日志、SQL、清单或 checksum 文件。
- `manifest.yaml`、`checksum.sha256` 和 `schema.sql` 的 SHA-256 必须一致;既有版本目录只允许内容完全一致的幂等验证,不允许覆盖。
@@ -176,7 +176,7 @@ count += 1;
- 后端评估数据量与算法复杂度、MySQL 查询/索引/N+1、Redis 用途/TTL/一致性/击穿、API 载荷与分页、Scheduler/Worker 并发/幂等/背压,以及外部数据源和 AI 的超时/重试/批处理/成本。
- 前端评估依赖与构建体积、渲染次数、长列表、图表数据量、交互响应和内存占用;不能只以开发环境主观感觉作为证据。
- 高风险路径必须提供 benchmark、profile 或负载测试;低频治理逻辑等不适用场景必须写明无需负载测试的原因和边界。
- 性能优化不得牺牲数据口径、安全、可观察性、异常恢复或 MySQL 5.7 兼容性;禁止无证据的预优化。
- 性能优化不得牺牲数据口径、安全、可观察性、异常恢复或 MySQL 5.7.x 兼容性;禁止无证据的预优化。
## 15. 代码 Review 要求
+3
View File
@@ -19,6 +19,7 @@
## 环境与部署
- [本地开发环境](deployment/local-development.md)
- [Tailscale + SSH 隧道访问 TDX 开发手册](deployment/tailscale-tdx-development.md)
- [Ubuntu 源码生产部署(唯一生产方式)](deployment/ubuntu-source-production.md)
## 数据库版本基线
@@ -36,6 +37,7 @@
- [GOV-001:工程治理基线](features/GOV-001-engineering-governance/manifest.yaml)
- [FEAT-MO-001:市场综合概览](features/FEAT-MO-001-market-overview/manifest.yaml)
- [FEAT-DS-001:数据源接入架构与 TDX PoC 规划(采集器延期)](features/FEAT-DS-001-tdx-ingestion-poc/manifest.yaml)
- [GOV-002:PRD 与 Review 门禁](features/GOV-002-prd-review-gates/manifest.yaml)
- [GOV-003:项目专用 Gitea 远程仓库](features/GOV-003-gitea-local-remote/manifest.yaml)
- [GOV-004:提交后强制推送 Gitea](features/GOV-004-mandatory-gitea-push/manifest.yaml)
@@ -45,5 +47,6 @@
- [GOV-008:RocketMQ 消息队列架构调整](features/GOV-008-rocketmq-adoption/manifest.yaml)
- [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)
功能档案是需求、设计、代码、测试、版本和回退之间的唯一正式关联入口。
+1 -1
View File
@@ -13,7 +13,7 @@ export interface RedisRuntimeConfig {
tls: boolean;
}
/** MySQL 配置固定 5.7.42 兼容口径,启用状态决定凭据是否必填。 */
/** MySQL 配置固定 5.7.x 兼容口径,启用状态决定凭据是否必填。 */
export interface MysqlRuntimeConfig {
enabled: boolean;
host: string;
@@ -23,7 +23,7 @@ describe('基础设施只读健康客户端', () => {
expect(commands).toEqual(['CONNECT', 'PING']);
});
it('MySQL 使用固定元数据查询并校验 5.7 与数据库口径', async () => {
it('MySQL 使用固定元数据查询并返回实际 5.7.x 版本', async () => {
const queries: string[] = [];
const client = new MysqlHealthClient(
{
@@ -32,7 +32,7 @@ describe('基础设施只读健康客户端', () => {
return [
[
{
version: '5.7.42-log',
version: '5.7.41-log',
databaseName: 'a_share_analysis_dev',
charset: 'utf8mb4',
collation: 'utf8mb4_general_ci',
@@ -49,7 +49,7 @@ describe('基础设施只读健康客户端', () => {
await expect(client.check()).resolves.toEqual({
status: 'healthy',
detail: 'MySQL 5.7.42 / a_share_analysis_dev / +08:00',
detail: 'MySQL 5.7.41 / a_share_analysis_dev / +08:00',
});
expect(queries).toEqual([MYSQL_HEALTH_QUERY]);
});
@@ -76,14 +76,17 @@ describe('基础设施只读健康客户端', () => {
'a_share_analysis_dev',
);
await expect(createClient({ version: '8.0.40' }).check()).rejects.toThrow(/MySQL 5.7/);
await expect(createClient({ version: '5.7.41' }).check()).rejects.toThrow(/5\.7\.42/);
for (const version of ['5.6.51', '8.0.40', '5.7', '5.7.x']) {
await expect(createClient({ version }).check()).rejects.toThrow(/MySQL 5\.7\.x/);
}
await expect(createClient({ databaseName: 'a_share_analysis' }).check()).rejects.toThrow(
/a_share_analysis_dev/,
);
await expect(createClient({ charset: 'utf8' }).check()).rejects.toThrow(/utf8mb4/);
await expect(createClient({ collation: 'utf8mb4_0900_ai_ci' }).check()).rejects.toThrow(
/utf8mb4_general_ci/,
);
await expect(createClient({ timezone: 'SYSTEM' }).check()).rejects.toThrow(/\+08:00/);
});
it('MySQL 按当前配置校验生产库名', async () => {
@@ -36,8 +36,9 @@ export class MysqlHealthClient implements OnModuleDestroy {
const [rows] = await this.client.query(MYSQL_HEALTH_QUERY);
const row = (rows as unknown as MysqlMetadataRow[])[0];
if (!row) throw new Error('MySQL 未返回元数据');
if (!/^5\.7\.42(?:[-+.]|$)/.test(row.version)) {
throw new Error('MySQL 5.7.42 版本要求未满足');
const versionMatch = /^(5\.7\.\d+)(?:[-+].*)?$/.exec(row.version ?? '');
if (!versionMatch) {
throw new Error('MySQL 5.7.x 版本要求未满足');
}
if (row.databaseName !== this.expectedDatabase) {
throw new Error(`MySQL 健康检查必须连接 ${this.expectedDatabase}`);
@@ -50,7 +51,7 @@ export class MysqlHealthClient implements OnModuleDestroy {
return {
status: 'healthy',
detail: `MySQL 5.7.42 / ${row.databaseName} / ${row.timezone}`,
detail: `MySQL ${versionMatch[1]} / ${row.databaseName} / ${row.timezone}`,
};
}
@@ -63,7 +64,7 @@ export class MysqlHealthClient implements OnModuleDestroy {
}
}
/** 创建最多两个连接的只读健康池,并显式应用 MySQL 5.7.42 会话时区。 */
/** 创建最多两个连接的只读健康池,并显式应用 MySQL 5.7.x 会话时区。 */
export function createMysqlHealthClient(config: MysqlRuntimeConfig): MysqlHealthClient {
const pool: Pool = createPool({
host: config.host,
@@ -3,7 +3,7 @@ import type { MysqlConnectionOptions } from 'typeorm/driver/mysql/MysqlConnectio
import type { MysqlRuntimeConfig } from '../../config/src/runtime-config';
/**
* 生成 MySQL 5.7.42 TypeORM 基线选项;迁移未落地前不自动运行,且永久禁止 synchronize。
* 生成 MySQL 5.7.x TypeORM 基线选项;迁移未落地前不自动运行,且永久禁止 synchronize。
*/
export function buildTypeOrmOptions(config: MysqlRuntimeConfig): MysqlConnectionOptions {
return {
+5 -5
View File
@@ -73,8 +73,8 @@ export function assertSafeDevelopmentConfiguration(config) {
}
/**
* 客户端保持 5.7 系列以生成兼容导出;服务端固定 5.7.42,避免开发、测试和生产
* 由不同补丁行为产生漂移。同时核对数据库真实字符规则,而不是信任 env 声明。
* mysql、mysqldump 与服务端统一接受完整 5.7.x;字符集和排序规则仍按精确值
* 校验,避免放宽补丁版本时意外放宽数据库结构兼容边界。
*/
export function assertMysql57Metadata(metadata) {
if (!/^5\.7\.\d+(?:[-+].*)?$/.test(metadata.mysqlClientVersion ?? '')) {
@@ -85,8 +85,8 @@ export function assertMysql57Metadata(metadata) {
`mysqldump 客户端必须为 5.7.x,实际 ${metadata.mysqldumpClientVersion || '(空)'}`,
);
}
if (!/^5\.7\.42(?:[-+].*)?$/.test(metadata.serverVersion ?? '')) {
throw new Error(`MySQL 服务端必须为 5.7.42,实际 ${metadata.serverVersion || '(空)'}`);
if (!/^5\.7\.\d+(?:[-+].*)?$/.test(metadata.serverVersion ?? '')) {
throw new Error(`MySQL 服务端必须为 5.7.x,实际 ${metadata.serverVersion || '(空)'}`);
}
requireExactValue(metadata.databaseCharset, REQUIRED_CHARSET, '开发数据库字符集不符合要求');
requireExactValue(
@@ -663,7 +663,7 @@ export function runBaselineGeneration(options) {
assertMysql57Metadata({
mysqlClientVersion,
mysqldumpClientVersion,
serverVersion: '5.7.42-pending-server-check',
serverVersion: '5.7.0-pending-server-check',
databaseCharset: REQUIRED_CHARSET,
databaseCollation: REQUIRED_COLLATION,
});
+20 -11
View File
@@ -132,19 +132,28 @@ test('拒绝错误字符集、排序规则和不完整的启用配置', () => {
);
});
test('只接受 MySQL 5.7 客户端、5.7.42 服务端和固定数据库字符规则', () => {
assert.doesNotThrow(() => assertMysql57Metadata(validMetadata));
test('接受完整 MySQL 5.7.x 服务端系列', () => {
for (const serverVersion of ['5.7.0', '5.7.41', '5.7.42-log']) {
assert.doesNotThrow(() =>
assertMysql57Metadata({ ...validMetadata, serverVersion }),
);
}
});
test('拒绝非 MySQL 5.7.x 版本并保持固定数据库字符规则', () => {
for (const serverVersion of ['5.6.51', '8.0.40', '5.7', '5.7.x', '']) {
assert.throws(
() => assertMysql57Metadata({ ...validMetadata, serverVersion }),
/MySQL 服务端必须为 5\.7\.x/,
);
}
assert.throws(
() => assertMysql57Metadata({ ...validMetadata, serverVersion: '8.0.39' }),
/服务端必须为 5\.7\.42/,
() => assertMysql57Metadata({ ...validMetadata, mysqlClientVersion: '8.0.40' }),
/mysql 客户端必须为 5\.7\.x/,
);
assert.throws(
() => assertMysql57Metadata({ ...validMetadata, serverVersion: '5.7.41' }),
/服务端必须为 5\.7\.42/,
);
assert.throws(
() => assertMysql57Metadata({ ...validMetadata, mysqlClientVersion: '8.0.39' }),
/mysql 客户端必须为 5\.7/,
() => assertMysql57Metadata({ ...validMetadata, mysqldumpClientVersion: '8.0.40' }),
/mysqldump 客户端必须为 5\.7\.x/,
);
assert.throws(
() => assertMysql57Metadata({ ...validMetadata, databaseCollation: 'utf8mb4_bin' }),
@@ -501,7 +510,7 @@ test('校验拒绝篡改成错误 MySQL 版本或伪造对象范围的真实清
const manifest = JSON.parse(readFileSync(manifestPath, 'utf8'));
manifest.mysql_server_version = '8.0.39';
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`);
assert.throws(() => verifyBaselineDirectory(target, 'v0.0.5'), /服务端必须为 5\.7\.42/);
assert.throws(() => verifyBaselineDirectory(target, 'v0.0.5'), /服务端必须为 5\.7\.x/);
manifest.mysql_server_version = '5.7.42-log';
manifest.objects.events = false;
@@ -181,7 +181,8 @@ test('部署文档要求本机外部 Redis 和唯一 Ubuntu 源码生产路径',
assert.doesNotMatch(source, /systemctl (?:restart|status) a-share-\w+\.service\.example/);
assert.match(source, /不负责安装/);
for (const document of [local, source]) {
assert.match(document, /MySQL 5\.7\.42/);
assert.match(document, /MySQL 5\.7\.x/);
assert.doesNotMatch(document, /MySQL 5\.7\.42/);
}
});
+6 -4
View File
@@ -5,19 +5,20 @@ import test from 'node:test';
const architecturePath = new URL('../../docs/architecture/system-architecture.md', import.meta.url);
const standardsPath = new URL('../../docs/governance/code-development-standards.md', import.meta.url);
test('系统架构固定 MySQL 5.7 字符集与排序规则', async () => {
test('系统架构固定 MySQL 5.7.x 系列、字符集与排序规则', async () => {
const architecture = await readFile(architecturePath, 'utf8');
assert.match(architecture, /MySQL 5\.7/);
assert.match(architecture, /MySQL 5\.7\.x/);
assert.doesNotMatch(architecture, /MySQL 5\.7\.42/);
assert.match(architecture, /utf8mb4/);
assert.match(architecture, /utf8mb4_general_ci/);
});
test('开发规范覆盖 MySQL 5.7 全链路兼容性要求', async () => {
test('开发规范覆盖 MySQL 5.7.x 全链路兼容性要求', async () => {
const standards = await readFile(standardsPath, 'utf8');
for (const requiredText of [
'MySQL 5.7',
'MySQL 5.7.x',
'utf8mb4',
'utf8mb4_general_ci',
'公用表表达式',
@@ -31,4 +32,5 @@ test('开发规范覆盖 MySQL 5.7 全链路兼容性要求', async () => {
]) {
assert.ok(standards.includes(requiredText), `开发规范缺少数据库基线:${requiredText}`);
}
assert.doesNotMatch(standards, /MySQL 5\.7\.42/);
});
+7 -5
View File
@@ -3,18 +3,20 @@ import test from 'node:test';
import { assertSupportedRuntime } from './verify-runtime.mjs';
test('只接受 Node 22 与 pnpm 10', () => {
assert.doesNotThrow(() =>
assertSupportedRuntime({ nodeVersion: '22.11.0', pnpmVersion: '10.25.0' }),
);
test('接受完整 Node.js 22.x 并拒绝相邻主版本', () => {
for (const nodeVersion of ['22.0.0', '22.11.0', '22.99.123-beta.1+build.7']) {
assert.doesNotThrow(() => assertSupportedRuntime({ nodeVersion, pnpmVersion: '10.25.0' }));
}
for (const nodeVersion of ['20.20.2', '24.0.0']) {
for (const nodeVersion of ['21.7.3', '23.0.0']) {
assert.throws(
() => assertSupportedRuntime({ nodeVersion, pnpmVersion: '10.25.0' }),
new RegExp(`Node\\.js 必须为 22\\.x,实际 ${nodeVersion.replaceAll('.', '\\.')}`),
);
}
});
test('只接受 pnpm 10.x', () => {
for (const pnpmVersion of ['9.15.0', '11.0.0']) {
assert.throws(
() => assertSupportedRuntime({ nodeVersion: '22.11.0', pnpmVersion }),