Files
cms-website/cms现状与SiteForge差距分析_V2.0.md
T
浅念 d60123ba41 docs: SiteForge 规划文档基线 + 纵向切片设计规格 V1
- V3.0 总体方案、主题与板块设计、实施计划
- cms 现状差距分析 V2.0(V1.0 已标注作废)与复用评估 V1.0
- 纵向切片设计规格(路线 C:全新架构 + 白名单资产移植)
- .gitignore 先行(storage/artifacts/env 永不入库)

Co-Authored-By: Claude Code <noreply@anthropic.com>
2026-10-20 16:10:34 +08:00

1012 lines
39 KiB
Markdown
Raw 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.
# cms 代码库现状与 SiteForge V3.0 差距分析 V2.0
> 评估对象:`D:\project\cms`
> 目标基线:`D:\project\cms-one\SiteForge_完整项目计划方案_V3.0.md`
> 版本:V2.0
> 日期:2026-10-20
> 用途:确定旧 CMS 的真实成熟度、可复用资产、生产风险及 SiteForge 改造顺序。
> 说明:本报告基于源码、Schema、测试代码、脚本和现有项目文档的静态核查;本轮没有重新安装依赖、启动全部服务或执行完整测试,因此“存在测试”不等于“本轮已经验证通过”。
---
## 1. 执行结论
`D:\project\cms` 已经不是空项目,也不是单纯的技术样例。它具备以下可运行主干:
- Vue 3 + TypeScript + Element Plus + Art Design Pro 管理后台。
- NestJS + Fastify + Drizzle + PostgreSQL 控制 API。
- WordPress REST/WXR 迁移、媒体抓取和基础幂等导入。
- 内容类型、工作副本、不可变修订和发布修订。
- Astro 静态网站运行时、基础 SEO 输出和本地质量门禁。
- 本地版本化产物、基础回滚、站点隔离测试和迁移测试。
- PostgreSQL、Redis、MinIO、ClickHouse 的开发环境配置。
因此,SiteForge 不应从零重建。推荐采用:
> **以 cms 源码为实现底座,以 SiteForge V3.0 为产品和架构基线,按领域净化、补强和替换。**
但 cms 目前仍然是“单站 MVP 向平台化演进”的原型,尚不具备安全生产上线所需的完整能力。主要阻塞点不是页面能否构建,而是:
1. 构建输入不冻结,API 失败时可能用 Seed 演示数据生成正式产物。
2. 所谓“原子发布”实际是删除旧目录后复制新目录,并非原子切换。
3. 构建历史、状态和锁只存在进程内存中。
4. 认证、CORS、默认凭据、SSRF、SVG、富文本等安全边界不足。
5. 迁移会自动发布,缺少审核、冲突保护和批次回滚。
6. 没有正式 URL 注册表,普通页面可能错误跳转首页。
7. 没有完整部署适配器、生产 HTTP 验证和真正可逆的 Release 回滚。
8. 没有系统备份、恢复演练、监控和告警。
9. 主题 Token 和模板表已预留,但主题协议、板块协议和 Schema 驱动后台没有真正落地。
按 SiteForge V3.0 的严格口径,17 项能力现状建议重新评为:
| 状态 | 数量 | 说明 |
|---|---:|---|
| ✅ 基本达到 | 1 | Astro 全量静态构建;仍需生产化加固 |
| 🟡 部分具备 | 12 | 已有代码或局部闭环,但未达到 V3.0 验收条件 |
| ❌ 缺失 | 4 | 扫描系统、主题协议以及两类部署适配器 |
其中 Nginx/SSH 与 S3/OSS+CDN 是目标部署方式二选一,不要求同时完成;当前两者均未实现。
---
## 2. 评估方法与成熟度定义
### 2.1 评估依据
本报告交叉核对以下证据:
- 实际 TypeScript/Vue/Astro 源码。
- Drizzle Schema 和 Seed。
- 单元、契约和 E2E 测试代码。
- Build、Gate、Redirect 和 Release 脚本。
- Docker Compose 与 CI 配置。
- 迁移台账、ADR、组件契约、主题 Token 契约和导入模板文档。
- SiteForge V3.0 的 V1 必须交付能力和安全要求。
不采用“README 声称存在即可视为完成”的判断方式。文档中的未来设计、空目录、TODO、未被调用的容器和表结构草案均不算已实现能力。
### 2.2 成熟度等级
为避免再次把“代码存在”误判成“生产可用”,后续所有能力统一使用五级成熟度:
| 等级 | 定义 | 是否可视为完成 |
|---|---|---:|
| L0 设计 | 仅有文档、接口设想或空目录 | 否 |
| L1 实现 | 有代码,但缺关键测试或未形成闭环 | 否 |
| L2 自动验证 | 有自动测试并在固定环境通过 | 否 |
| L3 真实数据验证 | 使用真实站点数据完成本地/预发布验证 | 部分 |
| L4 生产验证 | 完成真实部署、HTTP 验收、监控和回滚演练 | 是 |
本报告的“✅ 基本达到”至少要求核心验收目标达到 L3;正式上线验收必须达到 L4。
### 2.3 评级符号
- ✅ 基本达到:核心功能存在,接近目标验收,但仍可能有生产加固项。
- 🟡 部分具备:已有可复用实现,但缺少目标流程、数据模型、安全或验收闭环。
- ❌ 缺失:没有实际实现,或只有文档/空壳。
---
## 3. cms 实际代码资产盘点
### 3.1 已存在并可运行演进的代码
| 领域 | 目录 | 实际状态 |
|---|---|---|
| 管理后台 | `apps/admin-web` | Art Design Pro 基础完整,包含站点、内容、媒体、迁移、导航、设置、线索页面;夹杂大量演示代码 |
| 控制 API | `services/control-api` | NestJS/Fastify/Drizzle;认证、站点、内容、媒体、迁移、线索、构建模块已存在 |
| 静态运行时 | `runtimes/astro-site-runtime` | Astro 页面、公共组件、SEO 输出、Sitemap、Redirect 和 Gate 已存在 |
| 领域契约 | `packages/domain-contracts` | 当前主要是 ID 和事件类型,范围有限 |
| 构建 Worker | `services/build-worker` | 基本为空壳,实际构建仍由 control-api 启动子进程 |
| 事件网关 | `services/event-gateway` | 基本为空壳,不应计入现有能力 |
| 基础设施 | `infrastructure` | PostgreSQL/Redis/MinIO/ClickHouse 容器配置;Redis/MinIO/ClickHouse 尚未形成完整业务闭环 |
| 测试 | `tests`、`services/control-api/test` | 有契约测试、隔离测试、内容测试和迁移测试,但本轮未重新执行 |
### 3.2 实际数据库范围
实际 Drizzle Schema 主要包含:
- `sites`
- `site_locales`
- `users`
- `content_type_definitions`
- `content_entries`
- `entry_locales`
- `content_revisions`
- `content_relations`
- `audit_logs`
- `site_settings`
- `site_nav_items`
- `templates`
- `leads`
- `media_assets`
旧 ERD 文档中的 Route、Snapshot、Import Batch、Build Job、Release、Artifact、Form Version、Consent、身份分析等大量表尚未进入实际 Schema。后续必须以数据库迁移文件和运行代码为准,不能把 ERD 蓝图当成现状。
### 3.3 已有真实价值资产
最值得保留的资产包括:
1. WordPress REST/WXR 解析和真实兼容经验。
2. `UniversalRow` 中间数据结构。
3. `externalRef`、Slug 和 `sourceUrl` 的幂等思路。
4. 内容工作副本和不可变修订。
5. 显式站点上下文和已有隔离测试。
6. Astro 静态站页面、组件和 SEO 输出基础。
7. 主题 Token、组件契约和导入契约文档。
8. Gate、Redirect、迁移 E2E 等测试资产。
9. Art Design Pro 后台工程壳。
---
## 4. SiteForge V1 十七项能力严格对照
### 4.1 总表
| # | V3.0 必须交付能力 | 现状 | 成熟度 | 主要证据 | 核心差距 |
|---:|---|---|---|---|---|
| 1 | 多站点与环境管理 | 🟡 | L2 | sites、站点上下文、隔离 E2E | 无 environment 模型;部分查询仍缺 site 条件;构建状态仅内存 |
| 2 | 单一超级管理员 | 🟡 | L1 | 登录、bcrypt、基础审计 | 当前仍是站点级用户和 role 字段;Token 无过期/撤销;无 MFA/恢复;默认凭据和默认 Secret |
| 3 | WordPress REST/WXR/SQL/uploads 导入 | 🟡 | L3 子集 | REST、WXR、媒体远程抓取、单文件 sourceUrl 预入库、迁移 E2E | 无 SQL;无真正 uploads ZIP 解包;ACF 仅局部特例;导入后自动发布 |
| 4 | Sitemap/HTML/Playwright 扫描 | ❌ | L1 子集 | 仅 Sitemap 拉取 | 无 HTML 爬虫、浏览器渲染补扫、robots、日志/GSC 导入、扫描任务与审计清单 |
| 5 | 原始快照与差量同步 | 🟡 | L1 | WXR 文件按 Hash 落盘、重跑更新 | WXR 未绑定正式快照记录;REST 无原始快照;无新增/更新/删除/冲突分类;无人工编辑保护 |
| 6 | 统一内容与内容修订 | 🟡 | L2 | 5 类内容、工作副本、draft/published 修订 | 无修订恢复;无乐观锁;无删除/归档入口;Locale 硬编码 en/es;后台部分表单硬编码 |
| 7 | URL 注册表与路由编译 | 🟡 | L2 子集 | Redirect JSON、三种规则产物、基础报告 | 无 route_registry;无唯一占用、410、参数规则、环检测、部署能力预检;普通页面可能跳首页 |
| 8 | SEO 快照与差异报告 | 🟡 | L2 子集 | SEO Head、Yoast 部分字段、Gate | 无旧 HTML/导入值/新 HTML 三方快照;无 P0–P3 差异;无真实 HTTP 门禁 |
| 9 | 媒体迁移与旧路径保持 | 🟡 | L3 子集 | 全量抓取、sourceUrl 去重、alt、多尺寸 | 旧媒体 URL 未完整重定向;本地盘;无 Hash/MIME 魔数/SVG 清理/引用保护 |
| 10 | 主题/模板/板块协议 | ❌ | L0–L1 | templates 表、主题编辑 Tab | 模板无完整注册和版本;Token 未稳定驱动运行时;无 Block Manifest、Slot、Renderer、升级迁移 |
| 11 | 组件化公共包 | 🟡 | L2 子集 | Astro 公共组件、Token 契约测试、domain-contracts | 无四层分层、公共渲染包、多主题复用验证和组件版本策略 |
| 12 | Astro 全量静态构建 | ✅ | L3 | Astro 全量构建、独立 dist、基础 Gate | 构建实时访问 API且会回退 Seed;依赖/环境不可完全复现;需冻结快照和产物 Manifest |
| 13 | 预览、验收、发布、回滚 | 🟡 | L1–L2 | 本地 Gate、本地产物归档、本地回滚 | 无草稿预览、访问控制、持久化 Release、真正原子切换、生产冒烟和生产等价回滚演练 |
| 14 | Nginx/SSH 发布 | ❌ | L0 | 可生成 nginx redirect 片段 | 无 SSH/SFTP/rsync 部署器、凭据管理、临时版本目录、远端校验和切换 |
| 15 | S3/OSS + CDN 发布 | ❌ | L0 | MinIO 容器配置 | 无对象存储适配器、版本前缀、入口指针、CDN 刷新和回滚;与 #14 二选一 |
| 16 | 表单基础服务 | 🟡 | L1 | Lead 提交、Zod、后台状态更新 | 无限流、反垃圾、隐私同意、通知重试、Webhook、保留策略;存在更新隔离缺陷 |
| 17 | 备份、监控和操作日志 | 🟡 | L1 | audit_logs 和部分 writeAudit | 无自动备份/恢复演练/监控/告警;Fastify logger 关闭;审计覆盖不完整 |
### 4.2 对评级影响最大的事实修正
#### WordPress 导入不是完整的三通道
代码实现了 REST 和 WXR。媒体接口支持单个文件携带 `sourceUrl` 入库,但后台 ZIP 选择目前只读取文件信息和估算数量,没有完整的 ZIP 上传、解包、目录匹配、安全扫描和批次报告。因此不能把它等同于完整的 `wp-content/uploads` 导入。
#### 内容修订不等于内容回滚
当前系统可以创建和列出 draft/published 修订,但缺少读取指定修订全文并恢复为工作副本的正式接口。SiteForge V3.0 要求“可编辑和回滚”,因此只能评为部分具备。
#### 当前发布不是原子发布
`release.mjs` 的关键步骤是:
```text
删除 dist/<site>
复制 candidate 到 dist/<site>
删除 candidate
```
删除与复制之间存在不可用和半成品窗口。真正的文件系统发布应使用同文件系统版本目录加符号链接/目录重命名切换;对象存储应使用版本前缀加入口指针。
#### 当前回滚不是完整可逆回滚
回滚逻辑会删除更新版本的 Artifact,再复制上一版本。这样无法可靠地恢复回滚前版本,也没有同步恢复路由、响应头、动态配置和 CDN 状态。
#### 站点隔离尚未完全修复
主要端点已经接入站点上下文,但仍发现:
- Lead 状态更新和回读只按 ID,不同时限定 `site_id`。
- 内容修订列表只按 `entry_id`,没有传入和校验 `site_id`。
- 部分更新在完成前置检查后只按对象 ID 执行,仍需统一 Repository 约束和测试覆盖。
所以应表述为“主路径已有隔离基础,尚未完成系统性隔离审计”。
---
## 5. 当前已验证的优势与保留原则
### 5.1 WordPress 迁移兼容经验
现有 WXR 解析处理了 `_thumbnail_id`、产品图库、部分主题私有字段、Yoast 主分类和 PHP 序列化数据。这些属于真实迁移经验,应保留为适配器测试夹具和转换规则。
但“使用正则而无需 XML 库”不是架构优势本身。对更大 WXR、CDATA 边界、实体、命名空间和异常 XML,需要增加:
- 流式或受控 XML 解析。
- 文件大小、节点数和处理时限。
- 恶意 XML/压缩炸弹测试。
- 解析错误定位和可重试批次。
### 5.2 WAF 处理经验
REST 客户端已有全局节流和 403/429 退避,媒体抓取会识别 HTML 挑战页并快速失败。这些逻辑应保留,但需要统一到可配置的采集策略中,并增加:
- 域名并发上限。
- 全任务请求预算。
- 可恢复重试状态。
- SSRF 验证。
- 失败资产清单和补传流程。
### 5.3 URL 对照报告
`externalRef + Sitemap + Redirect` 的 kept/redirected/missing 报告很有价值,适合作为 `route_registry` 和 URL 基线报告的原型。
需要注意:`missing=0` 只说明当前输入集合都找到了去处,不代表:
- 输入集合覆盖了全部旧 URL。
- Redirect 目标语义正确。
- 没有重定向链和重定向环。
- 目标页面返回 200。
- Canonical、Locale 和索引状态正确。
- 普通页面没有被错误跳转首页。
### 5.4 契约测试
事件目录、Token、组件样式和 WordPress 文本清理的契约测试应保留。SiteForge 后续应将契约测试扩展到:
- Theme Manifest。
- Block Manifest。
- Source Adapter。
- Deploy Adapter。
- Route Compiler。
- Build Input Snapshot。
- Release Manifest。
- Form Definition。
### 5.5 多语言基础
现有 `entry_locales`、hreflang 和多语言 UI 可以作为基础,但当前代码大量硬编码 `en/es`,导入中其他 Locale 甚至会被静默归为 `en`。因此它是“多语言预留”,不是完整的通用多语言能力。
---
## 6. 上线前必须处理的 P0 风险
### P0-1 构建可能发布 Seed 演示数据
产品、新闻、案例和站点配置在 API 不可达或无数据时会回退到内置默认数据。该策略适合本地 Demo,不适合生产构建。
风险:
- API 短暂异常时,构建仍返回成功。
- Gate 只能检查 HTML 结构,无法判断内容是否属于正确站点。
- 演示内容可能被正式部署并被搜索引擎收录。
整改:
- 生产构建禁止任何 Seed fallback。
- 构建开始先生成不可变 `build_input_snapshot`。
- 校验站点、Locale、内容数、路由数、媒体数和快照 Hash。
- 快照不完整立即失败,不进入 Astro 构建。
### P0-2 发布切换和回滚不安全
风险:
- 删除旧目录后复制失败导致站点不可用。
- 并发构建可能覆盖较新的产物。
- 回滚会删除新版,不能可靠前滚。
- 路由规则和 HTML 不是同一事务切换。
整改:
- 建立持久化 `build_jobs`、`releases`、`artifacts` 和 `publish_locks`。
- 每个 Release 使用不可变版本目录。
- 文件系统通过 rename/symlink 指针切换;对象存储使用版本前缀和入口指针。
- 使用 `active_release_id` 比较并交换,防止旧任务覆盖新版本。
- 回滚只切换到已验证 Release,不删除其他 Release。
### P0-3 认证与公网暴露风险
已发现:
- 自制 HMAC Token 无过期、无刷新、无撤销。
- Token 默认 Secret 为开发值。
- 登录页预填默认账号密码。
- CORS 使用任意 Origin 反射。
- 无 MFA、恢复码、登录限流和异常提醒。
- 当前用户模型仍是站点级并保留 role 字段,不符合平台级单超管模型。
整改:
- 平台级 `super_admin`,不实现复杂 RBAC。
- 使用成熟会话/JWT 库和强密码哈希。
- 短期会话、HttpOnly/Secure/SameSite Cookie、CSRF 防护。
- MFA、恢复码、会话列表与撤销。
- 删除默认凭据和默认 Secret;启动时缺 Secret 直接失败。
- 收紧 CORS,后台如暂未完成 MFA,只能放在 VPN/零信任/IP 白名单后。
### P0-4 SSRF 与不受控下载
WordPress URL、Sitemap URL 和媒体 URL 会触发服务端 Fetch。目前缺少完整的地址安全控制。
风险包括访问:
- localhost、内网服务。
- 云主机元数据地址。
- DNS 重绑定目标。
- 重定向后的受限地址。
- 超大响应或长期连接。
整改:
- 仅允许 HTTP/HTTPS 和批准端口。
- DNS 解析后拒绝回环、内网、链路本地、保留地址和元数据地址。
- 每次重定向重新校验。
- 设置连接、响应、文件、批次和总任务预算。
- 采集任务使用受限网络出口,不携带控制面密钥。
### P0-5 SVG、MIME 和富文本安全
媒体上传允许 SVG,但没有净化;文件类型主要相信 multipart/远端 MIME;WordPress HTML 也没有形成明确的白名单清理层。
整改:
- 检查文件魔数和实际解码结果。
- SVG 默认禁用,或使用可靠净化器并以安全响应头提供。
- 对 HTML 使用明确的元素、属性、协议、iframe 域名白名单。
- 删除 script、事件属性、危险 URL 和不受信任嵌入。
- 发布产物增加 CSP 和敏感信息扫描。
### P0-6 迁移自动发布和人工内容覆盖
当前迁移批次导入后会逐条调用发布;重跑还会覆盖工作副本,没有字段级或条目级人工修改保护。
整改:
```text
上传/采集
→ 原始快照
→ 解析
→ 映射
→ 校验
→ 导入草稿
→ 冲突处理
→ 人工审核
→ 预览
→ 发布
```
必须建立:
- `import_batches` 和 `import_items`。
- Source Fingerprint 和 Mapping Version。
- 新增、更新、删除、无变化、冲突分类。
- `manual_override` 或字段来源元数据。
- 批次撤销和差异报告。
### P0-7 站点隔离缺口
已发现 Lead 状态更新、修订读取等查询没有完整带上 `site_id`。
整改:
- 所有 Repository 方法必须显式接收 `siteId`。
- 所有业务读写必须使用 `site_id + object_id`。
- 建立跨站读取、更新、删除、枚举和缓存污染测试。
- 对关键表考虑 PostgreSQL RLS 作为纵深防御。
### P0-8 无备份与恢复闭环
当前数据库、WXR、媒体和 Artifact 主要位于本地开发环境,没有可验证的恢复链路。
整改:
- PostgreSQL 定时备份和关键迁移/发布前备份。
- WXR、媒体、快照、Release、报告和路由规则复制到第二存储。
- 备份加密、校验、保留策略和访问控制。
- 在空环境完成至少一次恢复演练并记录 RPO/RTO。
### P0-9 路由错误可能造成 SEO 损失
当前路由来源是 `site_settings.redirects` JSON。非产品/案例/新闻类型可能被自动指向 `/en/`,容易形成 Soft 404。
整改:
- 建立 `route_registry`。
- 路由唯一占用和规范化。
- 对每条旧 URL 明确选择保留、301、410 或人工处理。
- 禁止无法映射的页面默认跳首页。
- 检查环、链、跨 Locale、Canonical 和最终 HTTP 状态。
---
## 7. P1 生产化与平台化差距
### 7.1 缺少正式环境模型
`sites` 有站点和域名,但没有开发、预览、预发布、生产等 Environment 实体。域名、部署目标、当前 Release、凭据引用和发布锁应属于 Environment,而不是散落在站点设置或进程变量中。
建议实体:
- `site_environments`
- `deployment_targets`
- `environment_domains`
- `environment_publish_locks`
- `releases`
- `release_artifacts`
### 7.2 缺少持久化任务系统
当前 BuildService 直接 `spawn pnpm`,历史保存在内存中。即使暂不采用 BullMQ,也必须先解决:
- Job 持久化。
- 幂等键。
- 重启恢复。
- 超时和取消。
- 日志存储。
- 失败重试和死信状态。
- 同站点同环境串行。
推荐 Redis + BullMQ;如果先用数据库任务表,也要满足同样的状态和恢复语义。
### 7.3 主题系统尚未真正成立
当前存在模板表、Theme Tab 和 Token,但未形成可版本化的主题契约。
SiteForge 应采用四层组件结构:
1. 基础 UI:Container、Button、Image、RichText、FormControl。
2. 业务区块:Hero、ProductGrid、NewsList、FAQ、CTA、ContactForm。
3. 页面模板:首页、列表页、详情页、普通页面、落地页。
4. 主题:Token、字体、布局、装饰、默认区块组合和可用模板集合。
主题包建议结构:
```text
themes/<theme-key>/
theme.manifest.ts
tokens.ts
blocks/
layouts/
templates/
styles/
migrations/
```
每个 Block Manifest 应声明:
- 版本。
- 字段 Schema。
- 默认值。
- 允许的 Slot 和父子关系。
- SEO 和可访问性行为。
- 媒体字段。
- 数据依赖。
- 兼容主题版本。
### 7.4 后台尚未完全 Schema 驱动
虽然内容类型表保存了字段定义,但后台产品、新闻、案例等页面仍存在大量硬编码逻辑,站点管理页面体积过大。
需要拆分:
- Schema Form Renderer。
- Field Registry。
- Validation Adapter。
- Media/Reference/Repeatable 等复杂字段组件。
- 内容列表配置。
- 内容编辑器 Shell。
- 预览和发布面板。
### 7.5 SEO Gate 仍是基础版
现有 Gate 能检查部分 Title、Description、Canonical、H1、内部链接、图片和 Sitemap,但主要依赖正则和本地产物。
还需要:
- DOM 解析。
- 重复 Title/Description。
- Canonical 唯一性和目标状态。
- hreflang 双向性。
- JSON-LD 合法性。
- robots/noindex 冲突。
- Redirect 环和多跳。
- 孤儿页面。
- 旧 URL 覆盖率。
- 真实部署后的 HTTP 状态、响应头和内容抽样。
- Lighthouse/性能预算和基础可访问性。
### 7.6 媒体系统仍是本地文件原型
应从本地文件升级为:
- S3 兼容对象存储。
- 内容 Hash 去重。
- 原文件与派生变体分离。
- AVIF/WebP 异步处理。
- `media_usage` 引用关系。
- 软删除和延迟物理删除。
- Alt、焦点、尺寸、版权和来源元数据。
- 对象存储生命周期与备份。
### 7.7 Form API 不完整
当前 Lead 模块只能视为最小提交接口,需要补充:
- 表单定义和版本。
- 蜜罐、验证码、限流和重复提交保护。
- 来源页面、UTM、Referrer 和 Locale。
- 隐私同意版本和时间。
- 邮件/Webhook/CRM 通知队列与重试。
- 数据保留、导出和删除策略。
- CSV 公式注入防护。
---
## 8. 可直接复用、改造复用和暂缓内容
### 8.1 高价值直接继承
| 资产 | 处理方式 |
|---|---|
| pnpm Workspace/Turborepo 骨架 | 保留,升级 CI 和锁文件策略 |
| Art Design Pro 后台壳 | 保留布局、请求、状态、表格表单组件 |
| NestJS/Fastify/Drizzle 基础 | 作为模块化单体控制面起点 |
| WordPress REST/WXR 解析 | 保留解析规则并增加正式 Adapter 接口 |
| UniversalRow | 演进为标准化 Source Record |
| 内容修订 | 保留不可变修订思想,补恢复和乐观锁 |
| Astro 运行时 | 保留构建基础和可复用页面组件 |
| Gate/Redirect 脚本 | 作为新质量门禁和路由编译器的起点 |
| 主题 Token/组件契约 | 合并进 SiteForge Theme/Block 契约 |
| 迁移和隔离测试 | 保留并扩大覆盖范围 |
| PostgreSQL/Redis/MinIO | 沿用技术选型,固定版本和生产配置 |
### 8.2 必须重构后使用
| 领域 | 不能原样使用的原因 |
|---|---|
| Auth | 自制 Token、默认 Secret、站点级用户、多角色遗留 |
| BuildService | 进程内状态、直接 spawn、无持久化恢复 |
| release.mjs | 非原子替换、无远端发布事务 |
| rollback | 删除新版、不能完整恢复路由/配置/CDN |
| MigrationService | 迁移即发布、Locale 硬编码、无冲突队列 |
| Redirect JSON | 无正式路由所有权、唯一性和状态模型 |
| MediaService | 本地盘、MIME/SVG 风险、无引用保护 |
| LeadService | 隔离缺陷、无反垃圾/隐私/通知可靠性 |
| Theme Tab | Token 到运行时链路不完整 |
| 管理后台业务页面 | 硬编码、演示代码多、单页过大 |
### 8.3 当前阶段暂缓
- ClickHouse 行为分析。
- Event Gateway。
- 客户画像和身份合并。
- 高级增长分析。
- 多租户计费。
- 复杂 RBAC。
- 工作流审批。
- 增量静态构建;V1 先按站全量构建。
### 8.4 禁止直接复制
- `.data`
- `storage`
- `node_modules`
- `.turbo`
- `.playwright-mcp`
- `.env` 和任何凭据
- 构建缓存和日志
- 未授权的客户内容、媒体、线索和导入文件
真实数据如需转为测试夹具,必须获得授权、脱敏并缩减为最小必要样本。
---
## 9. 推荐目标架构
### 9.1 控制面
```text
Vue 3 / Art Design Pro
↓
NestJS 模块化单体
├─ Auth
├─ Sites / Environments
├─ Content / Revisions
├─ Routes / SEO
├─ Media
├─ Migration / Import Batches
├─ Themes / Blocks
├─ Forms / Leads
├─ Build / Release
└─ Audit / Operations
↓
PostgreSQL + Redis + Object Storage
```
### 9.2 生产面
```text
Frozen Site Snapshot
↓
Isolated Build Worker
↓
Astro Static Compiler
↓
SEO / Route / Asset / Security Gates
↓
Immutable Release
↓
Nginx/SSH 或 OSS/CDN Deploy Adapter
↓
Production HTTP Smoke Test
```
### 9.3 四个冻结发布输入
每次发布必须绑定:
1. 内容快照。
2. 路由与 SEO 快照。
3. 媒体 Manifest。
4. 主题与站点配置版本。
构建过程中不得读取变化中的在线业务数据,也不得静默使用 Seed。
---
## 10. 改造路线图
以下周期按“单开发者 + AI 辅助、复用现有代码、需求不大幅变化”估算,只用于排序,不作为固定交付承诺。
### 阶段 A:证据基线与紧急保护(约 1 周)
任务:
1. 固定源码 Commit、Node、pnpm、数据库和依赖版本。
2. 建立干净开发环境并执行现有 lint/typecheck/unit/e2e/build。
3. 输出失败测试和真实能力基线。
4. 完成 PostgreSQL、媒体、WXR、Artifact 全量备份。
5. 在隔离环境完成一次恢复演练。
6. 删除前端默认凭据和后端默认 Secret。
7. 收紧 CORS,并暂时限制后台访问来源。
完成标准:
- 可从空环境恢复并运行。
- 测试结果可审计。
- 不再携带默认生产凭据。
### 阶段 B:安全和数据一致性(约 2–3 周)
任务:
1. 平台级单 `super_admin`。
2. 会话过期、撤销、MFA、恢复码和登录限流。
3. 全接口 `site_id` 审计和隔离测试。
4. SSRF 防护、下载预算和受限出口。
5. SVG、MIME、图片和 HTML 安全处理。
6. 媒体软删除和引用检查。
7. 禁止迁移自动发布。
完成标准:
- 安全测试通过。
- 后台具备最小公网安全条件;否则继续只允许内网/VPN。
- 所有跨站读写测试通过。
### 阶段 C:冻结快照与正式 Release(约 2–4 周)
任务:
1. 建立 `build_jobs`、`build_input_snapshots`、`releases`、`artifacts`、`publish_locks`。
2. 移除生产构建 Seed fallback。
3. 建立 Worker 和持久化 Job 状态。
4. 生成 Build/Route/Asset/Validation Manifest 和 Checksums。
5. 实现版本目录和真正原子切换。
6. 实现不删除历史版本的回滚。
7. 增加预览 Release、访问控制和 `noindex`。
完成标准:
- 相同快照可重复构建。
- API 中断不会生成错误成功产物。
- 服务重启后 Job 状态可恢复。
- 完成生产等价环境回滚演练。
### 阶段 D:URL、迁移和 SEO 闭环(约 2–4 周)
任务:
1. 建立 `source_snapshots`、`import_batches`、`import_items`。
2. 建立 `route_registry` 和路由编译器。
3. 完成 Sitemap + HTML 爬虫;Playwright 用于 JS/异常页面补扫。
4. 实现增量分类、冲突队列和人工覆盖保护。
5. 旧 HTML、导入 SEO、新预览 HTML 三方差异。
6. P0/P1 SEO 门禁、Redirect 环/链和 HTTP 检查。
7. 处理旧媒体 URL 和普通页面映射。
完成标准:
- 旧 URL 基线可审计。
- 所有 URL 有明确处置状态。
- P0/P1 差异为零或有正式豁免。
- 最终增量不会覆盖人工修改。
### 阶段 E:主题和组件平台化(约 3–5 周)
任务:
1. 把当前 Astro 页面抽成第一套正式主题。
2. 建立 Theme Manifest、Block Manifest、Slot 和 Renderer。
3. 打通后台 Token 到静态运行时。
4. 建立 Schema Form Renderer。
5. 清理后台演示页、注册/找回密码和多角色代码。
6. 实现第二套视觉差异明显的主题。
完成标准:
- 两套主题使用同一内容、SEO、媒体和交互逻辑。
- 无需复制整套页面代码即可新建差异化网站。
- 主题版本升级可迁移、可回退。
### 阶段 F:部署与正式试点(约 1–3 周)
任务:
1. 根据目标环境选择 Nginx/SSH 或 OSS/CDN Adapter。
2. 凭据进入 Secret 管理,只保存引用。
3. 上传不可变版本并校验文件数量、大小和 Hash。
4. 临时入口真实 HTTP 验收。
5. 获取发布锁后原子切换。
6. 生产冒烟、监控、告警和回滚。
7. 切站前最终增量和 DNS/CDN 计划。
完成标准:
- 完成一次真实发布和一次回滚演练。
- 旧路径、SEO、表单和关键媒体通过生产 HTTP 验收。
- 恢复和告警演练通过。
---
## 11. 第一试点上线阻断门槛
以下任一条件不满足,不允许正式切站:
### 安全
- 默认账号、密码和 Secret 已清除。
- MFA、会话撤销和登录限流有效,或后台完全位于受控私网且有书面临时豁免。
- SSRF、SVG/MIME 和富文本安全测试通过。
- CORS、CSRF、CSP 和必要安全响应头正确。
- 部署和数据源凭据未进入源码、日志或产物。
### 数据
- 完成切站前最终增量。
- 导入结果、冲突和失败条目全部可审计。
- 备份成功且已完成恢复演练。
- 媒体引用完整,没有未处理关键资源。
### URL 与 SEO
- 旧 URL 基线来源、数量和扫描时间明确。
- 每条旧 URL 已标记保留、301、410 或批准例外。
- 无 Redirect 环,重要路径无多跳。
- P0/P1 SEO 差异清零或有签字豁免。
- Canonical、hreflang、robots、Sitemap 和结构化数据通过。
### 构建与发布
- 构建输入已冻结并有 Hash。
- Release 和产物不可变。
- 发布切换原子且持久化。
- 发布锁和旧任务防覆盖有效。
- 临时入口和生产入口均完成 HTTP 冒烟。
- 回滚不重新构建,且已演练成功。
### 动态功能
- 表单具备限流、反垃圾和隐私记录。
- 通知失败可重试并可观察。
- Lead 站点隔离测试通过。
---
## 12. 风险登记
| 风险 | 概率 | 影响 | 等级 | 处置 |
|---|---:|---:|---:|---|
| Seed 数据被误发布 | 中 | 极高 | P0 | 冻结快照、失败即中止 |
| 非原子替换导致站点中断 | 中 | 极高 | P0 | 版本目录和原子指针切换 |
| Token/默认凭据泄露 | 中 | 极高 | P0 | 新会话体系、清默认值、MFA |
| SSRF 访问内网或元数据 | 中 | 极高 | P0 | DNS/IP/重定向校验和受限出口 |
| 跨站数据读写 | 中 | 高 | P0 | Repository 强制 siteId、RLS、隔离测试 |
| 迁移重跑覆盖人工内容 | 高 | 高 | P0 | 冲突队列和人工覆盖保护 |
| 普通页面跳首页造成 Soft 404 | 高 | 高 | P0 | route_registry、人工处理 |
| 无备份导致迁移成果丢失 | 中 | 极高 | P0 | 第二存储和恢复演练 |
| SVG/富文本持久化 XSS | 中 | 高 | P0 | 白名单净化、CSP |
| Build 进程重启后状态丢失 | 高 | 中高 | P1 | 持久化 Job 和 Worker |
| 主题抽象过度拖慢首站 | 中 | 中 | P1 | 先从已有站抽第一主题,再用第二主题验证协议 |
| WXR 正则解析遇到边界文件 | 中 | 中高 | P1 | 流式解析、异常夹具、资源限制 |
| 依赖或许可证不适用 | 低中 | 高 | P1 | SBOM、许可证和漏洞扫描 |
| 多语言硬编码造成数据误归类 | 中 | 中 | P1 | Locale 配置化,拒绝未知 Locale |
| 第三方 WAF 导致迁移不完整 | 高 | 中高 | P1 | WXR/SQL/uploads 备用通道、失败清单 |
---
## 13. 单人 + AI 模式下的合理取舍
可以简化:
- 只保留一个 `super_admin` 权限模型。
- V1 只做一个目标部署适配器。
- V1 按站全量构建,不做复杂增量构建。
- Playwright 作为异常页面和 JS 页补扫,不必替代普通 HTML 爬虫。
- 第一阶段不建设 ClickHouse、客户画像和复杂增长分析。
- 不做 SaaS 计费和复杂审批。
不能因为单人运营而省略:
- 数据备份和恢复演练。
- 认证过期、撤销和公网 MFA。
- 站点隔离。
- SSRF、SVG和富文本安全。
- URL 基线和旧路径覆盖率。
- 构建输入冻结。
- 持久化 Build/Release 记录。
- 最小发布锁和旧任务防覆盖。
- 真正可逆的回滚。
- 生产 HTTP 验收。
BullMQ、容器沙箱等具体实现可以分阶段,但它们承载的可靠性和安全目标不能被取消。
---
## 14. 文档治理建议
### 14.1 当前权威关系
建议明确:
1. `SiteForge_完整项目计划方案_V3.0.md`:产品和总体架构唯一基线。
2. `SiteForge_项目实施计划_V1.0.md`:目标实施节奏,后续需要结合本报告重新校准。
3. 本报告:旧 cms 代码现状、差距和改造优先级依据。
4. `SiteForge_现有CMS项目复用评估_V1.0.md`:复用边界参考。
5. 旧 cms 内部文档:历史设计和经验输入,不具有当前项目最高权威。
### 14.2 需要修正的旧文档表述
- 不再使用“已经原子发布”,改为“本地候选构建、门禁和非原子目录替换”。
- 不再使用“站点隔离已全部修复”,改为“主要路径已有隔离基础,仍需全量审计”。
- 不再把 ERD 里的 45 张表描述为已实现。
- 不再把 Build Worker/Event Gateway 空壳计入完成能力。
- 不再把单文件 sourceUrl 上传描述为完整 ZIP uploads 导入。
- 不再把修订历史描述为内容回滚。
- 区分本地真实数据验证与生产发布验证。
### 14.3 每次评估必须记录
- Git Commit SHA。
- 数据库迁移版本。
- Node/pnpm 和容器版本。
- 测试命令、结果、时间和环境。
- 使用的脱敏数据集版本。
- 已知失败和豁免。
- 生产验证证据。
---
## 15. 建议立即执行的首周任务
### 第 1–2 天:建立可信基线
1. 创建干净代码分支或新 SiteForge 仓库基线。
2. 排除数据、缓存、构建产物和 Secret。
3. 安装冻结依赖并执行 typecheck、unit、contract、e2e、build。
4. 形成实际失败清单,不以旧测试报告代替当前结果。
### 第 2–3 天:保护现有成果
1. 备份 PostgreSQL、media、WXR、Artifact 和配置。
2. 校验备份 Hash。
3. 在独立目录/实例完成恢复演练。
### 第 3–4 天:封堵最直接安全问题
1. 删除登录页默认账号密码。
2. 默认 Secret 改为缺失即拒绝启动。
3. CORS 改为明确后台来源。
4. 修复 Lead 更新和修订读取的 siteId 条件。
5. 暂停 SVG 上传或加入净化。
6. 为采集 URL 增加基础 SSRF 拒绝规则。
### 第 4–5 天:阻止错误发布
1. 生产构建禁止 Seed fallback。
2. 迁移不再自动发布,只创建草稿。
3. 普通页面不再自动 Redirect 到首页。
4. 为 Build/Release/Route/Import 核心表编写第一版迁移。
5. 确定第一试点部署方式:Nginx/SSH 或 OSS/CDN。
首周完成后再开始部署器开发;在此之前,不建议把当前后台和 API 直接暴露公网。
---
## 16. 最终判断
### 16.1 是否值得继续使用 cms
值得。旧项目已积累了大量可复用实现和真实迁移经验,尤其是:
- WordPress REST/WXR。
- 媒体抓取和去重。
- 内容修订。
- Astro 页面与组件。
- SEO 基础输出和 Gate。
- 管理后台工程壳。
- 迁移与隔离测试。
这些资产可以明显降低 SiteForge 的初始研发成本。
### 16.2 是否可以直接上线
不可以。当前只适合视为内部原型和代码底座。认证、隔离、采集安全、构建输入、发布一致性、路由、备份和监控均存在上线阻塞问题。
### 16.3 最合理的总体路线
```text
保留旧代码资产
→ 建立测试和备份基线
→ 修复 P0 安全与数据一致性
→ 冻结构建输入
→ 建立持久化 Release 和原子发布
→ 建立 URL/SEO/迁移闭环
→ 落地主题与 Block 协议
→ 实现一个部署适配器
→ 完成真实试点发布与回滚
```
### 16.4 项目定位
`D:\project\cms` 应被定位为:
- SiteForge 的实现底座。
- WordPress 迁移经验库。
- 测试夹具和兼容规则来源。
它不应被定位为:
- 已完成的生产平台。
- 当前产品范围的权威文档。
- 可以整体原样复制上线的系统。
SiteForge V3.0 继续作为产品和架构基线;本报告作为从 cms 演进到 SiteForge 的差距与改造依据。
---
## 附录 A:关键代码证据索引
| 结论 | 证据路径 |
|---|---|
| Build 状态仅存内存 | `services/control-api/src/modules/build/build.service.ts` |
| API 进程直接 spawn 构建 | `services/control-api/src/modules/build/build.service.ts` |
| 非原子删除后复制 | `runtimes/astro-site-runtime/scripts/release.mjs` |
| Token 无过期且有默认 Secret | `services/control-api/src/common/token.ts` |
| CORS origin=true、logger=false | `services/control-api/src/main.ts` |
| 迁移后逐条自动发布 | `services/control-api/src/modules/migration/migration.service.ts` |
| Redirect 存 settings JSON | `services/control-api/src/modules/migration/migration.service.ts` |
| 普通页面可能跳 `/en/` | `services/control-api/src/modules/migration/migration.service.ts` |
| Sitemap 仅基础递归 | `services/control-api/src/modules/migration/migration.service.ts` |
| Lead 更新缺 siteId 条件 | `services/control-api/src/modules/lead/lead.service.ts` |
| 修订查询缺 siteId 条件 | `services/control-api/src/modules/content/content.service.ts` |
| SVG 可直接上传与公开返回 | `services/control-api/src/modules/media/media.service.ts` |
| 媒体直接物理删除 | `services/control-api/src/modules/media/media.service.ts` |
| 表单邮件通知仍为 TODO | `services/control-api/src/modules/lead/lead.controller.ts` |
| 内容导入 Locale 硬编码 en/es | `services/control-api/src/modules/content/import.service.ts` |
| API 失败回退 Seed | `runtimes/astro-site-runtime/src/content/*.ts` |
| ZIP UI 未形成真实解包导入 | `apps/admin-web/src/views/site/manage.vue` |
| Build Worker 为空壳 | `services/build-worker` |
| Event Gateway 为空壳 | `services/event-gateway` |
## 附录 B:进入开发前待确认事项
1. 第一试点正式部署目标是 Nginx/SSH 还是 OSS/CDN。
2. 后台是否必须公网访问;如果不是,先采用 VPN/零信任/IP 白名单。
3. 旧站能否提供 SQL、uploads、服务器日志和 Search Console 数据。
4. 第一试点需要支持哪些 WordPress 插件、CPT、短代码和页面构建器。
5. 需要保留哪些 Locale,URL 是否含语言前缀。
6. 现有客户数据是否允许复制到开发/测试环境,如何脱敏。
7. Art Design Pro 和第三方图片、字体、图标的许可证是否满足商用与再分发。
8. 备份目标、RPO、RTO 和保留期。
9. 正式域名、DNS、证书、CDN 和缓存控制权归属。
10. 哪个真实网站作为第一个正式验收试点。