docs: carry over COMPLETION_PLAN.md (v2.0) from remote main

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
浅念
2026-10-22 16:51:00 +08:00
parent 8cea7dee20
commit 18e0c95ed2
+347
View File
@@ -0,0 +1,347 @@
# SiteForge 网站工厂 — 完整实现与生产落地计划
> 版本:v2.0(2026-10-22)
>
> 状态:评审后优化版
>
> 目标读者:项目负责人、产品负责人、实施工程师、测试与运维人员
>
> 配套文档:[PRODUCTION_ROADMAP.md](PRODUCTION_ROADMAP.md)、[执行级计划目录](superpowers/plans/)
---
## 1. 评审结论
原 v1.0 计划的产品方向和四类建站模式定义是合理的,但还不能直接作为完整的交付计划使用,主要问题如下:
1. **基线混杂**:源码已经是 v5.0.0,但 2026-10-22 实际运行在 `127.0.0.1:8787` 的实例仍报告 v4.0.0;“源码已完成”不等于“部署已生效”。
2. **遗漏实测缺陷**:静态页面能够生成,但预览页中的 `/products/`、`/about/` 等根路径链接会离开 `/preview/{site}/{build}/`,最终返回 404。
3. **P0 证据补齐**:同镜像标签导致 Compose 构建冲突已于 2026-10-22 实测复现(`docker compose up -d --build` 报 `image "siteforge/web:5.0": already exists`;已验证规避法:先 `docker compose build siteforge` 再 `up -d`),可直接定性修复。Worker 继承 Web 健康检查、favicon 无路由、缺 Linux CI 脚本问题均已确认。
4. **功能先于平台能力**:迁移、数据库/API 连接器和发布都依赖统一任务模型、幂等、进度、取消、审计、密钥管理和安全出网策略,原计划没有先补这些前置能力。
5. **安全边界不完整**:只写“Fernet 加密”和“仅 SELECT”不足以保护数据库连接器;爬虫、Sitemap、远程媒体、SFTP/S3 还需要 SSRF、DNS 重绑定、重定向、证书/主机密钥和路径穿越防护。
6. **验收不可重复**:仅以“一个真实 WordPress 网站”验收会受外网、站点改版和授权影响;必须同时维护确定性的本地测试夹具。
7. **范围有遗漏**:Phase 2 的目标提到 API 连接器,任务表中却没有 API 连接器;XML 也缺少 XXE、压缩炸弹和文件大小限制。
8. **发布闭环不足**:缺少预部署校验、不可变版本、原子切换、回滚、上线后探测及缓存策略。
9. **多语言模型过简**:只克隆站点不足以稳定维护页面级 hreflang 对应关系,需要明确站点语言组和内容翻译组。
10. **估算偏乐观**:17–28 人日没有包含安全设计、失败恢复、E2E、视觉回归、兼容性、文档和试点修复缓冲。
本 v2.0 计划将顺序调整为:**先稳定当前版本 → 建立平台底座 → 完成业务闭环 → 再扩大连接器和生产规模**。
---
## 2. 产品目标与交付边界
### 2.1 产品目标
把旧站、模板、结构化数据和可视化设计统一接入一条可追踪的生产流水线,输出可审计、可预览、可回滚、可独立部署的静态网站。
| 模式 | 输入 | 核心输出 |
|---|---|---|
| A. 旧站迁移 | WordPress/WXR/REST/Sitemap/受控爬取 | 保留 URL、SEO 与真实内容的新版静态站 |
| B. 模板建站 | 行业主题、企业资料、产品内容 | 可编辑、可复用、可发布的新站 |
| C. 数据装配 | Excel/CSV/JSON/XML/API/只读数据库 | 经映射、校验、去重后批量生成的内容与页面 |
| D. 自由设计 | 声明式区块、设计令牌、页面模板 | 安全可控且可复用的整站模板 |
### 2.2 本轮非目标
- 不做任意 HTML/JavaScript 上传和执行。
- 不在未确认授权的情况下抓取、复制或发布第三方内容。
- 不承诺像素级自由定位或完整替代专业设计工具。
- 不自动生成或机器翻译业务事实;系统只提供结构、占位和校验。
- 单机试点阶段不承诺多实例高可用;达到多实例门槛后再切 PostgreSQL 与独立队列。
---
## 3. 已确认基线
### 3.1 源码基线
- FastAPI + SQLite WAL + 原生 JavaScript + Jinja2 + Docker Compose。
- 源码版本常量为 v5.0.0。
- 依赖已固定版本;已有 `scripts/check.ps1`。
- 自动化回归已完成 54 项测试;Python 编译、JavaScript 语法和 Compose 配置检查通过。
- 已实现登录/CSRF、站点与内容管理、主题切换、页面区块、文件导入、构建、ZIP 下载、预览、发布审批、审计和异步构建基础能力。
### 3.2 运行实例基线
- 登录、管理台、内容搜索、模板页、构建历史和质量报告可用。
- 已有测试站点含 9 条内容和 2 个构建版本;最新版本生成 10 个 HTML 页面。
- 主要预览页面直接访问成功,浏览器控制台仅 favicon 404 一项告警。
- 最新构建只有“未配置正式域名,因此未生成绝对 canonical”告警。
- **运行实例仍为 v4.0.0,尚未加载当前 v5.0.0 源码。**
- **预览导航中的根路径链接会跳出预览前缀并返回 404。**
### 3.3 基线管理规则
此后文档中的“已完成”必须同时满足:
1. 代码已合入并有测试;
2. Docker 镜像已从目标提交构建;
3. `/api/health` 返回预期版本和提交标识;
4. 浏览器冒烟测试通过;
5. 回滚步骤已验证。
---
## 4. 全局完成定义(Definition of Done)
每个里程碑必须同时通过以下门禁:
| 类别 | 强制验收 |
|---|---|
| 功能 | 正常流程、空数据、重复提交、失败重试、中断恢复均有测试 |
| 安全 | 权限校验、CSRF、输入上限、路径安全、敏感字段脱敏、出网策略通过评审 |
| 数据 | 数据库变更可前滚;破坏性变更有备份和恢复演练 |
| 任务 | 幂等、进度、超时、重试、取消或明确说明不可取消 |
| 前端 | Chrome 桌面与 390px/360px 移动端冒烟;关键页面无控制台错误 |
| 静态站 | 内链、资源、canonical、sitemap、robots、404、搜索索引检查通过 |
| 部署 | Compose 构建/启动、健康检查、版本校验、升级和回滚通过 |
| 文档 | 配置项、限制、运维步骤和已知问题同步更新 |
所有测试必须使用本地固定夹具;真实外部网站和测试服务器仅作为补充验收,不能替代确定性测试。
---
## 5. 路线图总览
| 阶段 | 目标 | 依赖 | 估算人日 |
|---|---|---|---:|
| P0 | 当前版本稳定、部署与源码对齐 | 无 | 2–3 |
| P1 | 平台底座:迁移、任务、出网、密钥与可观测性 | P0 | 3–5 |
| P2 | 模式 A:WordPress 迁移闭环 | P1 | 5–8 |
| P3 | 模式 C:XML/API/数据库数据装配 | P1 | 7–11 |
| P4 | 模式 D:编辑器与整站模板 | P1 | 5–8 |
| P5 | 发布连接器与可回滚上线 | P0、P1 | 5–8 |
| P6 | 多语言内容关系与 hreflang | P2/P4 稳定后 | 5–8 |
| P7 | 多实例生产化与企业能力 | 业务试点通过 | 15–30 |
P0–P6 总量约 **32–51 人日**。两名工程师在 P1 完成后并行推进 P2/P3/P4,预计日历时间约 4–7 周;若单人串行执行约 7–10 周。该估算不含大规模历史数据清洗和第三方系统协调。
---
## 6. P0:稳定当前版本(2–3 人日)
### 6.1 任务
| ID | 任务 | 验收标准 |
|---|---|---|
| P0-1 | 从当前提交重建 Web/Worker 镜像;镜像加入版本与 Git SHA 标签 | `/api/health` 返回 v5.0.0 和目标提交;管理台标识一致 |
| P0-2 | 修复预览根路径链接:只在预览响应中安全改写站内 `href/src/action/poster`,不修改构建 ZIP | 点击首页、产品、关于、联系、搜索均保持在 `/preview/{site}/{build}/` 下;增加回归测试 |
| P0-3 | Worker 健康检查独立化 | Worker 不再继承访问 8787 的 Web HEALTHCHECK;采用进程/心跳检查或明确禁用并由任务监控替代 |
| P0-4 | 增加 favicon 路由或资源 | 登录页、管理台和预览无 favicon 404 |
| P0-5 | 修复 Compose 同标签构建冲突 | 已复现(见 §1);修复后 `docker compose up -d --build` 一条命令直接成功,不再需要先单独 build 的规避步骤 |
| P0-6 | 补齐跨平台 CI | 保留 `scripts/check.ps1`,新增等价 `scripts/check.sh`;运行 pytest、compileall、全部 JS 语法、Compose 配置和镜像构建 |
| P0-7 | 密钥卫生 | 轮换已在测试沟通中暴露的管理员密码与会话密钥;确认 `.env` 未被 Git 跟踪;日志和测试输出不得打印凭据 |
| P0-8 | 备份恢复冒烟 | 备份数据卷/SQLite/归档,在空目录恢复并能登录、预览、下载旧构建 |
### 6.2 退出条件
- 一条命令完成构建和启动,Web 健康、Worker 可观测。
- 当前 54 项测试保持通过,并增加预览导航、版本和 Worker 健康相关测试。
- Chrome 桌面与移动端完成登录、后台、构建历史、预览导航冒烟。
- 记录镜像摘要、数据库备份点和回滚命令。
---
## 7. P1:平台底座(3–5 人日)
业务功能开始扩张前先统一以下能力,避免每个模块重复实现且行为不一致。
| ID | 能力 | 关键要求 |
|---|---|---|
| P1-1 | 数据库迁移注册表 | 使用显式 schema 版本和顺序迁移;启动迁移可重复;失败不留下半完成状态 |
| P1-2 | 通用任务模型 | 完整字段设计为 `kind/state/progress/attempts/next_retry/lease/heartbeat/result/error/idempotency_key`;单机 SQLite 阶段先精简实现 `state/attempts/heartbeat/idempotency_key` 四个核心字段,其余留位,P7 扩规模时补全,避免过度设计 |
| P1-3 | 任务控制 | 查询进度、取消待执行任务、运行超时、同站点并发上限、全局容量上限 |
| P1-4 | 安全出网客户端 | 仅 http/https;禁止私网、环回、链路本地和云元数据地址;每次重定向重新校验;连接/读取/总时限和响应大小上限 |
| P1-5 | 密钥管理接口 | 应用只引用 secret ID;开发环境可用加密文件,生产对接 Docker/Kubernetes Secret 或专用密钥服务;支持轮换与删除 |
| P1-6 | 可观测性 | 结构化日志、request/job/build ID、任务耗时、失败分类、敏感字段脱敏、健康与就绪探针 |
| P1-7 | 配额与限流 | 上传大小、解压总量、条目数、并发任务、站点数和构建保留数均可配置 |
退出条件:用故障注入验证 Worker 在任务执行中被终止后能够恢复或明确失败,不产生重复内容或半成品构建。
---
## 8. P2:模式 A — WordPress 迁移闭环(5–8 人日)
### 8.1 实施内容
1. 建立版本化迁移会话:`created → analyzing → importing → auditing → media → building → review → completed/failed/cancelled`。
2. 每一步保存输入、输出摘要、错误和重试次数;重复提交使用幂等键,支持关闭页面后恢复。
3. 平台识别只给出证据和推荐,不依赖单一响应头或 HTML 特征。
4. WP REST 全量分页导入进入通用任务队列;使用游标/页码检查点,可从断点续跑。
5. WXR、REST 与爬虫使用稳定的源记录 ID 做去重;定义 `skip/update/fork` 冲突策略。
6. Sitemap URL 拉取复用安全出网客户端;支持 sitemap index、gzip 和数量/大小上限。
7. 受控爬虫遵守范围、深度、数量和速率限制;robots.txt 是合规提示,不是安全边界。
8. 导入后自动生成 URL 基线、媒体清单、未本地化资源和需要人工检查的组件列表。
9. 向导 UI 显示每一步的状态、进度、失败原因、重试/跳过条件和审计结果。
10. 构建前门禁:缺失旧 URL、错误 canonical、断链和未处理重定向按严重级别阻断或告警。
### 8.2 验收
- 本地 WordPress REST/WXR/Sitemap 夹具完成全流程,网络中断后可续跑。
- 重复启动同一迁移不会产生重复内容。
- 私网地址、云元数据地址、超大响应和重定向到私网均被拒绝。
- 经授权的真实 WordPress 站完成一次补充演示,并保存匿名化验收报告。
---
## 9. P3:模式 C — 数据装配与连接器(7–11 人日)
### 9.1 安全导入管道
所有来源统一进入:`采样 → 字段识别 → 映射预览 → 校验 → 暂存 → 分批提交 → 构建`。
- XML 使用 `defusedxml`,禁用外部实体和 DTD;限制文件大小、节点深度、节点数与文本长度。
- ZIP/压缩输入限制文件数、单文件大小、总解压大小和压缩比,防止压缩炸弹与路径穿越。
- 记录源行号、源主键和导入批次;支持批次回滚,而不是只记录成功数量。
- 内容类型和主题推荐使用可解释规则,显示命中的字段与分数;用户确认后才提交。
- 大批量按 500 条以内分批,默认总量上限 50,000;限制应可配置并经过压测后调整。
### 9.2 连接器
| 连接器 | 首发范围 | 安全要求 |
|---|---|---|
| XML | 扁平与两层记录结构 | 安全解析、明确根/记录节点、预览错误定位 |
| HTTP API | GET + 分页 + JSON 路径映射 | HTTPS 优先、域名白名单、超时、响应上限、重试、令牌脱敏 |
| MySQL | 单库、白名单表/视图、选列读取 | 必须使用数据库侧只读账号;TLS;参数化查询;禁止用户提交原始 SQL |
| PostgreSQL | P3 后半或 P7 | 复用连接器协议,不与应用主库迁移混为一谈 |
“应用代码检查 SELECT”不能替代数据库权限。凭据加密还必须包含主密钥存储、轮换、吊销和备份恢复策略。
### 9.3 验收
- 5,000 行车型数据完成推荐、映射、异步导入、品牌/分类聚合和构建。
- 中途取消或失败后可重试,不重复写入;整个导入批次可回滚。
- XML、API、MySQL 均有本地容器化夹具;测试不依赖真实生产数据库。
---
## 10. P4:模式 D — 编辑器与整站模板(5–8 人日)
| ID | 任务 | 验收重点 |
|---|---|---|
| P4-1 | 区块属性 Schema 注册表 | 前后端共享类型、默认值、限制和主题支持矩阵 |
| P4-2 | 新增 carousel、video、tabs、pricing、map、form-link | 无任意脚本;视频/地图域名白名单;键盘和屏幕阅读器可用 |
| P4-3 | 整站模板包 | 包含版本、主题约束、页面 blocks、导航、设计令牌和所需内容模型;JSON Schema 校验 |
| P4-4 | 兼容性预检 | 应用前展示缺失区块、字段、主题版本和降级方案;失败不修改原站 |
| P4-5 | 草稿与发布状态 | 编辑不直接影响已发布构建;预览、审批、发布对象边界清晰 |
| P4-6 | 响应式与无障碍 | 1440/1024/390/360 视口;焦点、标签、对比度和减少动画设置 |
退出条件:从多页站点保存模板,在空站应用并构建;视觉结构一致,内容数据不被错误复制,模板失败可完整回滚。
---
## 11. P5:发布连接器与回滚(5–8 人日)
发布优先于多语言,因为只有形成“构建—审批—上线—验证—回滚”闭环,系统才真正可交付。
1. 发布目标只保存 secret 引用,不在 API、日志和审计详情中返回凭据。
2. SFTP 强制校验主机密钥,限制目标根目录,禁止 `..`、符号链接逃逸和任意命令执行。
3. SFTP 上传到不可变版本目录,校验文件清单后原子切换 `current`;保留上一版本用于一键回滚。
4. S3 使用不可变版本前缀和 manifest;设置正确 Content-Type、Cache-Control、压缩元数据,最后切换发布指针。
5. 所有外部发布强制关联已批准的 release request;构建内容变化后旧审批失效。
6. 上线后执行主页、关键 URL、404、静态资源、canonical、sitemap 和重定向探测。
7. 失败发布不影响当前线上版本;发布历史记录目标、构建、执行人、结果和回滚关系。
验收:在本地 SFTP/S3 兼容测试容器中完成发布、故障注入、重试和回滚;任意一步失败时线上指针保持原版本。
---
## 12. P6:多语言(5–8 人日)
### 12.1 推荐模型
- `site_groups`:关联同一品牌的语言站。
- `site_locales`:定义 locale、默认语言、域名/路径策略。
- `translation_groups`:把不同语言站中语义相同的页面或内容条目关联起来。
- 不自动翻译事实内容;克隆时创建“待翻译”状态,并禁止其进入正式发布。
### 12.2 必须先决策
1. 语言 URL 使用独立域名、子域名还是 `/en/` 路径。
2. slug 是否本地化,以及变更后的重定向策略。
3. 缺少翻译时隐藏、回退默认语言还是返回 404。
4. `x-default` 指向哪个页面。
### 12.3 验收
- 中英文站的每个已关联页面生成对称 hreflang;不存在的翻译不输出错误链接。
- sitemap、canonical、语言切换器和搜索索引相互一致。
- “待翻译”内容不会意外发布。
---
## 13. P7:生产化与企业能力(15–30 人日,单独立项)
触发条件:完成真实试点,或出现多实例、并发构建、企业身份接入、SLO/合规要求。
- PostgreSQL + 正式迁移工具;Redis/RabbitMQ 队列;多 Worker 租约和死信队列。
- OIDC/SSO、MFA、会话撤销、最小权限角色与紧急停用。
- 不可篡改审计、集中日志、指标、追踪、告警和运行手册。
- 镜像/依赖扫描、SBOM、签名、主题供应链验证、恶意文件检测。
- 跨环境密钥管理、数据库与对象存储备份、RPO/RTO 和恢复演练。
- 性能与容量测试、灰度发布、CDN 刷新、Search Console/真实流量监测。
具体条目以 [PRODUCTION_ROADMAP.md](PRODUCTION_ROADMAP.md) 为基础,但开工前必须补充负责人、SLO、预算和目标部署架构。
---
## 14. 测试矩阵
| 层级 | 覆盖范围 |
|---|---|
| 单元测试 | URL/路径、映射规则、类型推荐、HTML 改写、迁移状态机、权限决策 |
| API 集成 | 认证/CSRF/RBAC、幂等、任务重试、导入回滚、发布审批失效 |
| 组件集成 | SQLite/数据库夹具、Worker 崩溃恢复、SFTP/S3、本地 WordPress/API 服务 |
| 静态 QA | 断链、资源、canonical/hreflang、sitemap、robots、404、搜索索引 |
| 浏览器 E2E | 登录、建站、导入、编辑、构建、预览导航、审批、发布、回滚 |
| 视觉回归 | 四主题首页/列表/详情/联系页,桌面和移动端基线截图 |
| 安全测试 | SSRF、重定向绕过、路径穿越、ZIP/XML 炸弹、越权、凭据泄漏、恶意主题包 |
| 恢复测试 | 数据库/归档恢复、Worker 中断、失败发布、旧版本回滚 |
最低门槛:新增代码有针对性测试;主分支不得降低现有覆盖;关键路径 E2E 必须在发布前执行。
---
## 15. 指标与验收目标
| 指标 | MVP 目标 |
|---|---|
| 构建成功率 | 本地固定夹具 ≥ 99% |
| 任务可恢复性 | Worker 异常终止后无重复内容、无半成品发布 |
| 预览内链 | 关键页面 0 个 404 |
| 迁移 URL 保留 | 基线中应保留的 200 URL 100% 有页面或批准的重定向 |
| 静态质量 | 0 error;warning 必须被确认或登记豁免 |
| 发布回滚 | 测试环境 5 分钟内恢复上一版本 |
| 凭据暴露 | API、日志、导出、Git 历史中为 0 |
| 可访问性 | 关键流程键盘可操作;自动检查无高严重度问题 |
---
## 16. 关键决策与负责人
| 决策 | 推荐方案 | 最晚决定时间 |
|---|---|---|
| 首个业务闭环 | WordPress 迁移 → 审计 → 发布 | P2 开工前 |
| 数据库连接器首发 | MySQL;PostgreSQL 作为第二实现 | P3 开工前 |
| API 认证首发 | Bearer token + 自定义请求头白名单,不支持用户脚本 | P3 开工前 |
| 发布首发 | 若客户环境明确则优先 SFTP,否则 S3 兼容 | P5 开工前 |
| 多语言 URL | 根据正式域名/CDN 架构决定,不在代码中硬编码 | P6 开工前 |
| 单机容量门槛 | 用压测确定;超过门槛触发 P7 | P7 立项前 |
每项决策必须记录负责人、日期、备选方案和影响,不再只保留“待确认”文字。
---
## 17. 推荐的下一迭代
下一迭代只执行 P0,不并行开发新连接器:
1. 轮换测试期间使用过的管理员密码和会话密钥。
2. 从当前源码重建容器,确认运行版本从 v4.0.0 升至 v5.0.0。
3. 修复预览链接 404,并增加自动化与浏览器回归。
4. 修复 Worker 健康检查,补 favicon。
5. 完成备份恢复、桌面/移动端冒烟,并记录可回滚版本。
6. P0 验收通过后,再为 P1 写执行级 TDD 计划。
只有 P0 全部退出条件满足,才能把当前系统标记为“v5 基线可用”。