Files
pure-note/README.md
T
wangairnan ad4a87fc9f
Release / release (push) Failing after 8s
feat(ci): 基于 v* 标签的多架构自动发版
- 新增 .gitea/workflows/release.yml:推送 v* 标签触发,构建前端嵌入后
  交叉编译 linux/darwin(amd64+arm64),生成变更日志并创建 Gitea Release
- 新增 scripts/build-release.sh:make dist 与 CI 共用的产物构建脚本,
  tar.gz 打包 + SHA256SUMS;不含 windows(internal/store 依赖 Unix Umask)
- Makefile 增加 dist 目标;版本注入沿用 git describe + ldflags(pn version)
2026-09-09 22:46:12 +08:00

120 lines
6.1 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.
# Pure Note
极简高安全私人笔记 + 博客。最终交付 = **一个二进制程序 + 一个数据文件(目录)**:
无数据库服务、无缓存服务、无 Node 运行时、无外部依赖。
> 设计文档:[docs/design.md](docs/design.md)(v1.1);实施决策记录:[docs/decisions.md](docs/decisions.md);提交规范:[docs/contributing.md](docs/contributing.md)
## 功能
- **笔记**:Markdown CRUD、粘贴/拖拽图片上传(≤5MB、魔数校验、BLOB 入库去重)、公开/私有两态、置顶、标签、发布日期可自选
- **博客**:首页(置顶优先 + 分页 + 标签云)、详情(上一篇/下一篇)、标签页、RSS、sitemap、SEO meta 注入(仅公开内容);站点名称前可显示自定义 Logo
- **管理**:单管理员口令登录(Argon2id)、会话 7 天滑动续期(CSRF 轮换保持不变)、防爆破限流(per-IP + per-账号)、改密
- **回收站**:删除 = 软删除,30 天内可恢复,可一键清空,`gc` 到期物理清除
- **界面**:9 页面响应式 SPA(React 19 + Tailwind 4 + Ant Design 6),深色/浅色/跟随系统三态主题
- **运维**:`init`(含 Markdown 示例文档与示例图片种子)/ `passwd`(重设口令并吊销全部会话)/ `start` / `backup`(在线一致快照)/ `gc`(默认 dry-run)/ `version`(亦可 `-v`)
## 快速开始
```bash
# 1. 构建单二进制(前端 + 后端)
make build
# 2. 初始化(设置管理员口令与站点标题,自动写入一篇 Markdown 示例文档)
./pn init
# 非交互:PN_ADMIN_PASSWORD=xxx PN_SITE_TITLE=yyy ./pn init
# 3. 启动
./pn start --addr 127.0.0.1:8080
# 4. 访问
# 博客: http://127.0.0.1:8080/
# 管理后台:http://127.0.0.1:8080/admin
```
开发模式(本机调试,Cookie 允许非 Secure,仅限 loopback 监听):
```bash
./pn start --dev --addr 127.0.0.1:8080
# 前端热重载(另开终端):
cd web && npm install && npm run dev # /api 代理到 127.0.0.1:8080
```
> **为什么必须带 `--dev`**:明文 HTTP 下 Safari/WebKit 不保存 `Secure` Cookie(Chrome/Firefox 有 localhost 豁免,Safari 没有),不带 `--dev` 时 `__Host-` 会话被静默丢弃,Safari 登录成功后仍会被弹回登录页。`--dev` 改用无 `Secure` 的 `pn_session` Cookie 并强制仅监听 loopback(§7.3-3);生产走 HTTPS 不带 `--dev`,自动恢复 `__Host-` + `Secure` 完整加固。
忘记口令(CLI 可达即具备服务器权限,可直接重设;重设后全部会话被吊销):
```bash
./pn passwd
# 非交互:PN_ADMIN_PASSWORD=xxx ./pn passwd
```
## 测试
```bash
make test # go vet + go test ./... + 前端 vitest
make smoke # 构建冒烟:起服务 → SPA 资源 200/MIME → meta 注入 → 可见性抽查
```
测试矩阵覆盖(§13):可见性矩阵(匿名 × 管理员 × {公开, 私有, 回收站, 不存在} × 全部出口)、
迁移与 user_version 守卫、登录限流 429、CSRF、上传魔数/去重、回收站生命周期、gc 宽限期、
slug 冲突策略、设置白名单(永不泄露口令哈希)、meta 注入转义。
## 部署(生产)
```bash
make linux # 产出 pn-linux-amd64
sudo cp pn-linux-amd64 /opt/pure-note/pn
sudo -u purenote ./pn init --data-dir /opt/pure-note/data
sudo cp deploy/pn.service deploy/pn-maint.{service,timer} /etc/systemd/system/
sudo systemctl enable --now pn pn-maint.timer
```
反向代理用 Caddy(自动 TLS),示例见 [deploy/Caddyfile](deploy/Caddyfile);
启动需带 `--behind-proxy`(取 X-Forwarded-For 最右条目)。
**升级 SOP**:`pn backup` → 停服 → 换二进制 → 起服(迁移自动执行;
库版本高于代码支持范围时拒绝启动,`--allow-newer` 显式放行)。
**恢复 SOP**:停服 → 删除 `data/pn.db-wal` 与 `-shm` → 以备份文件替换 `pn.db` → 起服。
## 版本与发版
版本号以 git tag 为唯一来源(语义化版本,从 `v0.0.1` 开始),构建时经 ldflags 注入,
`./pn version` 可查看:
```bash
git tag -a v0.0.1 -m "v0.0.1"
git push origin v0.0.1 # 推送 v* 标签即触发自动发版
```
推送 `v*` 标签后,Gitea Actions([.gitea/workflows/release.yml](.gitea/workflows/release.yml))
自动构建前端并嵌入,交叉编译 linux/darwin(amd64 + arm64)共 4 个产物,
连同 SHA256SUMS 与上一版本以来的变更日志一起发布到仓库的 Release 页面。
本地验证发布产物:`make dist`(版本缺省 `git describe --tags --always`,输出到 `dist/`)。
## 架构
```
cmd/pn/ CLI(start/init/passwd/backup/gc/version)
internal/config/ 命令行解析(--dev loopback 守卫)
internal/store/ SQLite(modernc 纯 Go 驱动):迁移(user_version) + DAO + 备份 + gc
internal/auth/ Argon2id(PHC) + 随机 token
internal/markdown/ goldmark + bluemonday(RSS/meta 服务端渲染)
internal/middleware/ 安全头 / 日志 / 限流 / Origin 校验 / MaxBytes
internal/httpapi/ 路由与 handler(公共 / 认证 / 管理 / feed)
internal/webui/ go:embed 前端产物 + SPA fallback + index.html meta 注入
web/ React 19 + Vite + Tailwind 4 前端
├─ src/pages/ 9 页面:首页 / 笔记详情 / 标签页 / 登录 / 后台列表 / 编辑 / 回收站 / 设置 / 404
├─ src/components/ Layout(导航与主题切换)、Editor、MarkdownViewer
├─ src/theme/ shadcnTheme(antd ConfigProvider 主题:品牌 token + 明暗算法 + 桥接样式)
├─ src/hooks/ use-toast(基于 antd notification 的操作反馈)
└─ src/lib/ api(CSRF 注入)/ auth(会话上下文)/ theme(三态主题)/ sanitize / invalidate
deploy/ systemd 单元 ×3 + Caddyfile
```
安全要点(详见设计 §9):CSP `script-src 'self'`、CSRF 双保险(token + Origin 校验)、
`__Host-` Cookie、服务端统一可见性过滤(单一可信点)、图片并集可见性、
上传魔数校验拒绝 SVG、统一 404 防枚举、安全响应头全家桶。