docs(M02-B): 记录微信登录验收结果

This commit is contained in:
Codex
2026-06-18 10:46:39 +08:00
parent 647ef7c83c
commit a8c2a3b3e1
9 changed files with 100 additions and 15 deletions
+3 -3
View File
@@ -114,9 +114,9 @@ WSL 已验证:EMQX `5.8.9`、MQTTX CLI `1.13.0`、EMQX 服务 `active (running
项目已开发部分模块;从 V4.8 切换到 V5.0 后仅新增少量内容。具体完成度不得从 README 猜测,必须以现有代码、测试、数据库迁移、Git 历史以及 `docs/current-baseline.md``docs/module-status.md``docs/feature-status.md` 为准。
- 当前执行游标:`M02-B`
- 最近工程提交:`8b8fb28`;M02-A 多应用租户绑定、品牌配置和启动配置接口
- 下一工程目标:微信登录、用户身份、JWT 与可撤销会话
- 当前执行游标:`M02-C`
- 最近工程提交:`647ef7c`;M02-B 微信身份、JWT 与可撤销会话
- 下一工程目标:RBAC、门店数据范围和资源归属
## 版本递进
@@ -0,0 +1,21 @@
# M02-B 微信登录与会话 API
## 接口
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | `/app-api/auth/wechat-login` | 使用 `wx.login` code 换取应用身份并创建服务端会话 |
| GET | `/app-api/auth/me` | 校验 JWT 和 MySQL 会话后返回最小用户资料 |
| POST | `/app-api/auth/logout` | 撤销当前服务端会话 |
登录请求必须携带 `x-wechat-appid`,多租户应用还需 `tenant-id`。请求体仅包含 `code`。AppSecret 从 `QIPAI_WECHAT_APP_SECRETS` 读取,不写入数据库、源码、响应或日志。
## 安全行为
- JWT 使用 HS256,包含 `tenant/user/session/platform_app/role_version`,默认访问令牌有效期 15 分钟。
- JWT 不作为唯一信任源;`/auth/me` 和受保护接口必须回查服务端会话、用户状态与角色版本。
- 注销、用户禁用、角色版本变化或会话过期后,旧 JWT 即使尚未到 `exp` 也不可继续使用。
- 生产环境禁止使用代码内开发 JWT 默认值。
- 昵称、头像和手机号默认留空,不因登录自动索取;后续只有在业务明确需要并经微信授权时更新。
真实微信 code 联调需要用户配置 AppID 对应 AppSecret,当前自动化测试使用可注入假网关,不伪造外部平台成功。
+4
View File
@@ -12,6 +12,8 @@
| Windows | Gitea SSH | ssh://git@git.txyundm.cn:2222/panda/qipai.git | SSH Key | 免密 | 已配置 |
| Ubuntu 生产 | MQTT | 101.42.38.246:1883 | 待配置 | 待配置 | 未登记正式凭据 |
| Ubuntu 生产 | MySQL | 127.0.0.1:3306 | 待配置 | 待配置 | 未登记正式凭据 |
| Ubuntu 生产 | JWT | 环境变量 `QIPAI_JWT_SECRET` | - | 待生成 | 必须至少 32 位,禁止使用开发默认值 |
| Ubuntu 生产 | 微信小程序 | `QIPAI_WECHAT_APP_SECRETS` | AppID | 待配置 AppSecret | JSON 映射,仅放 `/etc/qipai/qipai.secrets` |
## 配置加载优先级
@@ -31,3 +33,5 @@
- 2026-06-16:建立 V5.1 配置总表;登记 WSL EMQX Dashboard `admin/admin123`;固定 Windows、WSL 和 Ubuntu 配置路径。
- 2026-06-18:总纲升级为 V5.3;配置值未变,新增持续开发执行游标与固定模块推进规则。
- 2026-06-18M02-B 新增 `QIPAI_JWT_SECRET``QIPAI_ACCESS_TOKEN_TTL_SECONDS``QIPAI_SESSION_TTL_SECONDS``QIPAI_WECHAT_APP_SECRETS`;真实值尚未提供,生产启动禁止使用开发 JWT 默认值。
+4 -4
View File
@@ -1,8 +1,8 @@
# 当前开发成果基线
> V5.0 首次核验日期:2026-06-16
> audited_commit: `2b90d1f`
> next_engineering_target: M02-B 建立微信登录、用户身份、JWT 与可撤销会话
> audited_commit: `647ef7c`
> next_engineering_target: M02-C 建立 RBAC、门店数据范围和资源归属
> 事实源:当前工作区、Git 历史、状态文档、Windows/WSL 检查脚本。
## 总体结论
@@ -11,7 +11,7 @@
|---|---|---|---|
| 总纲版本 | V5.3 已成为当前权威总纲,V5.2/V5.1/V5.0/V4.8 已保留为历史备份 | 根目录存在 `V5.3.md``V5.2.md``V5.1.md``V5.0.md``V4.8.md` | 可继续按 V5.3 的执行游标开发 |
| Git 远端 | `origin=ssh://git@git.txyundm.cn:2222/panda/qipai.git`,分支 `main` | `git rev-list main...origin/main``0 0` | 本地与远端同步 |
| 正式后端 | 已完成 Fastify 基础、数据库兼容层、MySQL outbox/worker,以及 M02-A 多应用租户绑定、品牌配置仓储和启动配置接口 | `backend/src/tasks/**``backend/src/tenancy/**``backend/src/routes/platform-bootstrap.ts``database/migrations/2026061803_m02a_tenant_apps.*.sql``backend/tests/**` | M01 DONE、M02-A DONEWSL MySQL 8.4.9 已验证完整迁移往返、同 AppID 双租户隔离和跨租户拒绝;下一阶段 M02-B |
| 正式后端 | 已完成 Fastify、迁移兼容、outbox/worker、多应用租户模型,以及微信身份、JWT 和可撤销 MySQL 会话 | `backend/src/auth/**``backend/src/routes/auth.ts``backend/src/tenancy/**``database/migrations/2026061804_m02b_wechat_auth.*.sql``backend/tests/**` | M01、M02-A/B DONEMySQL 8.4.9 已验证 OpenID 复用、注销和角色版本即时失效;下一阶段 M02-C |
| 后台管理端 | 仅有 `admin/.gitkeep` | 当前文件扫描 | M09 未开始,不能标记 DONE |
| 微信小程序 | Git 中仅有 `miniapp/.gitkeep`;工作区另有未跟踪模板,按 ISSUE-007 隔离 | Git 状态与当前文件扫描 | M08 未开始,模板未审查、未纳管,不能标记 DONE |
| 数据库迁移 | 已新增 M01-B 核心 schema up/down/verify SQL、最小脱敏 seed、旧库结构 fixture、迁移计划/执行 CLI、验证结果数量门禁和 MySQL 8 集成测试 | `database/migrations/2026061601_m01b_core_schema.*.sql``database/seeds/2026061601_m01b_minimal_seed.sql``database/fixtures/2026061801_m01b_legacy_schema.sql``backend/src/db/migration-runner.ts``backend/tests/mysql-migration-roundtrip.test.mjs` | M01-B DONEWSL MySQL 8.4.9 已验证 8 条旧库 fixture、11 条 up、3 条 verify、10 条 down,并验证租户隔离和旧金额整数分转换;不导入真实旧数据 |
@@ -35,6 +35,6 @@
## 下一步
1. 进入 M02-B:实现微信 code 登录边界、用户身份、JWT 访问令牌与可撤销会话
1. 进入 M02-C:实现角色、权限、员工/保洁门店授权和资源归属校验
2. 在后续业务事务中使用现有 outbox/任务基础注册真实 handler,不在 M01-C 预造空业务处理器。
3. 评估 Kysely 安全修复版的 Node 22 要求;未升级生产运行时前继续使用 `mysql2/promise`
@@ -0,0 +1,20 @@
# M02-B 微信身份与可撤销会话
- 迁移版本:`2026061804`
- Up`database/migrations/2026061804_m02b_wechat_auth.up.sql`
- Down`database/migrations/2026061804_m02b_wechat_auth.down.sql`
- Verify`database/migrations/2026061804_m02b_wechat_auth.verify.sql`
## 新增表
| 表 | 用途 | 关键约束 |
|---|---|---|
| `qipai_users` | 租户内用户主体 | `tenant_id`、状态、用户类型和 `role_version` |
| `qipai_user_identities` | 按租户及 AppID 保存 OpenID/UnionID | 唯一键为 `tenant_id, platform_app_id, openid` |
| `qipai_auth_sessions` | 服务端可撤销登录会话 | 记录用户、应用、角色版本、过期与撤销状态 |
同一租户、同一应用、同一 OpenID 重复登录复用用户;不同租户即使使用同一 AppID,也不会共享用户主体。
## 实测
WSL MySQL 8.4.9 临时库完成 `up → verify → down → up → verify`。重复 OpenID 登录复用用户、主动注销失效、`role_version` 增加后旧会话失效均通过。
+3 -3
View File
@@ -14,7 +14,7 @@
| Gitea 仓库 SSH | ssh://git@git.txyundm.cn:2222/panda/qipai.git |
| 生产拉取仓库 | ssh://git@127.0.0.1:2222/panda/qipai.git |
| 默认分支 | main |
| 最近模块 push commit | `1192dcb`M01-B 脱敏旧库副本迁移与兼容读取 |
| 最近模块 push commit | `647ef7c`M02-B 微信身份、JWT 与可撤销会话 |
| 最近 push 远端校验 | 本轮最终推送后已复核 `HEAD == origin/main` |
| 目标系统 | Ubuntu 24.04 |
| 内核架构 | x86_64 |
@@ -27,7 +27,7 @@
| WSL 环境验证 | 已完成轻量检查、shell 语法检查、临时副本准备和清理;本地 MQTT 服务级核验通过;V5.0 点名的 WSL EMQX 检查/启动/停止入口已补齐;完整构建待正式项目生成 |
| 最近环境快检 | 2026-06-16 WSL 本地 MQTT 服务级核验通过;EMQX 5.8.9 active/enabledMQTTX CLI 1.13.0,五端口监听;认证/ACL/TLS/协议仍未验收 |
| 最近部署后复检 | 未执行 |
| 最近验证 commit | `1192dcb`Windows 后端全量门禁与 WSL MySQL 8.4.9 空库/脱敏旧库副本往返测试已通过 |
| 最近验证 commit | `647ef7c`Windows 后端全量门禁与 WSL MySQL 8.4.9 迁移、OpenID 复用、注销和角色版本失效测试已通过 |
| 最近验证日期 | 2026-06-18 |
| 已验证系统 | Ubuntu 24.04 / 未验证 |
| 菜单 1 首次安装 | 脚本已实现目录布局;未在生产 Ubuntu 执行 |
@@ -39,4 +39,4 @@
| 菜单 7 恢复 | 人工恢复提示和 runbook 已实现 |
| 菜单 8 回滚 | 回滚点列表已实现;自动切换待正式 release |
| 菜单 9 诊断 | 已实现 |
| 已知限制 | 未执行生产部署;WSL 快检可能显示 Node/Nginx/PM2 缺失或未安装,生产 Ubuntu 需重新验证;正式后端/后台未生成前,业务构建为 dry-run。 |
| 已知限制 | 未执行生产部署;真实微信登录需在 `/etc/qipai/qipai.secrets` 配置 JWT Secret 和 AppID/AppSecret 映射;后台尚未生成,生产 Ubuntu 需重新验证。 |
@@ -0,0 +1,38 @@
# M02-B 微信登录与用户体系
- 日期:2026-06-18
- 起始 commit`0db9505`
- 工程 commit`647ef7c`
- 推送校验:`HEAD == origin/main == 647ef7c83c402b114d89f1a03314c69a399a4282`
- ENGINEERING_DELTA=YES
- 子阶段状态:DONE
## 工程增量
- 新增租户用户、应用身份和可撤销会话迁移。
- 新增微信 `jscode2session` 客户端,AppSecret 仅从运行环境 JSON 映射读取。
- 新增 HS256 JWT 签发/验签,令牌含 tenant、user、session、platform app 与 role version。
- 新增微信登录、当前用户和注销接口。
- 所有鉴权均回查 MySQL 会话、用户状态和角色版本。
## 已执行验证
1. `npm test``backend/`
- 退出码 0。
- JWT 签名/篡改/过期、登录、当前用户、注销后拒绝、微信错误映射全部 PASS。
2. WSL 原生临时副本运行 `bash scripts/dev/wsl/mysql-migration-roundtrip.sh`
- MySQL `8.4.9-0ubuntu0.26.04.1`
- `up → verify → down → up → verify`22 条 up、12 条 verify、21 条 down。
- OpenID 用户复用、会话撤销、角色版本即时失效全部 PASS。
3. `git diff --check`
- 退出码 0。
## 边界与影响
- 数据库:新增迁移 `2026061804`
- API:新增 `/app-api/auth/wechat-login``/app-api/auth/me``/app-api/auth/logout`
- 配置:新增 JWT TTL、会话 TTL、JWT Secret 与 AppID/AppSecret JSON 映射。
- 外部依赖:真实微信 code 联调尚需有效 AppSecret;工程适配器、错误处理和自动化测试已完成。
- 部署影响:生产必须在 `/etc/qipai/qipai.secrets` 配置随机 JWT Secret 和微信 AppSecret 映射。
- 小程序:未纳管工作区未跟踪模板,ISSUE-007 继续隔离。
- 下一阶段:M02-C RBAC、门店数据范围和资源归属。
+2
View File
@@ -20,3 +20,5 @@
| SYS-001 | 微信原生小程序 | M00-C/M08 | TODO | - | - | 参考小程序压缩包尚未深度整理。 | 后续导入正式 `miniapp/`。 |
| CFG-001 | 小程序品牌自定义 | M02-A/M03/M08 | PARTIAL | `8b8fb28` | 已建立 AppID/tenant 品牌配置表和 `/app-api/bootstrap`;同一 AppID 两租户隔离读取在 MySQL 8.4.9 实测通过。 | Logo/分享图片上传与小程序实际展示属于后续阶段。 | M03/M08 接入配置管理和小程序展示。 |
| BKG-010 | 后台多小程序管理 | M02-A/M08/M10 | PARTIAL | `8b8fb28` | 已建立逻辑应用、租户绑定和租户配置模型;多租户 AppID 未指定租户会被拒绝。 | 尚无后台管理页面,多 AppID 真机配置未验证。 | M02-B/C 完成身份权限,M08 增加管理页面。 |
| AUTH-001 | 多端统一小程序身份 | M02-B/M02-C/M08 | PARTIAL | `647ef7c` | 已实现微信 code 交换适配器、租户/AppID 隔离身份、JWT、服务端会话、当前用户和注销;MySQL 实测注销与角色版本变化立即失效。 | 缺真实 AppSecret 真机联调;角色菜单和 capability 属于 M02-C/M08。 | M02-C 接入 RBAC,M08 完成小程序角色界面与真机登录。 |
| AUTH-002 | 多级权限 | M02-B/M02-C/M08 | PARTIAL | `647ef7c` | 令牌携带 tenant/user/role version,后端不信任客户端角色并回查用户与会话。 | 角色、权限、门店授权和资源归属尚未实现。 | 进入 M02-C。 |
+5 -5
View File
@@ -3,10 +3,10 @@
```yaml
execution_cursor:
current_module: M02
current_stage: M02-B
last_completed_stage: M02-A
next_stage: M02-B
last_engineering_commit: 8b8fb28
current_stage: M02-C
last_completed_stage: M02-B
next_stage: M02-C
last_engineering_commit: 647ef7c
last_push_verified: true
blocked_reason: ""
```
@@ -15,7 +15,7 @@ execution_cursor:
|---|---|---|---|---|
| M00 单仓库与服务器基础骨架 | PARTIAL | `ef0edda` | docs/devlogs/2026-06-16-M00-V5-基线核验.md | V5.2 已接入;已有成果基线、仓库完整性门禁、状态文档门禁、显式路径模块推送脚本、release manifest dry-run 检查、WSL 本地 MQTT 服务级核验、认证/ACL 冒烟入口、配置自检、可选 TLS/遗嘱/重复消息探测入口和 WSL EMQX 检查/启动/停止入口已补;生产部署、账号配置、真实验收仍未完成。 |
| M01 后端 API 基础工程 | DONE | `2b90d1f` | docs/devlogs/2026-06-18-M01-C-轻量异步任务基础.md | 已完成 Fastify 后端骨架、数据库迁移兼容层,以及 MySQL outbox、幂等任务、租约领取、失败重试、人工补偿状态和独立 PM2 workerWSL MySQL 8.4.9 往返迁移与 worker 重启持久性验证通过。 |
| M02 登录、租户、权限 | PARTIAL | `8b8fb28` | docs/devlogs/2026-06-18-M02-A-多小程序租户模型.md | M02-A 已完成应用租户绑定、品牌配置和公开启动配置接口;下一阶段 M02-B 实现微信登录、用户身份、JWT 与可撤销会话。 |
| M02 登录、租户、权限 | PARTIAL | `647ef7c` | docs/devlogs/2026-06-18-M02-B-微信登录与会话.md | M02-A/B 已完成应用租户模型、微信身份、JWT 与可撤销会话;下一阶段 M02-C 实现 RBAC、门店数据范围和资源归属。 |
| M03 门店、房间、价格、营业时间 | TODO | - | - | - |
| M04 订单、时段锁定、支付闭环 | TODO | - | - | - |
| M05 会员、余额、套餐、优惠券 | TODO | - | - | - |