# OpenSpec 开发归档 ## 归档日期 - 2026-03-28 ## 归档范围 本次归档覆盖 PocketBase hooks 项目在附件统一存储、文档管理页增强、字典项图片、用户图片字段附件化、SDK 直连权限页、文档文件字段 `document_file`、大文件上传 body limit 修复、以及对应 OpenAPI / 表结构文档同步方面的工作,涉及: - 所有业务文件统一收敛到 `tbl_attachments` - 业务表只保存 `attachments_id`,并由 hooks 联表返回文件流链接 - `tbl_document` 新增 `document_file`,与 `document_image`、`document_video` 一样支持多附件和 `|` 分隔存储 - `manage/document-manage` 页面新增文件附件区、初始隐藏编辑区、保存后保持当前编辑态、局部状态提示、拖拽上传与全屏图片预览 - `manage/dictionary-manage` 页面支持字典枚举项图片上传和全屏查看原图 - `manage/sdk-permission-manage` 页面支持按角色配置 collection CRUD 直连权限,并优化为即时保存 - 上传路由显式放宽 PocketBase custom route `bodyLimit` - 使用 `POCKETBASE_AUTH_TOKEN` 在线补齐 `tbl_document.document_file` - 新增 OpenSpec 归档目录 `openspec/changes/archive/2026-03-28-pocketbase-manage-media-and-sdk-permissions/` --- ## 一、附件集中存储 ### 1. 附件表作为唯一文件存储点 - 仅 `tbl_attachments.attachments_link` 保留真实 `file` 字段 - 其他业务表不再保存实际文件 - 文档、字典、用户图片字段统一改为保存 `attachments_id` ### 2. 附件回读策略 hooks 查询时统一联查 `tbl_attachments`,并补充: - 文件流链接 - 下载链接 - 附件元数据对象 适用对象包括: - 文档图片 / 视频 / 文件 - 字典枚举项图片 - 用户头像 / 身份图 / 资质图 ### 3. 附件访问控制 - PocketBase 原生 `tbl_attachments` 已放开公开读取与下载 - hooks 层原有 `ManagePlatform` 限制保持不变 - 业务访问控制继续由保存附件 ID 的业务表承担 --- ## 二、文档管理增强 ### 1. `tbl_document` 新增 `document_file` - 新字段:`document_file` - 类型:`text` - 用途:保存多个文件类 `attachments_id` - 存储格式:`id1|id2|id3` ### 2. 文档管理页行为 - 首次进入页面时只显示列表,不显示编辑区 - 点击“新建模式”或“编辑”后才进入编辑区 - 保存成功后保持当前文档编辑态,不再强制清空回到新建 - 保存 / 报错信息同时显示在顶部与保存按钮下方 - 图片、视频、文件三块附件区都支持拖拽上传 ### 3. 上传链路修复 - 上传接口继续使用 `/pb/api/attachment/upload` - 为自定义路由显式增加更大的 `bodyLimit` - 解决了文件未超过数据库与网关限制但仍在 hooks 层被 413 拒绝的问题 --- ## 三、SDK 直连权限管理 ### 1. 管理页能力 - 新增 `/pb/manage/sdk-permission-manage` - 支持创建角色后按角色给 `tbl_auth_users` 用户授权 - 支持逐 collection 配置 `list / view / create / update / delete` ### 2. 页面交互约束 - 页面不显示角色 ID,只显示角色名称 - 勾选权限后立即保存 - `public` 和 `custom` 规则不允许在页面里继续勾选改写 - 支持集合级 `全选` - 当某集合下所有操作都不可编辑时,`全选` 自动禁用 --- ## 四、OpenSpec 记录 本次新增的 OpenSpec 记录包括: - `openspec/specs/attachment-backed-media/spec.md` - `openspec/specs/document-manage-console/spec.md` - `openspec/specs/sdk-collection-permissions/spec.md` - `openspec/changes/archive/2026-03-28-pocketbase-manage-media-and-sdk-permissions/` --- ## 归档日期 - 2026-03-23 ## 归档范围 本次归档覆盖 PocketBase hooks 项目在微信登录注册、PocketBase 原生 token、openid 身份收敛、错误观测、索引修复与 auth 兼容字段方面的修复与规范同步,涉及: - `pocket-base/` 作为正式 hooks 项目继续收敛规范 - 微信登录链路错误显式返回 - `recordAuthResponse` 使用空 `authMethod` - 登录/资料更新阶段 auth 保存失败信息透传 - 移除 hooks 查询中的 `-created` 排序,修复 `invalid sort field "created"` - `users_phone` 唯一索引改普通索引,允许空手机号用户注册 - `tbl_auth_users` 继续以 `openid` 作为业务身份锚点 - 为 PocketBase `auth` 集合兼容写入占位 `email`、随机密码与 `passwordConfirm` - OpenSpec 变更文档补录到 `pocket-base/spec/` --- ## 一、接口与认证结果 ### 当前 active hooks 接口 - `POST /api/system/test-helloworld` - `POST /api/system/health` - `POST /api/wechat/login` - `POST /api/wechat/profile` - `POST /api/wechat/refresh-token` ### 当前认证规则 - 正式鉴权仅使用 `Authorization: Bearer ` - `Open-Authorization` 不属于接口契约 - `users_wx_openid` Header 已移除 - 业务身份由当前 auth record 的 `openid` 唯一确定 --- ## 二、数据模型与落库策略 ### 1. `tbl_auth_users` - 维持 PocketBase `auth` 集合 - 业务身份锚点为 `openid` - 目标规则:除 `openid` 外,自定义业务字段均允许为空 ### 2. auth 集合兼容字段 由于 `tbl_auth_users` 是 auth 集合,为满足 PocketBase 原生 auth 保存要求,登录创建阶段补充: - `email = @wechat.local` - 随机密码 - `passwordConfirm` 说明: - 上述 `email` 为占位认证标识,不代表真实邮箱。 --- ## 三、问题修复归档 ### 1. 通用 400 `Something went wrong while processing your request.` 处理方式: - 登录路由本地 try/catch 显式返回 `{ code, msg, data }` - 全局错误包装提前注册 - 保存 auth 用户时透传原始错误信息 ### 2. `invalid sort field "created"` 原因: - hooks 内多个精确查询误用了 `-created` 排序 处理方式: - 统一移除 active hooks 中所有 `-created` 排序 ### 3. 注册成功前数据库无新记录 已识别的高风险点: - `users_phone` 唯一索引会让空手机号重复冲突 处理方式: - 改为普通索引 - 手机号唯一性改由资料完善阶段业务校验负责 --- ## 四、规范同步位置 本次 OpenSpec 记录新增: - `pocket-base/spec/changes.2026-03-23-pocketbase-hooks-auth-hardening.md` 当前 active 契约文件: - `pocket-base/spec/openapi.yaml` --- ## 五、当前边界 1. `tbl_auth_users` 作为 PocketBase `auth` 集合,仍受 PocketBase 内置 auth 规则影响。 2. schema 脚本放宽自定义字段必填约束时,PocketBase 服务端更新 auth 集合可能返回通用 500,需要结合服务端日志进一步确认。 3. 若线上仍报旧错误,通常表示最新 hooks 或 schema 尚未部署生效。 --- ## 归档日期 - 2026-03-20 ## 归档范围 本次归档覆盖微信小程序后端交互相关接口的设计、实现、规范同步与部署调整,涉及: - 接口路径统一收敛到 `/api` - 微信登录/注册合一 - 微信资料完善接口重构 - 微信手机号服务端换取 - `users_type` 自动维护 - JWT 认证与刷新 token - PocketBase Token 模式访问 - OpenAPI 与项目文档同步 - dist 构建与部署产物 --- ## 一、接口演进结果 ### 系统接口 - `POST /api/test-helloworld` - `POST /api/health` ### 微信小程序接口 - `POST /api/wechat/login` - 登录/注册合一 - 接收 `users_wx_code` - 自动换取 `users_wx_openid` - 若无账号则自动创建游客账号 - 返回 `status`、`is_info_complete`、`token`、完整用户信息 - `POST /api/wechat/profile` - 从 headers 读取 `users_wx_openid` - 需要 `Authorization` - body 接收: - `users_name` - `users_phone_code` - `users_picture` - 服务端调用微信接口换取真实手机号后写入 `users_phone` - `POST /api/wechat/refresh-token` - 仅依赖 `users_wx_openid` - 不要求旧 `Authorization` - 返回新的 JWT token --- ## 二、关键业务规则 ### 1. 用户类型 `users_type` - 新账号初始化:`游客` - 当且仅当用户首次从: - `users_name` 为空 - `users_phone` 为空 - `users_picture` 为空 变为: - 三项全部完整 时,自动升级为:`注册用户` - 后续资料修改不再覆盖已确定类型 ### 2. 用户资料完整度 `is_info_complete` 以下三项同时存在时为 `true`: - `users_name` - `users_phone` - `users_picture` 否则为 `false` ### 3. 微信手机号获取 服务端使用微信官方接口: - `getuserphonenumber` 通过 `users_phone_code` 换取真实手机号,再写入数据库字段 `users_phone`。 --- ## 三、鉴权规则 ### 标准请求头 - `Authorization: Bearer ` - `users_wx_openid: ` ### 当前规则 - `/api/wechat/login`:不需要 token - `/api/wechat/profile`:需要 `users_wx_openid + Authorization` - `/api/wechat/refresh-token`:**只需要** `users_wx_openid` --- ## 四、请求格式规则 所有微信写接口统一要求: - `Content-Type: application/json` 不符合时返回: - `415 请求体必须为 application/json` --- ## 五、PocketBase 访问策略 当前统一使用: - `POCKETBASE_API_URL` - `POCKETBASE_AUTH_TOKEN` 已移除: - `POCKETBASE_USER_NAME` - `POCKETBASE_PASSWORD` --- ## 六、部署与产物 后端已支持 dist 构建: - `npm run build` - 产物目录:`back-end/dist/` 当前发布目录包含: - `dist/src/` - `dist/spec/` - `dist/package.json` - `dist/package-lock.json` - `dist/.env` 生产启动方式: - `npm start` - 实际运行:`node dist/src/index.js` --- ## 七、文档同步结果 已同步更新: - `back-end/spec/openapi.yaml` - `docs/api.md` - `docs/deployment.md` - `README.md` 其中 `openapi.yaml` 已与当前真实接口行为对齐。 --- ## 八、质量验证结果 本次归档前已验证通过: - `npm run lint` - `npm run test` - `npm run build` 测试覆盖包括: - 系统接口 - 统一 404 - 登录/注册合一 - 非 JSON 拒绝 - 资料更新 - token 刷新 - `users_type` 升级逻辑 - `is_info_complete` 返回逻辑 --- ## 九、当前已知边界 1. `refresh-token` 当前仅依赖 `users_wx_openid`,未校验旧 token 2. 微信手机号能力依赖微信官方 `access_token` 与 `users_phone_code` 3. 当前后端为 JavaScript + Express 架构,未引入 TypeScript 编译链