Files
2026-10-22 16:51:00 +08:00

348 lines
20 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 基线可用”。