128 KiB
构建版本与数据库支持矩阵
首次核查日期:2026 年 9 月 27 日;最新构建证据见本节,第二十六节及此前各节为历史批次。本文区分代码支持、隔离测试和正式生产准入,不把驱动存在视为兼容性验收。
最新正式构建验证(2026-09-30 21:07)
需求沿用已确认范围:规范克隆完成换行整改后的正式构建,不改写已有中文源码,不删除历史产物,也不缩减 Linux 原生、服务或数据库验收要求。
源码、环境及命令
- 精确源码:9e89edae282d8c18ddf9588751961015d220efcf;source_dirty=false。
- 规范独立克隆:.runtime/source-boundary-review-20260930-2015;本次先获取本地主仓库的新提交,再签出精确提交,未复制原工作区依赖。
- 构建机:Windows 11 Home China,版本 10.0.26200,amd64;PowerShell 5.1.26100.9444。
- Go 1.26.6、Node 24.19.0、npm 11.17.0;Vue 3.5.41、Vite 6.4.3。这些是本次清单记录的固定版本,不表示外部最新版本。
- 构建清单 source_line_endings 中后端、前端 policy 均为 lf,受跟踪文件分别为 547、105;依赖安装脚本禁用,使用 npm ci。
在规范克隆目录执行正式入口(本次默认构建两个目标):
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\build\build-release.ps1 -OutputDirectory .\build\review-release-eol
产物与复核
正式包目录为 build/review-release-eol/Scert-20260930-V0.1.0,两个归档位于其父目录。未部署以下产物。
| 产物 | SHA-256 |
|---|---|
| Windows 主程序 | f54bcb328db65dfb2c2fe4ecffb2a19a72aa60c1e91054847b573ff4803e189e |
| Windows 压缩包 | aafd03bc27cc4214945c7fbd1ed627a5e6c12456dd679152c8592669f419f071 |
| Linux 主程序 | 002066975ff917caf1c55b8b1f5fb55ba7d9459aa56d48e9b04cab0bf2be3372 |
| Linux 压缩包 | e9562afcd5ae71ff627cf4922dd46a03004d25c20742dcbe5a09cf12016945c6 |
- 清单中 33 项文件大小和 SHA-256 核对一致;trimpath=true,local_path_check=passed。
- Windows、Linux 的 SHA256SUMS 分别核对 8、21 项文件,不包括校验清单自身;含校验清单的实际压缩包分别为 9、22 个文件。
- 实际压缩包文件集合无缺失或多余项,无重复文件名;逐文件读取内容计算哈希,与 manifest 对应项一致。Linux 执行入口五项均为 0755,无非普通文件冒充文件项。
- 同一克隆执行 go test -count=1 ./...、go vet ./...、go test -count=1 ./internal/releasearchive 通过;前端 npm test 为 237 项通过、0 失败、0 跳过。
- 构建及测试结束后 git status 为空,五个依赖与安装策略文件没有差异。
- [~] 后端全量命令退出成功不证明外部数据库或平台条件跳过项完成;没有将其纳入生产通过声明。
- Linux 原生构建、双平台服务运行、三数据库、重启恢复及完整清库初始化仍待独立验收。
P0-04 保持进行中;本次双目标构建不替代 Linux 原生构建,也不证明归档可逐字节重复生成。线上仍运行此前已验证的 0bb427d,本地包与线上包身份严格区分。
运行时候选选型依据见第二十二节,成员接口验证见第二十三节,项目入口与页面验证见第二十四节;此前各节保留各自批次的源码、依赖和环境证据,不据此推断新代码已完成相同范围的验证。
一、工具链与依赖
| 项目 | 当前固定来源 | 当前核查值 | 发布要求 |
|---|---|---|---|
| Go | backend/go.mod、backend/go.sum |
模块内 go1.26.6 windows/amd64 |
在模块内记录实际版本,不使用仓库根目录的版本推断 |
| 工具链选择 | go env GOTOOLCHAIN |
auto |
自动选择仍必须与模块要求一致,不得降低版本绕过失败 |
| Node.js | frontend/package.json 的 engines、devEngines,锁文件 |
v24.19.0 |
精确匹配,升级需同步声明并重跑测试和构建 |
| npm | 同上,另有 packageManager |
11.17.0 |
精确匹配,使用锁文件安装;Windows 使用 npm.cmd |
| Vue | frontend/package.json、frontend/package-lock.json |
3.5.41 |
直接依赖固定精确版本,声明及锁文件必须一致 |
| Vite | 同上 | 6.4.3 |
同上 |
| Vue 构建插件 | 同上 | 5.2.4 |
同上 |
| SQLite Go 驱动 | backend/go.mod |
modernc.org/sqlite v1.59.0;libc v1.75.7 |
当前实测引擎 3.53.4;最终回归及限制见第二十二节 |
| MySQL Go 驱动 | 同上 | github.com/go-sql-driver/mysql v1.9.3 |
不代表 MySQL 所有服务端版本均通过验收 |
| PostgreSQL Go 驱动 | 同上 | github.com/jackc/pgx/v5 v5.9.2 |
同上 |
| 编译目标 | build/build-release.ps1 |
windows/amd64、linux/amd64 |
核心二进制 CGO_ENABLED=0、-trimpath |
核查命令:
cd backend
go version
go env GOVERSION GOTOOLCHAIN GOOS GOARCH
go mod verify
go test -p 1 -count=1 -timeout=3m ./...
go vet -p=1 ./...
cd ../frontend
node --version
npm.cmd --version
npm.cmd ci
npm.cmd test
npm.cmd run build
历史基线只验证过现有依赖;随后 P0-03 已在 fab98d1 独立克隆重新执行 npm ci、150 项前端测试和双平台候选构建。该次安装仍有脚本批准策略警告,不能证明安装脚本被禁止。P0-04 改为明确禁用依赖安装脚本,执行证据持续记录在《Scert整改任务执行清单.md》,不能将旧安装结果当作新策略验证。
构建机与安装策略
| 项目 | 固定基线或约束 | 验收边界 |
|---|---|---|
| 当前 Windows 构建机 | Windows 11 Home China,系统 10.0.26200,amd64;Windows PowerShell 5.1 |
记录实际值,不把系统显示名称误写成内核版本;系统更新后需重新验收 |
| Linux 原生构建机 | 脚本允许 Linux amd64,但尚无本批指定发行版、内核、PowerShell 版本的原生构建证据 | 不宣称 Linux 原生可重复构建已通过;Linux 候选包由 Windows 交叉编译 |
| 目标平台 | windows/amd64、linux/amd64,CGO_ENABLED=0、-trimpath、-mod=readonly |
构建机版本与生产运行系统分别记录 |
| 安装脚本 | .npmrc 固定 ignore-scripts=true,正式入口再显式传参 |
npm 未审查警告不是安全保证,禁止白名单和全量放行 |
| 可选平台包 | npm ci 显式包含开发和可选依赖 |
esbuild 不执行安装脚本,使用锁文件中的平台包;外部二进制覆盖被拒绝 |
| 发布追溯 | manifest.json 的 build_environment |
包含实际工具链、系统、直接前端依赖、安装策略和五份输入文件 SHA256;Go 驱动及依赖由模块文件哈希追溯 |
| 源码换行 | .gitattributes 固定文本 LF,二进制自动识别并保留 |
覆盖用户 core.autocrlf 差异;原目录不强制重写,正式验证使用干净克隆 |
正式发布入口自动校验工具链、核验 Go 模块缓存、按锁文件干净安装,并在构建结束后复核输入文件。环境不符时尽早失败;构建中版本文件漂移则不生成发布清单。toolchain.mjs 和配套测试属于正式构建代码,不作为替代真实部署的辅助验收脚本。具体流程见 build/README.md。
二、数据库支持矩阵
| 数据库 | 预期定位 | 代码现状 | 本轮验证 | 尚未满足的正式验收 |
|---|---|---|---|---|
| SQLite | 单机、开发、轻量部署 | 驱动 v1.59.0、实测引擎 3.53.4、迁移 1~14、CLI 备份恢复、项目成员与事务审计基础 | 当前取消查询和 WAL 专项 30 个叶子通过,Windows 独立程序历史备份/升级/成员恢复通过,见第二十二节;第十六、十七节保留历史证据 | 旧发行包实际数据、完整发行包、Linux 原生、真实服务重启、完整业务授权及生产门禁 |
| MySQL 5.7.44 | 历史兼容目标,仍保留实现 | 独立方言、迁移 1~14、连接恢复、InnoDB 快照、官方备份恢复及项目成员事务审计 | 当前成员/历史范围三轮组合 531 个叶子通过、无失败跳过,含 SQLite 用例,见第二十二节;777c716 的 176 个完整专项叶子用例为第十四节历史批次 |
旧索引元数据异常根因、更多编码与 SQL 模式、并发 DDL/授权变化、定义者迁移、独立发行命令、Linux 实库、Web 初始化及生产验证 |
| MySQL 8.0.45 | 正式生产支持目标 | 同上,额外处理不可见列实际数据、启用角色与部分撤销 | 当前独立三轮组合 531 个叶子通过、无失败跳过,含 SQLite 用例,见第二十二节;第十四节的 202 个完整专项为历史批次,不冒充本轮全范围验证 | 更多编码与 SQL 模式、并发 DDL/授权变化、定义者迁移、独立发行命令、Linux 实库、Web 初始化及生产验证;不代表全部补丁版本已验证 |
| PostgreSQL | 正式生产支持目标,实际服务端版本待本轮复核 | 独立方言、迁移 1~14、严格 TLS 和官方备份恢复工具接入 | 文件/嵌入/登记一致性、凭据/TLS 单元测试;当前候选实库未执行 | 当前版本真实集群、初始化、升级、失败回滚、备份恢复和业务回归 |
正式支持目标不等于已经生产放行。旧文档中的 PostgreSQL 实机记录仅作为线索,不替代当前候选版本复测。本批 MySQL 测试自行初始化 loopback 独立实例,不连接本机已有服务或生产数据库;PostgreSQL 当前候选实库测试未执行。
三、迁移与降级边界
- 三种数据库必须提供相同编号和名称的迁移,SQL 内容允许因方言不同而不同。
migration_catalog_test.go检查源码目录、嵌入资源和latestMigrationVersion;新增文件忘记登记或嵌入时必须失败。Migrate在执行后续迁移前读取完整有序版本历史;版本高于程序支持范围或历史不连续时拒绝启动,不自动删除或修补版本记录。- MySQL 的 DDL 重入和 PostgreSQL 的事务回滚必须用对应引擎验证,不能通过文件数量一致推断行为一致。
- 当前不存在通用向下迁移承诺。降级须使用兼容程序及对应已验证备份,在隔离环境验证后再操作,禁止通过删除
schema_migrations绕过拒绝。
四、真实实例验收步骤
每个数据库和声明支持的服务端版本独立执行以下步骤,保存版本、候选提交、命令退出码和脱敏证据:
- 建立明确归属的隔离空库和最小权限账户,验证 TLS 与主机身份;不使用现有业务库。
- 按正式初始化入口完成配置;创建用户、域名、DNS 账户、服务器和任务,验证权限隔离。
- 从支持的旧版本数据库升级,检查数据、索引、默认值、归属和任务状态;重复执行不产生额外变更。
- 注入迁移中断,在恢复后确认重入/回滚;新版数据库被旧程序拒绝且原数据保持不变。
- 按该数据库的 CLI 备份恢复流程在另一隔离空库恢复;验证敏感配置和证书关联,篡改备份必须拒绝。
- 重启服务验证持久化,完成前后端业务回归;记录未执行、跳过和失败项,不汇总为通过。
MySQL/PostgreSQL 没有当前实机证据的格子保持待验收。本矩阵不授权清理共享数据库或同机其他服务。
五、MySQL 隔离迁移正式回归
测试入口为 backend/internal/database/mysql_integration_test.go;同目录的 mysql_integration_helpers_test.go 适配共享夹具 backend/internal/testsupport/mysqltest/server.go,供数据库和 CLI 正式 Go 测试复用,不需要辅助脚本,也不进入生产程序依赖。未显式提供程序目录时显示跳过,不得把常规 go test ./... 的结果当作实库通过。
本批 Windows 实际命令如下,两个版本分别执行;产物根可复用,但测试每次创建全新数据目录,不复用业务库:
Set-Location D:\Desktop\Scert\backend
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-matrix-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -count=1 -v -timeout=8m -run '^TestMySQLRealMigrations$' ./internal/database
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\8.0\bin'
go test -count=1 -v -timeout=8m -run '^TestMySQLRealMigrations$' ./internal/database
安全和覆盖边界:
- 只接受绝对程序及产物目录,不接受外部 DSN;使用
--no-defaults,不会读取既有实例配置。数据库管理命令只作用于本次创建的随机端口与数据目录。 - 初始化不开放监听;首次启动在接收连接前设置随机密码。运行时仅绑定 loopback,强制 TLS,验证 CA 和 IP 身份;8.0 的额外 X 协议关闭。
- 迁移使用库级业务账户,不用管理账户替代最低权限检查;测试保留管理账户仅用于创建隔离库和正常关闭自己的进程。
- 每个历史起点及每个 DDL 中间状态升级后,比较表引擎、字段类型、默认值、字符集及全部索引。此比较证明升级结构与全新迁移一致,不单独证明业务设计本身完全正确。
- 冷重启用例关闭应用连接池、停止数据库、重启后重新打开连接。保留旧池的独立在线恢复测试见第六节,不能用冷重启结果代替。
- 测试正常结束会停止自己的进程,清空初始口令文件,保留日志和数据目录;产物已被 Git 忽略。非正常终止后应先核对具体进程归属,禁止批量停止所有 MySQL。
- 本批不是发布包部署、Web 初始化、备份恢复、Windows Service 或 Linux 运行验收;PostgreSQL 和 SQLite 剩余矩阵不得据此标记通过。
六、MySQL 在线连接池恢复
正式入口:backend/internal/database/mysql_recovery_integration_test.go;复用第五节隔离夹具。两个版本分别设置程序目录后运行:
go test -count=1 -v -timeout=8m -run '^TestMySQLReal(Migrations|PoolRecovery)$' ./internal/database
实现和行为边界:
- 锁定的 MySQL 驱动在 Windows 上没有有效的空闲套接字检查。复用连接之前通过驱动的
SessionResetter增加一次有界COM_PING;Linux 保留驱动原有检查,不增加这次往返。 - 单次探测最多 2 秒;调用者更短的截止时间或取消优先。探测失败关闭连接并返回
driver.ErrBadConn,让连接池在发送业务语句之前更换连接。 - 完整保留驱动的查询、写入、预编译、事务、参数转换和连接校验接口。不包装业务执行及提交错误,不新增 SQL 或事务重放逻辑。
checkConnLiveness默认开启;显式关闭时不启用上述额外检查,不保证失效空闲连接上的首次请求成功。连接仍可能在探测成功后断开,应用必须处理执行错误及提交结果不确定性。- 成本是 Windows 每次复用池连接时增加一次协议往返;同一已取得的事务连接内部不重复探测。当前没有远距离网络性能基准,不以 loopback 测试推断生产延迟。
新增 7 个实库场景每个使用单独业务库:保留旧池并重启数据库后的首次写入、空闲断线后的预编译语句、首次查询及迁移、无符号整数参数及正常提交、只读事务与正常回滚、活动事务连接中断、数据库不可用时有界失败并恢复。每次故障后的数据值均验证,避免把重复写入或未提交数据当作恢复成功。
mysql_pool_test.go 另行验证健康探测、驱动拒绝、探测失败、截止时间、取消、写入前更换连接,以及查询、写入和提交响应不确定时保留原错误且不重放。响应丢失场景是驱动接口层故障注入,不声称已完成真实网络丢弃提交确认包的演练。
候选 9cf3a3b 在 Windows 的 MySQL 5.7.44、8.0.45 均为 55 项子测试通过,0 失败、0 跳过。产物位于 artifacts/mysql-matrix-20260927/mysql57-9cf3a3b.log 和 mysql80-9cf3a3b.log,不纳入源码。Linux 数据库测试包交叉编译通过,但没有执行 Linux 实库恢复;其门禁仍然保留。
七、MySQL 基本备份恢复与指定失败回滚
候选 7bfd400;正式入口为 backend/internal/cli/mysql_integration_test.go 和 mysql_commands_integration_test.go,复用严格 TLS、随机账户、全新实例的共享夹具。
修复前在 5.7.44 的真实数据库上复现两类错误:禁用空闲连接后,会话变量跨 SQL 语句丢失;DECIMAL 文本字节被作为十六进制数值恢复,出现数值越界。修复固定恢复连接,并依据字段类型导出精确文本;旧 DECIMAL 备份没有自动转换,应重新生成并验证备份。
新增测试覆盖:
MaxIdleConns=0时,记录并比较同一恢复脚本中的真实连接编号。- 两种空闲连接配置下,恢复子表在前、父表在后的关联数据,核对中文、特殊字符、二进制、DECIMAL、NULL、微秒时间和自增;恢复后外键仍生效。
- 无效 SQL 前的写入保留,失败后的写入不执行;提前取消不修改当前数据库。底层导入函数不承诺事务原子性,整库回滚由正式恢复命令负责。
- 同进程调用正式备份和恢复命令,先执行完整 MySQL 迁移,再验证成功恢复、SQL 导入失败后的回滚、证书恢复失败后的回滚;检查业务行、审计行、配置文件、加密凭据、证书文件和恢复前快照。
重跑原有 55 项及新增 10 项的命令如下。两个版本分别设置程序目录,产物根每次生成独立数据目录:
Set-Location D:\Desktop\Scert\backend
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-restore-session-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\8.0\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli
JSON 日志保存为 artifacts/mysql-restore-session-20260927/mysql57-7bfd400.jsonl、mysql80-7bfd400.jsonl,不纳入源码。
候选最终复测结果如下,均为 0 失败、0 跳过;子测试计数包含两种连接池场景及其嵌套用例:
| 实际版本 | 数据库包 | CLI 包 | 通过子测试 |
|---|---|---|---|
| MySQL 5.7.44 | 43.949 秒 | 11.350 秒 | 65 |
| MySQL 8.0.45 | 51.125 秒 | 16.803 秒 | 65 |
最终 8 个隔离测试实例均已退出,对应端口无监听;原有 MySQL 进程保持不变,全部初始化口令文件为空。保留目录中的测试数据、随机测试密钥和日志仅作为本地忽略产物,不提交或分发。
本批边界与剩余门禁:
- TLS 注册名只存在于测试进程,正式命令测试是同进程调用,不是独立发行二进制验收。Linux CLI 测试包仅交叉编译,未在 Linux 运行。
- 本节候选尚无跨表统一一致性快照;后续 InnoDB 数据快照见第八节,并发 DDL 一致性仍不承诺。
- 视图、触发器、生成列、更多 SQL 模式与对象清单完整性仍须验证,不能把已测试表类型扩展为任意 MySQL 对象支持。
- 当前仍使用自有 SQL 导出;官方工具互操作、独立 CLI、完整生产业务及服务重启验收必须补齐。PostgreSQL、SQLite 和其他 44 项整改不因本批局部通过而缩减。
八、MySQL 跨表快照与备份失败边界
跨表快照候选为 8d742fe;取消锁等待与失败边界候选为 73df576。正式测试入口是 mysql_snapshot_integration_test.go、mysql_backup_failure_integration_test.go,均位于 backend/internal/cli/,复用第五节的隔离夹具;没有新增辅助验收脚本。
实现与复现
- 备份枚举表、读取表结构和数据使用同一只读可重复读事务。数据快照在首次一致性读取时建立,不声称事务开始瞬间已建立快照;外部并发 DDL 仍须禁止。
- 跨表测试锁住第二张表,等首表已导出后依次更新两张表,再解锁并恢复到另一个空库。数据库状态依次为
(0,0)、(1,0)、(1,1);原实现恢复为从未出现的(0,1),现实现两种连接池配置均恢复为(0,0)。 - 取消测试也使用同一真实锁边界。修复前客户端已经返回取消,但首表的后续 DDL 在 5 秒内不能取得锁。备份现在仅对自己的会话执行
SET SESSION lock_wait_timeout = 5;双版本实测取消后约 5 秒释放本场景阻塞,未修改全局值。 - 该限制针对单次元数据锁获取,不是整个备份的 5 秒执行期限,不为任意查询、多个锁等待或任意网络故障承诺统一取消完成时间。备份遇到锁超时直接失败,不重放事务;维护期间需要排除外部 DDL。
- 当前只允许 InnoDB 基础表;MyISAM 和视图明确失败,避免静默声称一致性备份。拒绝只是当前安全边界,不能将对象完整性任务标记完成。
- 成功发布前结束事务、同步并关闭临时文件、检查取消再重命名。失败只清理本次独占创建的临时文件;原有目标文件、其他操作占用的临时文件和目录内容不被修改。
新增正式回归
| 场景 | 子测试数 | 关键断言 |
|---|---|---|
| 跨表并发写入快照 | 2 | 两种空闲连接配置;真实导出并恢复后两表均为原快照 |
| MyISAM、视图 | 2 | 明确拒绝;不替换原有备份,不遗留本次临时文件 |
| 首表导出后取消 | 2 | 保留取消错误;分别验证无目标文件和已有目标文件;首表 DDL 恢复可执行 |
| 首表导出后 SQL 中断 | 2 | 管理连接仅中断已确认的本次备份语句;保留错误 1317,文件与锁收尾正确 |
| 元数据锁等待超时 | 2 | 自然触发错误 1205;不靠测试解锁促成返回,文件与锁收尾正确 |
| 临时文件冲突 | 1 | 保留已有目标及其他操作的临时文件 |
| 重命名发布失败 | 1 | 非空目录占用目标时返回发布错误,目录内容保留,本次临时文件清理 |
其中跨表快照为上一批新增 2 项,本批失败边界新增 10 项;加此前 65 项,最终每版 77 项。统计口径仍包含既有嵌套子测试,不将父级包成功再加一次。
最终候选证据
在 backend/ 执行,两个版本各运行一次,明确提供程序目录,不接受跳过结果:
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-backup-boundaries-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli |
Tee-Object -FilePath '../artifacts/mysql-backup-boundaries-20260927/mysql57-73df576.jsonl'
# 换为 E:\DB\8.0\bin,输出文件换为 mysql80-73df576.jsonl,再执行相同测试。
| 实际版本 | 数据库包 | CLI 包 | 通过子测试 | 失败 / 跳过 |
|---|---|---|---|---|
| MySQL 5.7.44 | 44.591 秒 | 41.001 秒 | 77 | 0 / 0 |
| MySQL 8.0.45 | 53.844 秒 | 51.178 秒 | 77 | 0 / 0 |
常规 go test -count=1 ./...、go vet ./...、go mod verify 通过。Linux CLI 测试包仅交叉编译成功,未作实库运行。最终复测创建 12 个隔离实例,连同复现和定向测试,本批目录共 18 个实例;全部正常退出,已记录端口无监听,初始化口令文件为空,共享 MySQL 进程不变。数据目录、随机测试密钥、日志和二进制均被忽略,不提交或分发。
剩余验收明确保留:触发器、生成列、例程、事件和视图等对象的完整性;官方工具互操作与独立发行 CLI;磁盘写满、同步失败和掉电等更广泛文件系统故障;Linux 实库、完整 Web 业务和服务部署;PostgreSQL、SQLite 剩余矩阵。本批不得替代这些证据,也不得据此关闭 P0-05 或全部 44 项目标。
九、生成列、不可见列与官方工具双向互操作
代码候选 f260b22,修改前检查点 e9bc156。正式测试为 TestMySQLRealOfficialInteroperability,共享调用代码位于 backend/internal/testsupport/mysqltest/tools.go,没有使用临时辅助验收脚本。
- 修复生成列被显式写入恢复语句,以及
SELECT *遗漏不可见列的问题;只读取可写列,并保留只有生成列的表的实际行数。 - 修复仅有生成列时扫描指针长度错误导致的越界。
- 源数据、恢复数据以及表、列、索引的实际元数据分别核对;不以
SHOW CREATE TABLE中等价的显式字符集写法差异误判结构变化。 - 5.7.44 验证基础值、混合生成列和仅生成列表的双向互操作;8.0.45 额外验证不可见列的非默认实际值。
- 官方工具从当前测试服务端的程序目录读取,检查版本系列;使用
VERIFY_IDENTITY,随机密码仅通过子进程环境传递。继承的MYSQL*环境和用户登录文件均隔离,未改写官方导出内容。 - 本机两个版本的默认扩展插入导出,在仅生成列表上实证出现无效 SQL;正式测试明确使用
--skip-extended-insert,该选项下双向恢复通过,不把默认选项记为通过。
最终专项证据:
| 实际版本 | 数据库包 | CLI 包 | 通过测试记录(含父项) | 叶子用例 | 失败 / 跳过 |
|---|---|---|---|---|---|
| MySQL 5.7.44 | 47.670 秒 | 45.554 秒 | 90 | 81 | 0 / 0 |
| MySQL 8.0.45 | 54.469 秒 | 57.907 秒 | 92 | 83 | 0 / 0 |
文件:artifacts/mysql-pending-review-20260927/review-mysql57.jsonl、review-mysql80.jsonl。这里明确区分父子测试记录总数与叶子用例,不把嵌套父项重复算成独立场景。后端常规测试、静态检查、模块校验通过;本批没有执行 Linux 实库或生产部署。
这只完成已列出的表和列类型的双向互操作,不能据此宣布视图、触发器、例程、事件、任意 SQL 模式及完整对象清单均受支持。P0-05 继续为 [~]。
十、官方存储对象 SQL 的分隔符恢复
修改前检查点 6707059,代码候选 e6e6719。本批处理的是官方导出文件到 Scert 恢复的方向,没有把 Scert 自有导出改为完整存储对象备份。
故障与修复
- 在隔离 MySQL 5.7.44 中实证:有效官方导出文件遇到
DELIMITER时,旧恢复实现返回 1064。该指令用于客户端拆句,不应发送给数据库。 - 解析器现在识别独立行上的分隔符切换,支持本批验证的
;;、$$、//;保留复合语句内部的分号、带引号的内容和可执行版本注释。 - 支持 UTF-8 BOM、CRLF、大小写与前导空白。无效分隔符、未闭合引号或块注释返回错误,并且不返回可执行的部分语句。
- 恢复仍使用单一数据库连接;数据库错误立即返回,不跳过错误、不提升权限、不切换连接重放。词法预检不等于完整 SQL 语义验证,也不宣称全部 DDL 可事务回滚。
正式测试范围
TestMySQLRealOfficialStoredPrograms 使用同版本的官方 mysqldump --routines --events 生成文件,文件未经改写,分别交给官方 mysql 和 Scert 恢复到全新隔离库。
- 验证两个同表触发器的定义与执行顺序,插入新行后核对
(4 + 2) * 3 = 18和中文标签。 - 验证存储过程、函数的定义、参数、返回类型、字符集、排序规则、定义者、SQL 模式和安全上下文;实际调用并核对结果。
- 验证禁用事件的定义、计划、时区及保留策略;仅在本测试实例中启用事件调度,并在目标库显式修改为两秒后的单次计划,检查实际执行且源库未变化。不是对生产数据库或机器共享实例开启调度。
- 使用没有对象管理权限的独立账户恢复同一文件,检查 1142、1227 或 1419 权限错误返回,且不继续恢复后面的例程。
- 无效分隔符出现在建表语句之后时,检查恢复拒绝整个词法输入,目标库仍无任何表。
每个版本运行 4 个新增叶子场景;常规单元测试另外覆盖分隔符、注释、转义、换行和无效输入。
权限和 SQL 模式边界
- 不改写
DEFINER,本批源库和两个恢复库使用同一隔离账户。跨账户、跨服务器定义者及跨库引用的迁移仍未验收。 - 5.7 工具读取例程需要相应系统元数据权限,本夹具只在独立实例给测试账户授予
mysql.proc读取权限。 - 8.0 实例启用二进制日志时,函数创建实证返回 1419;本夹具只给该实例的专用测试账户授予所需
SUPER,没有启用log_bin_trust_function_creators,也没有给实际业务账户扩权。 - 本机 5.7 官方导出会移除对象 SQL 模式中的
NO_AUTO_CREATE_USER,官方恢复对照也出现同样变化。本批正式用例明确创建于STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION,源、官方恢复及 Scert 恢复的元数据严格相等;不把默认模式或任意 SQL 模式记为通过。 NO_BACKSLASH_ESCAPES等其他词法模式、恢复已启用事件时的调度隔离和对象安全语义,仍需独立验证。
复测结果与证据
在 backend 目录执行:
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-stored-programs-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli |
Tee-Object -FilePath '../artifacts/mysql-stored-programs-20260927/mysql57-review.jsonl'
# 将程序目录换为 E:\DB\8.0\bin,输出文件换为 mysql80-review.jsonl,再执行相同测试。
| 实际版本 | 数据库包 | CLI 包 | 通过测试记录(含父项) | 叶子用例 | 失败 / 跳过 |
|---|---|---|---|---|---|
| MySQL 5.7.44 | 45.980 秒 | 59.816 秒 | 95 | 85 | 0 / 0 |
| MySQL 8.0.45 | 60.495 秒 | 72.856 秒 | 97 | 87 | 0 / 0 |
PowerShell 5.1 的 Tee-Object 文件使用 UTF-16,复核时用 Get-Content -Encoding Unicode。后端全量 go test -count=1 ./...、go vet ./...、go mod verify 通过;Linux CLI 测试包交叉编译通过但未运行,前端未修改、未重测。
本批复现、定向和全量测试共创建 22 个隔离实例,均已退出;全量测试记录的端口无监听,22 份初始化口令文件均为空,机器原有三个共享 MySQL 进程保持不变。数据、随机测试密钥、日志和编译文件仅留在忽略目录,没有提交。
尚未完成
Scert 自有导出仍需补齐触发器、例程、事件及视图,验证可见权限与完整对象清单,防止对象遗漏;本批导入能力不能证明导出完整。独立发行 CLI、Linux 实库、完整 Web 业务、服务重启和正式生产部署仍未验收。PostgreSQL、SQLite 和全部 44 项整改范围不变,P0-05 保持 [~]。
十一、MySQL 自有触发器备份与可见权限(2026-09-27)
进度与实现范围
本批触发器子任务状态:[x],实现与 Windows 隔离验证完成,等待完整范围复审;P0-05 总状态保持 [~]。修改前检查点为 d7f6ac1,实现与正式测试提交为 3f6d5b8,已推送。本节接续第十节的缺口,不把此前“官方文件导入”结果等同于自有导出完整。
[x]先复现:自有备份恢复后源库的触发器全部丢失;撤销TRIGGER后,源库真实存在触发器但information_schema.TRIGGERS返回空,旧实现仍成功并覆盖既有备份。证据为mysql57-before.jsonl。[x]自有导出增加触发器。按同一表、时机、事件的ACTION_ORDER读取,不按名称假定顺序;使用服务器原始创建语句保留定义者和正文。所有表数据导出完成后再创建触发器,避免恢复历史数据时重放触发器副作用。[x]保留 SQL 模式、客户端字符集、连接排序规则和创建时数据库排序规则。正文先转换回原客户端编码并做往返一致性检查;分隔符按正文选择。成功恢复后恢复保存的会话属性,并将数据库排序规则设回源库当前值。创建时间戳不是可恢复的业务定义属性,不作相等承诺。[x]备份前证明每张可见基础表的TRIGGER权限。支持全局、库级、表级、已启用角色及嵌套角色,识别 8.0 部分撤销、独立动态权限行,以及精确库授权对通配授权的遮蔽。空触发器列表不能代替权限证明。
实现文件:mysql_triggers.go、mysql_privileges.go;入口为 mysql_backup.go。正式测试为 mysql_triggers_integration_test.go、mysql_privileges_test.go。没有新增临时辅助验收脚本。
正式隔离验证
TestMySQLRealNativeTriggers 使用同一隔离账户在新建测试库间恢复,不改写 DEFINER。自有文件分别交给 Scert 和官方 mysql:
- 四个触发器逐字段比较定义、顺序、SQL 模式、定义者、字符集及两种排序规则。
- 两个同表触发器故意让名称顺序与执行顺序相反,实际插入后应得到
(4 + 2) * 3 = 18。 - 恢复已有数据后审计表仍为空,随后新插入才由第三个触发器向审计表写入
18。 - 第四个触发器以 Latin-1 创建,正文含
café;;,同时覆盖非 UTF-8 编码、分隔符冲突和创建时不同的数据库排序规则。 - 撤销源账户
TRIGGER,先确认元数据确实隐藏,再断言备份明确失败、原备份内容不变、临时文件不残留。
TestMySQLRealTriggerPrivileges 在管理员创建的真实触发器上验证有效授权,并核对当前账户实际可见数量:5.7 为 9 个权限场景;8.0 额外覆盖动态权限、启用角色、嵌套角色、未启用角色、部分撤销,共 14 个。另有权限语句解析单元测试。通用隔离账户新增 TRIGGER 可见权限,旧官方恢复的权限失败用例显式撤销该权限,避免测试前提被夹具改变。
8.0 在启用二进制日志时创建触发器实际返回过 1419;仅在本次独立实例给专用账户授予所需 SUPER,没有修改全局函数信任开关,也没有给任何真实业务账户扩权。共享 MySQL 实例、生产数据库、远端服务均未操作。
证据与命令
证据根目录:artifacts/mysql-native-triggers-20260927/,不提交数据库、密钥、日志或二进制。首轮全专项证据为 mysql57-review.jsonl、mysql80-review.jsonl;最终复测使用独立的 mysql57-final.jsonl、mysql80-final.jsonl,不覆盖先前证据。
在 backend 目录执行:
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-native-triggers-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli |
Tee-Object -FilePath '../artifacts/mysql-native-triggers-20260927/mysql57-final.jsonl'
# 8.0 使用 E:\DB\8.0\bin,并将证据文件名改为 mysql80-final.jsonl。
首轮完整专项:5.7.44 数据库包 54.342 秒、CLI 包 66.495 秒,109 个通过记录(含父项)、97 个叶子用例;8.0.45 分别 69.582 秒和 84.519 秒,116 个通过记录、104 个叶子用例。均无失败、无跳过。
最终候选复测(mysql57-final.jsonl、mysql80-final.jsonl):
| 实际版本 | 数据库包 | CLI 包 | 通过记录(含父项) | 叶子用例 | 失败 / 跳过 |
|---|---|---|---|---|---|
| MySQL 5.7.44 | 45.519 秒 | 67.048 秒 | 109 | 97 | 0 / 0 |
| MySQL 8.0.45 | 63.856 秒 | 80.795 秒 | 116 | 104 | 0 / 0 |
后端 go test -count=1 ./...、go vet ./...、go mod verify 通过;Linux amd64 CLI 测试包交叉编译通过,未运行 Linux 实库。前端未修改,未重跑前端或浏览器测试。常规全量测试不是实库证据的替代,实库非跳过结果以上表为准。PowerShell 5.1 的 JSONL 使用 UTF-16,复核用 Get-Content -Encoding Unicode。
收尾:本批目录中累计 51 个隔离实例均退出,记录的 78 个测试端口无监听,51 份初始化口令文件为空;原有三个共享 MySQL 进程保持不变。复现、扩展测试和最终复测产物全部保留在忽略目录,不提交。没有清空生产或共享数据库,没有新增辅助脚本。
权限变化与仍未完成的边界
- 备份账户现在需要对每张可见基础表具有可证明的有效
TRIGGER权限,即使实际没有触发器也不能省略。产品不会自行授予权限。恢复触发器还可能需要目标库ALTER、适当定义者权限及二进制日志模式要求的权限;由管理员按环境审核,不建议给实际应用账户照搬测试的全局权限。 - 多个相互遮蔽的通配库授权无法可靠证明权限时采取保守失败,应明确授予精确库或表权限。这是待完善的权限组合边界,不宣称任意授权组合均通过。
- 本轮只证明已列出的基础表上触发器可见,仍需补齐完整表清单及例程、事件、视图的权限与导出;不能把不可见表当作不存在。非 InnoDB 表及视图仍为临时拒绝边界。
NO_BACKSLASH_ESCAPES、其他非 UTF-8 多字节编码、跨账户/跨服务器定义者、跨库引用、备份期间 DDL/授权变化、恢复中途失败后的数据库排序规则回退仍需单独验证;当前词法预检不是 SQL 语义预检或 DDL 原子恢复。- 独立发行 CLI、Linux 实库、PostgreSQL、SQLite、Web 业务及生产门禁保持未完成。全部 44 项继续保留,P0-05 不作生产放行。
十二、MySQL 自有例程备份与注释编码(2026-09-27)
状态与实现
本节接续第十一节的例程缺口,不改变全部 44 项和 P0-05 的三库、双平台要求。原始实现前检查点为 db7d132,未完成实现已在 c4051c9 保存并推送。本轮在该检查点上修复已复现的 5.7 Latin-1 注释乱码,并补充拒绝异常元数据的正式测试;最终验证结果另列于本节末尾,P0-05 总状态仍为 [~]。
- 自有导出包含存储过程、函数的原始定义、参数、定义者、SQL 模式、客户端字符集、连接及数据库排序规则。数据全部恢复后创建例程,再创建依赖例程的触发器。
- 同名例程先删除再创建,支持重复恢复;删除和创建语句均按原客户端字符集输出并验证转换往返一致,分隔符避开正文冲突。
- 5.7 直接证明
mysql.proc完整读取权限并使用该目录列出例程;8.0 检查当前有效授权,包括启用角色和嵌套角色,要求SHOW_ROUTINE或没有被当前库部分撤销限制的全局SELECT。 - 即使元数据为空也不能省略权限检查。权限不足时保留已有备份,并清理本次临时文件;程序不对真实账户自动扩权。
复现与编码修复
先前证据 mysql57-before.jsonl 复现例程遗漏与权限不足仍覆盖原备份。扩展编码场景后,mysql57-encoding.jsonl 记录 Latin-1 注释从 café;; 变为 café;;;mysql80-encoding.jsonl 的定向通过不能覆盖这个 5.7 缺陷。
本轮将声明头与注释的处理分开:5.7 保留原声明头,8.0 还原目录声明头;两版都单独还原目录注释,不整体反解正文。反解必须同时满足字符集往返一致和 UTF-8 有效,不能静默替换无法表达的字符。正文与目录定义不一致时明确拒绝,不猜测边界或编码。
初次完整复测 mysql57-final.jsonl 通过;mysql80-final.jsonl 中新增有损注释拒绝用例发现 8.0 返回原始错误 3988,缺少例程上下文。随后补充中文上下文并保留底层错误,未删除或放宽失败断言。最终候选证据单独保存为 mysql57-verified.jsonl、mysql80-verified.jsonl,不能引用前一批结果代替最终候选结果。
正式测试范围
TestMySQLRealNativeRoutines 创建三个例程及一个依赖函数的触发器:包含 DECIMAL 参数、IN/INOUT/OUT 参数、中文说明、SQL SECURITY INVOKER、带反引号的名称,以及 Latin-1 名称、注释和正文。
- 分别使用 Scert 和官方
mysql导入自有备份,每条路径重复恢复两次。 - 目标预建同名错误函数,要求被正确替换;逐字段比较例程和参数元数据。
- 实际调用函数和过程,并执行依赖函数的触发器;检查原始数据没有被导入触发器改写。
- 检查数据库排序规则恢复;非 ASCII 名称、注释和正文须保持原值。
- 增加五个元数据拒绝场景:声明头不完整、正文不一致、注释声明缺失、有损转换、无效 UTF-8。失败时定义不能被部分改写。
TestMySQLRealRoutineVisibility 在 5.7 覆盖六种权限场景,在 8.0 覆盖十种场景。包括隐藏例程、无权限空库、全局 SELECT、仅 EXECUTE、列级 SELECT、角色及部分撤销;仅 EXECUTE 的对象实际可见但正文为 NULL。部分撤销场景先移除夹具自带库级 SELECT,避免把撤销库授权误认为已经限制了全局 SELECT;嵌套角色不保留直接角色授予。
全部测试仅使用每次新建的 loopback 独立实例、随机账户和严格 TLS,不接受现有服务连接串,不清理共享或生产数据库,不新增辅助验收脚本。Linux 交叉编译不等同于 Linux 实库或独立发行 CLI 验收。
复测命令与结果
在 backend 目录执行,证据目录为 artifacts/mysql-native-routines-20260927/:
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\mysql-native-routines-20260927'
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli |
Tee-Object -FilePath '../artifacts/mysql-native-routines-20260927/mysql57-verified.jsonl'
# 8.0 使用 E:\DB\8.0\bin,另存为 mysql80-verified.jsonl。
本批例程子任务状态:[x] 已完成,等待复审。最终候选以两个 verified 文件为准:
| 实际版本 | 数据库包 | CLI 包 | 通过记录(含父项) | 叶子用例 | 失败 / 跳过 |
|---|---|---|---|---|---|
| MySQL 5.7.44 | 35.018 秒 | 75.912 秒 | 125 | 110 | 0 / 0 |
| MySQL 8.0.45 | 57.781 秒 | 94.388 秒 | 136 | 121 | 0 / 0 |
后端 go test -json -count=1 ./... 结果另存为 backend-verified.jsonl:28 个有测试的包通过,1340 个通过记录(含父项)、1234 个通过叶子用例、0 失败;32 个测试因未启用对应实库或平台条件而跳过,不能算作通过。MySQL 非跳过实库证据以上表为准,不用常规回归替代。go vet ./...、go mod verify 均通过,Linux amd64 CLI 测试包交叉编译通过但未在 Linux 执行;前端未修改、未重测。PowerShell 5.1 的 JSONL 使用 UTF-16,复核用 Get-Content -Encoding Unicode。
收尾复核:本专项目录累计 90 个隔离实例均退出,167 个已记录端口无监听,90 份初始化口令文件均为空;原有三个共享 MySQL 进程保持不变。数据、随机测试密钥、原始日志和编译产物只留在忽略目录,不提交。上述数字包含前一轮复现和失败证据,不是本次通过用例数。
剩余门禁
- 事件、视图和完整表清单的导出及可见权限仍未完成,不能把隐藏表或其他对象当作不存在。
- 其他多字节编码、非 UTF-8 返回枚举类型、
NO_BACKSLASH_ESCAPES等 SQL 模式、跨账户或跨服务器定义者、跨库引用和备份期间 DDL/授权变化仍需验证。 - 保留原始
DEFINER;不会自动迁移账户授权或清除备份外的额外目标例程。恢复失败后的 DDL 原子性和数据库排序规则回退尚无完整承诺。 - 独立发行 CLI、Linux 实库、PostgreSQL、SQLite、正式 Web 业务与全部生产验收门禁继续保留。新增例程通过不提升 P0-05 总状态,也不作生产放行。
十三、MySQL 自有事件备份与恢复安全
日期:2026-09-27。修改前检查点 863202f,实现保存点 8cba0d5,最终通过源码 3625e8b,均已推送。仅使用独立 loopback 实例、随机测试账户和严格 TLS,不操作共享或生产数据库。P0-05 保持 [~],全部 44 项范围不变。
实现与安全边界
- 自有备份使用原始
SHOW CREATE EVENT,保存定义者、正文、计划、时区、启停状态及创建会话属性;同名事件先删除再创建。导出顺序为基础数据、例程、触发器、恢复外键检查、事件。 - 必须证明全局或库级 EVENT 权限完整可见,不能以表级权限、过滤后的空列表或当前没有事件作为依据。覆盖角色、部分撤销及精确/通配授权遮蔽,产品不自动扩权。
- 恢复前要求有效全局 PROCESS 权限,并检查工作线程。实库复现表明事件工作线程使用定义者身份,命令为
Connect,不能只筛选event_scheduler用户;其他正在建立的连接也可能被保守拒绝。 - 调度器 ON 且目标已有启用事件或导入可能启用事件时,首条恢复语句之前拒绝;调度器 OFF 但工作线程尚未退出时同样拒绝。产品不关闭调度器、不终止线程、不擅自改变既有事件状态。管理员仍须维持维护窗口,防止检查后外部会话改变调度或对象。
- 事件 DDL 识别区分正文、注释、引用和名称,展开版本化注释,并按两种反斜杠转义模式保守判断。Scert 拒绝导入内容直接设置事件调度器;此检查不是任意 SQL 的沙箱,恢复文件仍须可信。
- 两版事件声明头来自 UTF-8 目录,而正文沿用原客户端编码;按目录正文与
DO边界分离,只反解声明头,检查往返一致与有效 UTF-8。新增正文不一致、缺声明头、有损转换、无效 UTF-8 四个拒绝场景,失败不写回部分定义。 - 到期后重新创建会被删除或改变启用状态的事件,以及时区无法验证的事件拒绝备份,已有备份保持不变;已禁用且 PRESERVE 的历史事件允许。事件恢复遇到影响完整性的警告会停止后续语句,但不承诺已执行 DDL 的原子回滚。
- 官方客户端导入不会执行 Scert 的预检,管理员必须自行停止调度、等待工作线程退出、检查警告并核验对象,再恢复调度。不会自动迁移定义者账户或授权,也不清除备份外的额外对象。
正式测试与问题修正
TestMySQLRealNativeEvents:中文/反引号及 Latin-1 名称、注释和正文,一次性/周期计划,多个时区,复制禁用状态;Scert/官方客户端两条路径分别重复恢复两次,完整比较定义和计划,再显式开启隔离调度实际执行并检查源库未变。TestMySQLRealEventVisibility:5.7 的八类、8.0 的十三类可见权限场景,包括无权限空库和隐藏事件。TestMySQLRealEventRestoreSafety:九类常规场景及 OFF 后仍执行的工作线程;检查首条标记语句未执行、调度未被产品改变,线程自然退出后恢复成功。TestMySQLRealEventExpiry:五类到期导出/恢复场景;TestMySQLEventStatementSafety:二十二类 SQL 识别场景,每类检查两种转义模式。- 修正旧触发器精确库授权漏 EVENT:原精确 SELECT/TRIGGER 授权遮蔽了夹具通配库 EVENT 权限;补齐测试必要前提,不放宽产品检查。
- 修正旧官方存储对象测试竞态:事件有两条逐次提交的更新,原测试只等第一条完成;现在同时等待最终字段值及工作线程退出,再执行后续断言和子用例。
- 8.0 JSON_ARRAY 对周期字符串可能使用不透明 Base64 表示。现同时比较显式 UTF-8 文本、原始 HEX、字符集及排序规则,未忽略周期字段。
最终验证与证据
证据目录:artifacts/mysql-native-events-20260927/。JSONL 为 PowerShell UTF-16,读取使用 Get-Content -Encoding Unicode。
| 验证范围 | 最终证据或命令 | 结果 |
|---|---|---|
| Windows MySQL 5.7.44 全专项 | mysql57-commit-final.jsonl |
139 个叶子用例;含父项 159 条通过,0 失败、0 跳过 |
| Windows MySQL 8.0.45 全专项 | mysql80-commit-final.jsonl |
155 个叶子用例;含父项 175 条通过,0 失败、0 跳过 |
| 常规后端全量 | go test -count=1 -p 1 ./...,不设置实库测试变量 |
退出码 0;条件跳过不能充当实库通过 |
| 静态与模块 | go vet ./...、go mod verify |
退出码 0,模块校验通过 |
| Linux CLI 测试包 | GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go test -c ./internal/cli |
测试修正前产品代码交叉编译通过;不是 Linux 实库证据 |
实库命令为 go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli,分别指定 E:\DB\5.7\bin、E:\DB\8.0\bin 和上述隔离产物目录。最终 database/cli 耗时分别为 35.522/103.086 秒、50.614/133.481 秒。
mysql57-full.jsonl、mysql80-full.jsonl 留有旧授权失败;mysql57-commit-review.jsonl 留有多语句事件竞态失败,不能用它们作最终通过证据。其余早期复现、编码和到期日志保留追溯,不覆盖、不提交。
收尾核验:最终两版记录的端口无监听,本专项目录内所有 bootstrap.sql 均为空;仅保留原有三个共享 MySQL 进程。源码、正式 Go 测试与运维说明已提交,随机测试密钥、数据库、日志和编译产物只留在忽略目录。
剩余门禁与下一步
[~]推进视图自有备份与恢复,核对依赖顺序、原定义者、权限、字符集和官方工具互操作;当前版本仍拒绝视图,不能记作已支持。[ ]完整表清单权限、其他字符集/SQL 模式、跨库及跨服务器定义者、并发 DDL/授权变化和失败回滚完整语义。[ ]独立发行 CLI、Linux 实库、PostgreSQL、SQLite 并发锁、正式 Web 业务和 Windows/Linux 生产门禁。事件局部通过不提升 P0-05 总状态,不作生产放行。
十四、MySQL 视图与完整对象清单
本节接续第十三节的历史缺口。修改前检查点 a8f4a54;官方客户端错误码支持为 d95ecfa,本批实现及正式测试为 777c716,均已推送。全部 44 项范围不变,P0-05 保持 [~];不将 Windows 隔离证据当作生产放行。
实现与边界
- 读取表/视图清单前要求可证明的有效库级或全局 SELECT,不能把权限过滤后的对象列表当成完整备份;逐视图检查 SHOW VIEW。保留角色、部分撤销、精确与通配授权遮蔽的保守拒绝。
- 在固定会话模式下读取原始 SHOW CREATE VIEW,仅解析依赖而不重写定义;保留定义者、客户端编码、排序规则和检查选项。源会话设置在结束时恢复,失效视图拒绝导出。
- 本库视图按依赖排序,反向 DROP VIEW、正向 CREATE;不创建占位表,不 DROP 同名基础表。基础表仍仅支持 InnoDB;导出顺序为基础数据、例程、视图、触发器、外键检查恢复、事件。
- 覆盖普通/括号连接、子查询、函数内 FROM、CTE 及作用域、跨库引用排除、中文与反引号名称、1020 列宽视图;跨库测试只证明同实例既有依赖可引用,不代表跨服务器迁移已验证。
- 原始官方嵌套 CHECK OPTION 夹具在两版官方客户端均复现 1368。Scert 严格识别含 11 条语句的连续、闭合最终视图块,整块按依赖排序,不改变块内 SQL 或原文件,不跨业务语句、USE、未知 SET 等边界。
- 编码往返、重复名称、循环及 DROP/CREATE 名称不一致在执行输入文件前拒绝;对应重排块执行前再次核对实际数据库、SQL 模式及 UTF-8 客户端编码。此保护不承诺整个恢复脚本的事务回滚或任意 SQL 模式兼容。
- 官方工具错误码只在内存提取,不输出原始 stderr。测试修正仅补充进入目标权限检查的前提,不自动给产品扩权;例程定义可见与整库清单可读分开验证,缺 SELECT 时即使有 SHOW_ROUTINE 仍拒绝完整备份。
验证与证据
证据目录:artifacts/mysql-native-views-20260928/。目录名沿用本机测试时间;JSONL 为 PowerShell UTF-16,读取使用 Get-Content -Encoding Unicode。正式测试代码已提交,日志、数据库、随机密钥和编译产物不提交。
| 范围 | 证据 | 结果 |
|---|---|---|
| Windows MySQL 5.7.44 完整专项 | mysql57-commit-final.jsonl |
176 个叶子用例、含父项 201 条通过,0 失败、0 跳过 |
| Windows MySQL 8.0.45 完整专项 | mysql80-commit-final.jsonl |
202 个叶子用例、含父项 227 条通过,0 失败、0 跳过 |
| 常规后端全量 | backend-submit-final.jsonl |
1327 个叶子用例、含父项 1438 条通过,0 失败;43 项条件跳过不能充当实库通过 |
| 静态与依赖 | go vet ./...、go mod verify |
退出码 0,模块校验通过 |
| Linux CLI 测试包 | GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go test -c ./internal/cli |
交叉编译通过,未在 Linux 执行 |
两版完整专项命令为 go test -json -p 1 -count=1 -timeout=8m -run '^TestMySQLReal' ./internal/database ./internal/cli,分别设置 SCERT_MYSQL_TEST_BIN 为 E:\DB\5.7\bin、E:\DB\8.0\bin,并设置上述隔离根目录。5.7 完整专项之后仅调整了 8.0 部分撤销场景,随后用当前源码再次通过 5.7 的 TestMySQLRealRoutineVisibility;8.0 最终完整专项包含该调整。
mysql57-commit-review.jsonl、mysql80-commit-review.jsonl 记录视图夹具的 SELECT 前提缺失;mysql57-commit-full.jsonl 记录旧事件/触发器夹具前提问题;mysql80-commit-full.jsonl 记录旧例程测试未区分两种权限的问题。它们不是最终通过证据,均保留追溯。mysql80-routine-commit-review.jsonl 是修正后的例程定向通过记录,不能单独替代完整专项。
收尾核验当时:本目录 126 份初始化口令文件均为空,最终两版记录的 60 个端口无监听,本批隔离 mysqld 进程为 0;三个原有共享 MySQL 进程未动。未操作远端服务、生产数据库或真实 DNS。
任务状态与下一步
[x]本批视图导出/恢复、完整清单可见权限、官方互操作和失败保护实现及 Windows 隔离回归完成,等待完整范围复审。[~]下一步推进原定 SQLite 并发与锁要求,核对多连接/多实例、写锁等待和取消、事务回滚及会话配置恢复。[ ]MySQL 其他编码/SQL 模式、跨服务器定义者、并发 DDL/授权变化、独立发行 CLI、Linux 实库、PostgreSQL 当前复测、三库完整业务与双平台生产门禁。
十五、SQLite 连接池、并发与锁
本批日期:2026 年 9 月 28 日。修改前检查点为 6cab85d,正式源码为 af831ae,均已推送。测试使用 Windows 本机临时独立文件库;引擎为 SQLite 3.49.1,驱动仍为 modernc.org/sqlite v1.37.0。未操作远端部署、生产数据库或真实 DNS,也没有重跑第十四节的 MySQL 实库专项。
失败复现与实现边界
- 原先仅通过连接池执行一次忙等待配置,扩容、零空闲连接、连接替换和 DSN 自带其他等待值时,新连接配置不一致;四类正式回归先失败,修复后通过。
- 150 毫秒截止时间的写锁等待原先约 5.019 秒才返回,修复后约 153 毫秒返回。立即事务原先仅返回 SQLite BUSY,现保留底层错误并关联上下文超时信息。
- 使用
driver.Connector在每条物理连接入池前配置 WAL 和默认 5000 毫秒忙等待,保留正常连接池规模,不强制单连接掩盖竞争。 - 调用剩余截止时间不足 5 秒时,临时缩短等待预算并在结束后恢复;覆盖普通及预处理执行/查询、事务启动、结果逐行读取和连接初始化中的 WAL 设置。
- 配置失败或恢复失败时淘汰不确定连接,不重放业务 SQL;执行后的清理错误不转换为触发自动重试的
ErrBadConn。
正式回归范围
- 验证多连接、零空闲连接、连接替换、其他 DSN 参数保留、WAL 读写隔离和读事务快照。
- 双连接池的 8 个并发工作协程完成 200 次原子递增;三个独立测试子进程就绪后释放父进程写锁,共完成 150 次写入,并核对关闭重开后的持久化结果。
- 多进程测试复用正式 Go 测试二进制,没有生成辅助验收脚本;覆盖超时/回滚无错误写入副作用、连接继续使用及故障后不重放 SQL。
- 调用产品
backupSQLiteDatabase验证活动 WAL 快照:未提交数据不进入备份,提交后数据进入备份,并执行quick_check。
提交后复核证据
证据目录为 artifacts/sqlite-concurrency-20260928/,日志保留在本地且不纳入 Git。JSONL 为 PowerShell UTF-16,可用 Get-Content -Encoding Unicode 读取。最终提交源码的顺序复核会话退出码为 0,并输出 COMMITTED_SOURCE_ALL_CHECKS_PASSED。
| 检查 | 最终证据 | 实际结果 |
|---|---|---|
| SQLite 专项 | sqlite-commit-final.jsonl |
42 个叶子用例、含父项 49 条通过,2 个包,0 失败、0 跳过 |
| SQLite 竞态检测 | sqlite-race-commit-final.jsonl |
同上,竞态检测通过 |
| 后端全量 | backend-commit-final.jsonl |
1355 个叶子用例、含父项 1472 条通过,28 个包,0 失败;43 项条件跳过不算实库通过 |
| 核心重复回归 | sqlite-repeat-final.jsonl |
26 个不同叶子用例各重复 10 次,260 次叶子通过、含父项 310 条,0 失败、0 跳过 |
提交后前三项在 backend/ 下执行的命令:
go test -json -count=1 -timeout=90s -run '^TestSQLite' ./internal/database ./internal/cli
go test -race -json -count=1 -timeout=3m -run '^TestSQLite' ./internal/database ./internal/cli
go test -json -count=1 -timeout=8m ./...
失败记录 pool-before.jsonl、concurrency-review.jsonl、deadline-paths-review.jsonl 分别保留连接配置、短截止时间等待超限及立即事务错误信息缺失的复现,不作为最终通过证据。此前的 *-review.jsonl 定向通过记录也不替代本节最终全量结果。
已知限制与任务状态
[x]本节逐连接配置、短截止时间等待、并发竞争、回滚及 WAL 快照的 Windows 隔离回归完成,等待完整范围复审。[~]没有截止时间的手动取消仍可能等待约 5 秒;较长截止时间调用中途手动取消也不能承诺立即退出当前原生忙等待。边界测试记录这一限制,不表示立即取消已修复。[ ]事务提交/回滚仍沿用驱动接口;不承诺任意多语句脚本整体原子性。完整业务升级恢复、真实服务重启、断电恢复和网络文件系统仍需验证。[ ]Linux 原生运行、独立发行命令、其余数据库/平台和生产门禁继续保留;此前 Linux 测试包交叉编译不是 Linux 实机执行证据。
P0-05 总状态保持 [~],全部 44 项范围不变;本批局部通过不提升为生产验收通过。第十四节末的“下一步”保留为上一批历史记录,当前 SQLite 进展以本节为准。
十六、SQLite 异常退出及业务数据恢复
本批日期:2026 年 9 月 28 日(本机时间)。修改前检查点 5e5abf2,正式源码 6db5d7b,均已推送。仍使用 Windows 本机独立临时 SQLite 文件库,没有清理共享或生产数据库。第十四、十五节保留历史证据,本节补充当前恢复进展。
缺陷复现与产品修复
正式测试子进程打开数据库、提交修改后直接退出,不执行数据库关闭,确保留下真实且非空的 WAL。原恢复命令只替换主文件并报告成功,重新打开后却读到旧 WAL 中的数据,而非备份数据。wal-before.jsonl 保存该失败;同批还发现原恢复前副本没有合入已提交 WAL,不能独立代表恢复前状态。
修复由 operations.go 调用新增 sqlite_restore.go,在服务维护锁内、配置替换及恢复前副本生成之前执行:
- 核对主文件与 WAL/SHM/回滚日志状态,拒绝孤立日志及非普通路径。
- 由 SQLite 执行
wal_checkpoint(TRUNCATE),检查忙状态和检查点完成情况。 - 切换到 DELETE 日志模式并关闭连接,确认不再残留日志后才允许生成副本、替换主文件。
- 存在外部事务或无法完成预检时拒绝恢复;不手动删除日志、不重放业务 SQL。
成功恢复和后续证书资产失败两条路径都核对恢复前副本包含已提交 WAL 数据。后者还核对失败回滚后的业务内容,不能依赖残留 WAL 偶然保住旧数据。正常服务再次打开数据库时仍启用产品 WAL 配置。
当前业务样本覆盖
- 经正式迁移创建现有全部表,并在八张业务表中放入代表性数据:
settings、users、domains、servers、domain_servers、tasks、task_attempts、audit_logs。 - 使用正式备份/恢复命令处理器,不直接用测试复制替代命令;比较全部表内容、模式和索引定义、
schema_migrations及sqlite_sequence。 - 备份后修改业务字段、删除部署绑定和任务尝试、增加审计数据,并改变配置、加密凭据及证书内容,确保恢复不是空操作。
- 通过产品仓储读取用户密码/角色/分组、域名及到期时间、服务器凭据引用、任务操作者/证书版本、尝试记录和部署绑定;核对恢复后的自增写入。
- DNS 账户归属在配置中核对;恢复后重新打开凭据存储并验证内容一致。SSH 私钥与证书/私钥均在测试中随机生成,恢复后可解析或完成配对;没有真实云凭据或外部调用。
- 同一归档连续恢复两次,确认归档清单不被读取或恢复过程修改。
这些测试覆盖当前模式中的业务样本冷恢复,不证明带历史业务数据的跨版本升级、HTTP 登录、外部 DNS/SSH/邮件调用或独立发行二进制已经验收。
最终验证证据
证据目录为 artifacts/sqlite-restore-20260928/,JSONL 为 UTF-16,保留在本地并由 Git 忽略。失败历史不删除;未生成辅助验收脚本,异常退出场景复用正式测试二进制。
| 检查 | 证据或命令 | 实际结果 |
|---|---|---|
| SQLite 全专项 | sqlite-final.jsonl |
55 个叶子用例、含父项 66 条通过,2 个包,0 失败、0 跳过 |
| 新增恢复用例重复竞态检测 | restore-race-repeat.jsonl |
13 个叶子用例各执行 5 次,65 条叶子、含父项 85 条通过,0 失败、0 跳过 |
| 后端全量 | backend-final.jsonl |
1368 条叶子、含父项 1489 条通过,28 个包,0 失败,43 项条件跳过 |
| 静态与模块 | go vet ./...、go mod verify |
退出码 0,模块校验通过 |
| Linux CLI 测试包 | GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go test -c ./internal/cli |
交叉编译通过,未在 Linux 执行 |
后端全量的 1368 条叶子记录对应 1367 个不同的包/测试名称;已有 PostgreSQL 非安全 DSN 用例有一个名称重复输出,不把重复记录当成额外覆盖。43 项条件跳过仍不算实库通过。
主要测试命令在 backend/ 下执行:
go test -json -count=1 -timeout=90s -run '^TestSQLite' ./internal/database ./internal/cli
go test -race -json -count=5 -timeout=3m -run '^TestSQLite(Business|Restore)' ./internal/cli
go test -json -count=1 -timeout=8m ./...
wal-before.jsonl 为失败复现,wal-after.jsonl 和 business-review.jsonl 为中间定向结果;最终依据以上 *-final.jsonl 及 restore-race-repeat.jsonl。本轮未重跑 MySQL 实库,不沿用其历史通过结果冒充本轮复测。
剩余边界与任务状态
[x]异常退出恢复、恢复前 WAL 快照、资产失败回滚、外部读写事务占用、三类孤立/目录日志路径及取消前置检查的 Windows 隔离回归完成。[x]当前全部表的代表性业务样本、资源关联、凭据与证书冷恢复及重复恢复验证完成,等待完整范围复审。[ ]带历史业务数据的跨版本升级、独立发行命令、真实服务重启、Linux 原生执行、物理断电及磁盘故障。进程退出不等于断电,交叉编译不等于实机通过。[ ]取消边界、其余数据库/平台、Web/外部服务与生产门禁继续保留;维护锁不能阻止外部程序在预检之后重新访问数据库,整个恢复期间仍须停止所有外部访问。
P0-05 保持 [~],全部 44 项范围不变;本批修复和回归不作为生产放行结论。
十七、SQLite 历史业务数据升级及独立程序恢复
本批日期:2026 年 9 月 28 日(本机时间)。修改前检查点 0e16d28,正式源码 fd2810bf03f4e4f7b4dd25f36d28848aca185d22,均已推送。测试使用 Windows 本机临时 SQLite 文件库和临时工作目录,没有操作生产服务、生产数据库、真实 DNS、SSH 或邮件服务。
缺陷复现与产品修复
原迁移 4 直接向已有数据的 tasks 表添加 NOT NULL DEFAULT CURRENT_TIMESTAMP 列。SQLite 对非空表不接受该非固定默认值,历史模式 1、2、3 只要存在任务数据就会升级失败;旧测试只覆盖空表,未发现该缺陷。失败证据保留在 artifacts/sqlite-upgrade-20260928/upgrade-before.jsonl,该目录由 Git 忽略。
产品由 migrate.go 在 SQLite 迁移 4 中调用 sqlite_task_migration.go:固定物理连接,临时保存并关闭该连接的外键检查;在同一事务中读取原表定义,使用不冲突的临时表重建 tasks,保留原有业务列、行号、索引、视图、触发器、生成列和外键关联;完成 PRAGMA foreign_key_check 后记录迁移版本并提交。失败时整体回滚,临时表冲突、版本登记拒绝和外键冲突均不会覆盖原数据;排除阻塞后可再次迁移。事务完成后恢复原连接外键设置,恢复失败则不复用状态未知的连接。没有修改原迁移 SQL,也没有使用 writable_schema。
历史模式和依赖对象回归
- 模式 1~9 分别写入该模式支持的代表性业务数据后升级,连续执行两次,核对原字段内容、关联、历史时间和新任务默认时间。
- 覆盖外键开关、额外列、虚拟生成列、显式行号、中文命名唯一索引、级联子表、任务表触发器、外部引用触发器、依赖视图及视图上的
INSTEAD OF触发器。 - 覆盖迁移版本登记失败、临时表名称冲突和外键冲突;失败后模式、数据、迁移历史和连接设置保持不变,解除阻塞后重试成功。
- 这些历史模式由当前仓库迁移文件构造,不等同于旧发行二进制实际运行产生的数据;不承诺任意第三方改造的 SQLite 模式均可升级。
独立 Windows 产品程序恢复
使用干净提交构建的独立 scert.exe,通过正式应用入口执行两条恢复路径:
- 模式 3 旧备份恢复后再次由产品程序触发升级。
- 升级完成后的备份恢复到新工作目录。
测试在恢复前修改任务、删除部署绑定、破坏证书并变更加密凭据,核对恢复后的表结构、业务数据、迁移记录、自增序列、任务绑定、用户密码摘要、加密凭据和证书配对。子进程使用临时目录和超时,剔除继承的 SCERT_* 环境变量,输出不包含随机凭据或密码;未创建辅助验收脚本。该程序是干净源码构建的独立产品程序,不是完整发行包安装证据。
最终验证证据
| 检查 | 证据或命令 | 实际结果 |
|---|---|---|
| SQLite 专项 | sqlite-final.jsonl,go test -json -count=1 -timeout=3m -run '^TestSQLite' ./internal/database ./internal/cli |
71 个叶子用例、含父项 86 条通过,2 个包,0 失败、0 跳过 |
| 后端全量 | backend-final.jsonl,go test -json -count=1 -timeout=8m ./... |
1384 个叶子用例、含父项 1509 条通过,0 失败、43 项条件跳过 |
| 重复竞态 | upgrade-race.jsonl,`go test -race -json -count=3 -timeout=5m -run '^TestSQLite(BusinessUpgrade |
BusinessRestore |
| 静态与模块 | go vet ./...、go mod verify |
退出码 0,模块校验通过 |
| 独立产品程序 | TestSQLiteBusinessUpgradeStandaloneCLI |
干净提交构建的 Windows amd64 程序完成旧备份升级、恢复后再升级及升级后备份恢复 |
| Linux 目标验证 | GOOS=linux GOARCH=amd64 CGO_ENABLED=0 go test -c |
数据库和 CLI 测试包交叉编译通过;没有在 Linux 主机执行 |
干净提交构建程序信息:Go go1.26.6、windows/amd64、CGO_ENABLED=1、vcs.revision=fd2810bf03f4e4f7b4dd25f36d28848aca185d22、vcs.modified=false,SHA-256 为 F22736221E79E92928E86EB1EFC48F21994914C937CF9865FB1C4A691E36BD8B。该文件不是完整发行包。
剩余边界与任务状态
[x]历史模式 1~9 带业务数据升级、依赖对象保留、失败回滚和排除阻塞后重试完成。[x]独立 Windows 产品程序的两条备份恢复路径完成,测试未使用辅助验收脚本。[ ]旧发行包实际产生的数据和配置、完整发行包安装、真实服务重启、Linux 原生执行、断电/磁盘故障及取消边界。[ ]PostgreSQL 当前实库、MySQL 剩余门禁、Web/外部服务、双平台生产门禁和真实生产验收;交叉编译、隔离夹具和独立程序不能替代上述证据。
P0-05 保持 [~],全部 44 项范围不变;本节只记录当前局部修复和回归,不构成生产放行结论。
十八、项目根实体与模式 10 验证(2026 年 9 月 28 日)
18.1 实现范围与安全边界
新增 domain.Project、项目 SQL 仓储、三套 0010_projects.sql 及迁移登记。应用启动后创建项目表和默认项目,但既有域名、服务器、任务和审计尚未增加项目字段;本节不证明项目资源隔离。
默认项目 ID 固定为 default;仓储禁止重复创建或删除默认项目,允许调整名称和说明。迁移重试不覆盖已有资料;项目 ID 与创建时间不随资料更新改写。项目名称与说明支持中文及四字节字符,校验长度、编码和控制字符。项目仓储尚未接入 HTTP 路由,不能作为已交付的 Web 功能。
SQLite 版本登记失败时回滚项目表及种子,原业务不变;MySQL 建表后版本登记失败时保留部分 DDL 状态,解除故障后可重复迁移并保留用户资料,不承诺 MySQL DDL 自动回滚。PostgreSQL 文件已登记并通过目录一致性检查,但当前批次未执行 PostgreSQL 原生实库项目验证。
18.2 验证证据
本批目录:artifacts/project-model-20260928/。该目录及构建产物保持 Git 忽略,不包含在源码提交中。
| 层级 | 证据文件 | 实际结果 |
|---|---|---|
| 最终后端全量 | backend-all-final.jsonl |
1409 个叶子通过、含父项 1535 条,0 失败、46 项条件跳过 |
| 项目及迁移竞态 | race.jsonl |
每轮 54 个叶子,连续 3 轮共 162 个叶子通过;6 条外部 MySQL 条件跳过由下两行单独补验 |
| MySQL 5.7.44 | mysql57-final.jsonl |
8 个叶子、含父项 9 条通过,0 失败、0 跳过;独立临时实例、仅回环监听、严格 TLS |
| MySQL 8.0.45 | mysql80-final.jsonl |
8 个叶子、含父项 9 条通过,0 失败、0 跳过;独立临时实例、仅回环监听、严格 TLS |
| 独立 Windows 产品程序 | standalone-projects.jsonl |
旧备份恢复再升级、模式 10 备份恢复两条路径通过,核对全表/模式及默认和普通项目 |
| 静态与模块 | go vet ./...、go mod verify |
均退出 0,模块校验显示全部通过 |
MySQL 8.0 首轮 mysql80.jsonl 中,项目仓储通过,迁移故障测试在创建触发器时因产品连接缺少全局权限失败。故障注入已移到同一隔离实例的管理连接,产品连接的权限及安全配置不变;最终两版均从新的独立实例重新运行。首轮失败证据保留,不当作产品迁移成功或抹除失败记录。
完整后端命令:
cd D:\Desktop\Scert\backend
go test -json -count=1 -timeout=10m ./...
go vet ./...
go mod verify
项目与迁移重复竞态命令:
go test -race -json -count=3 -timeout=5m -run 'Project|MigrationCatalog|SQLiteUpgradeFromEverySupportedVersion|SQLiteBusinessUpgradeFromEveryVersion' ./internal/domain ./internal/repository ./internal/database
MySQL 专项分别设置 SCERT_MYSQL_TEST_BIN 为 E:\DB\5.7\bin、E:\DB\8.0\bin,SCERT_MYSQL_TEST_ROOT 分别为本批证据目录下的 mysql57-final、mysql80-final;不接受已有业务实例的连接串。
go test -json -p 1 -count=1 -timeout=5m -run 'TestMySQLRealProjectMigrationRetry|TestSQLProjectRepositoryMySQLReal' ./internal/database ./internal/repository
独立产品程序验证使用当批源码构建的 build/review-scert-project-windows-amd64.exe,通过 SCERT_SQLITE_TEST_CLI 显式指定程序绝对路径:
go build -o ..\build\review-scert-project-windows-amd64.exe ./cmd/scert
$env:SCERT_SQLITE_TEST_CLI = 'D:\Desktop\Scert\build\review-scert-project-windows-amd64.exe'
go test -json -count=1 -timeout=3m -run '^TestSQLiteBusinessUpgradeStandaloneCLI$' ./internal/cli
测试保留完整历史库模式和业务快照;模式 10 备份前通过项目仓储创建普通项目,恢复前修改项目名称,恢复后对全部表逐项比对。旧模式备份恢复后必须重新通过正式产品命令升级,而不是由测试直接调用迁移代替正式入口。该程序验证不等于完整发行包安装、后台服务重启或生产验收。
18.3 当前任务状态
- 项目根实体、默认项目、三库迁移文件和 SQL 仓储实现,等待复审。
- SQLite 模式 0~10 升级(1~10 含代表性业务)、默认项目不覆盖、失败回滚与重试;MySQL 两版实际 CRUD 和部分 DDL 重试。
- 默认与普通项目随 Windows 产品程序备份恢复;其他项目不会因单个项目删除而丢失。
- PostgreSQL 原生项目实库验证、完整三库备份矩阵、Linux 原生执行、旧发行程序实际数据、完整发布/安装/重启和生产门禁。
- 资源
project_id及归属字段、历史回填、外键/引用删除保护、跨项目部署约束、成员授权、Web/API 与越权测试。
P0-06、P0-07 保持 [~],P0-05 的完整支持矩阵也不提升;原始全部 44 项继续执行。本节不提供生产放行结论。
十九、资源归属与 SQLite 替换保护(2026 年 9 月 28 日)
19.1 源码与修复范围
模式 11 源码为 7284958,本批修改前检查点为 cad238a;模式 12 修复源码为 92c844f。此前第十八节描述项目根实体历史批次,不能代表当前模式 12 的完整验收。
模式 11 已接入域名/服务器的项目、所有者、创建者和更新者字段,回填默认项目,并约束同项目部署绑定。后续正式用例发现,SQLite 关闭递归触发器时,主键及隐藏行号冲突的替换操作可能隐式删除被引用行;外键开关不能独立弥补原触发器约束缺口。
新增模式 12,不修改已登记的历史迁移。SQLite 在迁移事务中校验既有引用并安装七个保护触发器;遇到无效引用、触发器冲突或版本登记失败时整体回滚,不删除业务数据。MySQL/PostgreSQL 沿用模式 11 外键,本版仅统一版本登记,不据此声称已验证两库全部替换语义。
19.2 最终证据
本批证据目录为 artifacts/resource-replacement-20260928/,原始日志留在本地忽略目录,不纳入源码提交。下列统计已读取最终日志,并确认原运行会话退出码为 0;通过数按叶子用例计数,条件跳过不包括无测试文件包。
| 验证 | 日志或命令 | 最终结果 |
|---|---|---|
| 修复前复现 | before.jsonl |
40 个组合叶子中 20 个失败、20 个通过;22 条失败事件包含父测试和包,不是 22 个失败用例 |
| 完整后端 | backend-final.jsonl |
1480 个叶子通过、含父项 1612 条,0 失败、47 项条件跳过 |
| 三次竞态 | race-final.jsonl |
三轮共 255 个叶子通过、含父项 276 条,0 失败、6 项条件跳过 |
| MySQL 5.7 | mysql57-final.jsonl |
83 个叶子通过、含父项 90 条,0 失败、0 跳过 |
| MySQL 8.0 | mysql80-final.jsonl |
83 个叶子通过、含父项 90 条,0 失败、0 跳过 |
| 独立 Windows 产品程序 | 完整后端日志中的 TestSQLiteBusinessUpgradeStandaloneCLI |
两条备份恢复路径通过,并实际拒绝恢复后的项目替换和域名行号替换 |
| 静态与模块 | go vet ./...、go mod verify |
同一顺序执行会话退出 0,模块校验显示全部通过 |
MySQL 每条专项命令同时包含 SQLite 用例,不能称为 83 个纯 MySQL 用例。使用既有 Go 隔离夹具、临时实例、回环监听与严格 TLS,没有清空业务数据库。完整后端日志中的外部环境条件跳过不等于相应环境验收通过。
上一批模式 11 的独立证据位于 artifacts/resource-project-20260928/:后端 1432 个叶子通过、含父项 1562 条、47 项条件跳过;三次竞态共 114 个叶子通过、6 项条件跳过;MySQL 两版专项各 37 个叶子通过且无跳过,也包含 SQLite 用例。不得与模式 12 的数字混用。
19.3 实际验证命令
以下命令在 backend/ 执行。产品程序在代码提交前构建,仅作本批独立程序验证,不称干净发行包。
go build -o ..\build\review-scert-replacement-windows-amd64.exe ./cmd/scert
$env:SCERT_SQLITE_TEST_CLI = 'D:\Desktop\Scert\build\review-scert-replacement-windows-amd64.exe'
go test -json -count=1 -timeout=10m ./...
go test -race -json -count=3 -timeout=5m -run 'ResourceProject|ResourceScope|MigrationCatalog|SQLiteBusinessUpgradeFromEveryVersion' ./internal/database ./internal/repository ./internal/httpapi
go vet ./...
go mod verify
MySQL 专项分别设置 SCERT_MYSQL_TEST_BIN 为 E:\DB\5.7\bin、E:\DB\8.0\bin,隔离目录通过 SCERT_MYSQL_TEST_ROOT 指向本批证据目录下的 mysql-isolated,不连接业务实例。
go test -json -count=1 -timeout=8m -run 'ResourceProject|SQLProjectRepositoryMySQLReal|MySQLRealProjectMigrationRetry' ./internal/repository ./internal/database
19.4 状态与未覆盖边界
- 模式 12 引用保护、正常写入、四种连接开关组合、故障回滚与重试正式回归通过,等待复审。
- 文档与最终日志核对完成,保留修复前失败证据。
- 干净源码发行包、Linux 原生运行、PostgreSQL 当前实库、完整三库备份恢复、服务重启及生产门禁。
- 任务/审计等剩余资源项目关联、项目成员授权、跨项目 Web/API 越权验证和大规模性能准入。
本次整理只提交已有有效修复及必要文档,不部署生产,不提升 P0-05/P0-06/P0-07 总项状态,也不将 44 项整改目标标记为完成。
二十、任务/审计范围快照与模式 13(2026 年 9 月 28 日)
20.1 源码与交付边界
修改前检查点为 5237e8d,本节与模式 13 实现及最终回归测试同批提交。新增三库迁移、历史范围回填、仓储校验、HTTP 与后台任务关联。模式 12 的第十九节保留原证据,不以其结果替代本批验证。
任务范围分为项目、系统与未知;实际业务任务必须关联当前存在的域名项目,新尝试拒绝资源删除、项目改变或未知父任务。历史任务/审计是快照,不加级联项目外键,不伪造历史身份;孤儿尝试仍可读。范围字段与新建校验不等于项目成员授权,也不保证任意直接 SQL 写入的正确性。
20.2 最终验证结果
证据目录:artifacts/history-scope-20260928/。原始日志和构建程序位于 Git 忽略目录,不作为源码提交。下表终态会话均确认退出 0,叶子统计不把父测试计为独立用例,条件跳过不计无测试文件包。
| 验证 | 日志 | 结果 |
|---|---|---|
| 完整后端 | backend-final.jsonl |
1514 个叶子通过、含父项 1649 条;0 失败,49 项条件跳过,28 个测试包通过 |
| 三次竞态专项 | race-final.jsonl |
三轮共 258 个叶子通过、含父项 294 条;0 失败,6 项条件跳过 |
| MySQL 5.7 | mysql57-review.jsonl |
135 个叶子通过、含父项 146 条;0 失败,0 跳过 |
| MySQL 8.0 | mysql80-review.jsonl |
135 个叶子通过、含父项 146 条;0 失败,0 跳过 |
| 登录与账户身份复测 | actor-after.jsonl |
28 个叶子通过、含父项 31 条;0 失败,0 跳过;之后又纳入最终全量及竞态验证 |
| 独立 Windows 产品程序 | 完整后端日志中的 TestSQLiteBusinessUpgradeStandaloneCLI |
historical_backup、upgraded_backup 两条路径通过;校验模式 13、历史任务项目及此前引用保护 |
| 静态与模块 | go vet ./...、go mod verify |
最终竞态之后顺序执行,整体退出 0,模块全部校验通过 |
MySQL 专项同时执行 SQLite 用例,不是 135 个纯 MySQL 用例。使用既有 Go 隔离夹具、独立数据库、回环监听与严格 TLS;未清空生产数据。双版本完成后仅追加 HTTP 身份修复及其测试,数据库/仓储实现未改变,最终后端和竞态在身份修复后重新执行。
独立程序由本批提交前工作区构建,不称干净发行包。条件跳过代表对应外部环境未配置,不能据此宣称 PostgreSQL、Linux 或生产环境通过。
20.3 原始失败记录与修复
initial.jsonl:审计响应字段增加后旧字段数断言失败;历史任务范围回填真实调用原有更新触发器,旧触发次数断言失败。更新正式预期,没有屏蔽触发器,也没有删历史数据。review-targeted.jsonl:新增管理续期断言误要求被故障注入拒绝的开始审计也存在。修正为通用断言检查实际审计关联,正常成功流程另行要求开始和收尾两条记录。actor-before.jsonl、actor-fixture-before.jsonl:首轮身份回归同时暴露测试夹具缺少账户查询、测试角色和密码不符合现有策略,原日志保留;未因此放宽产品权限或密码策略。actor-verified-before.jsonl:夹具修正后,四个失败叶子准确复现新登录无操作者、旧 Cookie 身份串用、失败登录误认旧身份及自身账户更新后身份丢失。修复使用本次认证结果/写入前会话身份;改密另补失效后审计与旧会话拒绝回归。- SQLite 新迁移验证历史保留、二次迁移、回填触发器拒绝、索引冲突、版本登记失败的整体回滚和修复重试。MySQL 注入回填/版本登记故障并重试,DDL 部分完成时不清空历史或覆盖已确认范围。
20.4 实际命令
以下命令在 backend/ 执行,无辅助验收脚本;JSON 日志在当前 Windows PowerShell 中按 Unicode 编码读取。
go build -o ..\build\review-scert-history-windows-amd64.exe ./cmd/scert
$env:SCERT_SQLITE_TEST_CLI = 'D:\Desktop\Scert\build\review-scert-history-windows-amd64.exe'
go test -json -count=1 -timeout=10m ./...
go test -race -json -count=3 -timeout=6m -run 'HistoryScope|TaskAPI|AuditLogResponse|CertificateTask|ManagementRenewal|SQLiteBusinessUpgradePreservesDependentObjects|AuthLogin|ChangePassword|UserManagement' ./internal/repository ./internal/database ./internal/httpapi ./internal/app
go vet ./...
go mod verify
MySQL 分别设置 SCERT_MYSQL_TEST_BIN 为 E:\DB\5.7\bin 和 E:\DB\8.0\bin,SCERT_MYSQL_TEST_ROOT 指向 D:\Desktop\Scert\artifacts\history-scope-20260928\mysql-isolated。
go test -json -count=1 -timeout=8m -run 'HistoryScope|ResourceProject|SQLProjectRepositoryMySQLReal|MySQLRealProjectMigrationRetry' ./internal/repository ./internal/database
20.5 仍未完成
- 剩余资源项目关联、成员关系与角色授权、撤权后的执行/重试/取消重新判权,以及跨项目列表、详情和危险操作越权验证。
- PostgreSQL 当前实库、完整三库备份恢复、Linux 原生、干净完整发行包、Windows Service/systemd 重启及生产部署门禁。
- 历史大数据回填和查询性能准入。
本批子项为 [x] 等待复审;P0-05、P0-06、P0-07 总项保持 [~],全部 44 项目标继续执行,不提供生产放行结论。
二十一、项目成员与实时判权基础(2026 年 9 月 28 日)
21.1 范围与修改前状态
修改前检查点 4f1900d 已推送;新增模式 14 及项目成员、六类角色、实时权限判定和同语句授权变更。成员独立于用户分组;旧用户不自动获得默认项目权限,普通管理员必须具备显式项目角色,普通账户不得读取完整私钥。详细能力矩阵见《项目资源关联模型.md》第九节。
本批不开放新的项目管理路由,不声称全部业务已接入授权。测试使用正式 Go 测试、既有隔离 MySQL 夹具和独立产品程序;没有创建辅助验收脚本,没有清理生产数据库或操作远端服务。
21.2 最终证据
日志位于 artifacts/project-members-20260928/,构建产物和隔离实例均不入 Git。叶子数排除父测试,三次竞态按实际三轮累计;测试级条件跳过与无测试文件的包事件分开统计。
| 验证 | 最终日志/结果 | 结论与边界 |
|---|---|---|
| 角色、成员、迁移专项 | targeted-verified.jsonl:115 个叶子通过,含父项 125 条,0 失败、2 项条件跳过 |
SQLite 与角色/仓储通过;此命令未配置外部 MySQL,不将跳过当实库通过 |
| 完整后端 | backend-verified.jsonl:1623 个叶子通过,含父项 1767 条,0 失败、51 项条件跳过,28 个测试包通过 |
最新模式 14、SQLite 历史升级及 Windows 独立产品程序均在本次运行内;外部环境条件跳过仍未验收 |
| 三次竞态 | race-verified.jsonl:633 个叶子通过,含父项 687 条,0 失败、18 项条件跳过 |
覆盖成员、角色、历史范围、资源项目、用户管理与登录;不是全部后端三次竞态 |
| MySQL 5.7 | mysql57-verified.jsonl:242 个叶子通过,含父项 262 条,0 失败、0 跳过 |
既有 Go 夹具的回环隔离实例及严格 TLS;命令包含 SQLite 用例,不称 242 个纯 MySQL 用例 |
| MySQL 8.0 | mysql80-verified.jsonl:同上 |
相同专项独立执行;两版验证均在最后空邮箱修复后进行,包含迁移完整性检查 |
| Windows 独立产品程序 | 完整日志中的 historical_backup、upgraded_backup 均通过 |
历史模式经正式入口升级至 14;新备份含成员两个项目角色,恢复后重新验证允许与跨项目拒绝;程序来自提交前工作区,不称干净完整发行包 |
| 静态与依赖 | go vet ./...、go mod verify 退出码均为 0 |
在最终竞态之后顺序执行,依赖输出 all modules verified |
SQLite 成员引用检查覆盖四种外键/递归触发器开关组合,包含主键、行号、用户名、邮箱、扩展唯一索引替换、负行号正常新增及多个空邮箱账户正常新增/更新。迁移版本登记或触发器冲突故障完整回滚,重试不改历史数据。MySQL 专项覆盖数据库默认字符集改变、版本登记失败后的 DDL 保留及重试、外键缺失时拒绝登记和修复后重试;不删除或重建业务用户表。
21.3 保留的初版失败证据
backend-initial.jsonl:独立 CLI 测试断言仍固定为模式 13,实际程序已升级为 14,因此失败;已更新断言,并补充成员多角色备份恢复和恢复后的重新判权,不仅修改版本数字。replacement-before.jsonl:两个失败叶子分别复现负行号关联记录导致正常新增被拒绝,以及用户扩展唯一索引的UPDATE OR REPLACE绕过成员引用保护。已修改插入前行号判定,并补充更新后引用检查;修复后的专项、双版本 MySQL、完整后端和竞态全部重新执行。empty-email-before.jsonl:正式回归复现成员保护误把空邮箱当作唯一冲突,导致其他空邮箱账户正常新增被拒绝;修复遵循users(email) WHERE email <> ''的既有唯一性规则,并覆盖更新路径。initial.jsonl、targeted.jsonl、mysql57.jsonl、mysql80-review.jsonl、backend-review.jsonl以及全部*-final.jsonl均为中间验证;后者早于最后空邮箱修复,不替代当前*-verified.jsonl。保留所有历史及失败证据。
21.4 实际命令
在 backend/ 执行;当前 Windows PowerShell 的重定向 JSON 日志按 Unicode 编码读取。
go build -o ..\build\review-scert-members-windows-amd64.exe ./cmd/scert
$env:SCERT_SQLITE_TEST_CLI = 'D:\Desktop\Scert\build\review-scert-members-windows-amd64.exe'
go test -json -count=1 -timeout=10m ./...
go test -json -count=1 -timeout=5m -run 'ProjectMembers|ProjectRolePermission|MigrationCatalog' ./internal/domain ./internal/database ./internal/repository
go test -race -json -count=3 -timeout=6m -run 'ProjectMembers|ProjectRolePermission|HistoryScope|ResourceProject|UserManagement|AuthLogin' ./internal/domain ./internal/database ./internal/repository ./internal/httpapi
go vet ./...
go mod verify
MySQL 分别设置 SCERT_MYSQL_TEST_BIN 为 E:\DB\5.7\bin、E:\DB\8.0\bin,SCERT_MYSQL_TEST_ROOT 为 D:\Desktop\Scert\artifacts\project-members-20260928\mysql-isolated:
go test -json -count=1 -timeout=8m -run 'ProjectMembers|HistoryScope|ResourceProject|SQLProjectRepositoryMySQLReal|MySQLRealProjectMigrationRetry' ./internal/repository ./internal/database
21.5 未完成项及后续依赖
- 成员管理 Web/API、界面、分页与成员变更审计;当前尚无完整对外项目管理入口。
- 所有业务资源根据真实记录解析项目的读写授权、私钥/凭据入口、任务提交/执行/取消/重试和排队期间撤权后的重新判权;不能把仓储判权基础当成完整业务隔离。
- 剩余核心资源项目关系、跨项目 Web/API 列表/详情/导出/删除/回滚越权矩阵。
- PostgreSQL 当前实库、完整三库恢复、Linux 原生、干净完整发行包、Windows Service/systemd 重启与原定 12 层生产门禁。
- 成员与资源规模扩大后的查询/触发器性能准入。
本批子项 [x] 等待复审;P0-05、P0-06、P0-07 总项仍为 [~]。原始 44 项及最终生产验收范围保持不变。
二十二、成员事务审计、SQLite 驱动与运行时回归(2026 年 9 月 28 日)
22.1 本批实现与版本边界
- 成员成功授予/撤销和审计共用数据库事务;审计插入失败或影响行数不是 1 时回滚成员变更,保留实际操作者、项目、目标账户和角色。MySQL 非 InnoDB 成员表/审计表拒绝变更,不自动修改存储引擎。源码先保存于检查点
83a3ada,不将检查点视为发布。 - 原
modernc.org/sqlite v1.37.0取消查询在驱动丢弃结果集时可遗留 statement;正式TestSQLiteCanceledQueriesReleaseFiles的 direct/prepared 均复现旧驱动失败。断言包括 WAL 检查点、数据库关闭及立即重命名文件,没有睡眠重试关闭,也未跳过公共服务关闭测试。 - v1.40.1 修复候选解决了上述结果集释放路径,并通过中间回归,但实测引擎为 3.50.4。SQLite 官方 WAL 文档列出该版本在 WAL-reset 缺陷影响范围内,因此不将此候选作为最终版本。
- 最终验证候选固定为
sqlite v1.59.0/libc v1.75.7/memory v1.12.1,运行时查询引擎版本为 3.53.4。依赖来源为 Go 校验模块和对应版本源码;不将版本升级表述为解决所有未知安全问题。 - 新增
TestSQLiteWALCheckpointIntegrity:三个真实连接,两个写入者各 256 个双行事务与检查点并发;最终 TRUNCATE 检查点后关闭并重新打开文件,验证integrity_check、1024 条记录、主键范围、逐行值及总和。它是应用回归,不是官方 WAL-reset 缺陷的确定性复现。 TestHistoryScopeMySQLMigrationRetry必须命中预期错误 1644 与注入消息;失败后和每次重试后校验三条索引字段顺序及CHECK TABLE。不能把任意迁移失败当作故障注入成功,也不使用 REPAIR/自动重建来掩盖元数据异常。
本批未修改生产迁移 SQL、服务关闭或续期调度逻辑,模式仍为 14。上游核查入口(2026-09-28 读取):
https://sqlite.org/wal.html#the_wal_reset_bug
https://gitlab.com/cznic/sqlite/-/blob/v1.59.0/CHANGELOG.md
https://gitlab.com/cznic/sqlite/-/blob/v1.59.0/go.mod
22.2 保留的失败和中间证据
证据目录:artifacts/project-member-audit-20260928/ 与 artifacts/runtime-migration-20260928/,文件均不进入源码提交。
| 批次/文件 | 已核实结果 | 解释 |
|---|---|---|
旧驱动 sqlite-cancel-before.jsonl |
direct/prepared 失败,退出码 1 | 取消查询遗留读事务与文件占用的回归证据 |
v1.40.1 sqlite-cancel-after.jsonl、service-close-after.jsonl |
20 个取消查询叶子及 30 次服务关闭通过 | 仅为中间驱动证据 |
v1.40.1 backend.jsonl、race.jsonl |
全后端 1634 个叶子通过、52 跳过;竞态 828 个叶子通过、15 跳过 | 不替代 v1.59.0 最终验证 |
mysql57-after.jsonl |
530 个叶子通过、1 失败,退出码 1 | 服务端日志确认初始化阶段缓冲池内存分配失败;包含 SQLite 用例 |
mysql80-after.jsonl |
完成 247 个叶子通过,数据库包进程异常终止,退出码 1 | Go 运行时无法分配内存,中断用例不能计通过 |
旧 mysql57-verified.jsonl |
历史迁移重试发生 Error 1280 | 服务端同时报 InnoDB 内部 3 个索引与 MySQL 元数据 2 个索引不一致;与后来内存失败不是同一个已证实根因 |
8.0 异常退出遗留的两个 mysqld 进程,经绝对程序路径和隔离数据目录核验后终止;未停止本机其他 MySQL 服务,未删除测试文件或清理生产库。保留旧失败,不能用后续重跑覆盖失败事实。
22.3 最终候选验证记录
当前采用 GOMAXPROCS=2 与 go test -p 1,按版本依次运行 MySQL,避免多批重型测试同时消耗内存;并未禁止测试内部并发,也未降低 TLS 或减少用例。进程退出码必须取回,不能只凭日志末尾出现 PASS。
- 最后源码的
sqlite-verified.jsonl:direct/prepared/WAL 各重复 10 次,共 30 个叶子通过、0 失败;初版sqlite-final.jsonl不作最后源码证据。 mysql57-final.jsonl与mysql80-final.jsonl:各三轮累计 531 个叶子通过、0 失败、0 跳过,两个进程退出码均为 0;组合包含 SQLite 用例,不称 531 个纯 MySQL 测试。backend-final.jsonl:1635 个叶子通过、0 失败、52 条条件跳过;条件跳过不算通过。独立 Windows 产品程序的TestSQLiteBusinessUpgradeStandaloneCLI/historical_backup与upgraded_backup均通过。service-close-final.jsonl:并发关闭重复 30 次通过;最终 Windows 构建、go vet -p 1 ./...、go mod verify和 Linux 交叉构建成功,全部顺序步骤退出码为 0,18:29 已取回最后进程结果。race-final.jsonl:最后候选三轮扩大竞态 831 个叶子通过、0 失败、15 条条件跳过,进程退出码为 0。五个外部 MySQL 条件测试各跳过三次,不将未带竞态的实库组合当作 MySQL 竞态通过;旧驱动的 828 个通过记录仅保留为历史。
候选二进制 SHA256(仅定位当前构建,不代表发行包或生产放行):
| 目标 | SHA256 |
|---|---|
| Windows amd64 | 885497724A940695F45F02027FB48C9D754A89D21F9071E7EECF52C08534308A |
| Linux amd64 | 64B9807A1231EEA3F6CA3D3484837AEF5ED20EF925F7CB02B6716EE0646DCEB3 |
在 backend/ 执行,JSONL 为当前 PowerShell 重定向编码;测试目录使用现有忽略的 artifacts/runtime-migration-20260928/,不创建辅助验收脚本。
$env:GOMAXPROCS = '2'
go test -p 1 -json -count=10 -timeout=5m -run '^TestSQLite(CanceledQueriesReleaseFiles|WALCheckpointIntegrity)$' ./internal/database
# 两个版本依次执行;程序和产物目录分别指向各自版本,不连接机器上的现有实例。
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\runtime-migration-20260928\mysql57-final-isolated'
go test -p 1 -json -count=3 -timeout=10m -run 'ProjectMember|HistoryScope' ./internal/repository ./internal/database
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\8.0\bin'
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\runtime-migration-20260928\mysql80-final-isolated'
go test -p 1 -json -count=3 -timeout=10m -run 'ProjectMember|HistoryScope' ./internal/repository ./internal/database
完整后端与独立程序验证在另一命令进程顺序执行,每一步检查退出码,失败即停止。以下为已执行命令,不需要新增辅助脚本;完整后端未设置外部 MySQL 程序目录,相关条件跳过不计作实库通过。
$env:GOMAXPROCS = '2'
$env:CGO_ENABLED = '0'
$env:GOOS = 'windows'
$env:GOARCH = 'amd64'
go build -p 1 -o ../build/review-scert-runtime-final-windows-amd64.exe ./cmd/scert
$env:SCERT_SQLITE_TEST_CLI = 'D:\Desktop\Scert\build\review-scert-runtime-final-windows-amd64.exe'
go test -p 1 -json -count=1 -timeout=12m ./... > ../artifacts/runtime-migration-20260928/backend-final.jsonl
go test -p 1 -json -count=10 -timeout=5m -run '^TestSQLite(CanceledQueriesReleaseFiles|WALCheckpointIntegrity)$' ./internal/database > ../artifacts/runtime-migration-20260928/sqlite-verified.jsonl
go test -p 1 -json -count=30 -timeout=5m -run '^TestDesktopConcurrentTransitionAndIdempotentClose$' ./service > ../artifacts/runtime-migration-20260928/service-close-final.jsonl
go vet -p 1 ./...
go mod verify
$env:GOOS = 'linux'
go build -p 1 -trimpath -o ../build/review-scert-runtime-final-linux-amd64 ./cmd/scert
最终三轮竞态在前一批退出后单独运行,显式恢复 Windows 目标并启用 CGO;本轮不设置独立 CLI 或外部 MySQL 程序目录,因此仍须单列条件跳过:
$env:GOMAXPROCS = '2'
$env:CGO_ENABLED = '1'
$env:GOOS = 'windows'
$env:GOARCH = 'amd64'
go test -race -p 1 -json -count=3 -timeout=12m -run 'SQLite|ProjectMember|HistoryScope|ConcurrentTransitionAndIdempotentClose' ./internal/database ./internal/repository ./service > ../artifacts/runtime-migration-20260928/race-final.jsonl
22.4 未关闭项与验收边界
- [!] 旧 Error 1280 的服务端索引元数据不一致根因未确定。强化断言及多轮未复现只能提高观测覆盖,不能标记根因修复或生产放行。
- 成员管理 Web/API、分页和失败请求审计;全部资源的实际项目授权以及排队任务执行/取消/重试重判。
- PostgreSQL 当前版本实库、Linux 原生、完整三库备份恢复、干净发行包安装、真实 Windows Service/systemd 重启及 12 层生产门禁。
- 大规模数据和长时间资源稳定性;有限次数回归不代表长期泄漏或并发风险全部消除。
P0-04/P0-05/P0-06/P0-07/P1-09 总项继续 [~],原始 44 项和最终验收标准不缩减。
二十三、项目成员 HTTP 接口、分页与失败审计(2026 年 9 月 28 日)
23.1 实现与范围
- 检查点
3857dac保存成员列表、授予/撤销、应用依赖接线和失败审计候选;随后增加正式边界测试。源码检查点不是发布或生产放行。 - 按用户账户分页,接口只允许每页 5、10、15、30 位成员,多角色不拆页;列表与变更均从真实账户和项目成员关系判权,不信任客户端声明或会话缓存的角色。
- 失败请求使用已验证身份并独立记录审计;请求取消不取消失败审计,有三秒等待上限。存储失败只写稳定诊断,不伪报持久化。
- 本批没有修改数据库模式、没有创建辅助验收脚本、没有清理现有业务库,也没有浏览器或远端部署测试。正式 Go 测试使用新的临时 SQLite 库和专用 MySQL 隔离实例。
23.2 已核对证据
证据目录为 artifacts/project-member-api-20260928/;首轮失败记录保留,不覆盖。
| 证据 | 结果 | 边界 |
|---|---|---|
focused-first.jsonl |
首轮失败 | 审计写入失败回滚用例期望 HTTP 500,实际为 409;不能计为通过 |
focused-after.jsonl |
35 个叶子通过,3 条条件跳过,退出码 0 | 修复精确唯一键错误分类,并包含实际应用接线 |
focused-boundaries.jsonl |
62 个叶子通过,3 条条件跳过,退出码 0 | 新增 DELETE 额外输入拒绝、会话验证后撤权/停用、取消请求审计、审计存储故障及多驱动错误分类 |
mysql57.jsonl |
三轮共 171 个叶子通过,0 失败、0 跳过,退出码 0 | 原有成员变更与新分页/失败审计组合,含 SQLite 和错误分类用例,不称纯 MySQL 用例 |
mysql80.jsonl |
三轮共 171 个叶子通过,0 失败、0 跳过,退出码 0 | 与 5.7 同范围,两个版本依次执行,不并行占用隔离数据库资源 |
两份本地专项的三个条件跳过是未设置实库环境的成员变更、列表和角色 MySQL 用例,不能计为通过。实库结果由后两份证据单独覆盖。PostgreSQL 错误分类测试使用驱动错误类型,不是 PostgreSQL 原生实库验收。
完整后端及构建顺序进程于 19:06 结束,退出码为 0:backend.jsonl 为 1679 个叶子通过、0 失败、53 条条件跳过;Windows 独立程序历史备份/升级/成员恢复路径通过,go vet -p 1 ./...、go mod verify、Windows 构建和 Linux 交叉构建均通过。条件跳过包括 Linux 专属、符号链接/权限、外部数据库、Named Pipe 与远程部署测试,不计作通过;相应实机门禁仍保留。
race.jsonl 三轮成员专项竞态共 186 个叶子通过、0 失败、9 条条件跳过,19:08 结束,已取回退出码 0。三个未配置外部 MySQL 的条件测试各跳过三次,不将普通实库测试当作 MySQL 竞态通过。Windows/Linux 候选二进制仅用于定位此批构建,不代表完整发行包:
| 目标 | SHA256 |
|---|---|
| Windows amd64 | 0FE034F129BFA23E59A951FDE79C28331AFF512FE37311BC861FA5C1EFC8370B |
| Linux amd64 | D0C129BB463A17FD9D7E3CFBA8CE4D899C4E059F7F715177CB22666B77E8DE0A |
23.3 已执行命令
以下均在 backend/ 执行。PowerShell 重定向日志按 Unicode 读取;日志、隔离数据库与候选二进制均在既有忽略目录,不提交到仓库。
$env:GOMAXPROCS = '2'
$env:CGO_ENABLED = '0'
go test -p 1 -json -count=1 -timeout=6m -run 'ProjectMember' ./internal/repository ./internal/httpapi ./internal/app
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\5.7\bin'
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\project-member-api-20260928\mysql57-isolated'
go test -p 1 -json -count=3 -timeout=10m -run 'ProjectMember' ./internal/repository
$env:SCERT_MYSQL_TEST_BIN = 'E:\DB\8.0\bin'
$env:SCERT_MYSQL_TEST_ROOT = 'D:\Desktop\Scert\artifacts\project-member-api-20260928\mysql80-isolated'
go test -p 1 -json -count=3 -timeout=10m -run 'ProjectMember' ./internal/repository
完整回归使用另一个命令进程,未设置外部 MySQL 程序目录;每一步检查退出码,失败则停止后续步骤。
$env:GOMAXPROCS = '2'
$env:CGO_ENABLED = '0'
$env:GOOS = 'windows'
$env:GOARCH = 'amd64'
go build -p 1 -o ../build/review-scert-members-api-windows-amd64.exe ./cmd/scert
$env:SCERT_SQLITE_TEST_CLI = 'D:\Desktop\Scert\build\review-scert-members-api-windows-amd64.exe'
go test -p 1 -json -count=1 -timeout=12m ./... > ../artifacts/project-member-api-20260928/backend.jsonl
go vet -p 1 ./...
go mod verify
$env:GOOS = 'linux'
go build -p 1 -trimpath -o ../build/review-scert-members-api-linux-amd64 ./cmd/scert
23.4 竞态范围
本批三轮竞态单独执行,范围为成员仓储、HTTP 及应用实际接线,不将其称为全仓库或实库竞态:
$env:GOMAXPROCS = '2'
$env:CGO_ENABLED = '1'
$env:GOOS = 'windows'
$env:GOARCH = 'amd64'
go test -race -p 1 -json -count=3 -timeout=12m -run 'ProjectMember|RequireAuthenticated' ./internal/repository ./internal/httpapi ./internal/app > ../artifacts/project-member-api-20260928/race.jsonl
23.5 尚未完成
- 成员管理页面、项目入口与授权目标选择;接口契约见 成员接口交接。Smail 参考接口文档保持原样。
- 所有资源入口的项目权限、排队任务执行/取消/重试重判,以及相应两项目端到端拒绝测试。
- [!] 旧 MySQL Error 1280 的根因未关闭,新成员专项通过不替代旧异常根因分析。
- PostgreSQL 当前实库、Linux 原生、三库完整恢复、完整发行包和十二层生产门禁。
P0-07 与其他未满足原始验收标准的总项仍为 [~],不按新增测试数量折算整体完成率。
二十四、项目入口与成员页面验证(2026-09-28)
24.1 源码与验证边界
修改前检查点为 af77981,本批新增当前身份可见项目的分页接口、成员页面及普通用户工作台入口。全量基础项目仓储不直接暴露给 HTTP;账户状态、合法全局角色、项目角色和能力提示在同一条 SQL 中判定。成员调用继续实时判权,用户分组不隐式赋权。项目和成员成功、认证失败及拒绝响应禁止缓存。
本批最后的缓存保护晚于首轮完整后端启动,因此 backend.jsonl 和早期构建记录仅为中间证据;最后源码重新构建产品程序,再运行 focused-final.jsonl、backend-final.jsonl、静态检查、模块校验和双平台构建,已取回各步退出码 0。MySQL 两轮版本测试之后仓储源码未变化,后续修改仅涉及 HTTP 缓存保护。
证据目录:artifacts/project-members-ui-20260928/。本批不清理业务库、不操作 DNS 或远端、不创建辅助验收脚本;正式测试使用隔离库。日志、数据库和二进制均在既有忽略目录,不提交。
24.2 已核对结果
| 证据 | 结果 | 边界 |
|---|---|---|
frontend-first.log |
首轮 175 项,172 通过、3 失败 | 新导航导致旧数量断言及组件注册失败,失败记录保留 |
frontend-final.log |
198 通过,0 失败、0 跳过 | 含真实 Vue 模板渲染、角色操作、错误分支和迟到响应隔离,不等于浏览器验收 |
frontend-build-final.log |
生产构建通过,顺序命令退出 0 | 构建成功不代表运行布局通过 |
focused-final.jsonl |
83 个叶子通过、0 失败、4 条条件跳过,退出 0 | 仓储、HTTP、实际应用接线与认证专项 |
mysql57.jsonl |
三轮共 195 个叶子通过,0 失败、0 跳过,退出 0 | 目录与成员组合,包含 SQLite 用例 |
mysql80.jsonl |
三轮共 195 个叶子通过,0 失败、0 跳过,退出 0 | 与 5.7 同范围,两个版本顺序执行 |
backend-final.jsonl |
1700 个叶子通过,0 失败、54 条条件跳过,退出 0 | 使用最后源码构建的 Windows 独立产品程序执行历史升级与备份恢复测试 |
vet-final.log、modules-final.log |
静态检查及模块校验均退出 0 | 模块校验明确返回全部模块验证成功 |
race-final.jsonl |
三轮共 249 个叶子通过、0 失败、12 条条件跳过,退出 0 | 仓储、HTTP、实际应用接线与认证专项,不是全仓库或实库竞态 |
专项的四条条件跳过分别为目录、成员变更、成员列表和成员角色的外部 MySQL 测试;由上述实库组合单独提供证据。三轮竞态中同样四条各跳过三次,合计 12 条,不将普通实库测试当作实库竞态。完整回归中的平台、外部数据库与远端前置条件跳过不计通过,不能推断 Linux、PostgreSQL 或生产验收完成。
24.3 可复核命令
前端在仓库根目录执行 npm.cmd --prefix frontend test 和 npm.cmd --prefix frontend run build。以下后端命令在 backend/ 执行,逐项核对退出码,失败即停止后续步骤;PowerShell 重定向日志按 Unicode 读取。
$env:GOMAXPROCS = '2'
$env:CGO_ENABLED = '0'
$env:GOOS = 'windows'
$env:GOARCH = 'amd64'
go build -p 1 -o ../build/review-scert-project-ui-windows-amd64.exe ./cmd/scert
$env:SCERT_SQLITE_TEST_CLI = 'D:\Desktop\Scert\build\review-scert-project-ui-windows-amd64.exe'
go test -p 1 -json -count=1 -timeout=6m -run 'ProjectDirectory|ProjectMember|VisibleProject|RequireAuthenticated' ./internal/repository ./internal/httpapi ./internal/app
go test -p 1 -json -count=1 -timeout=12m ./... > ../artifacts/project-members-ui-20260928/backend-final.jsonl
go vet -p 1 ./...
go mod verify
go build -p 1 -o ../build/review-scert-project-ui-windows-amd64.exe ./cmd/scert
$env:GOOS = 'linux'
go build -p 1 -trimpath -o ../build/review-scert-project-ui-linux-amd64 ./cmd/scert
MySQL 组合分别在独立命令环境设置 SCERT_MYSQL_TEST_BIN 为 E:\DB\5.7\bin、E:\DB\8.0\bin,SCERT_MYSQL_TEST_ROOT 为本批证据目录下的 mysql57、mysql80,顺序执行:
go test -p 1 -json ./internal/repository -run 'TestProjectDirectory|TestProjectMember' -count=3
完整后端结束后,另一个未配置外部 MySQL 的命令进程执行本批三轮竞态:
$env:GOMAXPROCS = '2'
$env:CGO_ENABLED = '1'
$env:GOOS = 'windows'
$env:GOARCH = 'amd64'
go test -race -p 1 -json -count=3 -timeout=12m -run 'ProjectDirectory|ProjectMember|VisibleProject|RequireAuthenticated' ./internal/repository ./internal/httpapi ./internal/app > ../artifacts/project-members-ui-20260928/race-final.jsonl
24.4 最后候选构建
| 目标 | SHA256 |
|---|---|
| Windows amd64 | 3E1E29DB5887D1BF4A1E0C99FD9ADF9C45A5F9CCE4720CC0FEAA2FD3825AB92B |
| Linux amd64 | B9871674ECC41E4DF8A18F71A3B61644A5BCAC9731E808500E6CEC021F89DC98 |
两次最终构建均退出 0,Linux 为交叉构建,不是 Linux 原生运行或完整发行包验收。候选哈希只定位本批产物,不替代源码提交号与生产证据。
24.5 未关闭事项
- 本批三轮专项竞态及对应进度、证据文档同步完成,等待复审;提交和推送状态以 Git 记录为准。
- 真实浏览器布局和完整交互验收;接口交接见
.claude/docs/ai/project-members/api-handoff-v2.md。 - 项目创建、编辑、删除及其事务审计。
- 全资源入口及排队任务执行、取消、重试的权限重判和跨项目拒绝测试。
- [!] 旧 MySQL Error 1280 的根因仍未关闭,本批实库成功不替代历史异常根因分析。
- PostgreSQL 当前实库、Linux 原生、三库完整恢复、完整发行包和生产门禁。
原始 44 项范围及验收标准不缩减;P0-07 保持 [~],生产部署验收未通过。
二十五、Windows 正式发布与首次初始化浏览器入口(2026-09-28 20:15)
25.1 范围和构建来源
本批承接第二十四节,但不把上一批前端模板测试当浏览器验收。源码为干净提交 5f9af326382d5aa623c917b77932e5243cb26fa1,仅构建 Windows 服务端与 Web;没有修改产品源码,没有清理既有业务库,也没有调用 RAM、修改 DNS、签发业务证书或部署远端。
使用已有正式脚本,不新增辅助验收脚本:
$env:GOMAXPROCS = '2'
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\build\build-release.ps1 -Target windows-amd64 -OutputDirectory D:\Desktop\Scert\.runtime\project-browser-release-20260928
构建进程退出 0;日志为 artifacts/project-members-ui-20260928/release-windows-browser.log。发布根为 .runtime/project-browser-release-20260928/Scert-20260928-V0.1.0/,清单声明 source_dirty=false、delivery_scope=[web, server]。Go 1.26.6、Node.js 24.19.0、npm 11.17.0;正式脚本执行依赖安装、Web 构建、主程序与运维工具构建以及本地路径检查。
25.2 产物与运行身份
重新读取清单并计算实际文件:10 个产物的大小及 SHA-256 全部匹配;直接读取 ZIP 内部的 9 个交付文件,其 SHA-256 与清单一致;隔离运行副本中的 scert.exe 和 4 个 Web 文件再次核对一致。记录为 artifacts/project-members-ui-20260928/release-browser-integrity.json。这证明文件身份,不证明安装脚本、Windows Service 或全功能可用。
| 产物 | SHA-256 |
|---|---|
| Windows 主程序 | 886141f0afa87ffd2c00e4ff8a457cc47789ee6ad7eb30085e8496f836fb7a64 |
| Windows 运维工具 | e1dffff8e864259c85c34ed5a1d951b01dc14ab1ac00d0d4835c76fea449aa9f |
| Windows ZIP 包 | 5378bffea546d9baf43ca9219000df35bbd915e1d72763b98238c02289b51110 |
发布主程序的 version 命令实际返回 Scert 0.1.0、退出 0。隔离运行目录为 .runtime/project-browser-20260928/Scert/,主程序于 20:02:26 启动,监听 127.0.0.1:55280,同时提供后端与正式 Web 静态文件。没有配置变更后的正式管理入口,也没有将前台进程当 Windows Service 验收。
25.3 临时 HTTPS 与真实浏览器观察
通过可信本机启动日志取得临时证书指纹,并使用严格的 TLS 连接核对 SHA-256 完全相等且没有主机名不匹配:
231F9582AE8089FED7FED46CEC7E6498AC669936A9497A93191734735D99014D
该连接读取初始化公开状态返回 HTTP 200。浏览器最初返回 ERR_CERT_AUTHORITY_INVALID;在完成上述核对后,仅对这个临时入口接受浏览器例外,再打开真实 Scert 页面。没有使用全局忽略证书错误、没有安装根证书、没有把自签名引导证书当作公信证书。
20:12 的浏览器同源请求实测如下,脱敏记录见 artifacts/project-members-ui-20260928/bootstrap-browser-observations.json:
| 请求或观察 | 实际结果 | 能证明的范围 |
|---|---|---|
GET /api/v1/bootstrap/status |
200,mode=bootstrap、session_required=true |
引导服务真实响应 |
无会话 GET /api/v1/bootstrap/settings |
401 | 不公开初始化配置 |
使用明确无效的测试令牌 POST /api/v1/bootstrap/session |
401 | 该无效输入未取得会话,不是穷举测试 |
| 无效兑换后再次读取配置 | 401 | 拒绝兑换后仍不放行 |
| 上述状态、配置与兑换响应 | Cache-Control: no-store;状态和配置另有 Referrer-Policy: no-referrer |
实测响应的缓存及来源策略 |
| 页面地址 | 无真实令牌片段 | 本轮没有向页面输入真实令牌,不能证明成功兑换后的历史清理 |
页面停留在提示需要一次性地址的状态。尝试通过浏览器文件工具传入本机 bootstrap-url 时,工具因配置的工作区根不包含 Scert 而拒绝;没有绕过该文件访问限制。临时文件选择元素已移除,没有改动交付页面源码,没有把这种令牌传递操作作为产品验收条件。
25.4 首次初始化后端专项复核
在 backend 执行已有正式测试,使用其隔离临时目录和数据,不复用或清空现有业务数据库:
$env:GOMAXPROCS = '2'
go test -p 1 -count=1 -json -timeout=6m ./internal/bootstrap
进程退出 0,128 个叶子通过、0 失败、4 条平台条件跳过。日志为 artifacts/project-members-ui-20260928/bootstrap-browser-regression.jsonl 及同名前缀的 stderr.log;按叶子用例统计,不重复累计父项。
跳过项:
TestCertificateRootRejectsFilesAndSymlinks:当前 Windows 账户不具备所需符号链接权限。TestGenerateManagementCertificateRejectsSymlinkTarget:同样缺少创建符号链接的权限。TestWriteBootstrapURLRejectsSymlinkAndUsesPrivateMode:当前环境不允许创建符号链接。TestCertificateRootRejectsUnwritableDirectory:要求 Unix 非 root 文件权限环境。
本次通过不覆盖这些跳过边界,也不等于 Linux 原生或完整初始化浏览器流程通过。
25.5 未完成项与下一步
- 正式 Windows 包构建、产物身份、实际前后端启动、临时 TLS 指纹和未认证入口拒绝路径已验证,等待复审。
- [!] 先修正当前项目专用浏览器工具的工作区配置,再通过原有一次性地址正常兑换会话;不得为此放开产品认证或输出真实令牌。
- 数据库与 DNS 验证、管理入口证书配置、首次初始化提交及切换后的访问尚未执行;相应外部前置条件仍须核实,不能预先记成已通过或失败。
- 项目入口、角色授予撤销、分页、撤权拒绝和桌面布局尚未完成真实浏览器验收。
- 项目生命周期与事务审计、所有资源和排队任务权限、PostgreSQL 当前实库、Linux 原生及完整生产门禁继续实施。
总清单和执行清单已同步到本批证据。原始 44 项范围、六阶段验收要求及大项状态不变;本批工具阻塞不替代其他可继续推进的整改,生产部署验收仍未通过。
二十六、生命周期收尾、资源隔离与多对多(2026-09-28,仅开发)
按用户最新要求先完成开发,再集中测试。本阶段未运行测试、构建、浏览器、SSH 或部署,未清理业务数据库。修改前检查点 709c1ef、f38e290 已提交推送,后续候选以 Git 记录为准。
| 范围 | 本批源码变化 | 当前证据等级 |
|---|---|---|
| 生命周期 | 统一项目 ID、控制字符、前端忙状态和表单渲染用例 | 已开发,未统一测试 |
| 读取隔离 | 七个 GET 按真实项目与能力过滤,无缺依赖回退 | 已开发,未统一测试 |
| 多对多绑定 | 同项目双向复用、去重、明确清空、事务审计及失败保留 | 已开发,未统一测试 |
| 共享路径 | 保存关联、修改服务器、部署前重新校验规范化路径 | 已开发,未统一测试 |
| SQLite/MySQL | 新增真实仓储多对多、权限及审计故障回滚用例 | 仅编写;双版本 MySQL 均未重跑 |
| HTTP/工作流/前端 | 新增多对多、409 冲突、停止远端调用及 Vue 多选渲染用例 | 仅编写,未运行 |
| PostgreSQL/Linux/生产 | 不增加任何通过声明 | 仍待独立验证 |
历史补记:生命周期首轮后端组合 136 个叶子通过、5 条条件跳过;完整前端曾为 210 项通过且构建成功。MySQL 5.7 组合曾通过;MySQL 8.0 三条故障注入因创建触发器权限失败,夹具已改为隔离实例管理员创建,尚未重跑。非法项目 ID 曾复现失败,修复亦未重跑。这些均是旧候选记录,不覆盖本节源码;历史日志位于 artifacts/project-lifecycle-20260928/。
路径预检只针对同一服务器记录的当前绑定,不把数据库事务延长到 SSH 阶段;同一主机多条服务器记录、在途任务与配置变更协调、远端实际路径及遗留文件占用仍待后续部署闭环。全资源写入和任务授权也未完成,不能将本批多对多开发记作 P0-06/P0-07 整项通过。
正式候选双 Linux 部署复核(2026-09-30)
本轮对正式候选包的两台 Linux 部署进行只读健康复核,结果仅更新部署状态,不改变数据库支持矩阵的验收边界。
| 维度 | 当前结果 | 证据等级 |
|---|---|---|
| Linux amd64 候选构建 | 已完成,源码工作区干净 | 已构建,等待最终复审 |
8.137.23.95 服务恢复 |
Scert、Nginx、存储 socket active,内部 /readyz=200 |
双服务器实机健康证据 |
45.136.13.241 服务恢复 |
Scert、Nginx、存储 socket active,内部 /readyz=200 |
双服务器实机健康证据 |
| 一个域名绑定多个服务器 | 代码和自动化测试通过,真实业务绑定尚未完成 | 待生产复审 |
| 一个服务器绑定多个域名 | 代码和自动化测试通过,真实业务绑定尚未完成 | 待生产复审 |
| SQLite | 已有本地和隔离初始化测试 | 不等同于完整生产门禁 |
| MySQL | 历史组合测试和部分专项证据存在,当前候选未完成完整矩阵复跑 | 待复审 |
| PostgreSQL | 当前实机和完整生产矩阵尚未完成 | 未通过 |
| Windows 服务 | 已有隔离构建与启动证据,实机服务验收尚未完成 | 待复审 |
odacm.cn 当前能够返回 Web 首页 HTTP 200,但本机 DNS 解析为 198.18.0.109,与两台测试服务器不一致。因此不能将该结果作为公网 DNS、HTTPS/SNI 或 ACME 通过证据。数据库类型支持声明仍以完整矩阵和生产环境证据为准,当前总体验收不得升级。
最新有效数据库整改进度(2026-10-01 17:45,北京时间)
本节沿用已确认需求并补充最新进度;前文各日期记录保留为历史证据,不再以旧版模式 14 推断当前代码状态。当前迁移最高版本为 18;只处理 Linux,不将本地交叉编译视作 Linux 原生构建。
- [✓] SQLite 正式 CLI 子项:修正写死模式 14 的过时断言,检查内嵌源码迁移序号及数据库历史连续性;增加幂等表、任务尝试、部署结果、部署事务与恢复证据的非空恢复样本。第二台 Linux 的历史备份、升级后备份两个恢复子场景通过,进程退出 0。测试修正提交
dbcdf05已推送。 - [✓] MySQL 8.0.46 仓储子项:第二台隔离实库的 9 个主测试、92 个子场景全部通过,无失败或跳过;涵盖项目、成员及资源相关仓储行为,不等同于完整 Web 验收。
- [✓] PostgreSQL 16.15 备份恢复子项:success、certificate、cancel、permission、inventory、authentication、tls 七场景通过,进程退出 0。六场景使用独立正式 CLI;cancel 是进程内确定性取消加真实数据库回退,不冒充独立 CLI 取消验收。
- [!] PostgreSQL 14.24 首次尝试:因工具版本低于当前备份入口要求而失败,保留失败记录;之后改用经官方签名索引验证的隔离 16.15 工具,不修改系统 APT 源、不安装全局 PostgreSQL 服务。
- [~] MySQL 中断恢复修复:原有实测发现模式 15~17 的四个中断边界因表已存在而失败。正在加入结构校验、可重入建表、事务内幂等回填与版本记录,并补充部分回填、数据冲突、字段和索引异常负向测试;新版实库回归尚在运行,不能提前标记通过。
- [✓] 网络边界只读复核:双机 Scert 仍只监听 127.0.0.1:8443,MySQL 只监听 127.0.0.1:3306;Web 由 Nginx 80/443 提供。没有增加公网服务端口。
- 待完成:MySQL 修复后的全量门禁、正式构建及双机部署;MySQL 5.7、本轮三库完整 Web 流程、系统发信及密码重置、备份恢复剩余矩阵、最终清库首次部署等。
本轮各实库测试创建自己的隔离数据库,未清空现有业务数据库;没有创建辅助验收脚本、没有额外备份远端业务数据。整体生产验收仍未放行。
最新有效复核结果(2026-10-01 18:02,北京时间)
本节更新 17:45 记录中的 MySQL 迁移修复及正式包部署状态;只关闭这些子项,不放行整体生产验收。
- [✓] MySQL 中断重入修复:提交
c6982ab827已推送。模式 15~17 恢复前校验字段、默认值、空值约束、排序规则、索引和存储引擎;模式 15 将幂等回填与版本标记放在同一事务,拒绝不一致历史,不覆盖冲突数据。 - [✓] Linux MySQL 8.0.46 最终实库回归:18 个部署迁移恢复与负向子场景、91 个完整迁移子场景,共 109 个子场景全部通过,无失败或跳过;临时单元已结束,退出 0。此前四个真实失败边界已复测通过。
- [✓] 本地质量门禁:后端 go test -count=1 ./...、go vet ./... 通过;database 和 cli 两个包竞态测试通过;前端 241 项通过。未启用的本地外部数据库测试不因此视为通过。
- [✓] 正式构建:仅生成 Linux 包,source_dirty=false,23 项 manifest 产物哈希与大小核对一致;此为交叉编译,不冒充 Linux 原生构建。归档 SHA-256 为 c075297e9f8f76f4ebb8fa28d43a4099ca853a3619212d5e7f51e78d4b0e9e4d。
- [✓] 新正式程序回归:SQLite 历史与升级后备份恢复两个子场景通过;PostgreSQL 16.15 七场景再次通过,独立 CLI 与进程内取消的范围区分不变。
- [✓] 双机部署:官方安装器安装及启动成功,主程序 SHA-256 均为 39b70a1a11148982baeb699bae749f7e2988a2fba02b001c0da740ba8b86f36d;服务 active、NRestarts=0,Nginx 校验成功,管理入口首页及 readyz 正常。双机仍为 Scert 回环监听、Nginx 80/443 对外,无新增公网业务端口。
- 停服保护现场:安装器先后拒绝主服务及目录 socket 尚未停止的操作;完整停服后重试成功,失败记录保留。这是停服升级,不宣称零中断。
- [~] MySQL 备份恢复剩余实库矩阵:已启动 scert-mysql-cli-20261001-1801,运行中,尚无最终结论。该套测试主要调用正式命令与维护实现的进程内入口,不能冒充全部独立发行 CLI 验收。
- [!] 其余限制仍有效:第一台测试域名公网平台拦截、两条无可信恢复证据历史事务、MySQL 5.7、完整 Web 流程、系统发信与密码重置、最终清库首次部署及其余原清单门禁尚未全部闭环。
最新接续状态与任务确认(2026-10-01 18:15,北京时间)
本节更新前文历史快照;旧章节中“当前有效”仅指其记录时点,不代表本轮状态。沿用原始四十四项需求,本次仅验收 Linux,Windows 不在本轮范围;不以历史 P0-03 局部状态代表全部生产门禁。
- 已完成,等待复审:MySQL 8.0.46 备份恢复矩阵单元
scert-mysql-cli-20261001-1801已真实结束,退出零;日志mysql-cli-release.log中二十一个主测试、一百三十六个子场景通过,零失败、零跳过。服务器日志开始时间为北京时间 18:01:26,结束为 18:06:49。 - 已完成,等待复审:本批矩阵覆盖备份快照、官方导入导出互操作、视图、触发器、例程、事件、权限和失败回退。主要调用进程内正式实现,不冒充独立发行程序全量验收。
- 已完成,等待复审:双机服务正常;Scert 仅监听回环 8443,MySQL 仅监听回环 3306;第二台的 33060 同样仅监听回环。Web 对外使用 Nginx 80/443,不新增公网业务端口,不修改第一台现有邮件端口。
- [!] 暂缓或存在阻塞:只读检查确认双机 Scert 均未启用 SMTP,主机、系统通知用户名、凭据引用均为空;缺少可用系统通知配置,不能宣称真实发信与邮件密码重置通过,不使用普通邮箱替代。
- [~] 进行中:复用仓库现有 MySQL 隔离实库测试,增加独立正式发行程序调用;保留严格 TLS、凭据加密存储、成功恢复及 SQL/证书失败回退断言,不创建辅助验收脚本,不接触业务数据库。
- 未开始:将新增测试编译到 Linux,在第二台隔离数据库中验证当前正式发行程序,再记录实际通过或失败结果。
- [!] 暂缓或存在阻塞:MySQL 5.7、完整三库 Web 流程、Linux 原生构建、其余部署负向场景、历史事务核查、系统发信与最终清库首次部署等仍未闭环;整体生产验收未放行。
MySQL 独立发行程序验收结果(2026-10-01 18:22,北京时间)
- 已完成,等待复审:新增仓库测试
TestMySQLRealReleaseBackupRestoreCommands,复用现有成功、SQL 失败、证书恢复失败场景;通过独立进程调用正式发行程序,不再依赖测试进程的 TLS 注册表。未创建辅助验收脚本。 - 已完成,等待复审:第二台 Linux 上单元
scert-mysql-release-cli-20261001-1818真实结束,退出零;三个子场景全部通过,耗时 33.85 秒,日志为/var/tmp/scert-db-matrix-20261001-1720/mysql-release-cli.log。 - 已完成,等待复审:验证对象为已部署候选同源的正式发行程序
/var/tmp/scert-release-mysql-reentry-20261001/scert,SHA-256 为39b70a1a11148982baeb699bae749f7e2988a2fba02b001c0da740ba8b86f36d;测试程序 SHA-256 为88ff0fec3f2ab9a14f89dd52f384a677ecfb450f679b077ec47e83649644eb09。 - 已完成,等待复审:隔离 MySQL 8.0.46 仅监听回环,使用严格 TLS;只在子进程中信任隔离证书,数据库密码通过加密凭据引用读取,未更改系统信任库。断言覆盖业务数据、审计数据、配置、主密钥、加密凭据、证书及失败后恢复前快照。
- 已完成,等待复审:本地后端全量测试、全量静态检查、CLI 竞态测试和差异检查通过。本地条件跳过不计实库通过;本批只修改测试,没有更换线上程序。
- [~] 进行中:准备在隔离目录使用固定工具链执行 Linux 原生正式构建,避免将 Windows 交叉编译包冒充 Linux 原生证据;不新增公网监听,不更改生产工具链或业务配置。
- [!] 暂缓或存在阻塞:上述三个独立 CLI 场景不代表全部数据库、Web 或生产流程验收通过;既有 SMTP 配置缺失、历史事务核查及其他未完成门禁继续保留。