# cfw-attachment 独立 Cloudflare 附件管理服务。认证通过 `AUTH` service binding 调用 `cfw-auth`,附件业务数据保存在本服务自己的 D1/R2。 附件表(元数据、分类、标签、业务关联、审计)全部归属当前登录用户:所有 D1 查询都带 `user_id` 条件,R2 object key 也按 `users/{userId}/...` 隔离。 ## 架构边界 - `cfw-auth`:只负责登录鉴权,本服务不修改它。 - `cfw-attachment`:独立 Worker,绑定自己的 D1(`DB`)/ R2(`ATTACHMENTS`),通过 `AUTH` service binding 调 `cfw-auth` 的 `/api/auth/get-session` 获取当前用户。 - `cfw-gateway`:只把 `/api/attachments*`、`/api/attachment-categories*`、`/api/attachment-tags*` 代理到本服务,并把本服务 OpenAPI 纳入聚合。 ## 本地检查 ```bash pnpm install pnpm db:apply:local pnpm ready ``` `pnpm ready` 会跑 `typecheck` 和 `test`。测试用内存 fake D1(`node:sqlite` 跑真实 SQL)和内存 fake R2,不需要 Cloudflare 连接。 ## 关键接口 附件: - `POST /api/attachments`:创建附件元数据,返回 `upload_pending` - `PUT /api/attachments/:id/content`:经 Worker 代理上传文件内容到 R2 - `POST /api/attachments/:id/finalize`:确认上传,状态变为 `available` - `GET /api/attachments/:id`:读取详情 - `PATCH /api/attachments/:id`:更新 filename / visibility / description / categoryId / tagIds - `DELETE /api/attachments/:id`:软删除,并尽力删 R2 object - `GET /api/attachments/:id/download`:仅 `available` 可下载,否则 `409 object-not-available` - `GET /api/attachments/search?page=1&pageSize=20&q=&categoryId=&tag=&status=`:分页检索当前用户附件 分类与标签: - `POST /api/attachment-categories`、`GET /api/attachment-categories`、`PATCH /api/attachment-categories/:id`、`DELETE /api/attachment-categories/:id` - `POST /api/attachment-tags`、`GET /api/attachment-tags`、`PATCH /api/attachment-tags/:id`、`DELETE /api/attachment-tags/:id` 分类/标签以 `user_id + slug` 唯一。删除分类会把当前用户下引用它的附件 `category_id` 置空;删除标签会先删当前用户下的标签关联再删标签。 ## 部署 ```bash pnpm db:apply:remote # 远端 D1 应用 schema pnpm deploy # 部署 Worker(含 AUTH service binding 到 cfw-auth) ```