From 8d62d07a1326c25c5435176f4ff824f21fd2636b Mon Sep 17 00:00:00 2001 From: eezd Date: Sun, 25 Oct 2026 20:47:55 +0800 Subject: [PATCH] docs: align project guidance with the modular application --- .agents/skills/v3-create-crud/SKILL.md | 6 +++ .agents/skills/v3-upsert-route/SKILL.md | 6 +++ .agents/skills/v3-upsert-store/SKILL.md | 6 +++ .agents/skills/v3-use-composables/SKILL.md | 6 +++ .agents/skills/v3-use-utils/SKILL.md | 6 +++ .cursor/rules/project.mdc | 5 +++ .gitignore | 4 ++ .trae/rules/project.md | 5 +++ AGENTS.md | 45 +++++++++++++++++++++- CLAUDE.md | 1 + README.md | 32 ++++++++++++--- 11 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 .agents/skills/v3-create-crud/SKILL.md create mode 100644 .agents/skills/v3-upsert-route/SKILL.md create mode 100644 .agents/skills/v3-upsert-store/SKILL.md create mode 100644 .agents/skills/v3-use-composables/SKILL.md create mode 100644 .agents/skills/v3-use-utils/SKILL.md create mode 100644 .cursor/rules/project.mdc create mode 100644 .trae/rules/project.md create mode 100644 CLAUDE.md diff --git a/.agents/skills/v3-create-crud/SKILL.md b/.agents/skills/v3-create-crud/SKILL.md new file mode 100644 index 0000000..a9c6a29 --- /dev/null +++ b/.agents/skills/v3-create-crud/SKILL.md @@ -0,0 +1,6 @@ +--- +name: v3-create-crud +description: 调整业务页面与表单 +--- + +先读根 AGENTS.md,核对后端路由和现有业务调用链。页面放 `web/src/pages//`,私有 API/类型跟随模块;真正跨模块共享才放 common。复用实际 Element Plus 控件和 `http/axios` 的 requestJSON/requestRaw,不预设分页、CRUD、导出或角色能力。失败保留原因,成功后再关闭/刷新,取消确认不得伪装成实际操作成功。按行为测试成功、失败与权限边界。 diff --git a/.agents/skills/v3-upsert-route/SKILL.md b/.agents/skills/v3-upsert-route/SKILL.md new file mode 100644 index 0000000..7a66e56 --- /dev/null +++ b/.agents/skills/v3-upsert-route/SKILL.md @@ -0,0 +1,6 @@ +--- +name: v3-upsert-route +description: 调整登录守卫与权限路由 +--- + +先读根 AGENTS.md、`web/src/router/` 和 `pinia/stores/{user,permission}.ts`。常驻与动态路由按现有实现登记,匿名路由使用 meta.anonymous,真实权限来自 /auth/me,无角色系统。唯一名称、懒加载;核对匿名/初始化/回跳、深链、403、401、注销及换会话,旧结果不能注册新会话路由。 diff --git a/.agents/skills/v3-upsert-store/SKILL.md b/.agents/skills/v3-upsert-store/SKILL.md new file mode 100644 index 0000000..39c1c95 --- /dev/null +++ b/.agents/skills/v3-upsert-store/SKILL.md @@ -0,0 +1,6 @@ +--- +name: v3-upsert-store +description: 调整 Pinia 共享状态 +--- + +先读根 AGENTS.md 和现有 store。跨页面共享状态放 `web/src/pinia/stores/`,使用 Setup Store;页面表单和工作区临时状态留在模块。setup 外显式传入 pinia,不增加转发函数或重复镜像。认证变更通过 user store 更新会话代号,持久化仅保留已有明确需求。验证旧请求隔离与状态重置。 diff --git a/.agents/skills/v3-use-composables/SKILL.md b/.agents/skills/v3-use-composables/SKILL.md new file mode 100644 index 0000000..e4f0ce3 --- /dev/null +++ b/.agents/skills/v3-use-composables/SKILL.md @@ -0,0 +1,6 @@ +--- +name: v3-use-composables +description: 提取或复用业务组合函数 +--- + +先读根 AGENTS.md 及实际调用方。当前项目没有模板分页、全屏加载等示例组合函数,不凭模板声明调用不存在的能力。页面私有组合函数跟随模块;仅为实际跨模块复用提取 common,不为单次代码建立新层。异步失败明确拒绝,同一错误由负责层展示。 diff --git a/.agents/skills/v3-use-utils/SKILL.md b/.agents/skills/v3-use-utils/SKILL.md new file mode 100644 index 0000000..c84f3db --- /dev/null +++ b/.agents/skills/v3-use-utils/SKILL.md @@ -0,0 +1,6 @@ +--- +name: v3-use-utils +description: 复用公共工具与认证能力 +--- + +先读根 AGENTS.md 和 `web/src/common/utils/` 的实际实现。命令、路径、通知、PWA 等按已有签名复用;认证 Token 由 user store 维护,不绕过会话与动态路由清理。没有模板示例的角色/日期工具,不引入虚构依赖。页面专用转换留在页面模块,未知外部输入在边界校验。 diff --git a/.cursor/rules/project.mdc b/.cursor/rules/project.mdc new file mode 100644 index 0000000..8b28884 --- /dev/null +++ b/.cursor/rules/project.mdc @@ -0,0 +1,5 @@ +--- +alwaysApply: true +--- + +先完整阅读仓库根目录 `AGENTS.md` 与适用的局部指引;目录职责、认证协议、验证及授权均以该文件为准,不维护另一套规则。前端路径均从 `web/` 开始。 diff --git a/.gitignore b/.gitignore index aa30730..46896b2 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,7 @@ web/dist/ # 本地开发数据 .dev-data/ deploy/data/ + +# 仓库维护的工具规则(其他本地技能不入库) +.agents/skills/* +!.agents/skills/v3-*/ diff --git a/.trae/rules/project.md b/.trae/rules/project.md new file mode 100644 index 0000000..8b28884 --- /dev/null +++ b/.trae/rules/project.md @@ -0,0 +1,5 @@ +--- +alwaysApply: true +--- + +先完整阅读仓库根目录 `AGENTS.md` 与适用的局部指引;目录职责、认证协议、验证及授权均以该文件为准,不维护另一套规则。前端路径均从 `web/` 开始。 diff --git a/AGENTS.md b/AGENTS.md index 43e5760..b7c9322 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -70,4 +70,47 @@ - 文档按任务、行为变化或项目约定维护;注释解释意图与约束,项目指引只记录已确认的事实,不额外生成无关文档或备份。 - 仅在已授权执行且交接信息无法从代码、Git 历史或已有文档恢复时,创建或更新 `CONTEXT.md`;简单修改无需记录。 - 交接内容原位更新,保留有效目标、决策及理由、未完成事项和风险,标注未验证信息,删除过时状态;当前状态不超过 100 行,全文不超过 500 行。 -- 保留 `CONTEXT.md` 原有跟踪策略:本地专用文件继续忽略,不擅自停止跟踪已纳入版本控制的文件。 \ No newline at end of file +- 保留 `CONTEXT.md` 原有跟踪策略:本地专用文件继续忽略,不擅自停止跟踪已纳入版本控制的文件。 + +## 项目定位与工具链 + +RawMark 是单用户 Markdown 网页笔记编辑器。文件是真源;Go 标准库 HTTP、SQLite 与文件系统负责服务端,CodeMirror 6 保留原文与 Live Preview,highlight.js 使用固定 Atom One Dark。保留现有明暗主题、排版、插件、图片与备份能力,不引入模板后台示例或虚构角色。 +前端采用 Vue 3.5、Router 5、Pinia 3、Element Plus、Axios、TypeScript 6、Vite 8、SCSS、UnoCSS,使用 pnpm 12.11.2;依赖以锁文件为准,不顺手升级。 + +## 目录与依赖边界 + +- `web/src/pages//`:页面入口及模块私有的组件、API、类型、业务状态、编辑器和资源;按实际需要建子目录,不建空目录或转发层。 +- `web/src/common/`:确实跨模块复用的 API、外观与字体、Markdown、高亮、插件 SDK、组件和工具。不得依赖页面私有代码;模块入口可提供明确的 props/emits 契约供应用装配。 +- `web/src/http/`:Axios、认证头、统一响应与请求错误;`router/`:路由与守卫;`pinia/`:实例及共享认证、权限、设置状态。工作区临时状态不强制放入全局 store。 +- `web/types/auto/`:由 Vite 自动导入插件生成;修改源配置并重新构建,不手改声明。业务类型就近定义,测试随模块存放。 +- `internal/api/` 定义路由、授权和 HTTP 契约,`internal/auth/` 管理密码与凭据,`internal/store/` 管理应用 SQLite;`internal/vault/` 管理真源文件,搜索索引可重建。`web/*.go` 保留生产嵌入与开发模式边界。 +- 模块内部优先相对导入,跨职责使用 `@`(`web/src`)和 `@@`(`web/src/common`)。Vue 组件使用 PascalCase,其他文件使用 kebab-case;SFC 使用 Composition API 与 TypeScript。既有编辑器主题、全局 CSS 和专用 DOM 控件按业务保留,普通表单优先 Element Plus。 +- 外部未知数据使用 unknown,在实际边界验证;不以 any、类型忽略或假数据掩盖契约。沿用 ESLint/Antfu,不增加另一套格式化工具。 + +## 认证与接口契约 + +- 登录是密码加后端六位图片验证码,首次初始化设置密码;无用户名、注册或角色系统。验证码有效五分钟,绑定挑战及来源,每次登录提交一次性消费,失败必须刷新;保留签发和登录限流。 +- 浏览器会话 Token 为 `rms_`,保存在 localStorage `rawmark.token`,固定三十天,不滑动续期;服务端只存哈希。退出请求撤销服务端会话,成功才清理本地身份,不以只删本地 Token 代替注销。 +- 受保护 API 只接受 `Authorization: Bearer `,不保留 Cookie 兜底。既有 `rm_` API 令牌及 read/write 权限保留;管理接口仅会话可用,只读令牌允许只读 POST 导出,不能给自己扩权。 +- 身份与权限来自 `/auth/me`。401 清理当前认证、权限和动态路由,403 保留身份;匿名跳登录、初始化与登录回跳由守卫负责,拒绝外部及循环回跳。 +- 每次替换或退出会话更新代号并取消旧请求;异步响应、用户信息、路由安装和排队写入必须核对所属会话。旧结果按 Axios 取消语义拒绝,不提示、不覆盖或注销新会话。 +- 普通 JSON 为 `{ code, data, message }`,成功 code=0;错误 code 非零、message 为可展示原因,保留 HTTP 状态。文件、下载、事件、204 与 OpenAPI 文档保持各自原语义,不叠 JSON。412 的当前版本在 data.rev,当前密码错误为 400,不清理身份。 +- 同一错误由一个责任层展示。请求默认提示;已有行内状态、保存重试或批量汇总的 API 明确使用 errorOwner=caller。失败仍 reject,不以空列表或默认值伪装成功。 +- 原生图片、字体与插件模块通过受限资源票据读取,主 Token 不进入 URL。票据持久保存哈希、每次检查父会话;事件握手票据一分钟且一次性消费,已连接事件继续核对父凭据。插件票据绑定 ID/版本并支持相对导入;API 与私有资源不进入 PWA 静态缓存。 + +## 命令与验证 + +```bash +pnpm -C web install --frozen-lockfile +scripts/dev.sh # 隔离开发数据默认 .dev-data,API_PORT/WEB_PORT 控制端口 +pnpm -C web lint:check +pnpm -C web typecheck +pnpm -C web test +pnpm -C web build +/usr/local/go/bin/go vet -tags dev ./... +/usr/local/go/bin/go test ./internal/... +/usr/local/go/bin/go test -tags dev ./web +``` + +按实际风险补充 Go race、Docker 构建和隔离浏览器验证。只用合成数据测试初始化、导入、恢复与删除,不对生产数据执行迁移或维护;生产部署、重启、数据库迁移执行及 commit/push 均需另行明确授权。 +本文件为规范唯一来源,`CLAUDE.md`、`.cursor/rules/`、`.trae/rules/` 仅指回本文件;`.agents/skills/v3-*` 仅提供对应任务的操作入口,不复制第二套规则。 diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..43c994c --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/README.md b/README.md index 8f123a9..ca85ab7 100644 --- a/README.md +++ b/README.md @@ -32,14 +32,14 @@ docker run -d --name rawmark \ rawmark ``` -- 首次打开直接设置登录密码,之后凭密码登录;请在将新实例开放给他人访问前完成初始化。 +- 首次打开直接设置登录密码,之后凭密码与图片验证码登录;请在将新实例开放给他人访问前完成初始化。 - 笔记以普通 `.md` 文件保存在 `数据目录/vault/`,粘贴、上传和导入的图片统一存放在笔记同级的 `assets/`,链接使用 `./assets/文件名`,同目录相同内容去重。笔记跨目录移动时图片跟随,仍被其他笔记引用的原图保留;删除单篇笔记不会删除共享图片。旧 `笔记名.assets/` 仍可读取、移动与恢复;外部修改会实时同步到网页。 - 知识工具:标准 Markdown 链接构成图谱,支持正文 `#标签` 与 YAML `tags`。笔记或文件夹在应用内改名、移动时维护入链和相对出链;公式和代码示例不参与关系提取。 - 外观:浅色玻璃工作台与深色模式,默认字体为 Maple Mono Normal NL NF CN v7.9(界面、正文与代码),字体资源随应用本地提供,文字在所需字体加载完成后显示,加载失败会提示刷新;代码块使用 highlight.js,固定采用官网的 Atom One Dark 配色,与页面明暗模式独立;界面、正文与代码字体可分别选择,各字体下拉均支持导入 TTF/OTF/WOFF/WOFF2(单个不超过30 MB)及删除;Maple为不可删除的默认字体,删除正在使用的字体会恢复Maple,导入字体保存在服务器数据目录的fonts/并跨设备共用。界面字号默认 14px,可输入 14–20px 并单独重置,与编辑器及阅读字号独立;排版、玻璃透明度、选中文本工具栏均可在设置中调整并即时保存。 - 选区格式:电脑与触屏选中文字后提供外观、加粗、斜体、下划线、删除线、高亮和链接。外观可设置配色、字体、局部字号与效果;下划线及外观以受限的标准 HTML 行内标签保存在 Markdown 中,源码与导出保留标签,其他软件的显示取决于其 HTML 支持。清除样式只重置局部外观;底部不再显示格式栏。 - 图片管理:侧栏默认隐藏 `assets` 和 `笔记名.assets`;右键文件夹选择「图片管理」,查看当前目录及直属附件目录的图片,支持检索、排序、网格/列表、批量上传、引用查看及预览、重命名、移动、替换。可切换整个知识库;清理孤立图片须确认候选,服务端再次核对全库引用后移入回收站,可恢复。上传至所选目录的 `assets/`,相同内容自动去重。根目录可在侧栏空白处右键或通过命令面板打开。图片改名/移动会更新笔记中的本地引用;替换保留路径,选择相同扩展名的图片(最大 50 MB),旧图片不进回收站。 - `--user` 让容器以宿主机用户身份读写数据目录;不指定时容器以 UID 65532 运行,需要该用户对目录有写权限。 -- 请通过 HTTPS 反向代理(Caddy、Nginx 等)访问,并转发 WebSocket(`/api/v1/events`)。 +- 请通过 HTTPS 反向代理(Caddy、Nginx 等)访问,并转发 WebSocket(浏览器使用 `/api/v1/resources//events/`,脚本可使用 Bearer 连接 `/api/v1/events`)。 - 多选与导出:Ctrl/Cmd 点击切换选择,Shift 点击选择可见范围;右键批量删除、移动或导出 Markdown。单篇无附件直接下载 `.md`,其他情况下载包含 Markdown 与本地附件的 ZIP;重名目标不会被覆盖,批量操作会汇报单项失败。 - 设置:桌面使用居中窗口,手机使用分类与内容两级布局;支持搜索设置并定位、常用排版项单独重置,自动保存状态与失败提示可见。外观与编辑器分别管理,安装入口位于「关于」。 - 回收站与存储:回收站支持清空全部;默认按原删除时间保留 30 天,0 表示永不自动删除,服务启动及每小时执行清理,修改期限同样影响已有条目。设置「存储空间」进入即统计数据目录、外置笔记库及内置可选字体(不含默认 Maple),支持刷新和字体明细;不跟随内部符号链接,附件与回收站包含在笔记库总量中。 @@ -61,7 +61,7 @@ docker run -d --name rawmark \ ## 开发 -需要 Go 1.27+ 与 Node 24+。开发时不必构建前端或 Docker 镜像,一键启动: +需要 Go 1.27+、Node 24+ 与 pnpm 12.11.2(可通过 Corepack 启用)。开发时不必构建前端或 Docker 镜像,一键启动: ```sh scripts/dev.sh # 后端 go run -tags dev + 前端 Vite 热更新,Ctrl+C 同时退出 @@ -74,8 +74,30 @@ scripts/dev.sh --host # 前端监听所有网卡,手机访问 http://<电脑 检查: ```sh -cd web && npm run typecheck && npm test -go vet -tags dev ./... && go test ./internal/... +pnpm -C web install --frozen-lockfile +pnpm -C web lint:check +pnpm -C web typecheck +pnpm -C web test +pnpm -C web build +go vet -tags dev ./... +go test ./internal/... +go test -tags dev ./web ``` 字体资源已入库,普通构建无需下载或转换。重新生成时,在独立 Python 环境安装 `fonttools[woff]`,下载 [v7.9 指定字体包](https://github.com/subframe7536/maple-font/releases/download/v7.9/MapleMonoNormalNL-NF-CN.zip),运行 `python3 scripts/prepare-maple-font.py /path/to/MapleMonoNormalNL-NF-CN.zip`;生成 WOFF2 与 `maple-font.css`,保留上游许可。 + +## 前端结构与接口升级 + +前端以 [vue3-starter](https://github.com/eezd/vue3-starter/tree/fd41d62ce3f1c8338a478e0be3e2f31b53b7ea5e) 为结构基线,保留 RawMark 的编辑器、主题与布局;模板许可在 `web/LICENSE`。`web/src/pages/workspace/` 管理笔记、目录、编辑器与图片,`pages/settings/` 管理设置及维护,`pages/login/` 管理初始化与验证码登录;私有 API 和类型跟随模块。实际共享的外观、Markdown、插件 SDK 与 API 位于 `common/`;请求、路由、共享状态分别由 `http/`、`router/`、`pinia/` 管理。唯一前端构建入口为 `web/`,使用 pnpm 锁文件。 + +本次协议升级需前后端一起发布,旧页面与旧 Cookie 会话不能继续使用,需要重新登录。升级前备份数据库和旧镜像;启动新程序时沿用现有 SQLite 初始化流程新增 `resource_tickets` 表及过期索引,保留笔记、设置、密码和 API 令牌。生产迁移与部署须另行授权,不手动运行历史清理 SQL。回滚使用配套数据库和旧镜像;新前端不能连接旧后端。 + +登录流程先 `POST /api/v1/auth/captcha`,取得 `{captchaId,imageDataUrl,expiresAt}`;刷新传 `replaceId` 使旧挑战失效。再提交 `POST /api/v1/auth/login` 的 `{password,captchaId,captchaCode}`,后端校验六位数字,挑战绑定来源、五分钟过期且一次性消费(密码或验证码失败也会消费)。保留登录防暴力破解与签发限流。首次 `POST /auth/setup` 直接设置密码,不需要已有登录挑战。 + +登录/初始化返回 `{token,expiresAt}`。浏览器将 `rms_` 会话 Token 保存于 localStorage `rawmark.token`,所有受保护请求带 `Authorization: Bearer `;服务端只存哈希、固定三十天有效,不滑动续期。`GET /auth/me` 返回真实权限及到期时间,`POST /auth/logout` 服务端撤销会话后返回 204;注销失败保留本地身份并明确报错。401 清除当前身份及动态路由,403 保留身份;旧请求或排队写入不能覆盖或注销新会话。localStorage 属于同源脚本可读的凭据,管理员安装的前端插件仍为全权限插件,不能承诺隔离。 + +普通 JSON 响应统一为 `{code,data,message}`,code=0 成功,message 表示成功或明确失败原因;错误保留 400/401/403/404/409/412/429/500 等 HTTP 状态。通用错误码为 HTTP 状态乘 100,40001 验证码错误/已使用、40002 验证码过期、40003 当前密码错误、40101 密码错误、41200 版本冲突;冲突版本位于 `data.rev`。文件原文、下载、WebSocket、204 和 OpenAPI 文档不包装。旧 JSON 客户端必须更新解包方式,不提供双格式兼容。 + +`rm_` API 令牌无需重新创建,read/write 权限不变;令牌不能管理账户、令牌、维护或资源票据。只读令牌仍可 POST 导出。第三方脚本只需保留 Bearer 请求头并按新 JSON 协议解包,文件/导出原始字节不变;WebSocket 客户端可继续以 Bearer 请求头连接 `/api/v1/events`。 + +浏览器原生图片、字体、插件相对模块导入及 WebSocket 无法统一设置认证头,使用 `POST /auth/tickets` 签发的受限资源 URL。图片/字体票据不超过父会话期限,插件另绑定 ID 和版本;每次读取都核对父会话,注销后立即不可读。事件握手票据一分钟有效、只能使用一次,已连接事件在发送与心跳时检查父凭据。主 Token 不放在 URL,不使用 Cookie 兜底;私有响应 no-store、Referrer-Policy=no-referrer,PWA 仅缓存静态外壳。部署代理也须避免记录票据 URL,仓库 Nginx 配置已提供脱敏日志格式;CDN/其他代理需按同样规则配置。