
刀豆 Console 工程设计文档 · 第 02 部分。状态:已根据实现代码重写(2026-07-16)。 本文仅讨论系统如何分层、各类数据归哪一侧所有,以及双方如何通信。身份验证请参阅03;集成配置请参阅05;数据库请参阅13;项目契约请参阅18。
刀豆 Console 是统一的控制平面,而每个项目都是自治的运行时平面。Console 集中管理身份、权限、内容、版本和发布;每个项目保留自己的管理端业务逻辑、组件实现和前端渲染。双方仅通过带版本的 REST、JWT/JWKS、HMAC 和浏览器 postMessage 通信。双方既不共享进程,也不共享业务数据库,更不会重复实现对方的渲染代码。
四项不可妥协的原则:
分层权威来源:组件 fields/sample 的源定义位于项目代码中,而 Console DB 存储每个环境中已通过契约验证的 LKG。对于落地页和博客,Console DB 是身份、草稿和当前已发布快照的唯一事实来源。
渲染归项目所有:组件结构和数据位于 Console 中,而组件样式和渲染器位于项目中。预览和生产环境都使用项目自己的渲染器。
安全边界相互独立:项目的管理端集成与内容/预览集成可以独立连接,并使用不同的配置、凭据、会话、Cookie 和权限目标。
物理环境隔离:控制平面位于 platform,测试内容位于 test,生产内容位于 prod。test/prod 配置也是两条相互独立的记录,不存在隐式继承。
Console 负责:
Better Auth 平台身份、用户、项目、角色和三维 RBAC。
管理端和内容这两类项目集成的配置、凭据、启用、停用和审计。
逻辑落地页、完整的本地化页面、共享组件拓扑、博客、多语言内容、SEO、主题选择和精确组件引用。
草稿采用显式保存(D-95:由用户决定何时保存;存在未保存的更改时,离开页面会收到警告);落地页执行 A/B/C 检查并应用到环境;博客的测试/生产与草稿/已发布状态对应,并以原子方式直接发布。
项目能力同步和最后已知良好状态投影。
将编辑状态实时传递到 iframe 预览,并对独立预览窗口读取草稿进行授权。
Console 不负责:
项目管理系统的业务逻辑和业务数据。
项目组件的 React/Vue/CSS 实现。
项目对前端路由框架或 SSR/SSG/ISR 策略的选择。
项目业务数据库的密码。
运行 Redis,或使用它存储任何平台状态。速率限制、项目 SID/租约和重放攻击防护均已统一迁移至 PostgreSQL。
项目负责:
自身的管理端业务逻辑、业务数据库和服务端授权守卫。
组件注册表,以及每个精确 technicalName 对应的模式、渲染器和实际样式;componentId 由项目生成。
语言、主题、颜色模式、组件清单、预览和重新验证的能力端点。
管理端/预览桥接 JWT 验证及其各自的本地会话。
前端从 Console 的已发布内容 API 读取内容,然后根据项目的策略,使用 SSR/SSG/ISR 对其进行缓存和渲染。
审计项目侧的关键业务操作,并使用 requestId 与 Console 记录进行核对。
项目不得将编辑后的内容另行保存为第二个权威 CMS;任何本地缓存都只能是可随时丢弃的已发布内容缓存。
┌────────────────────────── Console 控制面 :8888 ──────────────────────────┐
│ Better Auth │ 项目/RBAC │ Admin Integration │ Content Integration │
│ │ │ │ │
│ platform schema: 用户/Session、项目、接入、安全短状态、能力投影、审计 │
│ test schema: Landing Draft/Test;Blog Draft/Published;环境 taxonomy │
│ prod schema: Landing Prod C;Blog Draft A/Published B 当前槽位 │
└───────────────┬──────────────────────────────┬───────────────────────────┘
│ │
Admin 身份与复核 Content/Preview 契约
JWT/JWKS + HMAC HMAC + Preview JWT + REST
│ │
┌───────────────▼──────────────────────────────▼───────────────────────────┐
│ Project Launchpad / 其他项目运行面 │
│ /admin 业务后台 │ 项目业务库 │ component registry │ Preview renderer │
│ 项目本地 Session│ │ 前台 SSR/SSG/ISR │ revalidate/capability│
└───────────────────────────────────────────────────────────────────────────┘
项目可以使用内容集成而不使用管理端集成,也可以只使用管理端集成。即使将二者部署在同一域名下,也不会改变安全边界分离的原则。
Console iframe 入口点:
Console 校验平台 Session 与项目准入
→ 签发约 120 秒 Admin Bridge JWT
→ iframe 打开项目 embedded bridge
→ 项目用 Console JWKS 验签,并核对 project/env/target
→ 项目写入本地 Admin Session Cookie
→ 回到原 /admin deep link
直接打开项目管理端:
项目 /admin 无本地 Session
→ 项目生成独立 state transaction
→ 跳 Console authorize
→ Console 有 Session:直接验权;无 Session:先登录
→ Console 签 standalone Bridge JWT
→ 项目核对 state + JWT,建立本地 Session
→ 回原 deep link
桥接 JWT 仅用于一次性身份交接,并非长期访问令牌。项目会话最长持续 7 天,项目的服务端守卫每 5 分钟通过 Console 重新验证权限。在项目中执行本地退出只会清除项目会话,不会清除 Console 会话。
Console Landing Draft A
→ 强制检查后覆盖 Test B
→ 强制生产检查后覆盖 Prod C
→ 记录发布人/revision/审计
→ HMAC 通知项目 revalidate
→ 项目前台重新读取 published API / 更新本地缓存
内容会转移,配置和凭据则不会。生产项目读取 Console API 中的已发布状态,但无法访问草稿端点。如果缓存失效,项目可以回源;Console 不会将可编辑的数据库副本推送到项目。
Console 编辑器内存态
├─ iframe:postMessage 实时覆盖项目 Preview renderer
└─ DB:有变化时 debounce 1 秒,持续输入 maxWait 30 秒
独立 Preview 窗口
→ Preview Session 鉴权
→ 读取 Console 草稿接口
→ 每 5 秒按 revision 轮询;无变化不重复渲染
预览端和管理端共用平台身份根以及 JWT/JWKS/HMAC 基础设施,但不共用浏览器数据、会话、目标或长期凭据。iframe 的 postMessage 仅传递协议定义的编辑数据,不传递 HMAC 密钥。
数据 | 唯一事实来源 | 项目端形式 |
|---|---|---|
平台用户与会话 |
| 仅接收短期桥接身份,不复制平台会话 |
速率限制、项目 SID/租约及重放攻击防护 |
| 项目仅按契约定义调用消耗、重新验证和退出功能,不持有 Console 存储 |
用户最近的活动 |
| 不设三态在线状态;不同步到项目 |
项目成员与权限 |
| 本地会话存储必要的快照;权限每 5 分钟重新验证一次 |
管理端集成 |
| 环境变量中的管理端凭据和协议端点 |
内容/预览集成 |
| 环境变量中的内容凭据和协议端点 |
组件清单/模式/示例 | Console 同步投影 | 项目注册表是声明的来源,而 Console DB 是用于内容编排的同步事实来源 |
页面/博客/草稿 |
| 不存储可编辑的权威副本 |
已发布状态缓存 | Console 发布 API | 项目可以进行缓存或静态渲染,但必须能够重新构建 |
组件样式和渲染器 | 项目代码仓库 | 预览和生产环境复用同一套项目实现 |
内容表使用 project_id 实现项目隔离;不使用旧版 tenant_id 术语。审计表中的用户/项目标识符是写入时生成的快照,且没有 FK,从而确保关联实体被删除后,历史记录仍可读取。
环境包含两个不得混淆的维度:
内容环境:test / prod 模式。编辑操作仅写入 test;只有提升操作才能写入 prod。
项目部署环境:每个集成都有独立的测试和生产配置,其源站、路径、凭据和状态值完全相互独立。
UI 可以提供“将测试字段复制到生产表单”选项,但保存后,它就会成为一条独立的生产记录;此后对测试记录的更改不会影响生产记录。生产源站必须使用 HTTPS,而本地测试允许使用 HTTP。
项目通过内容能力声明以下信息:
支持的语言区域和默认语言区域。
支持的主题、默认主题,以及每个主题允许使用的颜色模式。
组件清单端点和稳定的预览路径。
重新验证等协议端点。
Console 使用内容 HMAC 主动获取能力,并存储最近一次确认有效的版本。组件的身份是由项目生成的 componentId + technicalName:相同的技术名称标识同一版本,内容也会精确引用该名称。只有当前线上生产环境中的引用会锁定字段;存在破坏性变更的新版本应使用新的 ID 和技术名称。如果缺少对应版本,应执行故障关闭,而不是猜测其他版本。
能力同步并非内容回退机制:当项目端点不可用时,可以显示最近一次成功同步的快照,但不得虚构模拟能力,也不得将同步失败视为成功。
每个请求都必须满足以下所有条件:
有效平台身份
∩ 有效项目成员关系
∩ permission domain
∩ environment scope
∩ 资源自身状态约束
典型角色层级:
运营成员:可以访问已获授权项目的管理区域并编辑内容,但无法查看集成凭据。
开发者:可以查看管理端/内容端集成配置,但不能修改。
项目所有者:可以保存、启用、禁用和重新签发凭据。对于启用、禁用或重新签发凭据等立即生效的操作,前端会显示确认对话框,而服务器仅依赖三维 RBAC 进行访问控制 (D-85)。
管理端凭据仅用于签署管理端验证请求;内容端凭据仅用于签署能力、内容和重新验证请求。严禁跨端验证和回退。
系统间不使用 2PC;该设计改用幂等性、requestId、双方审计和可重试的补偿机制。
预览断开连接不会影响草稿保存;如果草稿保存失败,系统不会假装已保存成功。
重新验证失败不会回滚已成功完成的发布操作,但必须能够观测并重试。
当项目端点无法访问时,Admin/Preview 会明确失败,而不会回退到 Console 模拟页面。
处于启用状态的配置会被冻结;必须先禁用,才能修改或使用单个凭据重新签名。
当 PostgreSQL 不可用时,Bridge 会对一次性消费采取故障关闭策略;标准 HMAC 重放保护和辅助限流仍各自沿用既定的故障策略,不会仅仅因为二者都使用 PG 就合并为单一策略。
系统每 15 分钟清理一次过期的 SID、重放和限流记录;清理失败只会影响容量,不会改变请求时的过期检查。
当前尚未达到生产就绪要求的部分包括:启用前的就绪探测、用于关键审计的可靠发件箱、并发 CAS,以及支持多个 kid 值的凭据零停机轮换。详情请参阅第 15 节 §9。
“将所有项目组件移入 Console 中的共享渲染器”会带来三个新问题:
Console 将不得不随每个项目的 UI 框架和依赖项同步发布,从而再次与主代码仓库形成耦合。
预览所用代码可能与项目生产部署中实际使用的代码不同,反而会破坏一致性。
项目特有的样式、运行时能力和数据源将被迫泄漏到平台中。
因此,共享的只有协议和纯类型契约,而不是具体的 UI 渲染器。“预览与生产一致性”是指项目的预览环境和生产环境复用项目代码仓库中的同一个渲染器,而不是由 Console 复制该渲染器。
/Users/edwin/coding/diaoyan/project-launchpad 是首个真实的参考项目:
管理员 iframe 和独立 SSO 流程均已通过验证。
在本地项目退出登录后,可以无感复用 Console 会话。
内容 HMAC 能力同步信息和组件清单均已持久化到数据库。
可以在 Console 中分别预览 15 个组件系列和 16 个不可变版本。
主题和 light/dark/system 模式通过项目能力进行声明;组件画布背景与组件模式相互独立。
未来的项目必须复用这些契约和边界,而不是照搬 Project Launchpad 的业务 UI 或技术栈。