132 lines
7.4 KiB
Markdown
132 lines
7.4 KiB
Markdown
# Scert 项目成员接口交接
|
||
|
||
> 本文件保留成员接口批次契约。新增可见项目入口和成员页面的当前交接见同目录 `api-handoff-v2.md`;下方“不提供项目列表或页面”描述仅对应原批次。
|
||
|
||
## 业务范围与交付边界
|
||
|
||
项目成员关系用于管理同一项目内的六类角色,与用户分组独立。普通用户可以担任项目管理员,普通全局管理员不因登录角色或同组身份自动取得项目权限。接口允许当前有效超级管理员或目标项目的项目管理员管理成员。
|
||
|
||
本批提供成员列表、授予与撤销接口,不提供项目列表/创建入口或成员页面,也不代表域名、证书、服务器、DNS 等全部业务资源已经接入项目授权。源码专项、实库与构建证据分别记录于《构建版本与数据库支持矩阵》第二十三节,不据此声明生产验收通过。
|
||
|
||
## 通用约定
|
||
|
||
- 前缀:`/api/v1/projects/:projectID/members`,路径必须使用实际项目标识。
|
||
- 使用正式登录接口建立的会话 Cookie;浏览器请求同源发送。服务器验证提供的 `Origin`/`Referer`,来源拒绝返回 403。
|
||
- 不传 `actor_id`、全局角色或项目权限;操作者仅取本次服务端验证的会话,仓储执行时重新核对账户状态和成员关系。
|
||
- 项目、用户及游标输入仅允许 1~128 位 ASCII 字母、数字、连字符、下划线;空游标例外。已有项目实体本身仍遵守其更严格的命名规则,此接口不创建项目。
|
||
- 响应头 `X-Scert-Request-ID` 可用于关联诊断。错误响应为 `{"error":"中文提示","request_id":"请求编号"}`,不能仅按文本匹配决定权限。
|
||
- 成功授权/撤销和成功审计在同一事务提交;失败时不得乐观更新界面。成功变更后应重新获取第一页,清空旧游标栈。
|
||
|
||
## 接口
|
||
|
||
### GET:读取成员列表
|
||
|
||
```http
|
||
GET /api/v1/projects/default/members?page_size=10&after=user-001
|
||
```
|
||
|
||
| 查询参数 | 类型 | 约束 |
|
||
|---|---|---|
|
||
| `page_size` | 整数 | 默认 10;只接受 5、10、15、30 |
|
||
| `after` | 字符串 | 默认空,从第一页读取;下一页使用上一响应的 `next_cursor` |
|
||
|
||
重复参数、未知参数、非法转义、无效页大小或游标返回 400。没有页码或总人数参数。
|
||
|
||
成功返回 200:
|
||
|
||
```json
|
||
{
|
||
"items": [
|
||
{
|
||
"user_id": "user-002",
|
||
"username": "测试成员",
|
||
"status": "active",
|
||
"roles": ["dns_admin", "read_only"]
|
||
}
|
||
],
|
||
"page_size": 10,
|
||
"has_more": false,
|
||
"next_cursor": ""
|
||
}
|
||
```
|
||
|
||
- 按用户 ID 升序的游标分页,不按角色关系计数,同一账户的角色合并到一个成员项中。
|
||
- `items` 始终为数组;合法空项目和末尾空页为 `[]`,不是未授权。`has_more=false` 时 `next_cursor` 为空。
|
||
- 列表包含仍有成员关系的停用账户,便于撤销其角色;停用账户自身无法操作接口。
|
||
- 不返回邮箱、密码摘要、用户分组或全局角色。角色顺序由接口稳定排序,界面应按角色值映射中文名称。
|
||
- 超级管理员不隐式出现在成员列表中;只有显式成员关系才列出。空默认项目不会自动增加成员。
|
||
- 游标不是快照。翻页期间发生授权变更时,应允许用户刷新并回到第一页,不承诺跨请求一致性。
|
||
|
||
### POST:授予角色
|
||
|
||
```http
|
||
POST /api/v1/projects/default/members
|
||
Content-Type: application/json
|
||
```
|
||
|
||
```json
|
||
{
|
||
"user_id": "user-002",
|
||
"role": "dns_admin"
|
||
}
|
||
```
|
||
|
||
- 目标必须为真实有效账户,不能凭用户名或邮箱替代 `user_id`。
|
||
- 正文只接受 `user_id`、`role`,拒绝未知字段、多段 JSON 和超过 64 KiB 的正文;不接受查询参数。
|
||
- 成功为 201:`{"message":"项目角色已授予"}`。
|
||
- 已存在相同项目/账户/角色关系返回 409,不生成重复关系;其他角色可另行授予。
|
||
- 同一账户可在多个项目持有多个角色,但该规则不改变普通用户只能属于一个用户分组的限制。
|
||
|
||
### DELETE:撤销角色
|
||
|
||
```http
|
||
DELETE /api/v1/projects/default/members/user-002/roles/dns_admin
|
||
```
|
||
|
||
- 不接受请求体或查询参数,空白请求体也拒绝。不能使用 DELETE 正文冒充操作者。
|
||
- 成功为 204,无响应体;客户端不要尝试解析成功响应 JSON。
|
||
- 不存在的目标关系与权限不足均返回 403,不作为幂等成功。
|
||
- 允许项目管理员撤销自己的项目管理员角色。成功后应退出成员管理状态或处理重新读取产生的 403,不能重试为自己恢复权限;有效超级管理员仍可恢复授权。
|
||
|
||
## 角色枚举与显示名称
|
||
|
||
| 值 | 中文名称 |
|
||
|---|---|
|
||
| `project_admin` | 项目管理员 |
|
||
| `certificate_admin` | 证书管理员 |
|
||
| `deployment_admin` | 部署管理员 |
|
||
| `dns_admin` | DNS 管理员 |
|
||
| `audit_viewer` | 审计查看者 |
|
||
| `read_only` | 只读用户 |
|
||
|
||
`super_admin` 不是可授予的项目角色。角色能力矩阵见《项目资源关联模型》9.1 节;不能因为名称相近就授予未接入资源的权限。普通账户不能读取完整私钥的上限不因项目管理员角色而解除。
|
||
|
||
## 错误与审计边界
|
||
|
||
| HTTP 状态 | 含义与界面处理 |
|
||
|---|---|
|
||
| 400 | 输入无效;显示中文提示,不重试相同请求 |
|
||
| 401 | 未登录、会话失效或账户已停用;重新认证 |
|
||
| 403 | 来源拒绝、无项目权限、项目不存在、目标账户/关系不满足条件;不区分这些情况枚举他人资源 |
|
||
| 409 | 项目成员关系已存在,或系统尚未初始化;以当前流程和错误响应区分,不当作成功 |
|
||
| 500 | 操作或事务审计失败;不展示底层数据库错误,不乐观认为授权已生效 |
|
||
| 503 | 成员服务未接入或不可用;禁止将空白页面解释为没有成员 |
|
||
|
||
会话验证后、仓储执行前发生撤权或停用仍会拒绝。失败审计保留本次已验证身份;未认证请求不归到客户端声明的账户。失败审计独立于回滚事务,记录固定动作、HTTP 状态、目标及请求编号,不保存请求正文或任意底层错误。请求取消后审计仍有独立的三秒上限;审计存储自身失败时只写稳定服务器诊断日志,原失败响应保持不变,不能承诺事件已持久化。
|
||
|
||
## 前端集成与验收场景
|
||
|
||
1. 按账户分页并显示中文角色标签;用户可选择 5、10、15、30 条,切换页大小回到第一页。
|
||
2. 保存各页起始游标用于上一页;不将 `next_cursor` 当作页码,不伪造总人数。
|
||
3. 授权提交后等待 201,再刷新列表;重复授权 409 显示冲突并刷新,不生成本地重复项。
|
||
4. 撤销前确认目标与角色,自我撤权单独提示;204 后不解析 JSON,失去权限时停止继续操作。
|
||
5. 分别验证普通全局管理员、只读项目成员、其他项目管理员均无法管理本项目成员。
|
||
6. 测试空列表、末页、停用成员、多角色账户和翻页期间关系变更;不显示邮箱或其他未返回字段。
|
||
7. 401/403/500/503 分别显示正确状态,不能统一伪装为空列表;诊断信息展示请求编号而非数据库原文。
|
||
|
||
## 待完成
|
||
|
||
- [ ] 项目列表/创建及入口选择、授权目标账户选择、成员页面与浏览器验收。
|
||
- [ ] 全部业务资源与排队任务执行/取消/重试的权限重判。
|
||
- [ ] PostgreSQL 当前实库、Linux 原生及完整生产部署验收;已通过的局部测试不替代这些门禁。
|