Files
Neo-ZQYY/docs/audit/changes/2026-03-27__miniprogram-permission-unification.md
Neo 14a12342b5 chore(audit): 补追 96 份未入仓审计孤本 — 覆盖 2026-02-26 ~ 2026-04-08
这些审计记录原本堆积在 docs/audit/changes/changes/ 嵌套误产物目录下(由开发机迁移
79d3c2e 前后的不明批量操作产生)。由于同期 .gitignore 屏蔽了 docs/audit/ 全目录,
它们从未入过 git 任何分支 history。删除即永久丢失。

按 docs/specs/audit-gap-recovery/tasks.md 阶段 1 执行,将全部 96 份 D 类孤本
(主目录无同名、git history 亦无记录)复制到 docs/audit/changes/ 主目录入仓。

涵盖主题: P1-P18 全栈集成 / 多模块累积变更 / ETL bug 修复 / 业务日切 /
   召回与任务引擎改造 / 租户管理与审批 / 董事会财务 / 客户与助教详情 /
   DDL 基线合并 / Kiro 到 Claude Code 迁移

阶段 2(B 类内容漂移 1 份)和阶段 4(嵌套目录删除)独立推进。

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 06:35:42 +08:00

188 lines
11 KiB
Markdown
Raw Permalink 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.
# 变更审计记录小程序权限体系统一改造W1-W5
| 字段 | 值 |
|------|-----|
| 日期 | 2026-03-27 09:55:17 |
| Prompt-ID | P20260327-083929 |
| Session-ID | 0ecf5499 |
| Session 路径 | docs/audit/session_logs/2026-03/27/11_476da926_075522 |
## 操作摘要
小程序权限体系统一改造——后端为权限唯一真相源,前端根据权限码动态控制页面/tab/按钮可见性。涵盖 5 个工作项W1-W5refresh_token 有效期延长、`/api/xcx/me` 返回 permissions 列表、角色-权限码映射修正、后端端点从 `require_approved` 迁移到 `require_permission("xxx")`、前端权限守卫重写为权限码驱动。
## 变更范围
- **W1 — Token 有效期**`apps/backend/app/config.py` — refresh_token 有效期从 7 天延长至 30 天
- **W2 — 权限下发**`apps/backend/app/schemas/xcx_auth.py` UserStatusResponse 新增 `permissions: list[str]` 字段;`apps/backend/app/routers/xcx_auth.py` `/api/xcx/me` 返回当前用户的 permissions 列表
- **W3 — 角色权限映射**`db/zqyy_app/migrations/2026-03-27__fix_role_permissions.sql` 修正角色-权限码映射关系
- **W4 — 后端端点权限化**
- `xcx_tasks.py`7 个端点从 `require_approved``require_permission("view_tasks")`
- `xcx_performance.py`2 个端点 → `require_permission("view_tasks")`
- `xcx_customers.py`2 个端点 → `require_permission("view_board_customer")`
- `xcx_coaches.py`1 个端点 → `require_permission("view_board_coach")`
- **W5 — 前端权限守卫重写**
- `auth-guard.ts`:重写为权限码驱动(不再基于角色硬编码)
- `app.ts`:改用 `syncPermissions` 同步权限
- `typings/index.d.ts`globalData 新增 `permissions` 字段
- 看板页面board-finance/board-customer/board-coach`.ts` + `.wxml` 改为动态二级 tab根据权限码控制可见性
## 风险与回滚
- 风险点:
- 权限码不匹配:若数据库 `auth.role_permissions` 映射遗漏某权限码,对应角色用户将被 403 拒绝
- 前后端权限一致性:前端 tab 可见性依赖 `permissions` 数组,后端 API 依赖 `require_permission`,两者必须使用相同的权限码字符串
- refresh_token 延长至 30 天:已签发的旧 token7 天有效期)不受影响,新 token 才生效
- 迁移脚本依赖 `auth.roles``auth.permissions` 表已存在且包含正确的角色/权限记录
- 回滚要点:
- 数据库:回滚 `2026-03-27__fix_role_permissions.sql` 中的映射变更
- 后端:将 12 个端点的 `require_permission(...)` 改回 `require_approved`;移除 UserStatusResponse 的 `permissions` 字段;恢复 config.py 的 7 天有效期
- 前端:恢复 `auth-guard.ts` 为角色驱动版本;恢复 `app.ts``syncVisibleTabs`;恢复看板页面的静态 tab 逻辑
## 改动注解
### `apps/backend/app/config.py`
- 变更类型:修改
- 原始原因W1 要求延长 refresh_token 有效期,减少用户频繁重新登录
- 思路分析:将 `REFRESH_TOKEN_EXPIRE_DAYS` 从 7 改为 30属于配置级变更不影响 token 签发/验证逻辑
- 修改结果:新签发的 refresh_token 有效期 30 天,已签发的旧 token 不受影响
### `apps/backend/app/schemas/xcx_auth.py`
- 变更类型:修改
- 原始原因W2 需要在 `/api/xcx/me` 响应中携带权限码列表,供前端做动态可见性控制
- 思路分析:在 `UserStatusResponse` Pydantic model 中新增 `permissions: list[str]` 字段,默认空列表
- 修改结果:前端可通过 `me.permissions` 获取当前用户的全部权限码
### `apps/backend/app/routers/xcx_auth.py`
- 变更类型:修改
- 原始原因W2 配合 schema 变更,在 `/api/xcx/me` 路由中查询并填充 permissions
- 思路分析:从 `auth.role_permissions` + `auth.permissions` 表 JOIN 查询当前用户角色对应的权限码列表
- 修改结果approved 用户调用 `/api/xcx/me` 时,响应中包含完整的 permissions 数组
### `apps/backend/app/routers/xcx_tasks.py`
- 变更类型:修改
- 原始原因W4 将端点级鉴权从"已审核即可访问"升级为"需持有特定权限码"
- 思路分析7 个端点的依赖注入从 `require_approved` 替换为 `require_permission("view_tasks")`,实现细粒度权限控制
- 修改结果:仅持有 `view_tasks` 权限码的角色可访问任务相关端点
### `apps/backend/app/routers/xcx_performance.py`
- 变更类型:修改
- 原始原因W4 绩效端点同样需要权限码控制
- 思路分析2 个端点改为 `require_permission("view_tasks")`,与任务模块共享同一权限码(绩效是任务的子功能)
- 修改结果:绩效端点与任务端点权限一致
### `apps/backend/app/routers/xcx_customers.py`
- 变更类型:修改
- 原始原因W4 客户看板端点需要独立权限码
- 思路分析2 个端点改为 `require_permission("view_board_customer")`
- 修改结果:仅持有 `view_board_customer` 权限码的角色可访问客户看板
### `apps/backend/app/routers/xcx_coaches.py`
- 变更类型:修改
- 原始原因W4 助教看板端点需要独立权限码
- 思路分析1 个端点改为 `require_permission("view_board_coach")`
- 修改结果:仅持有 `view_board_coach` 权限码的角色可访问助教看板
### `db/zqyy_app/migrations/2026-03-27__fix_role_permissions.sql`
- 变更类型:新增
- 原始原因W3 需要修正角色-权限码映射,确保各角色拥有正确的权限集合
- 思路分析:迁移脚本操作 `auth.role_permissions` 表,建立角色与权限码的多对多映射
- 修改结果:数据库中角色权限映射与 W4/W5 的权限码使用保持一致
### `apps/miniprogram/miniprogram/utils/auth-guard.ts`
- 变更类型:修改
- 原始原因W5 将前端权限守卫从角色硬编码改为权限码驱动
- 思路分析:重写核心逻辑——不再维护 `PAGE_ROLES` 角色→页面映射,改为从 `globalData.permissions` 读取权限码,页面/tab 可见性由权限码决定
- 修改结果:前端权限判断与后端权限码完全对齐,新增权限码时只需更新数据库映射,无需改前端代码
### `apps/miniprogram/miniprogram/app.ts`
- 变更类型:修改
- 原始原因W5 全局入口需要同步权限码到 globalData
- 思路分析:将 `syncVisibleTabs` 替换为 `syncPermissions`,在 `/api/xcx/me` 返回后将 permissions 存入 globalData
- 修改结果:小程序启动时自动同步权限码,后续页面/组件可直接读取
### `apps/miniprogram/typings/index.d.ts`
- 变更类型:修改
- 原始原因W5 TypeScript 类型定义需要同步新增 permissions 字段
- 思路分析:在 `IAppOption.globalData` 接口中新增 `permissions: string[]`
- 修改结果全局类型安全IDE 自动补全支持
### `apps/miniprogram/miniprogram/pages/board-finance/board-finance.ts`
- 变更类型:修改
- 原始原因W5 财务看板二级 tab 需要根据权限码动态显示
- 思路分析:从 globalData.permissions 过滤出当前用户可见的二级 tab动态渲染
- 修改结果:不同角色看到不同的二级 tab 组合
### `apps/miniprogram/miniprogram/pages/board-finance/board-finance.wxml`
- 变更类型:修改
- 原始原因W5 配合 .ts 的动态 tab 逻辑,模板需要支持动态渲染
- 思路分析tab 列表改为 `wx:for` 遍历动态数组
- 修改结果模板与逻辑层联动tab 可见性由权限码控制
### `apps/miniprogram/miniprogram/pages/board-customer/board-customer.ts`
- 变更类型:修改
- 原始原因W5 客户看板同上
- 思路分析:同 board-finance 的动态 tab 方案
- 修改结果:客户看板二级 tab 权限码驱动
### `apps/miniprogram/miniprogram/pages/board-customer/board-customer.wxml`
- 变更类型:修改
- 原始原因W5 配合动态 tab
- 思路分析:同 board-finance.wxml
- 修改结果:模板支持动态 tab 渲染
### `apps/miniprogram/miniprogram/pages/board-coach/board-coach.ts`
- 变更类型:修改
- 原始原因W5 助教看板同上
- 思路分析:同 board-finance 的动态 tab 方案
- 修改结果:助教看板二级 tab 权限码驱动
### `apps/miniprogram/miniprogram/pages/board-coach/board-coach.wxml`
- 变更类型:修改
- 原始原因W5 配合动态 tab
- 思路分析:同 board-finance.wxml
- 修改结果:模板支持动态 tab 渲染
## 本次对话文件变更
### 新增文件
- `docs/audit/prompt_logs/prompt_log_20260327_083929.md`
- `docs/audit/session_logs/2026-03/27/11_476da926_075522/main_01_db3ab14f.md`
- `docs/audit/session_logs/2026-03/27/11_476da926_075522/sub_01_db3ab14f.md`
### 删除文件
- `docs/audit/session_logs/2026-03/27/11_476da926_075522/main_01_77123f5a.md`
## 验证
1. 数据库验证:执行迁移后 `SELECT r.code, p.code FROM auth.role_permissions rp JOIN auth.roles r ON r.id=rp.role_id JOIN auth.permissions p ON p.id=rp.permission_id ORDER BY r.code, p.code;` 确认映射正确
2. 后端验证:`GET /api/xcx/me` 返回的 `permissions` 数组包含当前角色对应的全部权限码
3. 前端验证:
- coach 登录 → 看到任务 tab看不到客户/助教看板 tab
- staff 登录 → 看到看板 tab看不到任务 tab
- head_coach/manager 登录 → 看到全部 tab
- 无权限用户访问受保护端点 → 返回 403
4. 迁移状态:⚠️ `2026-03-27__fix_role_permissions.sql` 需确认已在测试库执行
## 文件清单
| 文件 | 操作 | 工作项 |
|------|------|--------|
| `apps/backend/app/config.py` | 修改 | W1 |
| `apps/backend/app/schemas/xcx_auth.py` | 修改 | W2 |
| `apps/backend/app/routers/xcx_auth.py` | 修改 | W2 |
| `apps/backend/app/routers/xcx_tasks.py` | 修改 | W4 |
| `apps/backend/app/routers/xcx_performance.py` | 修改 | W4 |
| `apps/backend/app/routers/xcx_customers.py` | 修改 | W4 |
| `apps/backend/app/routers/xcx_coaches.py` | 修改 | W4 |
| `db/zqyy_app/migrations/2026-03-27__fix_role_permissions.sql` | 新增 | W3 |
| `apps/miniprogram/miniprogram/utils/auth-guard.ts` | 修改 | W5 |
| `apps/miniprogram/miniprogram/app.ts` | 修改 | W5 |
| `apps/miniprogram/typings/index.d.ts` | 修改 | W5 |
| `apps/miniprogram/miniprogram/pages/board-finance/board-finance.ts` | 修改 | W5 |
| `apps/miniprogram/miniprogram/pages/board-finance/board-finance.wxml` | 修改 | W5 |
| `apps/miniprogram/miniprogram/pages/board-customer/board-customer.ts` | 修改 | W5 |
| `apps/miniprogram/miniprogram/pages/board-customer/board-customer.wxml` | 修改 | W5 |
| `apps/miniprogram/miniprogram/pages/board-coach/board-coach.ts` | 修改 | W5 |
| `apps/miniprogram/miniprogram/pages/board-coach/board-coach.wxml` | 修改 | W5 |