Files
ChuBlog/PLAN.md
T

14 KiB
Executable File
Raw Blame History

ChuBlog — 项目规划

状态:规划草案 v1.0 · 2026-10-15
定位:自托管个人技术博客;Markdown 文件是内容源,Git 管理版本,ChuSQL 提供可重建的内容索引。

1. 目标与原则

  • 面向个人作者,支持公开阅读、文章归档、标签、代码高亮、目录、SEO、RSS 和深色模式。
  • 管理员可在经过认证的后台上传 Markdown、预览、修改元数据、发布、撤回与删除文章;也支持本地 Git 工作流。
  • Git 仓库内的 Markdown 与资源文件是唯一权威内容源;ChuSQL 不保存唯一一份正文,只维护可重建索引。
  • 未授权用户不得发布页面、提交到内容仓库或触发任意服务器 Git 命令。
  • 保持 MVP 小而可靠;不引入公共用户注册、评论、插件市场、队列/微服务或复杂角色系统。
  • ChuSQL 暂不视为已通过生产验证的数据库;博客即使索引丢失,也能从 Git 恢复文章。

2. 技术栈

层 选型 职责
站点 Astro + TypeScript 内容页面、按需服务端渲染、SEO、RSS
样式 Tailwind CSS 响应式设计、暗色模式
Markdown Astro Markdown 管线(remark/rehype、Shiki) Markdown/Frontmatter 解析、代码高亮
后端 Rust + Axum + Tokio + Serde 管理员接口、认证、上传校验、Git 操作、索引同步
数据库 ChuSQL 已发布文章元数据、标签、搜索索引(按当前能力逐步实现)
DB 客户端 chusql-rs(独立 crate) ChuSQL 网络协议连接、查询、错误处理
反向代理 Caddy HTTPS、请求体限制、路由
运行 Debian + Docker Compose 管理服务与持久卷
版本控制 Git 文章与图片的版本记录、审计与恢复

不自行编写 Markdown 语法解释器。MVP 禁止文章中的原始 HTML 或采用严格清理策略;默认不启用任意 MDX/JS 组件,因为上传文档不能成为服务器执行代码的入口。

3. 系统架构

读者浏览器 ── HTTPS ── Caddy ── Astro(公共页面)
                                 │
                                 ├─ 只读文章文件 / content(挂载)
                                 └─ Axum 只读 API(必要时)── ChuSQL(索引)

管理员浏览器 ── HTTPS ── Caddy ── Axum(后台 API)
                                      │
                                      ├─ 管理员认证 / CSRF / 限流
                                      ├─ Markdown 校验及暂存
                                      ├─ 受控 Git 内容仓库
                                      └─ 索引同步 ── chusql-rs ── ChuSQL

管理员本地编辑器 ── Git 受保护分支 / 仓库同步流程 ── 内容仓库
  • 只暴露 80/443 TCP;Axum、Astro 与 ChuSQL 使用私有 Docker 网络。
  • 现有 P2P 服务可独立继续使用 UDP 7001,互不影响。
  • 不允许用户请求决定任意磁盘路径、Git 仓库地址、Git 参数或 shell 命令。
  • Astro 若需上传后立即生效,使用按需 SSR 读取受控的内容快照;不要依赖仅构建时扫描的静态内容集合。若改用纯静态生成,则明确采用“提交后重新构建并原子部署”的发布策略。MVP 选择 SSR + 已发布内容快照。

4. 内容模型与存储布局

chublog/
├── apps/
│   ├── web/                    # Astro 站点
│   └── api/                    # Axum 后台与只读 API
├── crates/
│   └── chusql-rs/              # 若尚无独立仓库,可先工作区开发再拆分
├── content/                    # 独立 Git 仓库或子目录(受控工作树)
│   ├── posts/
│   │   └── haskell-monad/
│   │       ├── index.md
│   │       └── cover.webp
│   └── .gitignore
├── deploy/
│   ├── compose.yaml
│   └── Caddyfile
└── PLAN.md

文章 Frontmatter 规范示例:

---
title: "Haskell Monad 入门"
slug: "haskell-monad"
date: "2026-10-15"
updated: "2026-10-15"
status: "published"
tags: ["Haskell", "Functional Programming"]
description: "Monad 的基础概念"
---

# Haskell Monad 入门

正文……
  • slug 是唯一的 URL 标识,仅允许小写英文字母、数字、短横线,校验长度和保留名称。
  • 文件路径由服务端基于已校验 slug 固定计算;禁止 ../、绝对路径、符号链接和路径穿越。
  • status 取 draft | published;草稿不可被未授权访问或从公开索引枚举。
  • 图片仅允许必要类型(如 PNG/JPEG/WebP),按真实文件内容与尺寸校验,限制单文件和文章总大小。SVG 暂不开放后台上传。
  • 内容文件和 Frontmatter 是权威信息;ChuSQL 中的记录可由全量扫描重新建立。

5. Git 内容管理工作流

5.1 后台上传与发布

  1. 管理员登录,上传 .md 与附属图片;后端检查会话、CSRF 与限流。
  2. 在隔离的暂存目录校验文件、解析 Frontmatter、检查重复 slug、限制大小和 Markdown 语法范围。
  3. 展示预览;管理员明确点击“发布”。预览默认不公开。
  4. 服务端通过受控文件操作写入仓库指定目录,创建 Git commit(提交者为固定服务身份,日志可附管理员操作 ID)。
  5. 提交成功后生成/切换已发布内容快照,并更新 ChuSQL 索引;公开页面仅读取已发布快照。
  6. 若索引更新失败,保留 Git 提交和待同步状态,由可重复执行的扫描任务恢复,不得静默显示“全部成功”。

5.2 本地 Git 编写

  • 管理员可以在本地仓库编辑 Markdown,向受保护的主分支推送,或通过 PR 合并。
  • 推荐在 CI 检查 Frontmatter、路径、大小、图片、链接及危险内容;只有已认证维护者可合并。
  • 服务器采用只读拉取/受控部署,不接受互联网匿名推送;可使用带最小权限的部署凭证。
  • 双入口写入存在冲突风险:MVP 应只开放一个写入主入口。建议首先采用“后台上传写入本地 Git 仓库”,后续引入远端同步时再明确由 CI 部署作为唯一发布入口;或者反过来完全让后台创建 PR。禁止两个入口不加协调地向同一工作树写入。

5.3 更新、撤回、删除

  • 更新是新的 Git commit;保留文章稳定 slug,必要时配置显式重定向。
  • 撤回把 status 改为 draft,新快照不可公开访问。
  • 删除从当前版本移除,但 Git 历史可能仍含内容;对于秘密泄露需要额外执行历史清理与凭证轮换,不能认为删除 commit 就彻底清除。
  • 上传的草稿与私有资源必须与公开静态目录隔离,避免直链泄露。

6. 身份认证与抗垃圾页面

MVP 采用单管理员、无公开注册、无公开投稿。 未登录者没有任何创建、编辑、上传或 Git 写权限。这比单纯依靠验证码或限流更能从根源上避免垃圾页面泛滥。

安全控制:

  1. 管理员账户配置在受保护的服务端环境或安全存储中;口令以 Argon2id 等成熟密码哈希存储,绝不保留明文。
  2. 登录成功后发放服务端会话;Cookie 使用 HttpOnly、Secure、SameSite,设置到期时间和退出失效机制。生产建议支持 TOTP 2FA 或使用成熟身份代理实现 MFA。
  3. 所有状态变更接口强制验证身份与 CSRF(包括上传、提交、发布和删除);校验 Origin,设置合理 CORS 策略。
  4. 登录端点按 IP 与账户维度限流、失败退避和审计;上传限制文件大小、数量、总磁盘配额、请求频率、并发和执行耗时。
  5. 反向代理和 API 分层限制请求体大小;服务仅接受预期 MIME 与文件结构;禁止 HTML/脚本执行、可疑链接协议与不受控资源嵌入。
  6. Git 命令通过固定参数的进程 API 执行,不用拼接 shell 字符串;Git 工作树不允许访问任意仓库 hook,服务运行身份权限最小化。
  7. 公开内容启用合理 CSP、HTML 清理、链接安全属性;后台不暴露到不必要的外部域名。
  8. 采用日志审计:谁在什么时候上传、预览、发布、撤回、删除,以及对应 commit hash;不要记录口令或会话令牌。

若以后支持访客投稿:所有投稿必须进入待审核区,经管理员人工批准后才能进入正式 Git 分支;不得让访客直接触发公开发布。

7. API 草案

方法 路径 权限 说明
POST /api/admin/login 公共、限流 管理员登录
POST /api/admin/logout 管理员 + CSRF 注销会话
GET /api/posts 公共 查询已发布文章元数据
GET /api/posts/:slug 公共 已发布文章信息(或由 Astro 直接读取文件)
POST /api/admin/uploads 管理员 + CSRF 上传临时文件、验证
POST /api/admin/posts/preview 管理员 + CSRF 安全预览
POST /api/admin/posts/publish 管理员 + CSRF 固定目录落盘并 Git 提交
PATCH /api/admin/posts/:slug 管理员 + CSRF 更新元数据/内容
POST /api/admin/posts/:slug/unpublish 管理员 + CSRF 撤回文章
DELETE /api/admin/posts/:slug 管理员 + CSRF 删除当前版本
POST /api/admin/index/rebuild 管理员 + CSRF 从 Git 内容重建 ChuSQL 索引

API 路由仅为计划,后续以实现的最小接口为准;对发布、更新、删除操作加互斥与幂等处理,防止并发提交损坏仓库状态。

8. ChuSQL 集成与一致性

MVP 仅需要 posts 元数据与 tags,字段例如 slug, title, description, status, published_at, updated_at, path, git_commit。字段类型、DDL、过滤和分页查询应按现有 ChuSQL 协议确定,不能预设兼容 PostgreSQL 或 SQLx。

  • chusql-rs 第一版支持:连接、超时、查询/执行、结果与类型映射、错误处理、断线识别、集成测试。
  • 不依赖目前未实现或未经验证的 ChuSQL 多语句事务;应用端以 Git 快照为权威,数据库仅做派生索引。
  • 每次发布记录 Git commit hash,索引带对应内容版本号。建立独立的 rebuild-index 命令与定期一致性检查。
  • ChuSQL 不可用时,已生成的公开内容快照仍能被读取;列表、标签等可从文件快照构建简易只读索引。禁止在数据库错误时覆盖或删除文章文件。
  • 上传发布时采用严格顺序和可恢复状态:校验 → 暂存 → Git commit → 更新已发布快照 → 尝试索引同步;出错后可依据 commit 重新同步。
  • 文章页面不要因 ChuSQL 宕机而泄露内部错误或凭证。

9. 实施阶段与验收

Phase 0 — 先验证接口

  • 检查 ChuSQL 服务端网络协议、查询语法和持久化行为。
  • 决定 Astro SSR 在容器内读取哪个受控内容目录。
  • 确定 Git 仓库部署路径、最小权限和快照切换方式。

Phase 1 — 纯文件博客 MVP

  • Astro 页面:首页、文章详情、标签、归档、404、暗色模式。
  • Markdown + Frontmatter 校验、Shiki 代码高亮、文章目录。
  • Astro SSR 读取已发布内容快照;提供 RSS、sitemap 和 SEO 元信息。
  • 测试异常文件、超大文件和 XSS 内容不会被执行。

Phase 2 — 后台 + Git 发布

  • 单管理员认证、会话与 CSRF。
  • 上传、预览、发布、编辑、撤回、删除。
  • 每次发布产生可追踪的 Git commit;冲突与重复提交有明确错误反馈。
  • 通过限流、文件配额、路径校验和无公开注册测试。

Phase 3 — ChuSQL 驱动与索引

  • 开发 chusql-rs 最小客户端及协议测试。
  • 建立文章元数据表、查询接口与索引同步。
  • 完成从 Git 仓库重建索引的命令与故障注入测试。
  • 验证 ChuSQL 故障期间公开阅读不中断、恢复后索引一致。

Phase 4 — 部署与运维

  • Docker Compose、Caddy TLS、仅开放必要公网端口。
  • 持久化 Git 内容与资源;数据库卷、日志独立管理。
  • 备份 Git 仓库(含远端镜像)与上传资源;定期进行真实恢复演练。
  • 监测磁盘、接口错误、登录失败、索引同步延迟。
  • 更新依赖、最小容器权限、限制容器挂载与网络访问。

MVP 完成判定:未经认证无法写入或发布;管理员可上传并发布一篇 Markdown,页面即刻可读,Git 中有对应提交;重启容器后内容存在;故意停止 ChuSQL 后仍可浏览已发布文章;重新建立数据库后可重建索引;恶意路径、超大文件和脚本注入测试均不能成功。

10. 生产就绪与风险边界

  • 文章内容生产可用性来自 Git、可恢复的文件快照、访问控制、备份及恢复演练,不取决于 ChuSQL 当前成熟度。
  • ChuSQL 仍按实验性组件管理:在事务原子性、并发控制、进程崩溃恢复、备份/恢复、认证与长时间稳定性未经验证前,不作为任何不可重建数据的唯一存储。
  • 文件与数据库之间不追求假想的跨系统原子事务,而采用幂等同步和可回放 Git 提交恢复一致性。
  • 不把管理员凭证、Git 写入凭证或 ChuSQL 密码写入 Git 仓库、镜像层和日志。

11. 暂不纳入 MVP

  • 访客注册、公开投稿、评论、点赞与复杂权限角色。
  • 前端在线富文本编辑器、协同编辑和复杂草稿工作流。
  • 全文搜索引擎、消息队列、分布式部署、对象存储、多租户。
  • 自建 Markdown 解释器、通用插件机制和 ChuSQL ORM/SQLx 适配。

12. 近期第一步

优先确认 ChuSQL 现有协议,同时创建 Astro 静态界面与 Axum 认证/上传原型。先跑通管理员上传 → 校验 → Git 提交 → 公开页面读取文件,之后再接入 ChuSQL 元数据索引。这样即使数据库研发推迟,博客仍可独立推进。