B1:RBAC 只读查询接口(4 个)+ docs/05 登记 A035-A038
在此之前,权限只能靠脚本改,平台里**没有任何地方能看"谁能访问什么"**。
B1 先把"看得见"做出来:
- GET /api/v1/admin/roles 角色清单 + 权限数 + 在用人数
- GET /api/v1/admin/roles/{role_code} 角色详情
- GET /api/v1/admin/roles/{role_code}/permissions 权限清单(按权限码排序,
便于与各 Service 的 require() 对照)
- GET /api/v1/admin/users/{user_id}/roles 某人**实际解析出来**的角色/权限/数据范围
几个刻意的决定:
1. 权限码复用 `audit:read` 而不新增 `rbac:read`:这份清单本身就是审计材料,且复用是零数据
改动、立刻可用(新增权限码要先改 sys_permission,而它目前由 seed_test_rbac.py 以
DELETE 重建语义管理)。将来要细分再加,不冲突。
2. `/users/{id}/roles` 直接复用 IdentityService.resolve,不自己拼 SQL —— 那正是请求进来时
走的链路(status 检查、assigned_at/expires_at 时间窗、data_scope 取最高、客户分配)。
自己写一遍必然漂移,而"这里查出的权限"与"实际能用的权限"不一致比没有这个接口更糟。
测试里加了一条交叉验证:该接口的 roles/data_scope 必须与登录响应完全一致。
3. 停用账号返回**空权限集**而不是 404 —— 用户存在但拿不到权限,如实呈现比 404 更利于排障。
4. 角色详情与权限清单分开:权限为空的角色不该被误判成"角色不存在"。
5. 全部只读、不写审计(它们返回的就是审计材料本身),docs/05 §19 登记时审计列标"否"。
权限变更(提权/降权)仍无接口 —— docs/05 §19 已注明那不是遗漏,而是需要单独评审
(审计留痕 + 禁止自我提权 + 保护内置角色三条红线)。
另:确认了 load_context 对 sys_user_role.expires_at 是有过滤的(assigned_at<=now AND
(expires_at IS NULL OR expires_at>now)),我上一轮只读了半段 SQL 差点误报。
验证:ruff 干净 / mypy 185 文件 0 错 / 文档守卫 38 份无编号冲突 /
unit+contract 1140 passed / integration 98 passed(本批新增 8 个)。
This commit is contained in:
@@ -1099,10 +1099,25 @@ GET /internal/metrics
|
||||
| A032 | `PUT /api/v1/admin/negative-word-rules/{rule_id}` | `config:write` | 必须 | `200` | 禁止表达 |
|
||||
| A033 | `GET /api/v1/admin/audit-records` | `audit:read` | 否 | `200` | 否 |
|
||||
| A034 | `POST /api/v1/auth/tokens` | 公开(登录前无身份) | 否 | `200` | 登录成功/失败 |
|
||||
| A035 | `GET /api/v1/admin/roles` | `audit:read` | 否 | `200` | 否 |
|
||||
| A036 | `GET /api/v1/admin/roles/{role_code}` | `audit:read` | 否 | `200` | 否 |
|
||||
| A037 | `GET /api/v1/admin/roles/{role_code}/permissions` | `audit:read` | 否 | `200` | 否 |
|
||||
| A038 | `GET /api/v1/admin/users/{user_id}/roles` | `audit:read` | 否 | `200` | 否 |
|
||||
| O001 | `GET /internal/health/live` | 内网 | 否 | `200` | 否 |
|
||||
| O002 | `GET /internal/health/ready` | 内网 | 否 | `200/503` | 否 |
|
||||
| O003 | `GET /internal/metrics` | 监控系统 | 否 | `200` | 否 |
|
||||
|
||||
> **A034 – A038 的两点说明**:
|
||||
>
|
||||
> - `POST /api/v1/auth/tokens` 是平台内**唯一的登录入口**(§11 已注明这是"平台不重复实现
|
||||
> 签发"的唯一例外;**刷新与注销仍归统一身份认证模块**)。
|
||||
> - A035 – A038 是 RBAC 的**只读**查询,供管理员回答"谁能访问什么""这个人为什么 403"。
|
||||
> 它们复用 `audit:read` 而**不新增** `rbac:read`:这份清单本身就是审计材料,且复用是
|
||||
> 零数据改动、立刻可用(新增权限码得先改 `sys_permission`,而它目前由
|
||||
> `seed_test_rbac.py` 以 DELETE 重建语义管理)。
|
||||
> **权限变更(提权 / 降权)尚无接口** —— 那条写路径必须带三条红线
|
||||
> (审计留痕、禁止自我提权、保护内置角色),需要单独评审,不是遗漏。
|
||||
|
||||
业务域接口 `/customer-service/handover-tickets/**`、`/advisory-plans/**`、`/sim-orders/**`、`/risk-scans/**` 和 `/risk-alerts/**` 的具体方法、请求体、领域状态机和错误码分别由对应业务文档登记;它们仍必须遵守本文第 3-5、11 和 12 节。
|
||||
|
||||
## 20. 变更流程
|
||||
|
||||
Reference in New Issue
Block a user