IWish Auth开发者文档
V1 Alpha GitHub

客户项目上下文

正确消费 clientAssignments 与业务授权

clientAssignments 是 IWish Auth 对“当前内部员工正在服务哪些客户项目、承担什么职责”的统一表达。各业务 App 可以按需消费,不要求所有 App 都使用。

1. 数据来源

管理员独立创建客户项目,然后从 active 飞书员工目录选择成员,并为一个员工配置一个或多个项目职责、主责标记、平台范围和生效期。

创建客户项目不需要外部客户账号,也不需要先创建客户组织。

平台管理员通过 POST /v1/admin/client-projects 创建项目,通过 POST /v1/admin/client-team-assignments 维护员工职责。飞书身份就是统一内部身份,项目团队成员必须从已同步的 active 飞书员工目录选择。

2. Session 结构

{
  "clientAssignments": [
    {
      "clientId": "00000000-0000-0000-0000-000000000401",
      "clientCode": "acme",
      "clientName": "Acme 出海项目",
      "shortName": "Acme",
      "roles": [
        {
          "assignmentId": "00000000-0000-0000-0000-000000000501",
          "code": "ad_optimizer",
          "name": "广告平台优化师",
          "category": "advertising",
          "isPrimary": false,
          "platformScopes": ["google", "meta"],
          "validFrom": "2026-07-01",
          "validUntil": null
        }
      ]
    }
  ]
}

只返回项目和职责均为 active、当前日期在有效期内、员工仍为 active 的记录。同一项目的多个职责聚合到一个项目条目。

3. 推荐用法

  • 为项目选择器提供默认可见项目。
  • 在工作台展示当前员工的服务关系和职责。
  • 缩小默认查询范围,减少误选客户。
  • 根据 platformScopes 预选 Google、Meta 等广告平台。
  • 在创建任务或需求时自动填充项目负责人候选人。

4. 不能做什么

clientAssignments 不是权限凭证,不能替代 permission 或业务数据授权。下面的判断是错误的:

// 错误:绑定项目不代表拥有删除权限
if (session.clientAssignments.some((item) => item.clientId === clientId)) {
  await deleteReport(reportId);
}

正确顺序:

const session = await auth.requirePermission(request, "reporting.report.delete");
const assignment = session.clientAssignments.find((item) => item.clientId === clientId);
await assertBusinessDataAccess({ user: session.user, assignment, clientId, reportId });
await deleteReport(reportId);

第一层是 IWish Auth App 权限,第二层是业务 App 自己的数据授权。两层都必须通过。

5. 空数据和外部账号

业务 App 必须把空数组视为正常状态:

  • 某些内部岗位不参与任何客户项目。
  • 新员工尚未分配项目。
  • 外部邮箱账号的项目可见范围由业务 App 自身模型决定,IWish Auth 不会把外部账号自动变成内部项目团队成员。

不要因为 clientAssignments 为空就把用户当成未登录,也不要自动授予全部项目。

6. 缓存与变更

项目团队会动态调整。优先使用当前 App session 返回值;长任务应在执行关键写操作前重新解析 session。不要永久存储 clientAssignments 快照作为授权依据。