fix(source): DB 事务化;storageRoot 入 metadata;siteCreated 与并发测试;CLI 体验与校验小修

评审修复(4 项 Important + 8 项 Minor):
- DB 事务化:site→connection→snapshots 全部落库包进 db.transaction 单事务
  ("任何失败零落库"字面成立);助手改收 Pick<select|insert|execute> 结构类型
  (tx 与直连 db 通用)。并发撞唯一约束不在事务内补查(语句失败后续查 25P02),
  改为 registerSource 层事务级重试(≤3 次,第二次 select 命中复用分支)
- connection 并发:select-then-insert 无约束可兜底,事务内 pg_advisory_xact_lock
  (siteId:name) 串行化同键登记(kind 枚举扩展推迟 REST 通道,注释注明)
- storageRoot 绝对路径固化进每条 snapshot metadata 与报告 inputs(快照不可变,
  事后无法补写——永久缺口封堵)
- ensureSite 返回 created;RegisterResult.siteCreated;CLI 站点已存在时提示
  --name/--locale/--origin 未生效
- 媒体复制期逐文件 sha 复核(copyAndHash 对拍清单,源中途变更 → COPY_FAILED)
- 空媒体目录拒绝(EMPTY_MEDIA_DIR)
- CLI:PATH_NOT_ALLOWED 追加 --allow 提示;--origin 经 new URL 校验(http/s)、
  --locale 语言标签形状校验,fail fast;开跑打印生效白名单(审计)
- makeRunId 服务导出、CLI 复用;.tmp 残留手工清理策略写入文件头注释
- 测试 +2:并发同输入恰好一组行/双方同 id/新建标志恰一(3 次重跑稳定);
  isUniqueViolation 形状单测(drizzle cause.code / 裸 code / 其他)

全套 263 绿;typecheck / lint 绿;CLI 冒烟对临时库验证事务路径、siteCreated
输出、defaults 落库(en-US / https://qa.example)、白名单打印与校验报错

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-21 13:06:48 +08:00
parent 9732e1b684
commit c28c1655a4
4 changed files with 255 additions and 126 deletions
@@ -141,6 +141,7 @@ cms-one/
### Task 9: 阶段 2 收尾
- [ ] ADR-016(saxes/commander/sanitize-html 选型与许可证);根 typecheck 链加 @sf/adapter-wp;lint 全绿;contracts 首个消费者接线验证(adapter-wp workspace 依赖 contracts——**Plan 1 终审前瞻项落实**:import 路径用 dist 还是 src 的决策一并入 ADR-016)
- [ ] **Task 7 审查移交**:① connection (site_id,name) 库级唯一索引须在第二个写入方(REST 通道)出现前完成 ② media_bundle→WXR attachment URL 的映射策略(uploads 路径约定)记入阶段 3 计划输入 ③ REST 化时重审:白名单 TOCTOU、cwd 自动放行、connection.kind 枚举扩 ④ sanitize-html engines>=22.12 与根 engines>=22 的口径(升根或记 ADR)
- [ ] 全量三绿 + push;plan 勾选;**移交阶段 3 清单**(内容/分类/媒体入库:media 魔数校验、source_records 落库、稳定身份 upsert、checksum skip、route_registry 生成;**续传携带:Task 0.2 cms 数据备份(用户暂缓,阶段 6 L3 验收前必须补做**——责任链不断)
## 验收(对照 spec §15 阶段 2)