中间件最终态整改执行计划
查看文档来源信息
- 来源目录:
addons/sys_base/docs - 来源文件:
功能说明/中间件最终态整改执行计划.md
cl-midserver-2026cl-midserver-pcweb-2026
2. 本阶段不处理的仓库
- 所有下游后端仓
- 所有下游 PCWEB 仓
- 所有 clapp 仓
cl-mid-wxapp-2026- SDK 镜像仓
- 文档平台仓以外的发布动作
3. 本阶段允许的改动
- 中间件后端代码
- 中间件 PCWEB 代码
- 中间件正式文档
- 中间件对外正式契约
- 为达成正式态所必需的数据库加字段、索引、数据修正脚本
- 为达成正式态所必需的验收脚本调整
4. 本阶段不做的事
- 不做下游实际迁移
- 不做历史兼容保留口径设计
- 不做 SDK 发布与消费接入
- 不做日志表大规模存储架构重构
- 不做 API 版本化双轨并存
- 不做“旧接口先 deprecated、以后再删”的过渡方案
二、阶段划分
第一阶段:中间件本体收口
目标:把中间件自身的安全、权限、菜单、认证、命名、文档、验收全部收口到正式态。
Task 1.1 安全问题修复
| 编号 | 问题 | 位置 | 正式整改要求 |
|---|---|---|---|
| S1 | kickOffline 暴露在 public 侧 | public/system/sys_base.go | 移出 public,改为 platform 受控接口;调用权限:仅限超管上下文或持有独立动作授权的角色;对应 manifest 中新增独立 action seed(例如 session_kick_offline),作为正式权限标识;不允许普通角色通过模糊菜单权限间接获得踢人能力 |
| S2 | getAccessTokenCheck 暴露在 public 侧 | 同上 | 改为 /sys_base/public/service/getAccessTokenCheck 服务态受控接口;默认优先读 Redis,forceRefresh=true 时真实请求微信刷新 |
| S3 | sys_external_app_keys 仍是明文 key 直查,无失效治理 | middleware/auth_api_protect.go、相关 model/api/service | 第一阶段(中间件端一步到位):key 列改为存 SHA-256 hash(创建时返回明文一次,此后不可查);新增字段 key_type、expired_at、last_used_at;permanent key 只用于换取 tempKey,不再作为每次请求的运行时凭证;tempKey 存 Redis,TTL 2 小时;支持删除、吊销、到期失效。第二阶段(SDK 自动换票):Go SDK 封装启动换票 + 过期前自动刷新,与第一阶段 DB/Redis 改造衔接 |
| S4 | wechatAppsInfo.secret / 支付相关 secret 读取口径 | model/app/app_wechat_apps_info.go 等 | 取消本轮新增的 APP_SECRET_KEY 加密依赖,应用 secret 按提交值保存;列表与详情接口一律脱敏展示,运行态和服务态同步链路读取当前库中真实值;历史已写成 enc:gcm:v1: 前缀的数据不做自动还原,必须重新录入真实 secret;后续如需重新设计密钥加密,必须先形成正式密钥来源、轮换、迁移和下游消费契约 |
| S5 | 用户与组织关联“先删后增”无事务 | service/platform/system/sys_user.go | 改为事务执行,避免半成功半失败 |
| S6 | 无正式 JWKS 公钥端点 | 新增 public 受控只读端点 | 新增 GET /.well-known/jwks.json;每个 JWK 必须带 kid;当前签名 key 命名明确,例如 signing-key-v1;旧 key 保留窗口明确,例如 7 天;iss 必须与正式中间件域名或配置值一致;aud 必须按业务配置校验;下游本地 JWT 校验以 JWKS 为准,不再依赖每次调用 /verifyToken |
| S7 | 无结构化审计事件与 trace-id 贯穿 | middleware/operation.go 等 | 建立正式审计事件模型,链路注入 trace-id,日志与审计记录贯通 |
| S8 | 登录 / 验证码缺频控 | LoginNew、captcha 相关接口 | 增加账号/IP 级限流、失败阈值与锁定策略 |
Task 1.2 认证体系收口
目标:把当前分裂的服务态认证、用户态认证、只读系统态认证收口成一套正式上下文机制。
1.2.1 AuthApiProtect 正式化
| 编号 | 问题 | 正式整改要求 |
|---|---|---|
| A1 | 当前 AuthApiProtect 仅做放行/拒绝,handler 层无法统一感知调用模式 | 建立统一 AuthContext,注入 gin context,由 handler 明确读取 |
| A2 | X-System-Key 白名单逻辑与 X-App-Key 逻辑割裂 | 收口为统一认证入口,认证后统一落到上下文,不允许 handler 继续读旧 header 自行猜模式 |
| A3 | 若干 /public/auth/* 接口在用户模式下缺组织/范围过滤 | 统一按 AuthContext 区分 service mode 与 user mode,明确每个接口在两种模式下的正式行为 |
1.2.2 AuthContext 统一注入
新增正式上下文字段建议:
go
type AuthContext struct {
Mode string // service / user
AppId string
AddonsType string
Claims *BaseClaims
DeepOrgIds []uint
AreaUuids []string
}正式要求:
- 所有
/sys_base/public/auth/*handler 不再自行推断调用来源 - 不再允许通过 header workaround 绕开正式权限链
- 服务模式看到的是服务态允许的数据
- 用户模式必须回到组织 / 区域 / 当前用户权限范围过滤
1.2.3 本阶段必须审计的 auth 公共接口
以下接口必须逐个确认在 service mode 和 user mode 下的正式行为,按最保守权限开口:
| 接口 | 允许模式 | 正式行为 |
|---|---|---|
getUserInfosBatch | service + user | user mode 按 ctx.DeepOrgIds 过滤;service mode 全量 |
getUserIdsByAuthorityIds | service + user | user mode JOIN org_user 过滤到当前用户组织范围 |
getSubOrgUserIdsByUser | service + user | user mode 验证请求者与 targetUserId 有组织交集 |
getUserAreaPermission | service + user | user mode 按当前用户校区权限过滤 |
getUserOrgInfo | service + user | user mode 仅返回当前用户自己的组织信息 |
batchGetAreaInfo | service + user | user mode 过滤到当前用户可见校区范围 |
getAreaListByApp | service + user | user mode 按应用与校区权限过滤 |
syncWechatAppsInfo | system_api | 服务态受控同步微信应用与支付主体资料,不返回 AccessToken、notifyHost 和业务子商户归属 |
getAccessTokenCheck | system_api | 服务态受控获取微信应用运行时 AccessToken,支持 forceRefresh 强刷 |
| 其他 auth 公共接口 | service only | 不属于用户前台正式链路的,默认仅服务态,不开放给 user mode |
Task 1.3 菜单与角色授权链路收口
目标:把菜单、页面授权、动作授权、默认页、Casbin 放行这条链正式讲清楚并收口。
| 编号 | 问题 | 正式整改要求 |
|---|---|---|
| M1 | LoginNew 返回 menus,前端又调用 asyncMenu,菜单链重复 | 本轮以 asyncMenu 为唯一正式菜单入口;LoginNew.menus 同轮删除;所有验收脚本、前端消费方同步调整;不允许保留双入口长期并存 |
| M2 | public / platform 各有一份 sys_menu* 逻辑镜像 | 合并为一套正式实现,删除镜像维护 |
| M3 | 菜单管理页、角色授权页缺搜索/过滤能力 | 增加菜单名称搜索、模块过滤、必要的层级可读性优化 |
| M4 | 角色授权、动作授权、默认页的正式行为虽已成型,但文档和前端解释仍不足 | 在中间件内把“页面授权 / 动作授权 / 默认页 / 运行时 API 放行”正式说明清楚 |
| M5 | 菜单清单发布后缺正式回滚机制 | 增加已发布版本切换能力,回滚必须是正式能力 |
| M6 | 角色缺复制能力 | 增加正式 copyAuthority 能力 |
| M7 | 当前角色授权必须继续确保“操作者不能下发自己没有的能力” | 保持并验收现有正式限制:只能操作可管理角色,只能下发自己已有菜单/动作/API 能力 |
Task 1.4 页面与治理入口整改
目标:把中间件治理页恢复成业务上可理解、可操作、不断链的正式形态。
1.4A 页面与入口具体整改项
| 编号 | 问题 | 具体整改内容 | 涉及位置 |
|---|---|---|---|
| G1 | 应用信息、KEY 管理、模块管理、角色管理、部门管理入口可能被治理过程中误删 | 逐项核对左侧菜单入口是否仍存在;缺失入口恢复到正式菜单清单;对应页面必须可打开、可保存、非空白页、非 404 | manifest/catalog/code_manifest.go、PCWEB 路由注册、菜单发布页与治理页 view |
| G2 | 应用菜单 / 系统菜单 / 应用准入 / 应用功能概念混淆 | 在页面标题、页头说明、帮助文案中明确:系统菜单是中间件治理菜单;应用菜单是下游应用菜单清单;应用准入是角色可进入哪些应用实例;应用功能授权是角色在正式页面/动作上的授权 | menu.vue、appMenuPublish.vue、authority/components/*.vue |
| G3 | 角色管理中的“可管理角色范围”含义不直观 | 页面标题、说明文案、保存成功提示、后端报错提示统一改成“当前角色还能继续管理哪些角色”口径 | authority.vue、datas.vue、后端 authority API 错误信息 |
| G4 | 超管上下文 / 普通角色上下文 / 角色切换结果用户难以理解 | 在登录后当前上下文展示、角色切换弹层、用户信息返回结构中明确当前使用的是“超级管理员上下文”还是“某角色上下文” | 登录相关前端、selectRole 相关逻辑、用户信息展示区 |
1.4B 验收清单:治理入口完整性
以下内容作为本阶段强制验收清单,不单独拆成代码任务,但必须全部满足:
- 应用信息页存在且可正常维护应用
- KEY 管理页存在且可正常维护 key
- 模块管理 / 应用准入页存在且可正常维护绑定关系
- 角色管理页存在且可正常配置应用、页面、动作、默认页、可管理角色范围
- 部门管理页存在且不因治理被误删
- 系统菜单页不是直接跳发布操作页,而是先能看当前正式结构,再执行发布
- 应用菜单页同样能先看当前正式结构,再执行发布
Task 1.5 结构调整与命名统一
目标:清掉旧命名、空壳、错拼、职责混乱文件,避免后续持续误导。
| 编号 | 问题 | 正式整改要求 |
|---|---|---|
| ST1 | sys_base.go 过度混杂 | 按职责拆分 handler 文件,但路由边界与 handler 拆分要分开处理 |
| ST2 | sys_jwt_manage.go 空壳 | 删除空壳路由文件及其引用 |
| ST3 | authorityBtn 空目录 | 删除 |
| ST4 | sysAuthoritiesSetting 空目录 | 删除 |
| ST5 | udateSysArea 拼写错误 | 全量改为 updateSysArea |
| ST6 | heardUploadFile 错拼 | 全量改为 headerUploadFile |
| ST7 | setUserAuthority / setUserAuthorities 命名混乱 | 改成语义明确的正式命名 |
| ST8 | sysArea / schoolAreaManage / organizationGroup / model / appModel 前后端命名不一致 | 统一正式命名,前后端目录与 API 命名同步调整 |
Task 1.6 代码清理
目标:清掉不再属于最终态的旧实现、旧说明、旧页面、旧接口。
| 编号 | 问题 | 正式整改要求 |
|---|---|---|
| CL1 | SysUserBlacklist 对后台用户治理意义弱且与 enable 能力重叠 | 评估后若确认不属于最终态,则后端接口、前端页面、路由、API 文件一并删除 |
| CL2 | 公众号相关接口耦合在 auth_service | 已审计:getSubscribeUserByOpenid(caller: takeaway/datacenter)、getSubscribeUserByUnionid(caller: deliverybox),属于正式链路,保留;本轮确保 AuthApiProtect 权限模式符合 1.2.3 口径 |
| CL3 | 下游死接口问题需要登记但本阶段不直接改下游 | 不在本阶段改下游代码,但必须登记到《SDK 与下游迁移总计划》的“已识别下游阻塞项”章节,至少记录接口名、调用仓、当前状态、建议处理方式 |
| CL4 | 旧注释、旧命名、无用函数、legacy/compat 口径残留 | 一律按正式态清理,不保留“以后可能用”的无效代码 |
Task 1.7 正式文档与契约同步
目标:中间件代码、仓库正式文档、文档平台三处口径统一。
正式要求:
- 中间件正式
docs只保留中文正式文档目录 - 一接口一文档
- 所有本阶段新增或变更接口必须同步文档
- 以下专题必须补齐正式文档:
- 登录与上下文切换
- 角色管理与可管理角色范围
- 页面授权 / 动作授权 / 默认页
- 菜单发布与版本切换
- 应用信息与 KEY 管理
- 服务态认证与
AuthContext - JWKS 公钥发布
- 仓库 docs 与
cl-api-2026文档平台口径必须同轮同步
Task 1.8 验收矩阵
本阶段不是只验能跑,而是验正式权限行为正确。验收分三层组织:
第一层:编译与自动化验收
| 类别 | 验收项 |
|---|---|
| 后端 | go build ./... 通过 |
| 后端 | 现有中间件正式验收脚本全部通过 |
| 前端 | npm run build 通过 |
第二层:自动化权限行为验收(优先 playwright e2e)
| # | 场景 | 预期 |
|---|---|---|
| 1 | 超管账号无角色时可登录 | loginNew 返回 availableRoles,不返回 menus/token |
| 2 | 超管账号多角色时可选择超管上下文 | 全部菜单可见、manifest_runtime_guard 直接放行 |
| 3 | 超管账号多角色时可选择普通角色 | 等同于普通角色上下文 |
| 4 | 上次普通角色登录,下次复用 | 直接进入普通角色上下文 |
| 5 | 上次超管上下文登录,下次复用 | 直接进入超管上下文 |
| 6 | 普通角色只能看到被授权页面 | 非授权页面不可见 |
| 7 | 普通角色只能执行被授权动作 | 非授权动作返回 403 |
| 8 | 普通角色不能给目标角色下发自己没有的页面/动作/API | 保存接口拒绝 |
| 9 | 普通角色只能操作可管理范围内的角色 | 越界角色不可见不可操作 |
| 10 | 服务模式调 auth 公共接口 | 返回服务态全量数据 |
| 11 | 用户模式调 auth 公共接口 | 返回按组织/区域/权限过滤结果 |
| 12 | 菜单发布 + 角色授权 + 默认页后 | 运行时菜单和 Casbin 同步生效 |
第三层:手工抽验
| # | 场景 |
|---|---|
| H1 | PCWEB 核心治理页可正常打开,不出现 404 / 空白页 / 权限误拦截 |
| H2 | 应用信息页存在且可正常维护 |
| H3 | KEY 管理页存在且可正常维护 key |
| H4 | 模块管理 / 应用准入页存在且可正常维护绑定关系 |
| H5 | 角色管理页存在且可正常配置应用、页面、动作、默认页、可管理角色范围 |
| H6 | 部门管理页存在且不因治理被误删 |
| H7 | 系统菜单页可先看当前正式结构,再执行发布 |
| H8 | 应用菜单页可先看当前正式结构,再执行发布 |
验收标准:三层全部通过 + 正式文档同步完成 = P1 完工。
第二阶段:SDK 建设
第二阶段在第一阶段稳定后再开工,不与中间件本体收口混做。
目标:把下游“复制中间件调用代码”的模式,替换成正式 SDK 调用模式。
Task 2.1 Go SDK clsdk-go
范围建议:
auth/menu/common/appinfo/sysdata/
正式职责:
- 中间件服务态认证接入
- token 校验与权限检查封装
- 菜单清单上传 / 提交 / 发布封装
- 应用信息本地内存缓存
- 校区 / 部门 / 用户主数据本地内存缓存
- trace-id 传播
- 超时、重试、断路器、singleflight 合并
Task 2.2 PC Web SDK clsdk-pcweb
正式职责:
- 登录态接入
- 菜单加载
- 路由生成
- axios 拦截器
- 权限判断
- 可选组件与 composables
Task 2.3 uni-app SDK clsdk-clapp
正式职责:
- 登录态接入
- 请求拦截
- 验证码封装
- 服务态接入封装
- 后续支付 / 组件扩展预留
Task 2.4 SDK 源码管理策略
正式原则:
- 各 SDK 仓独立维护源码与版本
clsdk-go:创链中间件体系面向所有 Go 下游后端服务的正式 SDK 仓clsdk-pcweb:创链中间件体系面向所有 PCWEB 下游管理端项目的正式前端 SDK 仓clsdk-clapp:创链中间件体系面向所有 uni-app / clapp 下游移动管理端项目的正式前端 SDK 仓- 中间件接口变更必须同轮更新 SDK 源码与文档
第三阶段:下游迁移
本阶段单独立计划,不并入中间件本体整改主单。
范围:
- 下游后端接 Go SDK
- 下游 PCWEB 接
@cl-mid/pcweb - 下游 clapp 接
@cl-mid/clapp - 删除下游重复 auth / menu /
user_auth_utils/wechat_apps_info复制逻辑
四、明确排除项
以下不属于“当前中间件本体完工”主任务:
- 下游实际改造
- SDK 镜像仓发布动作
- API 版本化双轨设计
- “保留旧 URL + deprecated header” 过渡方案
- 日志表从日表体系直接重构为 MySQL 分区单表
- 微服务拆分
- 大规模 UI 重构
- 第三方依赖普遍升级
五、日志与存储类问题的单独处理原则
日志问题重要,但不应拖垮本轮主链。
本轮只做止血项
- 操作日志写入异步化
- body / resp 长文本截断与受控存储
- 查询接口补日期范围
- 性能热点查询优化
- 不自动删历史日志
后续再做重构项
- 日表迁移到单表分区
- 历史日志结构迁移
- 大规模存储层调整
六、计划口径统一原则
为避免再次返工,本计划统一采用以下口径:
- 不写“deprecated,后续再删”
- 不写“兼容一个版本”
- 不写“先保留旧接口以防万一”
- 保留的能力必须属于正式态
- 删除的能力本轮直接删净
- 所有正式代码改动,必须同轮更新正式文档
- 所有正式接口改动,必须同轮更新验收脚本
七、建议时间线
| 阶段 | 预估工期 | 产出 |
|---|---|---|
| 第一阶段:中间件本体收口 | 2-3 周 | 中间件后端 + PCWEB 正式态稳定、文档同步、验收通过 |
| 第二阶段:SDK 建设 | 3-4 周 | Go SDK / PCWEB SDK / clapp SDK 源码完成,发布链打通 |
| 第三阶段:下游迁移 | 6-8 周 | 下游逐仓接入正式 SDK,删除重复逻辑 |
八、下一步建议
如果这份整理版你认可,下一步建议:
- 将本文档作为 中间件本体完工执行单,只保留第一阶段内容开工
- 单独编写 SDK 与下游迁移总计划,放入第二阶段和第三阶段详细内容
- SDK 仓创建时机:第一阶段开工不依赖 SDK 仓已创建;第二阶段开始前建好:
clsdk-go(Go SDK,内部 GitLab)clsdk-pcweb(PC Web SDK,内部 GitLab)clsdk-clapp(uni-app SDK,内部 GitLab)
这样线程执行时不会再跑去碰下游,也不会把中间件本体和 SDK、下游改造搅在一起。