Federation & Service

Organizations Federation API

Organizations Service 的 HTTP 与 SDK API Reference

Organizations Federation API

这篇文档描述客户端和 Bureau 可以调用的 Organizations Action。产品后端的身份和权限接入见 Bureau 接入 Organizations

安装

import { Federation } from "@downcity/bureau";
import { OrganizationsService } from "@downcity/services";

const federation = new Federation({ database });

federation.use(new OrganizationsService({
  max_organizations_per_user: 3,
}));
选项必填说明
max_organizations_per_user一个用户在 Federation 中最多拥有的 active Organization 总数

Service 支持 better-sqlite3、PostgreSQL 和 Cloudflare D1,并统一使用 context.transaction()

地址与鉴权

{federation_origin}/v1/organizations/{action}

所有 Action 都需要 Federation user_token

Authorization: Bearer ub_<JWT>

Federation 从已验证 Token 读取 user_idbureau_id。GET Action 使用 Query,POST Action 使用 JSON。

类型

type Organization = {
  organization_id: string;
  name: string;
  scope_type: "federation" | "bureau";
  scope_bureau_id: string;
  state: "active" | "archived";
  created_by: string;
  created_at: string;
  updated_at: string;
  archived_at: string;
};

type Membership = {
  membership_id: string;
  organization_id: string;
  user_id: string;
  role: "owner" | "admin" | "member";
  state: "active" | "removed";
  created_at: string;
  updated_at: string;
  removed_at: string;
  removed_by: string;
};

type JoinRequest = {
  request_id: string;
  organization_id: string;
  user_id: string;
  state: "pending" | "approved" | "rejected" | "canceled";
  requested_at: string;
  decided_at: string;
  decided_by: string;
};

scope_type = federationscope_bureau_id 为空字符串。scope_type = bureau 时,scope_bureau_id 来自创建请求的 user_token.bureau_id

权限

操作OwnerAdminMember
读取 Organization 和成员
修改名称
审批 Join Request
移除 Member
移除 Admin
任命或撤销 Admin
转移 Owner
归档
主动退出转移后

Action

MethodAction权限说明
GETmyUser列出当前用户可见的 Organization
GETgetMember读取 Organization 与当前 Membership
POSTcreateUser创建 Organization 并成为 Owner
POSTupdateOwner/Admin修改名称
POSTarchiveOwner归档 Organization
GETmembership/getMember读取当前 Membership
GETmembers/listMember列出 active Membership
POSTmembers/roleOwner设置 Admin 或 Member
POSTmembers/removeOwner/Admin移除可管理的成员
POSTmembers/leaveAdmin/Member主动退出
POSTowner/transferOwner转移唯一 Owner
POSTjoin-requests/createUser申请加入
POSTjoin-requests/cancelApplicant取消 pending 申请
GETjoin-requests/listOwner/Admin列出 pending 申请
POSTjoin-requests/decideOwner/Admin批准或拒绝申请

Organization Action

GET my

GET /v1/organizations/my

默认只返回 active Organization。包含归档记录:

GET /v1/organizations/my?include_archived=true

返回 { "items": UserOrganization[] }。Federation Organization 在任意 Token Bureau 可见;Bureau Organization 只在当前 Token Bureau 匹配时可见。

GET get

GET /v1/organizations/get?organization_id=org_01J...

要求 active Membership,返回 { organization, membership }。成员可以读取 archived Organization,但不能继续治理写入。

POST create

创建全局 Organization:

{
  "name": "Genesis Research",
  "scope_type": "federation"
}

创建当前 Bureau Organization:

{
  "name": "Genesis Research",
  "scope_type": "bureau"
}

Service 返回 { organization, membership },Membership 是唯一 Owner。名称去除首尾空白后必须为 1–120 个字符。

POST update

{
  "organization_id": "org_01J...",
  "name": "New Name"
}

Owner/Admin 可修改名称。Organization 作用域创建后不能修改。

POST archive

{ "organization_id": "org_01J..." }

Owner 可执行。归档不可恢复,会停止治理写入并释放 Owner 额度。Membership 和 Join Request 历史保留。

Membership Action

GET membership/get

GET /v1/organizations/membership/get?organization_id=org_01J...

返回 { organization, membership }。Bureau 可以携带用户提交的同一个 user_token 调用此接口。被移除的用户返回 403 NOT_AN_ORGANIZATION_MEMBER

GET members/list

GET /v1/organizations/members/list?organization_id=org_01J...

返回 { "items": Membership[] },只包含 active Membership。

POST members/role

{
  "organization_id": "org_01J...",
  "membership_id": "mem_01J...",
  "role": "admin"
}

Owner 可将非 Owner 成员设置为 adminmember。转移 Owner 使用 owner/transfer

POST members/remove

{
  "organization_id": "org_01J...",
  "membership_id": "mem_01J..."
}

Owner 可以移除 Admin 或 Member;Admin 只能移除 Member。唯一 Owner 不能被移除。

POST members/leave

{ "organization_id": "org_01J..." }

Admin 和 Member 可以退出。Owner 必须先转移所有权。

POST owner/transfer

{
  "organization_id": "org_01J...",
  "membership_id": "mem_new_owner"
}

目标必须是 active Member,并且还有 Owner 额度。原 Owner 变为 Admin。

Join Request Action

POST join-requests/create

{ "organization_id": "org_01J..." }

用户通过已知 ID 申请加入。重复申请返回同一个 pending 记录。已有 active Membership 时返回 { state: "joined", organization, membership }

POST join-requests/cancel

{ "request_id": "join_01J..." }

申请人可以取消自己的 pending 申请。

GET join-requests/list

GET /v1/organizations/join-requests/list?organization_id=org_01J...

Owner/Admin 调用,返回 pending Join Request。

POST join-requests/decide

{
  "request_id": "join_01J...",
  "decision": "approved"
}

decision 接受 approvedrejected。批准时,Service 在同一事务中创建新的 Member Membership。

错误

HTTPCode含义
400ORGANIZATION_INPUT_INVALID名称、ID、角色或决策无效
400ORGANIZATION_SCOPE_INVALIDscope_type 无效
401AUTH_REQUIRED缺少有效用户身份
403ORGANIZATION_BUREAU_MISMATCHToken Bureau 不能访问该 Bureau Organization
403NOT_AN_ORGANIZATION_MEMBER当前用户没有 active Membership
403ORGANIZATION_ROLE_DENIED治理角色不允许操作
404ORGANIZATION_NOT_FOUNDOrganization 不存在
404ORGANIZATION_MEMBERSHIP_NOT_FOUNDMembership 不存在或已失效
404JOIN_REQUEST_NOT_FOUNDJoin Request 不存在或不可操作
409ORGANIZATION_LIMIT_REACHEDOwner 额度已满
409OWNER_TRANSFER_REQUIRED必须先转移 Owner
410ORGANIZATION_ARCHIVEDOrganization 已归档

客户端应按 error.code 分支,不要依赖错误文本。