- V3.0 总体方案、主题与板块设计、实施计划 - cms 现状差距分析 V2.0(V1.0 已标注作废)与复用评估 V1.0 - 纵向切片设计规格(路线 C:全新架构 + 白名单资产移植) - .gitignore 先行(storage/artifacts/env 永不入库) Co-Authored-By: Claude Code <noreply@anthropic.com>
39 KiB
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 向平台化演进”的原型,尚不具备安全生产上线所需的完整能力。主要阻塞点不是页面能否构建,而是:
- 构建输入不冻结,API 失败时可能用 Seed 演示数据生成正式产物。
- 所谓“原子发布”实际是删除旧目录后复制新目录,并非原子切换。
- 构建历史、状态和锁只存在进程内存中。
- 认证、CORS、默认凭据、SSRF、SVG、富文本等安全边界不足。
- 迁移会自动发布,缺少审核、冲突保护和批次回滚。
- 没有正式 URL 注册表,普通页面可能错误跳转首页。
- 没有完整部署适配器、生产 HTTP 验证和真正可逆的 Release 回滚。
- 没有系统备份、恢复演练、监控和告警。
- 主题 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 主要包含:
sitessite_localesuserscontent_type_definitionscontent_entriesentry_localescontent_revisionscontent_relationsaudit_logssite_settingssite_nav_itemstemplatesleadsmedia_assets
旧 ERD 文档中的 Route、Snapshot、Import Batch、Build Job、Release、Artifact、Form Version、Consent、身份分析等大量表尚未进入实际 Schema。后续必须以数据库迁移文件和运行代码为准,不能把 ERD 蓝图当成现状。
3.3 已有真实价值资产
最值得保留的资产包括:
- WordPress REST/WXR 解析和真实兼容经验。
UniversalRow中间数据结构。externalRef、Slug 和sourceUrl的幂等思路。- 内容工作副本和不可变修订。
- 显式站点上下文和已有隔离测试。
- Astro 静态站页面、组件和 SEO 输出基础。
- 主题 Token、组件契约和导入契约文档。
- Gate、Redirect、迁移 E2E 等测试资产。
- 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 的关键步骤是:
删除 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 迁移自动发布和人工内容覆盖
当前迁移批次导入后会逐条调用发布;重跑还会覆盖工作副本,没有字段级或条目级人工修改保护。
整改:
上传/采集
→ 原始快照
→ 解析
→ 映射
→ 校验
→ 导入草稿
→ 冲突处理
→ 人工审核
→ 预览
→ 发布
必须建立:
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_environmentsdeployment_targetsenvironment_domainsenvironment_publish_locksreleasesrelease_artifacts
7.2 缺少持久化任务系统
当前 BuildService 直接 spawn pnpm,历史保存在内存中。即使暂不采用 BullMQ,也必须先解决:
- Job 持久化。
- 幂等键。
- 重启恢复。
- 超时和取消。
- 日志存储。
- 失败重试和死信状态。
- 同站点同环境串行。
推荐 Redis + BullMQ;如果先用数据库任务表,也要满足同样的状态和恢复语义。
7.3 主题系统尚未真正成立
当前存在模板表、Theme Tab 和 Token,但未形成可版本化的主题契约。
SiteForge 应采用四层组件结构:
- 基础 UI:Container、Button、Image、RichText、FormControl。
- 业务区块:Hero、ProductGrid、NewsList、FAQ、CTA、ContactForm。
- 页面模板:首页、列表页、详情页、普通页面、落地页。
- 主题:Token、字体、布局、装饰、默认区块组合和可用模板集合。
主题包建议结构:
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 禁止直接复制
.datastoragenode_modules.turbo.playwright-mcp.env和任何凭据- 构建缓存和日志
- 未授权的客户内容、媒体、线索和导入文件
真实数据如需转为测试夹具,必须获得授权、脱敏并缩减为最小必要样本。
9. 推荐目标架构
9.1 控制面
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 生产面
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 四个冻结发布输入
每次发布必须绑定:
- 内容快照。
- 路由与 SEO 快照。
- 媒体 Manifest。
- 主题与站点配置版本。
构建过程中不得读取变化中的在线业务数据,也不得静默使用 Seed。
10. 改造路线图
以下周期按“单开发者 + AI 辅助、复用现有代码、需求不大幅变化”估算,只用于排序,不作为固定交付承诺。
阶段 A:证据基线与紧急保护(约 1 周)
任务:
- 固定源码 Commit、Node、pnpm、数据库和依赖版本。
- 建立干净开发环境并执行现有 lint/typecheck/unit/e2e/build。
- 输出失败测试和真实能力基线。
- 完成 PostgreSQL、媒体、WXR、Artifact 全量备份。
- 在隔离环境完成一次恢复演练。
- 删除前端默认凭据和后端默认 Secret。
- 收紧 CORS,并暂时限制后台访问来源。
完成标准:
- 可从空环境恢复并运行。
- 测试结果可审计。
- 不再携带默认生产凭据。
阶段 B:安全和数据一致性(约 2–3 周)
任务:
- 平台级单
super_admin。 - 会话过期、撤销、MFA、恢复码和登录限流。
- 全接口
site_id审计和隔离测试。 - SSRF 防护、下载预算和受限出口。
- SVG、MIME、图片和 HTML 安全处理。
- 媒体软删除和引用检查。
- 禁止迁移自动发布。
完成标准:
- 安全测试通过。
- 后台具备最小公网安全条件;否则继续只允许内网/VPN。
- 所有跨站读写测试通过。
阶段 C:冻结快照与正式 Release(约 2–4 周)
任务:
- 建立
build_jobs、build_input_snapshots、releases、artifacts、publish_locks。 - 移除生产构建 Seed fallback。
- 建立 Worker 和持久化 Job 状态。
- 生成 Build/Route/Asset/Validation Manifest 和 Checksums。
- 实现版本目录和真正原子切换。
- 实现不删除历史版本的回滚。
- 增加预览 Release、访问控制和
noindex。
完成标准:
- 相同快照可重复构建。
- API 中断不会生成错误成功产物。
- 服务重启后 Job 状态可恢复。
- 完成生产等价环境回滚演练。
阶段 D:URL、迁移和 SEO 闭环(约 2–4 周)
任务:
- 建立
source_snapshots、import_batches、import_items。 - 建立
route_registry和路由编译器。 - 完成 Sitemap + HTML 爬虫;Playwright 用于 JS/异常页面补扫。
- 实现增量分类、冲突队列和人工覆盖保护。
- 旧 HTML、导入 SEO、新预览 HTML 三方差异。
- P0/P1 SEO 门禁、Redirect 环/链和 HTTP 检查。
- 处理旧媒体 URL 和普通页面映射。
完成标准:
- 旧 URL 基线可审计。
- 所有 URL 有明确处置状态。
- P0/P1 差异为零或有正式豁免。
- 最终增量不会覆盖人工修改。
阶段 E:主题和组件平台化(约 3–5 周)
任务:
- 把当前 Astro 页面抽成第一套正式主题。
- 建立 Theme Manifest、Block Manifest、Slot 和 Renderer。
- 打通后台 Token 到静态运行时。
- 建立 Schema Form Renderer。
- 清理后台演示页、注册/找回密码和多角色代码。
- 实现第二套视觉差异明显的主题。
完成标准:
- 两套主题使用同一内容、SEO、媒体和交互逻辑。
- 无需复制整套页面代码即可新建差异化网站。
- 主题版本升级可迁移、可回退。
阶段 F:部署与正式试点(约 1–3 周)
任务:
- 根据目标环境选择 Nginx/SSH 或 OSS/CDN Adapter。
- 凭据进入 Secret 管理,只保存引用。
- 上传不可变版本并校验文件数量、大小和 Hash。
- 临时入口真实 HTTP 验收。
- 获取发布锁后原子切换。
- 生产冒烟、监控、告警和回滚。
- 切站前最终增量和 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 当前权威关系
建议明确:
SiteForge_完整项目计划方案_V3.0.md:产品和总体架构唯一基线。SiteForge_项目实施计划_V1.0.md:目标实施节奏,后续需要结合本报告重新校准。- 本报告:旧 cms 代码现状、差距和改造优先级依据。
SiteForge_现有CMS项目复用评估_V1.0.md:复用边界参考。- 旧 cms 内部文档:历史设计和经验输入,不具有当前项目最高权威。
14.2 需要修正的旧文档表述
- 不再使用“已经原子发布”,改为“本地候选构建、门禁和非原子目录替换”。
- 不再使用“站点隔离已全部修复”,改为“主要路径已有隔离基础,仍需全量审计”。
- 不再把 ERD 里的 45 张表描述为已实现。
- 不再把 Build Worker/Event Gateway 空壳计入完成能力。
- 不再把单文件 sourceUrl 上传描述为完整 ZIP uploads 导入。
- 不再把修订历史描述为内容回滚。
- 区分本地真实数据验证与生产发布验证。
14.3 每次评估必须记录
- Git Commit SHA。
- 数据库迁移版本。
- Node/pnpm 和容器版本。
- 测试命令、结果、时间和环境。
- 使用的脱敏数据集版本。
- 已知失败和豁免。
- 生产验证证据。
15. 建议立即执行的首周任务
第 1–2 天:建立可信基线
- 创建干净代码分支或新 SiteForge 仓库基线。
- 排除数据、缓存、构建产物和 Secret。
- 安装冻结依赖并执行 typecheck、unit、contract、e2e、build。
- 形成实际失败清单,不以旧测试报告代替当前结果。
第 2–3 天:保护现有成果
- 备份 PostgreSQL、media、WXR、Artifact 和配置。
- 校验备份 Hash。
- 在独立目录/实例完成恢复演练。
第 3–4 天:封堵最直接安全问题
- 删除登录页默认账号密码。
- 默认 Secret 改为缺失即拒绝启动。
- CORS 改为明确后台来源。
- 修复 Lead 更新和修订读取的 siteId 条件。
- 暂停 SVG 上传或加入净化。
- 为采集 URL 增加基础 SSRF 拒绝规则。
第 4–5 天:阻止错误发布
- 生产构建禁止 Seed fallback。
- 迁移不再自动发布,只创建草稿。
- 普通页面不再自动 Redirect 到首页。
- 为 Build/Release/Route/Import 核心表编写第一版迁移。
- 确定第一试点部署方式:Nginx/SSH 或 OSS/CDN。
首周完成后再开始部署器开发;在此之前,不建议把当前后台和 API 直接暴露公网。
16. 最终判断
16.1 是否值得继续使用 cms
值得。旧项目已积累了大量可复用实现和真实迁移经验,尤其是:
- WordPress REST/WXR。
- 媒体抓取和去重。
- 内容修订。
- Astro 页面与组件。
- SEO 基础输出和 Gate。
- 管理后台工程壳。
- 迁移与隔离测试。
这些资产可以明显降低 SiteForge 的初始研发成本。
16.2 是否可以直接上线
不可以。当前只适合视为内部原型和代码底座。认证、隔离、采集安全、构建输入、发布一致性、路由、备份和监控均存在上线阻塞问题。
16.3 最合理的总体路线
保留旧代码资产
→ 建立测试和备份基线
→ 修复 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:进入开发前待确认事项
- 第一试点正式部署目标是 Nginx/SSH 还是 OSS/CDN。
- 后台是否必须公网访问;如果不是,先采用 VPN/零信任/IP 白名单。
- 旧站能否提供 SQL、uploads、服务器日志和 Search Console 数据。
- 第一试点需要支持哪些 WordPress 插件、CPT、短代码和页面构建器。
- 需要保留哪些 Locale,URL 是否含语言前缀。
- 现有客户数据是否允许复制到开发/测试环境,如何脱敏。
- Art Design Pro 和第三方图片、字体、图标的许可证是否满足商用与再分发。
- 备份目标、RPO、RTO 和保留期。
- 正式域名、DNS、证书、CDN 和缓存控制权归属。
- 哪个真实网站作为第一个正式验收试点。