docs(plan): P2 Task 7 勾选

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-21 12:31:31 +08:00
parent 586d715455
commit 46b823e667
@@ -116,19 +116,19 @@ cms-one/
- [ ] Step 2 实现(含 validateUniversalRow **加法式**检查:复用 isUniversalRow + 返回 issue[] 的浅扩展,不动 contracts 包)
- [ ] Step 3 绿 → commit `feat(adapter-wp): 全链组装与导入前报告`
### Task 7: source:register 服务与 CLI
### Task 7: source:register 服务与 CLI ✅ 完成(586d715,260 测试;CLI 冒烟双命令通过——probe mini.xml 5 row/2 term + 报告落盘、register 对临时库建站/快照/幂等复用/越界拒绝,验后 DROP 无残留)
**Files:** Create `apps/api/src/modules/source/{register.service.ts,source.module.ts}`;`scripts/sf.ts`(commander,命令 `source:register --site <key> --wxr <path> [--sitemap <path>] [--media <dir>]`、`wxr:probe --wxr <path>` 只解析出报告不入库);Test `tests/integration/source-register.test.ts`
- [ ] Step 1 失败测试(临时库):
- [x] Step 1 失败测试(临时库):
- register WXR+sitemap+media 目录 → 三条 source_snapshots 落库(kind 各异、sha256 与文件一致、storage_path 指向 content-addressed 副本)、source_connections upsert 幂等(**判重键 (site_id, name),应用层 select-then-insert**——表无此库级唯一,注释注明)
- **media_bundle 的 sha256 定义(钉死)**:规范化清单哈希 = 目录内全部文件的排序相对路径(分隔符统一 `/`)+ 每文件 sha256 → canonical JSON(键排序、无空白)→ 对该 JSON 串再 sha256。**不含 mtime、不依赖遍历顺序**。清单本体(路径+大小+每文件哈希)存入 snapshot 的 metadata jsonb(兼满足 spec §7.1 媒体清单)
- **重复 register 同文件/同目录** → 复用既有 snapshot(UNIQUE(site,kind,sha256) 生效,不重复行)——媒体目录重跑哈希必须一致(分隔符归一化保证)
- 副本落 `storage/snapshots/<kind>/<sha256前2位>/<sha256>`;原输入不再被后续任务读取
- 路径安全:register 的输入路径必须在允许目录(storage/incoming 或显式绝对路径白名单校验——拒绝越界读取);**wxr:probe 例外:只读诊断命令,接受任意可读路径(Task 8 直读 cms 即用此通道),不写任何东西**
- [ ] Step 2 实现服务(copy 流式+sha256 双算、媒体清单哈希、DB 写入、报告输出 **artifacts/register/<runId>/reports/**——阶段 2 无 import_jobs,runId 为本次 register 运行生成)+ CLI 接线
- [x] Step 2 实现服务(copy 流式+sha256 双算、媒体清单哈希、DB 写入、报告输出 **artifacts/register/<runId>/reports/**——阶段 2 无 import_jobs,runId 为本次 register 运行生成)+ CLI 接线
- [ ] **CLI 执行机制(钉死)**:根 devDependency 加 `tsx`;根 package.json scripts 加 `"sf": "tsx scripts/sf.ts"`;`commander` **定为根依赖**(CLI 在根,adapter-wp 纯函数包不消费);CLI 经 tsx 直吃 TS 源码(**无需预构建 dist**;apps/api 的 Nest 装饰器源码同样由 tsx 运行)。Task 8 命令相应为 `pnpm sf wxr:probe --wxr ...`
- [ ] Step 3 绿(75+新增)→ commit `feat(source): 输入登记服务与 sf CLI(content-addressed 快照)`
- [x] Step 3 绿(75+新增)→ commit `feat(source): 输入登记服务与 sf CLI(content-addressed 快照)`
### Task 8: 真实 WXR 冒烟(阶段 2 验收)