Scert/.claude/docs/ai/project-members/api-handoff.md

7.4 KiB
Raw Blame History

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:读取成员列表

GET /api/v1/projects/default/members?page_size=10&after=user-001
查询参数 类型 约束
page_size 整数 默认 10;只接受 5、10、15、30
after 字符串 默认空,从第一页读取;下一页使用上一响应的 next_cursor

重复参数、未知参数、非法转义、无效页大小或游标返回 400。没有页码或总人数参数。

成功返回 200:

{
  "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:授予角色

POST /api/v1/projects/default/members
Content-Type: application/json
{
  "user_id": "user-002",
  "role": "dns_admin"
}
  • 目标必须为真实有效账户,不能凭用户名或邮箱替代 user_id。
  • 正文只接受 user_id、role,拒绝未知字段、多段 JSON 和超过 64 KiB 的正文;不接受查询参数。
  • 成功为 201:{"message":"项目角色已授予"}。
  • 已存在相同项目/账户/角色关系返回 409,不生成重复关系;其他角色可另行授予。
  • 同一账户可在多个项目持有多个角色,但该规则不改变普通用户只能属于一个用户分组的限制。

DELETE:撤销角色

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 原生及完整生产部署验收;已通过的局部测试不替代这些门禁。