www_site/docs/phase-4-report.md

71 lines
5.5 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.

# Phase 4 CMS 基础报告
日期2026-09-09
范围P4-01 至 P4-03
状态CMS 数据边界、模型、公共内容 API、可复现迁移、受控管理员、访问控制与真实内容闭环均已验收通过。
## 1. 已完成
### 数据边界与模型
- 新增独立 Payload CMS 应用:`apps/cms`。
- CMS 使用独立 PostgreSQL 数据库 `kaotings_cms` 和独立数据库账号,不读取业务 API 用户表。
- 已配置 systemd 服务 `kaotings-cms`,仅监听 `127.0.0.1:3001`
- Caddy 保留 `/cms` 外部边界,不向公网开放 CMS 回环端口。
- 建立模型:`Users`、`Products`、`Media`、`SiteSettings`、`HomeContent`。
- Product 支持 `draft`、`published`、`unpublished`slug、分类、摘要、描述、媒体、features、specs、SEO 和排序字段。
- Media 为受控上传集合,普通访客只读媒体,写入需要 CMS 用户。
### 公共内容 API 与 Caddy 前缀
- Next.js basePath 为 `/cms`Caddy 用 `handle /cms/*` 原样透传给 CMS 服务(不剥离前缀),避免资源地址/重定向丢失 `/cms`
- `/cms/admin`、`/cms/admin/create-first-user` 可正常渲染 Payload 管理界面200资源以 `/cms/_next/...` 加载正常,无重定向循环。
- 公共 Products API `GET /cms/api/products` 返回 `200` 和空集合,未泄露草稿。
- Website 内容适配器已切换到 CMS 公共 API`lib/content.ts` 的 `getProducts``?where[status][equals]=published` 拉取,`cache: no-store`CMS 未发布产品时显示明确空状态。
### 数据库初始化固化P4-01
- 核对执行记录:`payload_migrations` 仅含 `20260909_100120_initial`batch 1与现有 `kaotings_cms` 结构一致。
- 已重新生成初始迁移并修正类型导入,命名为 `20260909_100120_initial` 以对齐已应用记录,避免重复应用。
- 迁移文件提交进仓库:`apps/cms/src/migrations/20260909_100120_initial.ts`。
- 使用独立临时库 `kaotings_cms_verify` 从仓库 `payload migrate` 重建,得到 14 张表,列类型比对 `SCHEMA_IDENTICAL`;随后删除临时库,现有 `kaotings_cms` 未清空。
- 迁移类型导入已修正(`MigrateUpArgs/MigrateDownArgs` 用 `import type``sql` 用值导入),本地与服务端构建均通过。
### 受控初始化 CMS 管理员P4-02
- 通过一次性受控路由 `apps/cms/src/app/api/seed-admin/route.ts` 初始化管理员,凭据来自 `/etc/kaotings/cms-admin.secrets`root-only 0600未写入 Git/报告/日志。
- 路由以 `x-cms-seed-token` 守卫,且仅在用户表为空时创建;已存在用户时返回 `409 {"ok":false,"error":"user exists"}`,防止重复初始化。
- 管理员:`tech@kaotings.com``displayName: CMS Admin`)。登录验证 `200 {"message":"Authentication Passed"}`
- 修正seed 路由不得在 Next 运行时调用 `payload.destroy()`(会销毁共享数据库连接池,导致后续请求 500
### 访问控制验证P4-02
- 匿名 `POST /cms/api/users/first-register``403`(已有用户后 create-first-user 失效)。
- 匿名 `POST /cms/api/users`(注册)→ `403`
- 匿名 `GET /cms/api/users`、`GET /cms/api/users/1`(读取用户资料)→ `403`
- 匿名 `PATCH /cms/api/users/1`(提权/修改)→ `403`
- 匿名 `GET /cms/api/access``canAccessAdmin:false`(枚举到字段级权限,非仅状态码)。
- 管理员 `GET /cms/api/access``canAccessAdmin:true`。
- 普通网站用户属独立数据库 `kaotings`(角色 `kaotings_app`CMS 使用 `kaotings_cms` 且签发自有 `payload-token` JWT网站 `kaotings_session` cookie 不会被 CMS 接受,跨库无法获取 CMS 管理会话。
### 真实内容闭环P4-03
- 以管理员登录后创建明确标注的测试产品slug `p4-test-draft-product`
- 草稿:公共列表/API `docs:[]`,官网 `/products` 与详情不显示。
- 发布:`GET /cms/api/products` 返回该产品;官网 `/products` 列表显示,详情页渲染正确。
- 修改:更新 summary/name 后,公共列表与官网详情立即反映新内容(`no-store`,无缓存陈旧)。
- 下架:`status:unpublished` 后,公共列表/API 为空,官网详情 `404 Not Found`
- 测试产品已下架(当前 `status:unpublished`),不对公网提供内容。
## 2. 修复的集成问题
- `/cms/admin` 前缀重定向/404Next 恢复 `basePath: "/cms"`Caddy 改用 `handle /cms/*` 透传,不再由 Caddy 剥离前缀。
- Website `CMS_PUBLIC_API_URL` 需指向 `http://127.0.0.1:3001/cms`(此前缺 `/cms` 前缀导致官网 `/products` 500已更新 `kaotings-web.service` 环境变量。
- Payload Admin 的 serverFunction/importMap 接线:改用生成的真实 `importMap``@payloadcms/next/layouts``handleServerFunctions`
- 已知遗留CMS REST 按 slug 的详情查询(`/cms/api/products/:slug`)会因 Payload 以数值 id 处理返回 `500`;官网详情页走列表而非该路径,不受影响。
## 3. 范围边界
- CMS 不管理业务用户、Role/Plan、额度、TTS 任务或认证会话。
- P4-04 至 P4-07 的用户、VIP、额度、TTS 管理界面尚未开始。
- 旧 Big-TTS Web 不参与 CMS推理服务继续由新网站 API 调用。
## 4. 后续
- 本命中遗留的按 slug 详情 REST `500` 可后续在 CMS 侧提供按 slug 查询端点或文档化;当前不影响公网产品展示闭环。
- 迁移、seed 路由与集成修复已提交仓库并通过本地/服务端构建CMS 现有数据库未清空,有受控备份(`infra/scripts/backup-cms-db.sh`)。